sync with private git
[apps/core/preloaded/quickpanel.git] / daemon / notifications / noti.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (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 <appsvc.h>
18
19 #include <time.h>
20 #include <vconf.h>
21 #include <appcore-common.h>
22 #include <app_service.h>
23 #include <Ecore_X.h>
24 #include <notification.h>
25
26 #include "quickpanel-ui.h"
27 #include "quickpanel_def.h"
28 #include "common.h"
29 #include "noti_node.h"
30 #include "noti_gridbox.h"
31 #include "noti_box.h"
32 #include "noti_listbox.h"
33 #include "noti_list_item.h"
34 #include "noti_section.h"
35 #include "noti.h"
36 #include "list_util.h"
37
38 #ifndef VCONFKEY_QUICKPANEL_STARTED
39 #define VCONFKEY_QUICKPANEL_STARTED "memory/private/"PACKAGE_NAME"/started"
40 #endif /* VCONFKEY_QUICKPANEL_STARTED */
41
42 #define QP_NOTI_ONGOING_DBUS_PATH       "/dbus/signal"
43 #define QP_NOTI_ONGOING_DBUS_INTERFACE  "notification.ongoing"
44
45 static noti_node *g_noti_node;
46 static Evas_Object *g_noti_section;
47 static Evas_Object *g_noti_listbox;
48 static Evas_Object *g_noti_gridbox;
49 static Eina_List *g_animated_image_list;
50
51 static int quickpanel_noti_init(void *data);
52 static int quickpanel_noti_fini(void *data);
53 static int quickpanel_noti_suspend(void *data);
54 static int quickpanel_noti_resume(void *data);
55 static void quickpanel_noti_lang_changed(void *data);
56 static void quickpanel_noti_refresh(void *data);
57
58 QP_Module noti = {
59         .name = "noti",
60         .init = quickpanel_noti_init,
61         .fini = quickpanel_noti_fini,
62         .suspend = quickpanel_noti_suspend,
63         .resume = quickpanel_noti_resume,
64         .lang_changed = quickpanel_noti_lang_changed,
65         .hib_enter = NULL,
66         .hib_leave = NULL,
67         .refresh = quickpanel_noti_refresh,
68         .get_height = NULL,
69 };
70
71 static notification_h _quickpanel_noti_update_item_progress(const char *pkgname,
72                                                             int priv_id,
73                                                             double progress)
74 {
75         char *noti_pkgname = NULL;
76         int noti_priv_id = 0;
77
78         noti_node_item *node = noti_node_get(g_noti_node, priv_id);
79
80         if (node != NULL && node->noti != NULL) {
81                 notification_get_pkgname(node->noti, &noti_pkgname);
82                 notification_get_id(node->noti, NULL, &noti_priv_id);
83                 if (!strcmp(noti_pkgname, pkgname)
84                     && priv_id == noti_priv_id) {
85
86                         if (notification_set_progress(node->noti, progress) != NOTIFICATION_ERROR_NONE) {
87                                 ERR("fail to set progress");
88                         }
89                         return node->noti;
90                 }
91         }
92
93         return NULL;
94 }
95
96 static notification_h _quickpanel_noti_update_item_size(const char *pkgname,
97                                                         int priv_id,
98                                                         double size)
99 {
100         char *noti_pkgname = NULL;
101         int noti_priv_id = 0;
102
103         noti_node_item *node = noti_node_get(g_noti_node, priv_id);
104
105         if (node != NULL && node->noti != NULL) {
106                 notification_get_pkgname(node->noti, &noti_pkgname);
107                 notification_get_id(node->noti, NULL, &noti_priv_id);
108                 if (!strcmp(noti_pkgname, pkgname)
109                     && priv_id == noti_priv_id) {
110                         notification_set_size(node->noti, size);
111                         return node->noti;
112                 }
113         }
114
115         return NULL;
116 }
117
118 static notification_h _quickpanel_noti_update_item_content(const char *pkgname,
119                                                         int priv_id,
120                                                         char *content)
121 {
122         char *noti_pkgname = NULL;
123         int noti_priv_id = 0;
124
125         noti_node_item *node = noti_node_get(g_noti_node, priv_id);
126
127         if (node != NULL && node->noti != NULL) {
128                 notification_get_pkgname(node->noti, &noti_pkgname);
129                 notification_get_id(node->noti, NULL, &noti_priv_id);
130                 if (!strcmp(noti_pkgname, pkgname)
131                     && priv_id == noti_priv_id) {
132                         notification_set_text(node->noti,
133                                 NOTIFICATION_TEXT_TYPE_CONTENT,
134                                 content, NULL,
135                                 NOTIFICATION_VARIABLE_TYPE_NONE);
136                         return node->noti;
137                 }
138         }
139
140         return NULL;
141 }
142
143 static void _quickpanel_noti_update_progressbar(void *data,
144                                                 notification_h update_noti)
145 {
146         struct appdata *ad = NULL;
147         Elm_Object_Item *found = NULL;
148         noti_node_item *node = NULL;
149
150         retif(!data, , "data is NULL");
151         ad = data;
152
153         retif(!ad->list, , "ad->list is NULL");
154
155         int priv_id = 0;
156
157         if (notification_get_id(update_noti, NULL, &priv_id) == NOTIFICATION_ERROR_NONE) {
158                 node = noti_node_get(g_noti_node, priv_id);
159
160                 if (node != NULL) {
161                         found = node->view;
162                 }
163         }
164
165         retif(node == NULL, , "fail to find node of priv_id:%d", priv_id);
166         retif(node->view == NULL, , "fail to find %p", node->view);
167
168         listbox_update_item(g_noti_listbox, node->view);
169 }
170
171 static void _quickpanel_noti_item_progress_update_cb(void *data,
172                                                 DBusMessage *msg)
173 {
174         DBusError err;
175         char *pkgname = 0;
176         int priv_id = 0;
177         double progress = 0;
178         notification_h noti = NULL;
179
180         retif(data == NULL || msg == NULL, , "Invalid parameter!");
181
182         dbus_error_init(&err);
183         dbus_message_get_args(msg, &err,
184                         DBUS_TYPE_STRING, &pkgname,
185                         DBUS_TYPE_INT32, &priv_id,
186                         DBUS_TYPE_DOUBLE, &progress,
187                         DBUS_TYPE_INVALID);
188
189         if (dbus_error_is_set(&err)) {
190                 ERR("dbus err: %s", err.message);
191                 dbus_error_free(&err);
192                 return;
193         }
194
195         if (pkgname == NULL) {
196                 ERR("pkgname is null");
197                 return;
198         }
199
200         /* check item on the list */
201         noti = _quickpanel_noti_update_item_progress(pkgname,
202                                                 priv_id, progress);
203         retif(noti == NULL, , "Can not found noti data.");
204
205         DBG("pkgname[%s], priv_id[%d], progress[%lf]",
206                                 pkgname, priv_id, progress);
207         if (!quickpanel_is_suspended())
208                 _quickpanel_noti_update_progressbar(data, noti);
209 }
210
211 static void _quickpanel_noti_item_size_update_cb(void *data, DBusMessage * msg)
212 {
213         DBusError err;
214         char *pkgname = 0;
215         int priv_id = 0;
216         double size = 0;
217         notification_h noti = NULL;
218
219         retif(data == NULL || msg == NULL, , "Invalid parameter!");
220
221         dbus_error_init(&err);
222         dbus_message_get_args(msg, &err,
223                         DBUS_TYPE_STRING, &pkgname,
224                         DBUS_TYPE_INT32, &priv_id,
225                         DBUS_TYPE_DOUBLE, &size, DBUS_TYPE_INVALID);
226         if (dbus_error_is_set(&err)) {
227                 ERR("dbus err: %s", err.message);
228                 dbus_error_free(&err);
229                 return;
230         }
231
232         if (pkgname == NULL) {
233                 ERR("pkgname is null");
234                 return;
235         }
236
237         /* check item on the list */
238         noti = _quickpanel_noti_update_item_size(pkgname, priv_id, size);
239         retif(noti == NULL, , "Can not found noti data.");
240
241         DBG("pkgname[%s], priv_id[%d], progress[%lf]",
242                                 pkgname, priv_id, size);
243
244         if (!quickpanel_is_suspended())
245                 _quickpanel_noti_update_progressbar(data, noti);
246 }
247
248 static void _quickpanel_noti_item_content_update_cb(void *data,
249                                                 DBusMessage *msg)
250 {
251         DBusError err;
252         char *pkgname = NULL;
253         int priv_id = 0;
254         char *content = NULL;
255         notification_h noti = NULL;
256
257         retif(data == NULL || msg == NULL, , "Invalid parameter!");
258
259         dbus_error_init(&err);
260         dbus_message_get_args(msg, &err,
261                         DBUS_TYPE_STRING, &pkgname,
262                         DBUS_TYPE_INT32, &priv_id,
263                         DBUS_TYPE_STRING, &content, DBUS_TYPE_INVALID);
264
265         if (pkgname == NULL) {
266                 ERR("pkgname  is null");
267                 return;
268         }
269         if (content == NULL) {
270                 ERR("content is null");
271                 return;
272         }
273
274         if (dbus_error_is_set(&err)) {
275                 ERR("dbus err: %s", err.message);
276                 dbus_error_free(&err);
277                 return;
278         }
279
280         DBG("pkgname[%s], priv_id[%d], content[%s]",
281                                 pkgname, priv_id, content);
282
283         /* check item on the list */
284         noti = _quickpanel_noti_update_item_content(pkgname, priv_id, content);
285         retif(noti == NULL, , "Can not found noti data.");
286
287         if (!quickpanel_is_suspended())
288                 _quickpanel_noti_update_progressbar(data, noti);
289 }
290
291 static void _quickpanel_noti_ani_image_control(Eina_Bool on)
292 {
293         const Eina_List *l = NULL;
294         const Eina_List *ln = NULL;
295         Evas_Object *entry_obj = NULL;
296
297         retif(g_animated_image_list == NULL, ,"");
298
299         EINA_LIST_FOREACH_SAFE(g_animated_image_list, l, ln, entry_obj) {
300                 if (entry_obj == NULL) continue;
301
302                 if (on == EINA_TRUE) {
303                         if (elm_image_animated_play_get(entry_obj) == EINA_FALSE) {
304                                 elm_image_animated_play_set(entry_obj, EINA_TRUE);
305                         }
306                 } else {
307                         if (elm_image_animated_play_get(entry_obj) == EINA_TRUE) {
308                                 elm_image_animated_play_set(entry_obj, EINA_FALSE);
309                         }
310                 }
311         }
312 }
313
314 static void _quickpanel_noti_ani_image_deleted_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
315 {
316         retif(obj == NULL, , "obj is NULL");
317         retif(g_animated_image_list == NULL, , "list is empty");
318
319         g_animated_image_list = eina_list_remove(g_animated_image_list, obj);
320 }
321
322 static void _quickpanel_do_noti_delete(notification_h noti) {
323         char *pkgname = NULL;
324         char *caller_pkgname = NULL;
325         int flags = 0, priv_id = 0, flag_delete = 0;
326         notification_type_e type = NOTIFICATION_TYPE_NONE;
327
328         quickpanel_play_feedback();
329
330         retif(noti == NULL, , "Invalid parameter!");
331
332         notification_get_pkgname(noti, &caller_pkgname);
333         notification_get_application(noti, &pkgname);
334         if (pkgname == NULL)
335                 pkgname = caller_pkgname;
336
337         notification_get_id(noti, NULL, &priv_id);
338         notification_get_property(noti, &flags);
339         notification_get_type(noti, &type);
340
341         if (flags & NOTIFICATION_PROP_PERMANENT_DISPLAY)
342                 flag_delete = 0;
343         else
344                 flag_delete = 1;
345
346         if (flag_delete == 1 && type == NOTIFICATION_TYPE_NOTI) {
347                 notification_delete_by_priv_id(caller_pkgname, NOTIFICATION_TYPE_NOTI,
348                                 priv_id);
349         }
350 }
351
352 static void _quickpanel_do_noti_press(notification_h noti, int pressed_area) {
353         int ret = -1;
354         char *pkgname = NULL;
355         char *caller_pkgname = NULL;
356         bundle *args = NULL;
357         bundle *group_args = NULL;
358         bundle *responding_service_handle = NULL;
359         bundle *single_service_handle = NULL;
360         bundle *multi_service_handle = NULL;
361         int flags = 0, group_id = 0, priv_id = 0, count = 0, flag_launch = 0,
362                         flag_delete = 0;
363         notification_type_e type = NOTIFICATION_TYPE_NONE;
364
365         quickpanel_play_feedback();
366
367         retif(noti == NULL, , "Invalid parameter!");
368
369         notification_get_pkgname(noti, &caller_pkgname);
370         notification_get_application(noti, &pkgname);
371         if (pkgname == NULL)
372                 pkgname = caller_pkgname;
373
374         notification_get_id(noti, &group_id, &priv_id);
375         notification_get_property(noti, &flags);
376         notification_get_type(noti, &type);
377
378         if (flags & NOTIFICATION_PROP_DISABLE_APP_LAUNCH)
379                 flag_launch = 0;
380         else
381                 flag_launch = 1;
382
383         if (flags & NOTIFICATION_PROP_DISABLE_AUTO_DELETE)
384                 flag_delete = 0;
385         else
386                 flag_delete = 1;
387
388         notification_get_execute_option(noti,
389                         NOTIFICATION_EXECUTE_TYPE_RESPONDING,
390                                 NULL, &responding_service_handle);
391         notification_get_execute_option(noti,
392                                 NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH,
393                                 NULL, &single_service_handle);
394         notification_get_execute_option(noti,
395                                 NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH,
396                                 NULL, &multi_service_handle);
397
398         if (pressed_area == NOTI_PRESS_BUTTON_1 && responding_service_handle != NULL) {
399                 DBG("");
400                 quickpanel_close_quickpanel(true);
401                 ret = quickpanel_launch_app(NULL, responding_service_handle);
402                 quickpanel_launch_app_inform_result(pkgname, ret);
403         } else if (flag_launch == 1) {
404                 /* Hide quickpanel */
405                 quickpanel_close_quickpanel(true);
406
407                 char *text_count = NULL;
408                 notification_get_text(noti, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, &text_count);
409
410                 if (text_count != NULL) {
411                         count = atoi(text_count);
412                 } else {
413                         count = 1;
414                 }
415
416                 if (single_service_handle != NULL && multi_service_handle == NULL) {
417                         DBG("");
418                         ret = quickpanel_launch_app(NULL, single_service_handle);
419                         quickpanel_launch_app_inform_result(pkgname, ret);
420                 }
421                 if (single_service_handle == NULL && multi_service_handle != NULL) {
422                         DBG("");
423                         ret = quickpanel_launch_app(NULL, multi_service_handle);
424                         quickpanel_launch_app_inform_result(pkgname, ret);
425                 }
426                 if (single_service_handle != NULL && multi_service_handle != NULL) {
427                         DBG("");
428                         if (count <= 1) {
429                                 ret = quickpanel_launch_app(NULL, single_service_handle);
430                                 quickpanel_launch_app_inform_result(pkgname, ret);
431                         } else {
432                                 ret = quickpanel_launch_app(NULL, multi_service_handle);
433                                 quickpanel_launch_app_inform_result(pkgname, ret);
434                         }
435                 }
436                 if (single_service_handle == NULL && multi_service_handle == NULL) {
437                         DBG("");
438                         notification_get_args(noti, &args, &group_args);
439
440                         if (count > 1 && group_args != NULL) {
441                                 ret = quickpanel_launch_app(pkgname, group_args);
442                                 quickpanel_launch_app_inform_result(pkgname, ret);
443                         } else {
444                                 ret = quickpanel_launch_app(pkgname, args);
445                                 quickpanel_launch_app_inform_result(pkgname, ret);
446                         }
447                 }
448         }
449
450         if (flag_delete == 1 && type == NOTIFICATION_TYPE_NOTI) {
451                 notification_delete_by_priv_id(caller_pkgname,
452                                 NOTIFICATION_TYPE_NOTI,
453                                 priv_id);
454         }
455 }
456
457 static void quickpanel_notibox_delete_cb(void *data, Evas_Object * obj) {
458         DBG("");
459         noti_node_item *item = data;
460         retif(item == NULL, , "Invalid parameter!");
461
462         notification_h noti = item->noti;
463         retif(noti == NULL, , "Invalid parameter!");
464
465         _quickpanel_do_noti_delete(noti);
466
467 }
468
469 static void quickpanel_notibox_button_1_cb(void *data, Evas_Object * obj) {
470         DBG("");
471         noti_node_item *item = data;
472         retif(item == NULL, , "Invalid parameter!");
473
474         notification_h noti = item->noti;
475         retif(noti == NULL, , "Invalid parameter!");
476
477         _quickpanel_do_noti_press(noti, NOTI_PRESS_BUTTON_1);
478 }
479
480 static void quickpanel_notibox_select_cb(void *data, Evas_Object * obj) {
481         DBG("");
482         noti_node_item *item = data;
483         retif(item == NULL, , "Invalid parameter!");
484
485         notification_h noti = item->noti;
486         retif(noti == NULL, , "Invalid parameter!");
487
488         _quickpanel_do_noti_press(noti, NOTI_PRESS_BG);
489 }
490
491 static void quickpanel_noti_listitem_select_cb(void *data, Evas_Object * obj) {
492         DBG("");
493         noti_node_item *item = data;
494         retif(item == NULL, , "Invalid parameter!");
495
496         notification_h noti = item->noti;
497         retif(noti == NULL, , "Invalid parameter!");
498
499         _quickpanel_do_noti_press(noti, NOTI_PRESS_BG);
500 }
501
502 static inline void __ongoing_comp_n_copy(notification_h old, notification_h new)
503 {
504         int priv_id = 0;
505         int new_priv_id = 0;
506         char *pkgname = NULL;
507         char *new_pkgname = NULL;
508
509         if (!old)
510                 return;
511
512         if (!new)
513                 return;
514
515         notification_get_id(old, NULL, &priv_id);
516         notification_get_id(new, NULL, &new_priv_id);
517
518         notification_get_pkgname(old, &pkgname);
519         notification_get_pkgname(new, &new_pkgname);
520
521         if (!pkgname || !new_pkgname)
522                 return;
523
524         if (!strcmp(pkgname, new_pkgname) && priv_id == new_priv_id) {
525                 double percentage = 0.0;
526                 double size = 0.0;
527                 time_t insert_time = 0;
528                 time_t new_insert_time = 0;
529
530                 notification_get_progress(old, &percentage);
531                 notification_get_size(old, &size);
532                 if (notification_set_progress(new, percentage) != NOTIFICATION_ERROR_NONE) {
533                         ERR("fail to set progress");
534                 }
535                 if (notification_set_size(new, size) != NOTIFICATION_ERROR_NONE) {
536                         ERR("fail to set size");
537                 }
538                 notification_get_insert_time(old, &insert_time);
539                 notification_get_insert_time(new, &new_insert_time);
540
541                 if (insert_time == new_insert_time) {
542                         char *content = NULL;
543                         notification_get_text(old,
544                                 NOTIFICATION_TEXT_TYPE_CONTENT, &content);
545                         notification_set_text(new,
546                                 NOTIFICATION_TEXT_TYPE_CONTENT, content,
547                                 NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
548                 }
549         }
550 }
551
552 static void _quickpanel_noti_clear_ongoinglist()
553 {
554         if (g_noti_listbox != NULL) {
555                 listbox_remove_all_item(g_noti_listbox, EINA_FALSE);
556         }
557 }
558
559 static void _quickpanel_noti_clear_notilist(void)
560 {
561         if (g_noti_gridbox != NULL) {
562                 gridbox_remove_all_item(g_noti_gridbox, EINA_FALSE);
563         }
564 }
565
566 static void _quickpanel_noti_clear_list_all(void)
567 {
568         _quickpanel_noti_clear_ongoinglist();
569         _quickpanel_noti_clear_notilist();
570 }
571
572 static void _quickpanel_noti_section_add(void)
573 {
574         struct appdata *ad = quickpanel_get_app_data();
575         retif(ad == NULL, , "Invalid parameter!");
576         retif(ad->list == NULL, , "Invalid parameter!");
577
578         if (g_noti_section == NULL) {
579                 g_noti_section = noti_section_create(ad->list);
580                 if (g_noti_section != NULL) {
581                         quickpanel_list_util_sort_insert(ad->list, g_noti_section);
582                         DBG("noti section[%p]", g_noti_section);
583                 }
584         }
585 }
586
587 static void _quickpanel_noti_section_remove(void)
588 {
589         struct appdata *ad = quickpanel_get_app_data();
590         retif(ad == NULL, , "Invalid parameter!");
591         retif(ad->list == NULL, , "Invalid parameter!");
592
593         if (g_noti_section != NULL) {
594                 quickpanel_list_util_item_unpack_by_type(ad->list, QP_ITEM_TYPE_NOTI_GROUP);
595                 noti_section_remove(g_noti_section);
596                 g_noti_section = NULL;
597         }
598 }
599
600 static void _quickpanel_noti_box_deleted_cb(void *data, Evas_Object *obj) {
601         int priv_id = -1;
602
603         retif(data == NULL, , "Invalid parameter!");
604         DBG("deleting:%p", data);
605
606         noti_node_item *item = data;
607         notification_h noti = item->noti;
608
609         if (noti != NULL) {
610                 notification_get_id(noti, NULL, &priv_id);
611                 noti_node_remove(g_noti_node, priv_id);
612         }
613 }
614
615 static void _quickpanel_list_box_deleted_cb(void *data, Evas_Object *obj) {
616         int priv_id = -1;
617
618         retif(data == NULL, , "Invalid parameter!");
619         DBG("deleting:%p", data);
620
621         noti_node_item *item = data;
622         notification_h noti = item->noti;
623
624         if (noti != NULL) {
625                 notification_get_id(noti, NULL, &priv_id);
626                 noti_node_remove(g_noti_node, priv_id);
627         }
628 }
629
630 static void _quickpanel_noti_ongoing_add(Evas_Object *list, void *data, int is_prepend)
631 {
632         Evas_Object *noti_list_item = NULL;
633         notification_ly_type_e layout = NOTIFICATION_LY_ONGOING_EVENT;
634
635         retif(list == NULL, , "Invalid parameter!");
636         notification_h noti = data;
637
638         if (noti != NULL) {
639                 notification_get_layout(noti, &layout);
640                 noti_list_item = noti_list_item_create(g_noti_listbox, layout);
641
642                 if (noti_list_item != NULL) {
643                         noti_node_item *item = noti_node_add(g_noti_node, (void*)data, (void*)noti_list_item);
644                         if (item != NULL) {
645                                 noti_list_item_node_set(noti_list_item, item);
646                                 noti_list_item_set_item_selected_cb(noti_list_item, quickpanel_noti_listitem_select_cb);
647                                 listbox_add_item(g_noti_listbox, noti_list_item, is_prepend);
648                         }
649                 } else
650                         ERR("fail to insert item to list : %p", data);
651         }
652
653         DBG("noti[%p] data[%p] added listbox[%p]",
654                         data, noti_list_item, g_noti_listbox);
655 }
656
657 static void _quickpanel_noti_noti_add(Evas_Object *list, void *data, int is_prepend)
658 {
659         notification_h noti = data;
660         notification_ly_type_e layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
661         Evas_Object *noti_box = NULL;
662
663         retif(list == NULL, , "Invalid parameter!");
664
665         if (g_noti_section == NULL) {
666                 _quickpanel_noti_section_add();
667         }
668
669         if (noti != NULL) {
670                 notification_get_layout(noti, &layout);
671                 Evas_Object *noti_box = noti_box_create(g_noti_gridbox, layout);
672
673                 if (noti_box != NULL) {
674                         noti_node_item *item = noti_node_add(g_noti_node, (void*)data, (void*)noti_box);
675                         if (item != NULL) {
676                                 noti_box_node_set(noti_box, item);
677                                 noti_box_set_item_selected_cb(noti_box, quickpanel_notibox_select_cb);
678                                 noti_box_set_item_button_1_cb(noti_box, quickpanel_notibox_button_1_cb);
679                                 noti_box_set_item_deleted_cb(noti_box, quickpanel_notibox_delete_cb);
680                                 gridbox_add_item(g_noti_gridbox, noti_box, is_prepend);
681                         }
682                 } else
683                         ERR("fail to insert item to list : %p", data);
684         }
685
686         int noti_count =
687                         noti_node_get_item_count(g_noti_node, NOTIFICATION_TYPE_NOTI);
688
689         if (g_noti_section != NULL) {
690                 noti_section_update(g_noti_section, noti_count);
691         }
692
693         DBG("noti[%p] view[%p] added gridbox[%p]",
694                         data, noti_box, g_noti_gridbox);
695 }
696
697 static void _quickpanel_noti_update_notilist(struct appdata *ad)
698 {
699         Evas_Object *list = NULL;
700         notification_h noti = NULL;
701         notification_h noti_save = NULL;
702         notification_list_h get_list = NULL;
703         int applist = NOTIFICATION_DISPLAY_APP_ALL;
704
705         DBG("");
706
707         retif(ad == NULL, , "Invalid parameter!");
708
709         list = ad->list;
710         retif(list == NULL, , "Failed to get noti genlist.");
711
712         _quickpanel_noti_clear_list_all();
713
714         notification_get_list(NOTIFICATION_TYPE_ONGOING, -1, &get_list);
715         while (get_list != NULL) {
716                 noti = notification_list_get_data(get_list);
717                 notification_get_display_applist(noti, &applist);
718
719                 if (applist &
720                     NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY) {
721                         notification_clone(noti, &noti_save);
722                         _quickpanel_noti_ongoing_add(list, noti_save, LISTBOX_APPEND);
723                 }
724                 get_list = notification_list_get_next(get_list);
725         }
726         notification_free_list(get_list);
727
728         notification_get_list(NOTIFICATION_TYPE_NOTI , -1, &get_list);
729         while (get_list != NULL) {
730                 noti = notification_list_get_data(get_list);
731                 notification_get_display_applist(noti, &applist);
732
733                 if (applist &
734                     NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY) {
735                         notification_clone(noti, &noti_save);
736                         _quickpanel_noti_noti_add(list, noti_save, GRIDBOX_APPEND);
737                 }
738                 get_list = notification_list_get_next(get_list);
739         }
740         notification_free_list(get_list);
741
742         if (g_noti_gridbox != NULL) {
743                 elm_box_recalculate(g_noti_gridbox);
744         }
745 }
746
747 static void _quickpanel_noti_delete_volatil_data(void)
748 {
749         notification_list_h noti_list = NULL;
750         notification_list_h noti_list_head = NULL;
751         notification_h noti = NULL;
752         int property = 0;
753
754         notification_get_grouping_list(NOTIFICATION_TYPE_NONE, -1, &noti_list);
755
756         noti_list_head = noti_list;
757
758         while (noti_list != NULL) {
759                 noti = notification_list_get_data(noti_list);
760                 notification_get_property(noti, &property);
761
762                 if (property & NOTIFICATION_PROP_VOLATILE_DISPLAY) {
763                         notification_set_property(noti,
764                                 property |
765                                 NOTIFICATION_PROP_DISABLE_UPDATE_ON_DELETE);
766                         notification_delete(noti);
767                 }
768
769                 noti_list = notification_list_get_next(noti_list);
770         }
771
772         notification_free_list(noti_list_head);
773
774         notification_update(NULL);
775 }
776
777 static void _quickpanel_noti_detailed_changed_cb(void *data, notification_type_e type, notification_op *op_list, int num_op)
778 {
779         int i = 0;
780         int op_type = 0;
781         int priv_id = 0;
782         struct appdata *ad = NULL;
783         notification_h new_noti = NULL;
784         notification_type_e noti_type = NOTIFICATION_TYPE_NONE;
785         int noti_applist = NOTIFICATION_DISPLAY_APP_ALL;
786         notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
787
788         retif(data == NULL, , "Invalid parameter!");
789         ad = data;
790
791         DBG("test detailed quickpanel:%d", num_op);
792
793         for (i = 0; i < num_op; i++) {
794                 notification_op_get_data(op_list + i, NOTIFICATION_OP_DATA_TYPE, &op_type);
795                 DBG("op_type:%d", op_type);
796                 notification_op_get_data(op_list + i, NOTIFICATION_OP_DATA_PRIV_ID, &priv_id);
797                 DBG("op_priv_id:%d", priv_id);
798
799                 if (op_type == NOTIFICATION_OP_INSERT) {
800                         new_noti = notification_load(NULL, priv_id);
801                         if (new_noti == NULL) continue;
802
803                         notification_get_type(new_noti, &noti_type);
804                         notification_get_display_applist(new_noti, &noti_applist);
805                         notification_get_layout(new_noti, &noti_layout);
806
807                         DBG("layout:%d", noti_layout);
808
809                         if (noti_applist & NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY) {
810                                 noti_node_item *node = noti_node_get(g_noti_node, priv_id);
811                                 if (node != NULL) {
812                                         if (noti_type == NOTIFICATION_TYPE_NOTI) {
813                                                 DBG("cb after inserted:%d", priv_id);
814                                         }
815                                 } else {
816                                         if (noti_type == NOTIFICATION_TYPE_NOTI) {
817                                                 _quickpanel_noti_noti_add(ad->list, new_noti, GRIDBOX_PREPEND);
818                                         } else if (noti_type == NOTIFICATION_TYPE_ONGOING) {
819                                                 _quickpanel_noti_ongoing_add(ad->list, new_noti, LISTBOX_PREPEND);
820                                         }
821                                 }
822                                 DBG("%d noti added", priv_id);
823                         } else {
824                                 notification_free(new_noti);
825                         }
826                 }
827                 if (op_type == NOTIFICATION_OP_DELETE) {
828                         noti_node_item *node = noti_node_get(g_noti_node, priv_id);
829
830                         if (node != NULL && node->noti != NULL) {
831                                 notification_h noti = node->noti;
832                                 notification_get_type(noti, &noti_type);
833
834                                 if (noti_type == NOTIFICATION_TYPE_NOTI) {
835                                         gridbox_remove_item(g_noti_gridbox, node->view, 0);
836                                 } else if (noti_type == NOTIFICATION_TYPE_ONGOING) {
837                                         listbox_remove_item(g_noti_listbox, node->view, 0);
838                                 }
839                                 noti_node_remove(g_noti_node, priv_id);
840                         }
841                         DBG("%d noti deleted", priv_id);
842                 }
843                 if (op_type == NOTIFICATION_OP_UPDATE) {
844                         noti_node_item *node = noti_node_get(g_noti_node, priv_id);
845                         notification_h old_noti = NULL;
846
847                         new_noti = notification_load(NULL, priv_id);
848                         retif(new_noti == NULL, , "fail to load updated noti");
849
850                         if (node != NULL && node->view != NULL && node->noti != NULL) {
851                                 notification_get_type(new_noti, &noti_type);
852
853                                 if (noti_type == NOTIFICATION_TYPE_NOTI) {
854                                         gridbox_remove_item(g_noti_gridbox, node->view, 0);
855                                         _quickpanel_noti_noti_add(ad->list, new_noti, GRIDBOX_PREPEND);
856 /*
857                                         gridbox_remove_and_add_item(g_noti_gridbox, node->view,
858                                                         _quickpanel_noti_noti_add
859                                                         ,ad->list, new_noti, GRIDBOX_PREPEND);
860 */
861                                 } else if (noti_type == NOTIFICATION_TYPE_ONGOING) {
862                                         old_noti = node->noti;
863                                         node->noti = new_noti;
864
865                                         listbox_update_item(g_noti_listbox, node->view);
866                                 }
867
868                                 if (old_noti != NULL) {
869                                         notification_free(old_noti);
870                                 }
871                         } else {
872                                 notification_get_display_applist(new_noti, &noti_applist);
873
874                                 if (noti_applist & NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY) {
875
876                                         if (noti_type == NOTIFICATION_TYPE_NOTI) {
877                                                 _quickpanel_noti_noti_add(ad->list, new_noti, GRIDBOX_PREPEND);
878                                         } else if (noti_type == NOTIFICATION_TYPE_ONGOING) {
879                                                 _quickpanel_noti_ongoing_add(ad->list, new_noti, GRIDBOX_PREPEND);
880                                         }
881                                 }
882                         }
883
884                         DBG("%d noti updated", priv_id);
885                 }
886         }
887
888         int noti_count = 0;
889
890         if ((noti_count = noti_node_get_item_count(g_noti_node, NOTIFICATION_TYPE_NOTI))
891                         <= 0) {
892                 DBG("");
893                 _quickpanel_noti_clear_notilist();
894                 _quickpanel_noti_section_remove();
895         } else {
896                 if (g_noti_section != NULL) {
897                         DBG("");
898                         noti_section_update(g_noti_section, noti_count);
899                 }
900         }
901 }
902
903 static void _quickpanel_noti_update_desktop_cb(keynode_t *node, void *data)
904 {
905         char *event = NULL;
906         char type[10] = {0,};
907         char package[1024] = {0,};
908
909         event = vconf_get_str(vconf_keynode_get_name(node));
910         retif(NULL == event, , "invalid event");
911
912         DBG("%s", event);
913
914         if (sscanf(event, "%10[^:]:%1023s", type, package) != 2) {
915                 DBG("Failed to parse the event format : [%s], [%s]", type, package);
916         }
917
918         if (strncasecmp(type, "delete", strlen(type)) == 0) {
919                 notification_delete_all_by_type(package, NOTIFICATION_TYPE_NONE);
920         }
921
922         if (event != NULL)
923                 free(event);
924 }
925
926 static void _quickpanel_noti_update_sim_status_cb(keynode_t *node, void *data)
927 {
928         struct appdata *ad = data;
929
930         if (ad != NULL && ad->list != NULL) {
931                 _quickpanel_noti_update_notilist(ad);
932         }
933 }
934
935 static int _quickpanel_noti_register_event_handler(struct appdata *ad)
936 {
937         int ret = 0;
938         retif(ad == NULL, QP_FAIL, "Invalid parameter!");
939
940         /* Add dbus signal */
941         e_dbus_init();
942         ad->dbus_connection = e_dbus_bus_get(DBUS_BUS_SYSTEM);
943         if (ad->dbus_connection == NULL) {
944                 ERR("noti register : failed to get dbus bus");
945                 return -1;
946         }
947
948         ad->dbus_handler_size =
949                 e_dbus_signal_handler_add(ad->dbus_connection, NULL,
950                         QP_NOTI_ONGOING_DBUS_PATH,
951                         QP_NOTI_ONGOING_DBUS_INTERFACE, "update_progress",
952                         _quickpanel_noti_item_progress_update_cb,
953                         ad);
954         if (ad->dbus_handler_size == NULL)
955                 ERR("fail to add size signal");
956
957         ad->dbus_handler_progress =
958                 e_dbus_signal_handler_add(ad->dbus_connection, NULL,
959                         QP_NOTI_ONGOING_DBUS_PATH,
960                         QP_NOTI_ONGOING_DBUS_INTERFACE, "update_size",
961                         _quickpanel_noti_item_size_update_cb,
962                         ad);
963         if (ad->dbus_handler_progress == NULL)
964                 ERR("fail to add progress signal");
965
966         ad->dbus_handler_content =
967                 e_dbus_signal_handler_add(ad->dbus_connection, NULL,
968                         QP_NOTI_ONGOING_DBUS_PATH,
969                         QP_NOTI_ONGOING_DBUS_INTERFACE, "update_content",
970                         _quickpanel_noti_item_content_update_cb,
971                         ad);
972         if (ad->dbus_handler_content == NULL)
973                 ERR("fail to add content signal");
974
975         /* Notify vconf key */
976         ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT,
977                                        _quickpanel_noti_update_sim_status_cb,
978                                        (void *)ad);
979         if (ret != 0)
980                 ERR("Failed to register SIM_SLOT change callback!");
981
982         /* Notify vconf key */
983         ret = vconf_notify_key_changed(VCONFKEY_MENUSCREEN_DESKTOP,
984                                        _quickpanel_noti_update_desktop_cb,
985                                        (void *)ad);
986         if (ret != 0)
987                 ERR("Failed to register DESKTOP change callback!");
988
989         /* Register notification changed cb */
990         notification_register_detailed_changed_cb(_quickpanel_noti_detailed_changed_cb, ad);
991
992         return ret;
993 }
994
995 static int _quickpanel_noti_unregister_event_handler(struct appdata *ad)
996 {
997         int ret = 0;
998
999         /* Unregister notification changed cb */
1000         notification_unregister_detailed_changed_cb(_quickpanel_noti_detailed_changed_cb, (void *)ad);
1001
1002         /* Ignore vconf key */
1003         ret = vconf_ignore_key_changed(VCONFKEY_MENUSCREEN_DESKTOP,
1004                         _quickpanel_noti_update_desktop_cb);
1005         if (ret != 0)
1006                 ERR("Failed to ignore DESKTOP change callback!");
1007
1008         ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT,
1009                                 _quickpanel_noti_update_sim_status_cb);
1010         if (ret != 0)
1011                 ERR("Failed to ignore SIM_SLOT change callback!");
1012
1013         /* Delete dbus signal */
1014         if (ad->dbus_handler_size != NULL) {
1015                 e_dbus_signal_handler_del(ad->dbus_connection,
1016                                 ad->dbus_handler_size);
1017                 ad->dbus_handler_size = NULL;
1018         }
1019         if (ad->dbus_handler_progress != NULL) {
1020                 e_dbus_signal_handler_del(ad->dbus_connection,
1021                                 ad->dbus_handler_progress);
1022                 ad->dbus_handler_progress = NULL;
1023         }
1024         if (ad->dbus_handler_content != NULL) {
1025                 e_dbus_signal_handler_del(ad->dbus_connection,
1026                                 ad->dbus_handler_content);
1027                 ad->dbus_handler_content = NULL;
1028         }
1029
1030         if (ad->dbus_connection != NULL) {
1031                 e_dbus_connection_close(ad->dbus_connection);
1032                 ad->dbus_connection = NULL;
1033         }
1034
1035         return QP_OK;
1036 }
1037
1038 static int _quickpanel_noti_check_first_start(void)
1039 {
1040         int status = 0;
1041         int ret = 0;
1042
1043         ret = vconf_get_bool(VCONFKEY_QUICKPANEL_STARTED, &status);
1044         if (ret) {
1045                 INFO("fail to get %s", VCONFKEY_QUICKPANEL_STARTED);
1046                 /* reboot */
1047                 ret = vconf_set_bool(VCONFKEY_QUICKPANEL_STARTED, 1);
1048                 INFO("set : %s, result : %d", VCONFKEY_QUICKPANEL_STARTED, ret);
1049         }
1050
1051         if (status)
1052                 return 0;
1053
1054         return 1;
1055 }
1056
1057 static void _quickpanel_noti_init(void *data)
1058 {
1059         struct appdata *ad = NULL;
1060
1061         retif(data == NULL, , "Invalid parameter!");
1062         ad = data;
1063
1064         retif(ad->list == NULL, , "Invalid parameter!");
1065
1066         DBG("wr");
1067
1068         if (g_noti_listbox == NULL) {
1069                 g_noti_listbox = listbox_create(ad->list, quickpanel_get_app_data());
1070                 listbox_set_item_deleted_cb(g_noti_listbox, _quickpanel_list_box_deleted_cb);
1071                 quickpanel_list_util_sort_insert(ad->list, g_noti_listbox);
1072         }
1073
1074         if (g_noti_gridbox == NULL) {
1075                 g_noti_gridbox = gridbox_create(ad->list, quickpanel_get_app_data());
1076                 gridbox_set_item_deleted_cb(g_noti_gridbox, _quickpanel_noti_box_deleted_cb);
1077                 quickpanel_list_util_sort_insert(ad->list, g_noti_gridbox);
1078         }
1079
1080         /* Update notification list */
1081         _quickpanel_noti_update_notilist(ad);
1082 }
1083
1084 static void _quickpanel_noti_fini(void *data)
1085 {
1086         struct appdata *ad = NULL;
1087
1088         retif(data == NULL, , "Invalid parameter!");
1089         ad = data;
1090
1091         retif(ad->list == NULL, , "Invalid parameter!");
1092
1093         DBG("dr");
1094
1095         if (g_noti_listbox != NULL) {
1096                 quickpanel_list_util_item_unpack_by_object(ad->list
1097                                 , g_noti_listbox);
1098                 listbox_remove(g_noti_listbox);
1099                 g_noti_listbox = NULL;
1100         }
1101
1102         if (g_noti_gridbox != NULL) {
1103                 quickpanel_list_util_item_unpack_by_object(ad->list
1104                                 , g_noti_gridbox);
1105                 gridbox_remove(g_noti_gridbox);
1106                 g_noti_gridbox = NULL;
1107         }
1108 }
1109
1110 static int quickpanel_noti_init(void *data)
1111 {
1112         struct appdata *ad = data;
1113         int is_first = 0;
1114
1115         retif(ad == NULL, QP_FAIL, "Invalid parameter!");
1116
1117         noti_node_create(&g_noti_node);
1118
1119         is_first = _quickpanel_noti_check_first_start();
1120         if (is_first) {
1121                 /* Remove ongoing and volatile noti data */
1122                 notifiation_clear(NOTIFICATION_TYPE_ONGOING);
1123                 _quickpanel_noti_delete_volatil_data();
1124         }
1125
1126         _quickpanel_noti_init(ad);
1127
1128         _quickpanel_noti_register_event_handler(ad);
1129
1130         return QP_OK;
1131 }
1132
1133 static int quickpanel_noti_fini(void *data)
1134 {
1135         struct appdata *ad = data;
1136         retif(ad == NULL, QP_FAIL, "Invalid parameter!");
1137
1138         /* Unregister event handler */
1139         _quickpanel_noti_unregister_event_handler(data);
1140
1141         _quickpanel_noti_clear_list_all();
1142
1143         _quickpanel_noti_fini(ad);
1144
1145         if (g_noti_node != NULL) {
1146                 noti_node_destroy(&g_noti_node);
1147         }
1148
1149         return QP_OK;
1150 }
1151
1152 static int quickpanel_noti_suspend(void *data)
1153 {
1154         struct appdata *ad = data;
1155         retif(ad == NULL, QP_FAIL, "Invalid parameter!");
1156
1157         if (ad->list) {
1158                 _quickpanel_noti_ani_image_control(EINA_FALSE);
1159         }
1160
1161         return QP_OK;
1162 }
1163
1164 static int quickpanel_noti_resume(void *data)
1165 {
1166         struct appdata *ad = data;
1167         retif(ad == NULL, QP_FAIL, "Invalid parameter!");
1168
1169         if (ad->list) {
1170                 listbox_update(g_noti_listbox);
1171
1172                 _quickpanel_noti_ani_image_control(EINA_TRUE);
1173         }
1174
1175         return QP_OK;
1176 }
1177
1178 static void quickpanel_noti_refresh(void *data) {
1179         struct appdata *ad = NULL;
1180
1181         retif(data == NULL, , "Invalid parameter!");
1182         ad = data;
1183
1184         if (g_noti_gridbox != NULL) {
1185                 gridbox_rotation(g_noti_gridbox, ad->angle);
1186         }
1187 }
1188
1189 static void quickpanel_noti_lang_changed(void *data)
1190 {
1191         struct appdata *ad = data;
1192
1193         retif(ad == NULL, , "Invalid parameter!");
1194
1195         _quickpanel_noti_update_notilist(ad);
1196 }