50b35e7fb6d1ea05201d6b8444258eda791b5b5f
[apps/core/preloaded/quickpanel.git] / daemon / datetime / util-time.c
1 /*
2  * Copyright (c) 2009-2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
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
18
19 #include <Elementary.h>
20 #include <ctype.h>
21 #include <glib.h>
22
23 #include <unicode/utypes.h>
24 #include <unicode/putil.h>
25 #include <unicode/uiter.h>
26 #include <unicode/udat.h>
27 #include <unicode/udatpg.h>
28 #include <unicode/ustring.h>
29
30 #include <appcore-common.h>
31 #include <app_control.h>
32 #include <vconf.h>
33 #include <vconf-keys.h>
34 #include <dlog.h>
35 #include <system_settings.h>
36 #include <utils_i18n.h>
37 #include <tzsh.h>
38 #include <tzsh_quickpanel_service.h>
39 #include <notification.h>
40 #include <E_DBus.h>
41
42 #include "common.h"
43
44 #include "quickpanel-ui.h"
45 #include "util-time.h"
46 #include "datetime.h"
47 #include "noti_node.h"
48 #include "noti.h"
49
50 #define TIME_ZONEINFO_PATH      "/usr/share/zoneinfo/"
51 #define TIME_ZONEINFO_PATH_LEN  (strlen(TIME_ZONEINFO_PATH))
52 #define BUF_FORMATTER 64
53
54 static const char *colon = ":";
55 static const char *ratio = "&#x2236;";
56 static int _init(void *data);
57 static int _fini(void *data);
58 static void _lang_changed(void *data);
59 static void _util_time_heartbeat_do(void);
60
61 QP_Module qp_datetime_controller = {
62         .name = "qp_datetime_controller",
63         .init = _init,
64         .fini = _fini,
65         .suspend = NULL,
66         .resume = NULL,
67         .lang_changed = _lang_changed,
68         .refresh = NULL,
69 };
70
71 static struct info {
72         int is_initialized;
73         Ecore_Timer *timer;
74         int is_timer_enabled;
75         UDateFormat *formatter_date;
76         UDateFormat *formatter_time;
77         UDateFormat *formatter_ampm;
78         UDateTimePatternGenerator *generator;
79         UDateTimePatternGenerator *date_generator;
80         int timeformat;
81         char *timeregion_format;
82         char *dateregion_format;
83         char *timezone_id;
84         Eina_Bool is_pre_meridiem;
85 } s_info = {
86         .is_initialized = 0,
87         .timer = NULL,
88         .is_timer_enabled = 0,
89         .formatter_date = NULL,
90         .formatter_time = NULL,
91         .formatter_ampm = NULL,
92         .generator = NULL,
93         .date_generator = NULL,
94         .timeformat = APPCORE_TIME_FORMAT_24,
95         .timeregion_format = NULL,
96         .dateregion_format = NULL,
97         .timezone_id = NULL,
98         .is_pre_meridiem = EINA_FALSE,
99 };
100
101 static Eina_Bool _timer_cb(void *data);
102
103 static UChar *uastrcpy(const char *chars)
104 {
105         int len = 0;
106         UChar *str = NULL;
107         len = strlen(chars);
108         str = (UChar *) malloc(sizeof(UChar) *(len + 1));
109         if (!str) {
110                 return NULL;
111         }
112         u_uastrcpy(str, chars);
113         return str;
114 }
115
116 static void ICU_set_timezone(const char *timezone)
117 {
118         DBG("ICU_set_timezone = %s ", timezone);
119         UErrorCode ec = U_ZERO_ERROR;
120         UChar *str = uastrcpy(timezone);
121         retif(str == NULL, , "uastrcpy error!");
122
123         ucal_setDefaultTimeZone(str, &ec);
124         if (U_SUCCESS(ec)) {
125                 DBG("ucal_setDefaultTimeZone() SUCCESS ");
126         } else {
127                 ERR("ucal_setDefaultTimeZone() FAILED : %s ",
128                                 u_errorName(ec));
129         }
130         free(str);
131 }
132
133 static char *_get_locale(void)
134 {
135         char locale_tmp[32] = { 0, };
136         char *locale = NULL; //vconf_get_str(VCONFKEY_REGIONFORMAT);
137         int ret = 0;
138
139         ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, &locale);
140         msgif(ret != SYSTEM_SETTINGS_ERROR_NONE, "failed to ignore key(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY) : %d", ret);
141
142         if (locale == NULL) {
143                 ERR("vconf_get_str() failed : region format");
144                 return strdup("en_GB");
145         }
146
147         strncpy(locale_tmp, locale, sizeof(locale_tmp) - 1);
148
149         // remove .UTF-8
150         if (strlen(locale_tmp) > 0) {
151                 char *p = strstr(locale_tmp, ".UTF-8");
152                 if (p) {
153                         *p = 0;
154                 }
155         }
156
157         free(locale);
158
159         if (strlen(locale_tmp) > 0) {
160                 return strdup(locale_tmp);
161         }
162
163         return strdup("en_GB");
164 }
165
166 /*static char *_get_locale_for_date(void)
167   {
168   char *locale = vconf_get_str(VCONFKEY_REGIONFORMAT);
169   if (locale == NULL) {
170   ERR("vconf_get_str() failed : region format");
171   return strdup("en_GB.UTF8");
172   }
173
174   if (strlen(locale) > 0) {
175   return locale;
176   }
177
178   return strdup("en_GB.UTF8");
179   }*/
180
181 static inline char *_extend_heap(char *buffer, int *sz, int incsz)
182 {
183         char *tmp;
184
185         *sz += incsz;
186         tmp = realloc(buffer, *sz);
187         if (!tmp) {
188                 ERR("Heap");
189                 return NULL;
190         }
191
192         return tmp;
193 }
194
195 static char *_string_replacer(char *src, const char *pattern, const char *replace)
196 {
197         char *ptr;
198         char *tmp = NULL;
199         char *ret = NULL;
200         int idx = 0;
201         int out_idx = 0;
202         int out_sz = 0;
203         enum {
204                 STATE_START,
205                 STATE_FIND,
206                 STATE_CHECK,
207                 STATE_END,
208         } state;
209
210         if (!src || !pattern) {
211                 return NULL;
212         }
213
214         out_sz = strlen(src);
215         ret = strdup(src);
216         if (!ret) {
217                 ERR("Heap");
218                 return NULL;
219         }
220
221         out_idx = 0;
222         for (state = STATE_START, ptr = src; state != STATE_END; ptr++) {
223                 switch (state) {
224                 case STATE_START:
225                         if (*ptr == '\0') {
226                                 state = STATE_END;
227                         } else if (!isblank(*ptr)) {
228                                 state = STATE_FIND;
229                                 ptr--;
230                         }
231                         break;
232                 case STATE_FIND:
233                         if (*ptr == '\0') {
234                                 state = STATE_END;
235                         } else if (*ptr == *pattern) {
236                                 state = STATE_CHECK;
237                                 ptr--;
238                                 idx = 0;
239                         } else if (*ptr == '-') {
240                                 state = STATE_CHECK;
241                                 *ptr = *pattern;
242                                 ptr--;
243                                 idx = 0;
244                         } else {
245                                 ret[out_idx] = *ptr;
246                                 out_idx++;
247                                 if (out_idx == out_sz) {
248                                         tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
249                                         if (!tmp) {
250                                                 free(ret);
251                                                 return NULL;
252                                         }
253                                         ret = tmp;
254                                 }
255                         }
256                         break;
257                 case STATE_CHECK:
258                         if (!pattern[idx]) {
259                                 /*!
260                                  * If there is no space for copying the replacement,
261                                  * Extend size of the return buffer.
262                                  */
263                                 if (out_sz - out_idx < strlen(replace) + 1) {
264                                         tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
265                                         if (!tmp) {
266                                                 free(ret);
267                                                 return NULL;
268                                         }
269                                         ret = tmp;
270                                 }
271
272                                 strcpy(ret + out_idx, replace);
273                                 out_idx += strlen(replace);
274
275                                 state = STATE_FIND;
276                                 ptr--;
277                         } else if (*ptr != pattern[idx]) {
278                                 ptr -= idx;
279
280                                 /* Copy the first matched character */
281                                 ret[out_idx] = *ptr;
282                                 out_idx++;
283                                 if (out_idx == out_sz) {
284                                         tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
285                                         if (!tmp) {
286                                                 free(ret);
287                                                 return NULL;
288                                         }
289
290                                         ret = tmp;
291                                 }
292
293                                 state = STATE_FIND;
294                         } else {
295                                 idx++;
296                         }
297                         break;
298                 default:
299                         break;
300                 }
301         }
302
303         ret[out_idx] = '\0';
304         return ret;
305 }
306
307 static UDateTimePatternGenerator *__util_time_generator_get(void *data)
308 {
309         UErrorCode status = U_ZERO_ERROR;
310         UDateTimePatternGenerator *generator = NULL;
311
312         struct appdata *ad = data;
313         retif_nomsg(ad == NULL, NULL);
314         retif_nomsg(s_info.timeregion_format == NULL, NULL);
315
316         generator = udatpg_open(s_info.timeregion_format, &status);
317         if (U_FAILURE(status)) {
318                 ERR("udatpg_open() failed");
319                 generator = NULL;
320                 return NULL;
321         }
322         return generator;
323 }
324
325 static UDateTimePatternGenerator *__util_date_generator_get(void *data)
326 {
327         UErrorCode status = U_ZERO_ERROR;
328         UDateTimePatternGenerator *generator = NULL;
329
330         struct appdata *ad = data;
331         retif_nomsg(ad == NULL, NULL);
332         retif_nomsg(s_info.dateregion_format == NULL, NULL);
333
334         generator = udatpg_open(s_info.dateregion_format, &status);
335         if (U_FAILURE(status)) {
336                 ERR("udatpg_open() failed");
337                 generator = NULL;
338                 return NULL;
339         }
340         return generator;
341 }
342
343 static UDateFormat *__util_time_date_formatter_get(void *data, const char *timezone_id, const char *skeleton)
344 {
345         UErrorCode status = U_ZERO_ERROR;
346
347         UChar u_skeleton[BUF_FORMATTER] = {0,};
348         int skeleton_len = 0;
349
350         UChar u_best_pattern[BUF_FORMATTER] = {0,};
351         int32_t u_best_pattern_capacity;
352         UDateFormat *formatter = NULL;
353
354         struct appdata *ad = data;
355         retif_nomsg(ad == NULL, NULL);
356         retif_nomsg(s_info.date_generator == NULL, NULL);
357
358         u_uastrncpy(u_skeleton, skeleton, strlen(skeleton));
359         skeleton_len = u_strlen(u_skeleton);
360
361         u_best_pattern_capacity =
362                 (int32_t) (sizeof(u_best_pattern) / sizeof((u_best_pattern)[0]));
363
364         udatpg_getBestPattern(s_info.date_generator, u_skeleton, skeleton_len,
365                         u_best_pattern, u_best_pattern_capacity, &status);
366         if (U_FAILURE(status)) {
367                 ERR("udatpg_getBestPattern() failed");
368                 return NULL;
369         }
370
371         UChar u_timezone_id[BUF_FORMATTER] = {0,};
372         if (timezone_id == NULL) {
373                 u_uastrncpy(u_timezone_id, s_info.timezone_id, sizeof(u_timezone_id));
374                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.dateregion_format, u_timezone_id, -1,
375                                 u_best_pattern, -1, &status);
376         } else {
377                 u_uastrncpy(u_timezone_id, timezone_id, sizeof(u_timezone_id));
378                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.dateregion_format, u_timezone_id, -1,
379                                 u_best_pattern, -1, &status);
380         }
381         if (U_FAILURE(status)) {
382                 ERR("udat_open() failed");
383                 return NULL;
384         }
385
386         char a_best_pattern[BUF_FORMATTER] = {0,};
387         u_austrcpy(a_best_pattern, u_best_pattern);
388
389         return formatter;
390 }
391
392 static UDateFormat *__util_time_ampm_formatter_get(void *data, const char *timezone_id)
393 {
394         UErrorCode status = U_ZERO_ERROR;
395
396         UChar u_best_pattern[BUF_FORMATTER] = {0,};
397         UDateFormat *formatter = NULL;
398
399         struct appdata *ad = data;
400         retif_nomsg(ad == NULL, NULL);
401
402         u_uastrcpy(u_best_pattern, "a");
403
404         UChar u_timezone_id[BUF_FORMATTER] = {0,};
405         if (timezone_id == NULL) {
406                 u_uastrncpy(u_timezone_id, s_info.timezone_id, sizeof(u_timezone_id));
407                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.timeregion_format, u_timezone_id, -1,
408                                 u_best_pattern, -1, &status);
409         } else {
410                 u_uastrncpy(u_timezone_id, timezone_id, sizeof(u_timezone_id));
411                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.timeregion_format, u_timezone_id, -1,
412                                 u_best_pattern, -1, &status);
413         }
414         if (U_FAILURE(status)) {
415                 ERR("udat_open() failed");
416                 return NULL;
417         }
418
419         char a_best_pattern[BUF_FORMATTER] = {0,};
420         u_austrcpy(a_best_pattern, u_best_pattern);
421
422         return formatter;
423 }
424
425 static UDateFormat *__util_time_time_formatter_get(void *data, int time_format, const char *timezone_id)
426 {
427         char buf[BUF_FORMATTER] = {0,};
428         UErrorCode status = U_ZERO_ERROR;
429         UChar u_pattern[BUF_FORMATTER] = {0,};
430         UChar u_best_pattern[BUF_FORMATTER] = {0,};
431         int32_t u_best_pattern_capacity;
432         char a_best_pattern[BUF_FORMATTER] = {0,};
433
434         UDateFormat *formatter = NULL;
435
436         struct appdata *ad = data;
437         retif_nomsg(ad == NULL, NULL);
438         retif_nomsg(s_info.generator == NULL, NULL);
439
440         if (time_format == APPCORE_TIME_FORMAT_24) {
441                 snprintf(buf, sizeof(buf)-1, "%s", "HH:mm");
442         } else {
443                 /* set time format 12 */
444                 snprintf(buf, sizeof(buf)-1, "%s", "h:mm");
445         }
446
447         if (u_uastrncpy(u_pattern, buf, sizeof(u_pattern)) == NULL) {
448                 ERR("u_uastrncpy() is failed.");
449                 return NULL;
450         }
451
452         u_best_pattern_capacity =
453                 (int32_t) (sizeof(u_best_pattern) / sizeof((u_best_pattern)[0]));
454
455         udatpg_getBestPattern(s_info.generator, u_pattern, u_strlen(u_pattern),
456                         u_best_pattern, u_best_pattern_capacity, &status);
457         if (U_FAILURE(status)) {
458                 ERR("udatpg_getBestPattern() failed");
459                 return NULL;
460         }
461
462         u_austrcpy(a_best_pattern, u_best_pattern);
463
464         if (a_best_pattern[0] == 'a') {
465                 s_info.is_pre_meridiem = EINA_TRUE;
466         } else {
467                 s_info.is_pre_meridiem = EINA_FALSE;
468         }
469
470         u_uastrcpy(u_best_pattern, buf);
471
472         UChar u_timezone_id[BUF_FORMATTER] = {0,};
473         if (timezone_id == NULL) {
474                 u_uastrncpy(u_timezone_id, s_info.timezone_id, sizeof(u_timezone_id));
475                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.timeregion_format, u_timezone_id, -1,
476                                 u_best_pattern, -1, &status);
477         } else {
478                 u_uastrncpy(u_timezone_id, timezone_id, sizeof(u_timezone_id));
479                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.timeregion_format, u_timezone_id, -1,
480                                 u_best_pattern, -1, &status);
481         }
482         if (U_FAILURE(status)) {
483                 ERR("udat_open() failed");
484                 return NULL;
485         }
486
487         return formatter;
488 }
489
490 static void _util_time_formatters_create(void *data)
491 {
492         struct appdata *ad = data;
493         retif_nomsg(ad == NULL, );
494
495         if (s_info.generator == NULL) {
496                 s_info.generator = __util_time_generator_get(ad);
497         }
498
499         if (s_info.date_generator == NULL) {
500                 s_info.date_generator = __util_date_generator_get(ad);
501         }
502
503         if (s_info.formatter_date == NULL) {
504                 s_info.formatter_date = __util_time_date_formatter_get(ad, NULL, "MMMMEd");
505         }
506
507         if (s_info.timeformat == APPCORE_TIME_FORMAT_12) {
508                 if (s_info.formatter_ampm == NULL) {
509                         s_info.formatter_ampm = __util_time_ampm_formatter_get(ad, NULL);
510                 }
511         }
512
513         if (s_info.formatter_time == NULL) {
514                 s_info.formatter_time = __util_time_time_formatter_get(ad, s_info.timeformat, NULL);
515         }
516 }
517
518 static void _util_time_formatters_destroy(void *data)
519 {
520         struct appdata *ad = data;
521         retif_nomsg(ad == NULL, );
522
523         if (s_info.date_generator) {
524                 udat_close(s_info.date_generator);
525                 s_info.date_generator = NULL;
526         }
527
528         if (s_info.generator) {
529                 udat_close(s_info.generator);
530                 s_info.generator = NULL;
531         }
532
533         if (s_info.formatter_date) {
534                 udat_close(s_info.formatter_date);
535                 s_info.formatter_date = NULL;
536         }
537         if (s_info.formatter_time) {
538                 udat_close(s_info.formatter_time);
539                 s_info.formatter_time = NULL;
540         }
541         if (s_info.formatter_ampm) {
542                 udat_close(s_info.formatter_ampm);
543                 s_info.formatter_ampm = NULL;
544         }
545 }
546
547 static char *_util_time_regionformat_get(void)
548 {
549         return _get_locale();
550 }
551
552 static char *_util_date_regionformat_get(void)
553 {
554         return _get_locale();
555 }
556
557 static char* _get_timezone_from_vconf(void)
558 {
559         char *szTimezone = NULL;
560         szTimezone = vconf_get_str(VCONFKEY_SETAPPL_TIMEZONE_ID);
561         if (szTimezone == NULL || strlen(szTimezone) == 0)
562         {
563                 ERR("QUICKPANEL TIMEZONE - Cannot get time zone.");
564                 return strdup("N/A");
565         }
566
567         return szTimezone;
568 }
569
570 static char *_util_time_timezone_id_get(void)
571 {
572         char buf[1024] = {0,};
573         ssize_t len = readlink("/opt/etc/localtime", buf, sizeof(buf)-1);
574
575         INFO("QUICKPANEL TIMEZONE -  %s",  buf);
576
577         if (len != -1) {
578                 buf[len] = '\0';
579         } else {
580                 ERR("QUICKPANEL TIMEZONE - failed to get a timezone information");
581                 return _get_timezone_from_vconf();
582         }
583
584         return strdup(buf + 20);
585 }
586
587 static int _util_time_formatted_time_get(UDateFormat *formatter, time_t tt, char *buf, int buf_len)
588 {
589         i18n_udate u_time = (i18n_udate)(tt) * 1000;
590         i18n_uchar u_formatted_str[BUF_FORMATTER] = {0, };
591         int32_t u_formatted_str_capacity;
592         int32_t formatted_str_len = -1;
593         int status = I18N_ERROR_INVALID_PARAMETER;
594
595         u_formatted_str_capacity =
596                 (int32_t)(sizeof(u_formatted_str) / sizeof((u_formatted_str)[0]));
597
598         status = i18n_udate_format_date(formatter, u_time, u_formatted_str, u_formatted_str_capacity, NULL, &formatted_str_len);
599         if (status != I18N_ERROR_NONE) {
600                 ERR("i18n_udate_format_date() failed");
601                 return -1;
602         }
603
604         if (formatted_str_len <= 0) {
605                 ERR("formatted_str_len is less than 0");
606         }
607
608         buf = i18n_ustring_copy_au_n(buf, u_formatted_str, (int32_t)buf_len);
609         DBG("date:(%d)[%s][%d]", formatted_str_len, buf, tt);
610
611         return (int)u_strlen(u_formatted_str);
612 }
613
614 static void _formatter_create(void *data)
615 {
616         int ret = 0;
617         struct appdata *ad = data;
618         retif_nomsg(ad == NULL, );
619         bool status = false;
620
621         ret = system_settings_get_value_bool(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR, &status);
622         msgif(ret != SYSTEM_SETTINGS_ERROR_NONE, "failed to ignore key(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR) : %d", ret);
623
624         if (status == true){
625                 s_info.timeformat = APPCORE_TIME_FORMAT_24;
626         }else{
627                 s_info.timeformat = APPCORE_TIME_FORMAT_12;
628         }
629
630         if (s_info.timeregion_format == NULL) {
631                 s_info.timeregion_format = _util_time_regionformat_get();
632         }
633
634         if (s_info.dateregion_format == NULL) {
635                 s_info.dateregion_format = _util_date_regionformat_get();
636         }
637
638         if (s_info.timezone_id == NULL) {
639                 s_info.timezone_id = _util_time_timezone_id_get();
640         }
641
642         ICU_set_timezone(s_info.timezone_id);
643
644         _util_time_formatters_create(ad);
645
646         s_info.is_initialized = 1;
647         DBG("%d %s %s", s_info.timeformat, s_info.timeregion_format, s_info.timezone_id);
648 }
649
650 static void _formatter_destory(void *data)
651 {
652         struct appdata *ad = data;
653         retif_nomsg(ad == NULL, );
654
655         if (s_info.timeregion_format) {
656                 free(s_info.timeregion_format);
657                 s_info.timeregion_format = NULL;
658         }
659         if (s_info.dateregion_format) {
660                 free(s_info.dateregion_format);
661                 s_info.dateregion_format = NULL;
662         }
663         if (s_info.timezone_id) {
664                 free(s_info.timezone_id);
665                 s_info.timezone_id = NULL;
666         }
667
668         _util_time_formatters_destroy(ad);
669
670         s_info.is_initialized = 0;
671 }
672
673 static void _util_time_setting_changed_cb(system_settings_key_e key, void *data)
674 {
675         struct appdata *ad = data;
676
677         _formatter_destory(ad);
678         _formatter_create(ad);
679
680         _util_time_heartbeat_do();
681
682         //upate noti time information.
683         quickpanel_noti_update_by_system_time_changed_setting_cb(key, ad);
684 }
685
686 static void _util_time_vconf_changed_cb(keynode_t *key, void *data)
687 {
688         struct appdata *ad = data;
689
690         _formatter_destory(ad);
691         _formatter_create(ad);
692
693         _util_time_heartbeat_do();
694
695         //upate noti time information.
696         quickpanel_noti_update_by_system_time_changed_vconf_cb(key, ad);
697 }
698
699 static void _time_event_deattach(void *data)
700 {
701         int ret = 0;
702         struct appdata *ad = data;
703         retif_nomsg(ad == NULL, );
704
705         /* unregister vconf cbs */
706         ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT, _util_time_vconf_changed_cb);
707         msgif(ret != 0, "failed to set key(%s) : %d", VCONFKEY_SETAPPL_TIMEZONE_INT, ret);
708         ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_TIMEZONE_ID, _util_time_vconf_changed_cb);
709         msgif(ret != 0, "failed to set key(%s) : %d", VCONFKEY_SETAPPL_TIMEZONE_ID, ret);
710         ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SVC_ROAM, _util_time_vconf_changed_cb);
711         msgif(ret != 0, "failed to set key(%s) : %d", VCONFKEY_TELEPHONY_SVC_ROAM, ret);
712
713         ret = system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_TIME_CHANGED);
714         msgif(ret != SYSTEM_SETTINGS_ERROR_NONE, "failed to set key(%d) : %d", SYSTEM_SETTINGS_KEY_TIME_CHANGED, ret);
715         ret = system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR);
716         msgif(ret != SYSTEM_SETTINGS_ERROR_NONE, "failed to set key(%d) : %d", SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR, ret);
717         ret = system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY);
718         msgif(ret != SYSTEM_SETTINGS_ERROR_NONE, "failed to set key(%d) : %d", SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, ret);
719 }
720
721 static void _time_event_attach(void *data)
722 {
723         int ret = 0;
724         struct appdata *ad = data;
725         retif_nomsg(ad == NULL, );
726
727         /* register vconf cbs */
728         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT, _util_time_vconf_changed_cb, data);
729         msgif(ret != 0, "failed to set key(%s) : %d", VCONFKEY_SETAPPL_TIMEZONE_INT, ret);
730         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_ID, _util_time_vconf_changed_cb, data);
731         msgif(ret != 0, "failed to set key(%s) : %d", VCONFKEY_SETAPPL_TIMEZONE_ID, ret);
732         ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SVC_ROAM, _util_time_vconf_changed_cb, data);
733         msgif(ret != 0, "failed to set key(%s) : %d", VCONFKEY_TELEPHONY_SVC_ROAM, ret);
734
735         ret = system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_TIME_CHANGED, _util_time_setting_changed_cb, data);
736         msgif(ret != SYSTEM_SETTINGS_ERROR_NONE, "failed to set key(%d) : %d", SYSTEM_SETTINGS_KEY_TIME_CHANGED, ret);
737         ret = system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR, _util_time_setting_changed_cb, data);
738         msgif(ret != SYSTEM_SETTINGS_ERROR_NONE, "failed to set key(%d) : %d", SYSTEM_SETTINGS_KEY_LOCALE_TIMEFORMAT_24HOUR, ret);
739         ret = system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, _util_time_setting_changed_cb, data);
740         msgif(ret != SYSTEM_SETTINGS_ERROR_NONE, "failed to set key(%d) : %d", SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, ret);
741
742 }
743
744 static void _util_time_get(int is_current_time, time_t tt_a, char **str_date, char **str_time, char **str_meridiem)
745 {
746         time_t tt;
747         struct tm st;
748         char buf_date[512] = {0,};
749         char buf_time[512] = {0,};
750         char buf_ampm[512] = {0,};
751
752         char *convert_formatted_str = NULL;
753
754         if (is_current_time == 1) {
755                 tt = time(NULL);
756         } else {
757                 tt = tt_a;
758         }
759         localtime_r(&tt, &st);
760
761         /* date */
762         _util_time_formatted_time_get(s_info.formatter_date, tt, buf_date, sizeof(buf_date));
763
764         /* time */
765         if (s_info.timeformat == APPCORE_TIME_FORMAT_24) {
766                 _util_time_formatted_time_get(s_info.formatter_time, tt, buf_time, sizeof(buf_time)-1);
767         } else {
768                 _util_time_formatted_time_get(s_info.formatter_time, tt, buf_time, sizeof(buf_time)-1);
769                 int ampm_len = _util_time_formatted_time_get(s_info.formatter_ampm, tt, buf_ampm, sizeof(buf_ampm)-1);
770                 if (ampm_len > 4) {
771                         if (st.tm_hour >= 0 && st.tm_hour < 12) {
772                                 snprintf(buf_ampm, sizeof(buf_ampm)-1, "AM");
773                         } else {
774                                 snprintf(buf_ampm, sizeof(buf_ampm)-1, "PM");
775                         }
776                 }
777         }
778
779         if (strstr(s_info.timeregion_format, "ar_")) {
780                 convert_formatted_str = strdup(buf_time);
781         } else {
782                 convert_formatted_str = _string_replacer(buf_time, colon, ratio);
783         }
784
785         if (str_date != NULL) {
786                 *str_date = strdup(buf_date);
787         }
788
789         if (str_meridiem != NULL) {
790                 *str_meridiem = strdup(buf_ampm);
791         }
792
793         if (convert_formatted_str)
794         {
795                 if (str_time != NULL) {
796                         *str_time = strdup(convert_formatted_str);
797                 }
798                 free(convert_formatted_str);
799         }
800 }
801
802 static void _timer_add(void)
803 {
804         time_t tt;
805         struct tm st;
806
807         tt = time(NULL);
808         localtime_r(&tt, &st);
809
810         s_info.timer = ecore_timer_add(60 - st.tm_sec, _timer_cb, NULL);
811 }
812
813 static void _timer_del(void)
814 {
815         if (s_info.timer != NULL) {
816                 ecore_timer_del(s_info.timer);
817                 s_info.timer = NULL;
818         }
819 }
820
821 static Eina_Bool _timer_cb(void *data)
822 {
823         _util_time_heartbeat_do();
824
825         if (s_info.is_timer_enabled ==1) {
826                 _timer_del();
827                 _timer_add();
828         }
829         return ECORE_CALLBACK_CANCEL;
830 }
831
832 static int _init(void *data)
833 {
834         _formatter_create(data);
835         _time_event_attach(data);
836
837         return QP_OK;
838 }
839
840 static int _fini(void *data)
841 {
842         _time_event_deattach(data);
843         _formatter_destory(data);
844
845         return QP_OK;
846 }
847
848 static void _lang_changed(void *data)
849 {
850         _util_time_vconf_changed_cb(NULL, data);
851 }
852
853 static void _util_time_heartbeat_do(void)
854 {
855         int type_meridiem = UTIL_TIME_MERIDIEM_TYPE_NONE;
856         char *str_date = NULL;
857         char *str_time = NULL;
858         char *str_meridiem = NULL;
859
860         if (s_info.is_initialized == 0) {
861                 ERR("time information ins't initialized");
862                 return;
863         }
864
865         _util_time_get(1, 0, &str_date, &str_time, &str_meridiem);
866
867         if (str_meridiem != NULL) {
868                 if (s_info.is_pre_meridiem == EINA_TRUE) {
869                         type_meridiem = UTIL_TIME_MERIDIEM_TYPE_PRE;
870                 } else {
871                         type_meridiem = UTIL_TIME_MERIDIEM_TYPE_POST;
872                 }
873         }
874         quickpanel_datetime_view_update(str_date, str_time, str_meridiem, type_meridiem);
875
876         if (str_date) {
877                 free(str_date);
878         }
879         if (str_time) {
880                 free(str_time);
881         }
882         if (str_meridiem) {
883                 free(str_meridiem);
884         }
885 }
886
887 HAPI void quickpanel_util_time_timer_enable_set(int is_enable)
888 {
889         _timer_del();
890
891         if (is_enable == 1) {
892                 _timer_add();
893         }
894
895         _util_time_heartbeat_do();
896
897         s_info.is_timer_enabled = is_enable;
898 }