dad8096f248710f0284dff2257bb1ac9266d46b2
[apps/core/preloaded/quickpanel.git] / daemon / notifications / noti_list_item.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *  http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <string.h>
18 #include <Ecore_X.h>
19
20 #include "quickpanel-ui.h"
21 #include "common.h"
22 #include "list_util.h"
23 #include "quickpanel_def.h"
24 #include "noti_list_item.h"
25 #include "noti_node.h"
26 #include "noti.h"
27 #include "noti_util.h"
28 #ifdef QP_ANIMATED_IMAGE_ENABLE
29 #include "animated_image.h"
30 #endif
31
32 #define QP_DEFAULT_ICON ICONDIR"/quickpanel_icon_default.png"
33
34
35 static Evas_Object *_check_duplicated_progress_loading(Evas_Object *obj, const char *part, const char *style_name) {
36         Evas_Object *old_content = NULL;
37         const char *old_style_name = NULL;
38
39         retif(obj == NULL, NULL, "Invalid parameter!");
40         retif(part == NULL, NULL, "Invalid parameter!");
41         retif(style_name == NULL, NULL, "Invalid parameter!");
42
43         DBG("");
44
45         old_content = elm_object_part_content_get(obj, part);
46         if (old_content != NULL) {
47                 old_style_name = elm_object_style_get(old_content);
48                 if (old_style_name != NULL) {
49                         DBG("%s", old_style_name);
50                         if (strcmp(old_style_name, style_name) == 0)
51                                 return old_content;
52
53                         elm_object_part_content_unset(obj, part);
54                         evas_object_del(old_content);
55                 }
56         }
57
58         return NULL;
59 }
60
61 static Evas_Object *_check_duplicated_image_loading(Evas_Object *obj, const char *part, const char *file_path) {
62         Evas_Object *old_ic = NULL;
63         const char *old_ic_path = NULL;
64
65         retif(obj == NULL, NULL, "Invalid parameter!");
66         retif(part == NULL, NULL, "Invalid parameter!");
67         retif(file_path == NULL, NULL, "Invalid parameter!");
68
69         old_ic = elm_object_part_content_get(obj, part);
70         if (old_ic != NULL) {
71                 elm_image_file_get(old_ic, &old_ic_path, NULL);
72                 if (old_ic_path != NULL) {
73                         DBG("%s:%s", old_ic_path, file_path);
74                         if (strcmp(old_ic_path, file_path) == 0)
75                                 return old_ic;
76                 }
77
78                 elm_object_part_content_unset(obj, part);
79                 evas_object_del(old_ic);
80         }
81
82         return NULL;
83 }
84
85 static void _set_text_to_part(Evas_Object *obj, const char *part, const char *text) {
86         const char *old_text = NULL;
87
88         retif(obj == NULL, , "Invalid parameter!");
89         retif(part == NULL, , "Invalid parameter!");
90         retif(text == NULL, , "Invalid parameter!");
91
92         old_text = elm_object_part_text_get(obj, part);
93         if (old_text != NULL) {
94                 if (strcmp(old_text, text) == 0) {
95                         return ;
96                 }
97         }
98
99         elm_object_part_text_set(obj, part, text);
100 }
101
102 static char *_noti_get_progress(notification_h noti, char *buf,
103                                            int buf_len)
104 {
105         double size = 0.0;
106         double percentage = 0.0;
107
108         retif(noti == NULL, NULL, "Invalid parameter!");
109         retif(buf == NULL, NULL, "Invalid parameter!");
110
111         notification_get_size(noti, &size);
112         notification_get_progress(noti, &percentage);
113
114         if (percentage > 0) {
115                 if (percentage < 1.0 ) {
116                         if (snprintf(buf, buf_len, "%d%%", (int)(percentage * 100)) <= 0) {
117                                 return NULL;
118                         }
119                 }
120                 if (percentage >= 1.0) {
121                         snprintf(buf, buf_len, "%d%%", 100);
122                 }
123
124                 return buf;
125         } else if (size > 0 && percentage == 0) {
126                 if (size > (1 << 30)) {
127                         if (snprintf(buf, buf_len, "%.1lfGB",
128                                 size / 1000000000.0) <= 0)
129                                 return NULL;
130
131                         return buf;
132                 } else if (size > (1 << 20)) {
133                         if (snprintf(buf, buf_len, "%.1lfMB",
134                                 size / 1000000.0) <= 0)
135                                 return NULL;
136
137                         return buf;
138                 } else if (size > (1 << 10)) {
139                         if (snprintf(buf, buf_len, "%.1lfKB",
140                                 size / 1000.0) <= 0)
141                                 return NULL;
142
143                         return buf;
144                 } else {
145                         if (snprintf(buf, buf_len, "%lfB", size) <= 0)
146                                 return NULL;
147
148                         return buf;
149                 }
150         }
151
152         return NULL;
153 }
154
155 static void _noti_list_item_ongoing_set_progressbar(Evas_Object *noti_list_item)
156 {
157         notification_h noti = NULL;
158         Evas_Object *ic = NULL;
159         Evas_Object *old_ic = NULL;
160         double size = 0.0;
161         double percentage = 0.0;
162         notification_type_e type = NOTIFICATION_TYPE_NONE;
163         notification_ly_type_e layout = NOTIFICATION_LY_NONE ;
164
165         retif(noti_list_item == NULL, , "Invalid parameter!");
166
167         noti_list_item_h *noti_list_item_data = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_ITEM_H);
168         retif(noti_list_item == NULL, , "data is NULL");
169
170         noti_node_item *item = noti_list_item_data->data;
171         retif(item == NULL, , "data is NULL");
172
173         noti = item->noti;
174         retif(noti == NULL, , "noti is NULL");
175
176         notification_get_type(noti, &type);
177         if (type == NOTIFICATION_TYPE_ONGOING) {
178                 notification_get_size(noti, &size);
179                 notification_get_progress(noti, &percentage);
180                 notification_get_layout(noti, &layout);
181
182                 if (layout != NOTIFICATION_LY_ONGOING_EVENT) {
183                         if (percentage > 0 && percentage <= 1) {
184                                 old_ic = _check_duplicated_progress_loading(noti_list_item,
185                                                 "elm.swallow.progress", "quickpanel/list_progress");
186                                 if (old_ic == NULL) {
187                                         ic = elm_progressbar_add(noti_list_item);
188                                         if (ic == NULL)
189                                                 return ;
190                                         elm_object_style_set(ic, "quickpanel/list_progress");
191                                 } else {
192                                         ic = old_ic;
193                                 }
194
195                                 elm_progressbar_value_set(ic, percentage);
196                                 elm_progressbar_horizontal_set(ic, EINA_TRUE);
197                                 elm_progressbar_pulse(ic, EINA_FALSE);
198                         } else if (size >= 0 && percentage == 0) {
199                                 old_ic = _check_duplicated_progress_loading(noti_list_item,
200                                                 "elm.swallow.progress", "quickpanel/pending_list");
201                                 if (old_ic == NULL) {
202                                         ic = elm_progressbar_add(noti_list_item);
203                                         if (ic == NULL)
204                                                 return ;
205                                         elm_object_style_set(ic, "quickpanel/pending_list");
206                                 } else {
207                                         ic = old_ic;
208                                 }
209
210                                 elm_progressbar_horizontal_set(ic, EINA_TRUE);
211                                 elm_progressbar_pulse(ic, EINA_TRUE);
212                         }
213                 }
214         }
215
216         if (ic != NULL) {
217                 elm_object_part_content_set(noti_list_item, "elm.swallow.progress", ic);
218         }
219 }
220
221 static void _noti_list_item_ongoing_set_icon(Evas_Object *noti_list_item)
222 {
223         notification_h noti = NULL;
224         Evas_Object *ic = NULL;
225         Evas_Object *old_ic = NULL;
226         char *icon_path = NULL;
227         char *thumbnail_path = NULL;
228         char *main_icon_path = NULL;
229         char *sub_icon_path = NULL;
230
231         retif(noti_list_item == NULL, , "Invalid parameter!");
232
233         noti_list_item_h *noti_list_item_data = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_ITEM_H);
234         retif(noti_list_item == NULL, , "data is NULL");
235
236         noti_node_item *item = noti_list_item_data->data;
237         retif(item == NULL, , "data is NULL");
238
239         noti = item->noti;
240         retif(noti == NULL, , "noti is NULL");
241
242         notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL,
243                                &thumbnail_path);
244         notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON, &icon_path);
245
246         if (thumbnail_path != NULL && icon_path != NULL) {
247                 main_icon_path = thumbnail_path;
248                 sub_icon_path = icon_path;
249         } else if (icon_path != NULL && thumbnail_path == NULL) {
250                 main_icon_path = icon_path;
251                 sub_icon_path = NULL;
252         } else if (icon_path == NULL && thumbnail_path != NULL) {
253                 main_icon_path = thumbnail_path;
254                 sub_icon_path = NULL;
255         } else {
256                 main_icon_path = NULL;
257                 sub_icon_path = NULL;
258         }
259
260         if (main_icon_path != NULL) {
261                 old_ic = _check_duplicated_image_loading(noti_list_item,
262                                 "elm.swallow.thumbnail", main_icon_path);
263
264                 if (old_ic == NULL) {
265                         ic = elm_image_add(noti_list_item);
266                         elm_image_resizable_set(ic, EINA_FALSE, EINA_TRUE);
267                         elm_image_file_set(ic, main_icon_path, main_icon_path);
268                         elm_object_part_content_set(noti_list_item, "elm.swallow.thumbnail", ic);
269 #ifdef QP_ANIMATED_IMAGE_ENABLE
270                         quickpanel_animated_image_add(ic);
271 #endif
272                 }
273         }
274
275         if (sub_icon_path != NULL) {
276                 old_ic = _check_duplicated_image_loading(noti_list_item,
277                                 "elm.swallow.icon", sub_icon_path);
278
279                 if (old_ic == NULL) {
280                         ic = elm_image_add(noti_list_item);
281                         elm_image_resizable_set(ic, EINA_FALSE, EINA_TRUE);
282                         elm_image_file_set(ic, sub_icon_path, sub_icon_path);
283                         elm_object_part_content_set(noti_list_item, "elm.swallow.icon", ic);
284                 }
285         }
286
287         if (main_icon_path == NULL && sub_icon_path == NULL) {
288                 old_ic = _check_duplicated_image_loading(noti_list_item,
289                                 "elm.swallow.thumbnail", QP_DEFAULT_ICON);
290
291                 if (old_ic == NULL) {
292                         ic = elm_image_add(noti_list_item);
293                         elm_image_resizable_set(ic, EINA_FALSE, EINA_TRUE);
294                         elm_image_file_set(ic, QP_DEFAULT_ICON, QP_DEFAULT_ICON);
295                         elm_object_part_content_set(noti_list_item, "elm.swallow.thumbnail", ic);
296 #ifdef QP_ANIMATED_IMAGE_ENABLE
297                         quickpanel_animated_image_add(ic);
298 #endif
299                 }
300         }
301 }
302
303 static void _noti_list_item_ongoing_set_text(Evas_Object *noti_list_item)
304 {
305         notification_h noti = NULL;
306         notification_error_e noti_err = NOTIFICATION_ERROR_NONE;
307         char *text = NULL;
308         char *text_utf8 = NULL;
309         char *domain = NULL;
310         char *dir = NULL;
311         char *pkgname = NULL;
312         char *caller_pkgname = NULL;
313         int group_id = 0, priv_id = 0;
314         char buf[128] = { 0, };
315         notification_type_e type = NOTIFICATION_TYPE_NONE;
316         double size = 0.0;
317         double percentage = 0.0;
318         int isProgressBarEnabled = 1;
319         notification_ly_type_e layout = NOTIFICATION_LY_NONE ;
320
321         retif(noti_list_item == NULL, , "Invalid parameter!");
322
323         noti_list_item_h *noti_list_item_data = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_ITEM_H);
324         retif(noti_list_item == NULL, , "data is NULL");
325
326         noti_node_item *item = noti_list_item_data->data;
327         retif(item == NULL, , "data is NULL");
328
329         noti = item->noti;
330         retif(noti == NULL, , "noti is NULL");
331
332         /* Set text domain */
333         notification_get_text_domain(noti, &domain, &dir);
334         if (domain != NULL && dir != NULL)
335                 bindtextdomain(domain, dir);
336
337         /* Get pkgname & id */
338         notification_get_pkgname(noti, &pkgname);
339         notification_get_application(noti, &caller_pkgname);
340         notification_get_id(noti, &group_id, &priv_id);
341         notification_get_type(noti, &type);
342         notification_get_size(noti, &size);
343         notification_get_progress(noti, &percentage);
344         notification_get_layout(noti, &layout);
345
346         DBG("percentage:%f size:%f", percentage, size);
347
348         if (percentage <= 0.0 && size <= 0.0) {
349                 isProgressBarEnabled = 0;
350         }
351
352         noti_err = notification_get_text(noti,
353                                                         NOTIFICATION_TEXT_TYPE_TITLE,
354                                                         &text);
355
356         if (noti_err == NOTIFICATION_ERROR_NONE && text != NULL) {
357                 quickpanel_util_char_replace(text, _NEWLINE, _SPACE);
358                 _set_text_to_part(noti_list_item, "elm.text.title", text);
359         }
360
361         noti_err = notification_get_text(noti,
362                         NOTIFICATION_TEXT_TYPE_CONTENT,
363                                                         &text);
364         if (noti_err == NOTIFICATION_ERROR_NONE && text != NULL) {
365                 if (layout == NOTIFICATION_LY_ONGOING_EVENT) {
366                         text_utf8 = elm_entry_utf8_to_markup(text);
367                         if (text_utf8 != NULL) {
368                                 _set_text_to_part(noti_list_item, "elm.text.content.multiline", text_utf8);
369                                 free(text_utf8);
370                         } else {
371                                 _set_text_to_part(noti_list_item, "elm.text.content.multiline", text);
372                         }
373
374                         elm_object_signal_emit(noti_list_item, "elm,state,elm.text.content.multiline,active", "elm");
375                 } else {
376                         quickpanel_util_char_replace(text, _NEWLINE, _SPACE);
377                         _set_text_to_part(noti_list_item, "elm.text.content", text);
378                         elm_object_signal_emit(noti_list_item, "elm,state,elm.text.content,active", "elm");
379                 }
380         }
381
382         if (isProgressBarEnabled != 0
383                         && layout != NOTIFICATION_LY_ONGOING_EVENT) {
384                 text = _noti_get_progress(noti, buf,
385                                                                           sizeof(buf));
386                 if (text != NULL) {
387                         quickpanel_util_char_replace(text, _NEWLINE, _SPACE);
388                         _set_text_to_part(noti_list_item, "elm.text.time", text);
389                 }
390         }
391 }
392
393 static void _noti_list_item_call_item_cb(Evas_Object *noti_list_item, const char *emission) {
394         retif(noti_list_item == NULL, , "invalid parameter");
395         retif(emission == NULL, , "invalid parameter");
396
397         DBG("%s", emission);
398
399         void (*cb)(void *data, Evas_Object *obj) = NULL;
400         noti_list_item_h *data = NULL;
401
402         data = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_ITEM_H);
403
404         if (strncmp(emission,"selected", strlen("selected")) == 0) {
405                 cb = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_CB_SELECTED_ITEM);
406
407                 if (cb != NULL && data != NULL) {
408                         cb(data->data, noti_list_item);
409                 }
410         }
411         if (strncmp(emission,"button_1", strlen("button_1")) == 0) {
412                 cb = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_CB_BUTTON_1);
413
414                 if (cb != NULL && data != NULL) {
415                         cb(data->data, noti_list_item);
416                 }
417         }
418         if (strncmp(emission,"deleted", strlen("deleted")) == 0) {
419                 cb = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_CB_DELETED_ITEM);
420
421                 if (cb != NULL && data != NULL) {
422                         cb(data->data, noti_list_item);
423                 }
424         }
425 }
426
427 static void _signal_cb(void *data, Evas_Object *o, const char *emission, const char *source)
428 {
429         retif(data == NULL, , "invalid parameter");
430         retif(o == NULL, , "invalid parameter");
431         retif(emission == NULL, , "invalid parameter");
432
433         _noti_list_item_call_item_cb(o, emission);
434 }
435
436 HAPI Evas_Object *noti_list_item_create(Evas_Object *parent, notification_ly_type_e layout) {
437         Evas_Object *box = NULL;
438
439         retif(parent == NULL, NULL, "Invalid parameter!");
440
441         box = elm_layout_add(parent);
442
443         DBG("");
444         elm_layout_file_set(box, DEFAULT_EDJ,
445                         "quickpanel/listitem/default");
446
447         evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
448         evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
449         evas_object_show(box);
450
451         noti_list_item_h *box_h = (noti_list_item_h *) malloc(sizeof(noti_list_item_h));
452         box_h->layout = layout;
453         box_h->status = STATE_NORMAL;
454         box_h->data = NULL;
455         evas_object_data_set(box, E_DATA_NOTI_LIST_ITEM_H, box_h);
456         DBG("created box:%p", box);
457
458         //add event
459         elm_object_signal_callback_add(box,
460                         "selected",
461                         "edje",
462                         _signal_cb,
463                         parent
464         );
465
466         //add event
467         elm_object_signal_callback_add(box,
468                         "button_1",
469                         "edje",
470                         _signal_cb,
471                         parent
472         );
473
474         //add event
475         elm_object_signal_callback_add(box,
476                         "deleted",
477                         "edje",
478                         _signal_cb,
479                         parent
480         );
481
482         return box;
483 }
484
485 static void _noti_list_item_set_layout_ongoing_noti(Evas_Object *noti_list_item,
486                 notification_h noti) {
487         DBG("");
488         retif(noti_list_item == NULL, , "invalid parameter");
489
490         _noti_list_item_ongoing_set_progressbar(noti_list_item);
491         _noti_list_item_ongoing_set_icon(noti_list_item);
492         _noti_list_item_ongoing_set_text(noti_list_item);
493 }
494
495 static void _noti_list_item_set_layout(Evas_Object *noti_list_item, notification_h noti,
496                 notification_ly_type_e layout) {
497
498         DBG("layout:%d", layout);
499
500         switch (layout) {
501                 case NOTIFICATION_LY_NOTI_EVENT_SINGLE:
502                         break;
503                 case NOTIFICATION_LY_NOTI_EVENT_MULTIPLE:
504                         break;
505                 case NOTIFICATION_LY_NOTI_THUMBNAIL:
506                         break;
507                 case NOTIFICATION_LY_NONE:
508                         break;
509                 case NOTIFICATION_LY_ONGOING_EVENT:
510                 case NOTIFICATION_LY_ONGOING_PROGRESS:
511                         _noti_list_item_set_layout_ongoing_noti(noti_list_item, noti);
512                         break;
513                 case NOTIFICATION_LY_MAX:
514                         DBG("not supported layout type:%d", layout);
515                         break;
516         }
517 }
518
519 HAPI void noti_list_item_remove(Evas_Object *noti_list_item) {
520
521         retif(noti_list_item == NULL, , "invalid parameter");
522
523         noti_list_item_h *noti_list_item_h = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_ITEM_H);
524
525         if (noti_list_item_h != NULL)
526                 free(noti_list_item_h);
527
528         evas_object_data_del(noti_list_item, E_DATA_NOTI_LIST_ITEM_H);
529         evas_object_data_del(noti_list_item, E_DATA_NOTI_LIST_CB_SELECTED_ITEM);
530         evas_object_data_del(noti_list_item, E_DATA_NOTI_LIST_CB_BUTTON_1);
531         evas_object_data_del(noti_list_item, E_DATA_NOTI_LIST_CB_DELETED_ITEM);
532
533         evas_object_del(noti_list_item);
534 }
535
536 HAPI void noti_list_item_update(Evas_Object *noti_list_item) {
537         retif(noti_list_item == NULL, , "invalid parameter");
538
539         _noti_list_item_ongoing_set_progressbar(noti_list_item);
540         _noti_list_item_ongoing_set_icon(noti_list_item);
541         _noti_list_item_ongoing_set_text(noti_list_item);
542 }
543
544 HAPI void noti_list_item_set_status(Evas_Object *noti_list_item, int status) {
545         retif(noti_list_item == NULL, , "invalid parameter");
546
547         noti_list_item_h *noti_list_item_h = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_ITEM_H);
548
549         if (noti_list_item_h != NULL) {
550                 noti_list_item_h->status = status;
551         }
552 }
553
554 HAPI int noti_list_item_get_status(Evas_Object *noti_list_item) {
555         retif(noti_list_item == NULL, STATE_NORMAL, "invalid parameter");
556
557         noti_list_item_h *noti_list_item_h = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_ITEM_H);
558
559         if (noti_list_item_h != NULL) {
560                 return noti_list_item_h->status;
561         }
562
563         return STATE_DELETING;
564 }
565
566 HAPI void noti_list_item_node_set(Evas_Object *noti_list_item, void *data) {
567         retif(noti_list_item == NULL, , "invalid parameter");
568         retif(data == NULL, , "invalid parameter");
569
570         noti_list_item_h *noti_list_item_data = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_ITEM_H);
571
572         if (noti_list_item_data != NULL) {
573                 noti_list_item_data->data = data;
574
575                 if (data != NULL) {
576                         noti_node_item *item = data;
577                         _noti_list_item_set_layout(noti_list_item, item->noti, noti_list_item_data->layout);
578                 }
579         }
580 }
581
582 HAPI void *noti_list_item_node_get(Evas_Object *noti_list_item) {
583         retif(noti_list_item == NULL, NULL, "invalid parameter");
584
585         noti_list_item_h *noti_list_item_data = evas_object_data_get(noti_list_item, E_DATA_NOTI_LIST_ITEM_H);
586
587         if (noti_list_item_data != NULL) {
588                 return noti_list_item_data->data;
589         }
590
591         return NULL;
592 }
593
594 HAPI void noti_list_item_set_item_selected_cb(Evas_Object *noti_list_item,
595                 void(*selected_cb)(void *data, Evas_Object *obj)) {
596         retif(noti_list_item == NULL, , "invalid parameter");
597         retif(selected_cb == NULL, , "invalid parameter");
598
599         evas_object_data_set(noti_list_item, E_DATA_NOTI_LIST_CB_SELECTED_ITEM, selected_cb);
600 }
601
602 HAPI void noti_list_item_set_item_button_1_cb(Evas_Object *noti_list_item,
603                 void(*button_1_cb)(void *data, Evas_Object *obj)) {
604         retif(noti_list_item == NULL, , "invalid parameter");
605         retif(button_1_cb == NULL, , "invalid parameter");
606
607         evas_object_data_set(noti_list_item, E_DATA_NOTI_LIST_CB_BUTTON_1, button_1_cb);
608 }
609
610 HAPI void noti_list_item_set_item_deleted_cb(Evas_Object *noti_list_item,
611                 void(*deleted_cb)(void *data, Evas_Object *obj)) {
612         retif(noti_list_item == NULL, , "invalid parameter");
613         retif(deleted_cb == NULL, , "invalid parameter");
614
615         evas_object_data_set(noti_list_item, E_DATA_NOTI_LIST_CB_DELETED_ITEM, deleted_cb);
616 }