2 * Copyright (c) 2009-2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <Elementary.h>
25 #include <notification.h>
26 #include <notification_internal.h>
27 #include <notification_text_domain.h>
28 #include <system_settings.h>
30 #include <tzsh_quickpanel_service.h>
32 #include "quickpanel-ui.h"
33 #include "common_uic.h"
35 #include "list_util.h"
36 #include "quickpanel_def.h"
37 #include <vi_manager.h>
38 #include "noti_node.h"
39 #include "noti_list_item.h"
41 #include "noti_util.h"
42 #include "animated_icon.h"
44 #ifdef QP_SCREENREADER_ENABLE
45 #include "accessibility.h"
48 #ifdef QP_ANIMATED_IMAGE_ENABLE
49 #include "animated_image.h"
52 #define LEN_UNIT_TEXTBLOCK 555
53 #define QP_DEFAULT_ICON RESDIR"/quickpanel_icon_default.png"
55 #ifdef QP_SCREENREADER_ENABLE
56 static inline void _check_and_add_to_buffer(Eina_Strbuf *str_buf, const char *text)
58 char buf_number[QP_UTIL_PHONE_NUMBER_MAX_LEN * 2] = { 0, };
60 retif(str_buf == NULL, , "Invalid parameter!");
63 if (strlen(text) > 0) {
64 if (quickpanel_common_util_is_phone_number(text)) {
65 quickpanel_common_util_phone_number_tts_make(buf_number, text,
66 (QP_UTIL_PHONE_NUMBER_MAX_LEN * 2) - 1);
67 eina_strbuf_append(str_buf, buf_number);
69 eina_strbuf_append(str_buf, text);
71 eina_strbuf_append_char(str_buf, '\n');
77 static Evas_Object *_check_duplicated_progress_loading(Evas_Object *obj, const char *part, const char *style_name)
79 Evas_Object *old_content = NULL;
80 const char *old_style_name = NULL;
82 retif(obj == NULL, NULL, "Invalid parameter!");
83 retif(part == NULL, NULL, "Invalid parameter!");
84 retif(style_name == NULL, NULL, "Invalid parameter!");
86 old_content = elm_object_part_content_get(obj, part);
87 if (old_content != NULL) {
88 old_style_name = elm_object_style_get(old_content);
89 if (old_style_name != NULL) {
90 if (strcmp(old_style_name, style_name) == 0) {
94 elm_object_part_content_unset(obj, part);
95 evas_object_del(old_content);
103 static Evas_Object *_check_duplicated_image_loading(Evas_Object *obj, const char *part, const char *file_path)
105 Evas_Object *old_ic = NULL;
106 const char *old_ic_path = NULL;
108 retif(obj == NULL, NULL, "Invalid parameter!");
109 retif(part == NULL, NULL, "Invalid parameter!");
110 retif(file_path == NULL, NULL, "Invalid parameter!");
112 old_ic = elm_object_part_content_get(obj, part);
114 if (quickpanel_animated_icon_is_same_icon(old_ic, file_path) == 1) {
118 if (old_ic != NULL) {
119 elm_image_file_get(old_ic, &old_ic_path, NULL);
120 if (old_ic_path != NULL) {
121 if (strcmp(old_ic_path, file_path) == 0)
125 elm_object_part_content_unset(obj, part);
126 evas_object_del(old_ic);
133 static void _set_text_to_part(Evas_Object *obj, const char *part, const char *text)
135 const char *old_text;
137 if (!obj || !part || !text) {
138 ERR("Invalid parameters");
142 old_text = elm_object_part_text_get(obj, part);
143 if (old_text != NULL) {
144 if (strcmp(old_text, text) == 0) {
149 elm_object_part_text_set(obj, part, text);
152 static char *_noti_get_progress(notification_h noti, char *buf, int buf_len)
155 double percentage = 0.0;
157 retif(noti == NULL, NULL, "Invalid parameter!");
158 retif(buf == NULL, NULL, "Invalid parameter!");
160 notification_get_size(noti, &size);
161 notification_get_progress(noti, &percentage);
163 if (percentage > 0) {
164 if (percentage < 1.0 ) {
165 if (snprintf(buf, buf_len, "%d%%", (int)(percentage * 100.0 + 0.5)) <= 0) {
169 if (percentage >= 1.0) {
170 snprintf(buf, buf_len, "%d%%", 100);
174 } else if (size > 0 && percentage == 0) {
175 if (size > (1 << 30)) {
176 if (snprintf(buf, buf_len, "%.1lfGB",
177 size / 1000000000.0) <= 0)
181 } else if (size > (1 << 20)) {
182 if (snprintf(buf, buf_len, "%.1lfMB",
183 size / 1000000.0) <= 0)
187 } else if (size > (1 << 10)) {
188 if (snprintf(buf, buf_len, "%.1lfKB",
194 if (snprintf(buf, buf_len, "%.0lfB", size) <= 0)
204 static void _set_progressbar(Evas_Object *item, notification_h noti)
206 Evas_Object *ic = NULL;
207 Evas_Object *old_ic = NULL;
209 double percentage = 0.0;
210 notification_type_e type = NOTIFICATION_TYPE_NONE;
211 notification_ly_type_e layout = NOTIFICATION_LY_NONE ;
213 retif(item == NULL, , "Invalid parameter!");
214 retif(noti == NULL, , "noti is NULL");
216 notification_get_type(noti, &type);
217 if (type == NOTIFICATION_TYPE_ONGOING) {
218 notification_get_size(noti, &size);
219 notification_get_progress(noti, &percentage);
220 notification_get_layout(noti, &layout);
222 if (layout != NOTIFICATION_LY_ONGOING_EVENT) {
223 if (percentage > 0.0 && percentage <= 1.0) {
224 old_ic = _check_duplicated_progress_loading(item, "elm.swallow.progress", "list_progress");
225 if (old_ic == NULL) {
226 ic = elm_progressbar_add(item);
227 elm_progressbar_unit_format_set(ic, "%0.0f%%");
230 elm_object_style_set(ic, "list_progress");
235 elm_progressbar_value_set(ic, percentage);
236 elm_progressbar_horizontal_set(ic, EINA_TRUE);
237 elm_progressbar_pulse(ic, EINA_FALSE);
238 } else if ((size >= 0.0 && percentage == 0.0) || ((size < 0.0 && percentage == 0.0)|| (size == 0.0 && percentage < 0.0))) {
239 old_ic = _check_duplicated_progress_loading(item, "elm.swallow.progress", "pending");
240 if (old_ic == NULL) {
241 ic = elm_progressbar_add(item);
242 elm_progressbar_unit_format_set(ic, "%0.0f%%");
245 elm_object_style_set(ic, "pending");
250 elm_progressbar_horizontal_set(ic, EINA_TRUE);
251 elm_progressbar_pulse(ic, EINA_TRUE);
257 elm_object_part_content_set(item, "elm.swallow.progress", ic);
261 static void _set_icon(Evas_Object *item, notification_h noti)
263 Evas_Object *ic = NULL;
264 Evas_Object *old_ic = NULL;
265 char *icon_path = NULL;
266 char *icon_sub_path = NULL;
267 char *thumbnail_path = NULL;
268 char *main_icon_path = NULL;
269 char *sub_icon_path = NULL;
270 char *icon_default = NULL;
271 char *pkgname = NULL;
273 retif(item == NULL, , "Invalid parameter!");
274 retif(noti == NULL, , "noti is NULL");
276 notification_get_pkgname(noti, &pkgname);
277 notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL,
279 notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON, &icon_path);
280 notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON_SUB, &icon_sub_path);
282 if (thumbnail_path != NULL && icon_path != NULL) {
283 main_icon_path = thumbnail_path;
284 sub_icon_path = icon_path;
285 } else if (icon_path != NULL && thumbnail_path == NULL) {
286 main_icon_path = icon_path;
287 sub_icon_path = icon_sub_path;
288 } else if (icon_path == NULL && thumbnail_path != NULL) {
289 main_icon_path = thumbnail_path;
290 sub_icon_path = icon_sub_path;
292 icon_default = quickpanel_common_ui_get_pkginfo_icon(pkgname);
293 main_icon_path = icon_default;
294 sub_icon_path = NULL;
297 if (main_icon_path != NULL) {
298 old_ic = _check_duplicated_image_loading(item,
299 "elm.swallow.thumbnail", main_icon_path);
301 if (old_ic == NULL) {
302 ic = quickpanel_animated_icon_get(item, main_icon_path);
304 ic = elm_image_add(item);
305 elm_image_resizable_set(ic, EINA_FALSE, EINA_TRUE);
306 elm_image_file_set(ic, main_icon_path, quickpanel_animated_image_get_groupname(main_icon_path));
307 #ifdef QP_ANIMATED_IMAGE_ENABLE
308 quickpanel_animated_image_add(ic);
310 if (!strncmp(main_icon_path, QP_PRELOAD_NOTI_ICON_PATH, strlen(QP_PRELOAD_NOTI_ICON_PATH))) {
311 DBG("Apply color theme [%s]", main_icon_path);
312 evas_object_color_set(ic, 155, 216, 226, 255);
314 elm_image_aspect_fixed_set(ic, EINA_TRUE);
317 elm_object_part_content_set(item, "elm.swallow.thumbnail", ic);
321 if (sub_icon_path != NULL) {
322 old_ic = _check_duplicated_image_loading(item,
323 "elm.swallow.icon", sub_icon_path);
325 if (old_ic == NULL) {
326 ic = elm_image_add(item);
327 elm_image_resizable_set(ic, EINA_FALSE, EINA_TRUE);
328 elm_image_file_set(ic, sub_icon_path, quickpanel_animated_image_get_groupname(sub_icon_path));
329 elm_object_part_content_set(item, "elm.swallow.icon", ic);
330 elm_object_signal_emit(item, "elm.icon.bg.show", "elm");
334 if (main_icon_path == NULL && sub_icon_path == NULL) {
335 old_ic = _check_duplicated_image_loading(item,
336 "elm.swallow.thumbnail", QP_DEFAULT_ICON);
338 if (old_ic == NULL) {
339 ic = elm_image_add(item);
340 elm_image_resizable_set(ic, EINA_FALSE, EINA_TRUE);
341 elm_image_file_set(ic, QP_DEFAULT_ICON, quickpanel_animated_image_get_groupname(QP_DEFAULT_ICON));
342 elm_object_part_content_set(item, "elm.swallow.thumbnail", ic);
343 #ifdef QP_ANIMATED_IMAGE_ENABLE
344 quickpanel_animated_image_add(ic);
349 if (icon_default != NULL) {
354 static void _set_text(Evas_Object *item, notification_h noti)
357 char *text_utf8 = NULL;
360 char *pkgname = NULL;
361 // char *caller_pkgname = NULL;
362 int group_id = 0, priv_id = 0;
363 char buf[128] = { 0, };
364 notification_type_e type = NOTIFICATION_TYPE_NONE;
366 double percentage = 0.0;
367 notification_ly_type_e layout = NOTIFICATION_LY_NONE ;
368 #ifdef QP_SCREENREADER_ENABLE
369 Evas_Object *ao = NULL;
370 Eina_Strbuf *str_buf = NULL;
372 Evas_Object *textblock = NULL;
373 int len_w = 0, num_line = 1, view_height = 0;
374 struct appdata *ad = quickpanel_get_app_data();
375 char *text_count = NULL;
378 if (!ad || !item || !noti) {
379 ERR("Invalid parameters: %p %p %p", ad, item, noti);
383 /* Set text domain */
384 notification_get_text_domain(noti, &domain, &dir);
385 if (domain != NULL && dir != NULL) {
386 bindtextdomain(domain, dir);
389 #ifdef QP_SCREENREADER_ENABLE
390 ao = quickpanel_accessibility_screen_reader_object_get(item, SCREEN_READER_OBJ_TYPE_ELM_OBJECT, "focus", item);
392 str_buf = eina_strbuf_new();
393 elm_access_info_set(ao, ELM_ACCESS_TYPE, _("IDS_QP_BUTTON_NOTIFICATION"));
397 /* Get pkgname & id */
398 ret = notification_get_pkgname(noti, &pkgname);
399 if (ret != NOTIFICATION_ERROR_NONE) {
400 ERR("Unable to get the pkgname");
402 // notification_get_application(noti, &caller_pkgname);
403 ret = notification_get_id(noti, &group_id, &priv_id);
404 if (ret != NOTIFICATION_ERROR_NONE) {
405 ERR("Unable to get id");
407 ret = notification_get_type(noti, &type);
408 if (ret != NOTIFICATION_ERROR_NONE) {
409 ERR("Unable to get type");
411 ret = notification_get_size(noti, &size);
412 if (ret != NOTIFICATION_ERROR_NONE) {
413 ERR("Unable to get size");
415 ret = notification_get_progress(noti, &percentage);
416 if (ret != NOTIFICATION_ERROR_NONE) {
417 ERR("Unable to get progress");
419 ret = notification_get_layout(noti, &layout);
420 if (ret != NOTIFICATION_ERROR_NONE) {
421 ERR("Unable to get layout");
423 ret = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, &text_count);
424 if (ret != NOTIFICATION_ERROR_NONE) {
425 ERR("Unable to get event_count");
428 SDBG("percentage:%f size:%f", percentage, size);
430 text = quickpanel_noti_util_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE);
431 if (ret == NOTIFICATION_ERROR_NONE && text != NULL) {
432 quickpanel_common_util_char_replace(text, _NEWLINE, _SPACE);
433 _set_text_to_part(item, "elm.text.title", text);
434 #ifdef QP_SCREENREADER_ENABLE
435 _check_and_add_to_buffer(str_buf, text);
439 text = quickpanel_noti_util_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT);
441 if (layout == NOTIFICATION_LY_ONGOING_EVENT) {
442 text_utf8 = elm_entry_utf8_to_markup(text);
443 if (text_utf8 != NULL) {
444 _set_text_to_part(item, "elm.text.content", text_utf8);
447 _set_text_to_part(item, "elm.text.content", text);
449 textblock = (Evas_Object *)edje_object_part_object_get(_EDJ(item), "elm.text.content");
450 evas_object_textblock_size_native_get(textblock, &len_w, NULL);
451 num_line = len_w / (LEN_UNIT_TEXTBLOCK * ad->scale);
452 num_line = (len_w - (num_line * (LEN_UNIT_TEXTBLOCK * ad->scale))) > 0 ? num_line + 1 : num_line;
454 elm_object_signal_emit(item, "line1.set", "prog");
455 view_height = QP_THEME_LIST_ITEM_ONGOING_EVENT_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT;
456 } else /*if (num_line >= 2 && num_line < 3)*/ {
457 elm_object_signal_emit(item, "line2.set", "prog");
458 view_height = QP_THEME_LIST_ITEM_ONGOING_EVENT_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT;
460 elm_object_signal_emit(item, "line3.set", "prog");
461 view_height = QP_THEME_LIST_ITEM_ONGOING_EVENT_LINE3_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT;
463 quickpanel_uic_initial_resize(item, view_height);
464 #ifdef QP_SCREENREADER_ENABLE
465 _check_and_add_to_buffer(str_buf, text);
468 quickpanel_common_util_char_replace(text, _NEWLINE, _SPACE);
469 _set_text_to_part(item, "elm.text.content", text);
470 #ifdef QP_SCREENREADER_ENABLE
471 _check_and_add_to_buffer(str_buf, text);
476 if (layout != NOTIFICATION_LY_ONGOING_EVENT) {
477 text = _noti_get_progress(noti, buf, sizeof(buf));
479 quickpanel_common_util_char_replace(text, _NEWLINE, _SPACE);
480 #ifdef QP_SCREENREADER_ENABLE
481 _check_and_add_to_buffer(str_buf, text);
484 _set_text_to_part(item, "elm.text.time", "");
487 const char *get_content;
489 get_content = elm_object_part_text_get(item, "elm.text.content");
490 if (get_content == NULL || strlen(get_content) == 0) {
491 // if there is no content, move title to vertical center.
492 elm_object_signal_emit(item, "title.move.center", "prog");
496 if (layout == NOTIFICATION_LY_ONGOING_PROGRESS && text_count != NULL) {
497 _set_text_to_part(item, "elm.text.count", text_count);
498 if (elm_object_part_text_get(item, "elm.text.count") != NULL) {
499 elm_object_signal_emit(item, "content.short", "prog");
500 elm_object_signal_emit(item, "count.show", "prog");
504 #ifdef QP_SCREENREADER_ENABLE
505 if (ao != NULL && str_buf != NULL) {
506 elm_access_info_set(ao, ELM_ACCESS_INFO, eina_strbuf_string_get(str_buf));
507 eina_strbuf_free(str_buf);
512 static Evas_Object *_create(notification_h noti, Evas_Object *parent)
515 Evas_Object *view = NULL;
516 const char *view_layout_group = NULL;
517 retif(parent == NULL, NULL, "Invalid parameter!");
518 retif(noti == NULL, NULL, "Invalid parameter!");
520 notification_ly_type_e layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
521 notification_get_layout(noti, &layout);
523 if (layout == NOTIFICATION_LY_ONGOING_EVENT) {
524 view_layout_group = "quickpanel/listitem/event";
525 view_height = QP_THEME_LIST_ITEM_ONGOING_EVENT_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT;
526 } else if (layout == NOTIFICATION_LY_ONGOING_PROGRESS) {
527 view_layout_group = "quickpanel/listitem/progress";
528 view_height = QP_THEME_LIST_ITEM_ONGOING_PROGRESS_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT;
531 view = elm_layout_add(parent);
533 elm_layout_file_set(view, DEFAULT_EDJ, view_layout_group);
534 evas_object_size_hint_weight_set(view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
535 evas_object_size_hint_align_set(view, EVAS_HINT_FILL, EVAS_HINT_FILL);
536 quickpanel_uic_initial_resize(view, view_height);
537 evas_object_show(view);
539 ERR("failed to create ongoing notification view");
545 static void _update(noti_node_item *noti_node, notification_ly_type_e layout, Evas_Object *item)
547 retif(item == NULL, , "Invalid parameter!");
548 retif(noti_node == NULL, , "Invalid parameter!");
550 _set_progressbar(item, noti_node->noti);
551 _set_icon(item, noti_node->noti);
552 _set_text(item, noti_node->noti);
555 Noti_View_H ongoing_noti_view_h = {
556 .name = "ongoing_noti_view",