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