tizen 2.3.1 release
[apps/home/b2-clocksetting.git] / src / setting-language.c
1 /*
2  *  Copyright (c) 2014 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 /*
18  * setting-language.c
19  *
20  *  Created on: Oct 9, 2013
21  *      Author: min-hoyun
22  */
23
24 #include <vconf.h>
25 #include <vconf-keys.h>
26 #include <unicode/ustring.h>
27 #include <unicode/udat.h>
28 #include <unicode/udatpg.h>
29
30 #include "setting-language.h"
31 #include "setting_view_toast.h"
32 #include "util.h"
33
34
35 static struct _lang_menu_item lang_menu_its[LANGUAGE_ITEM_COUNT];
36 static Evas_Object *g_lang_radio = NULL;
37
38 static void change_language_enabling(keynode_t *key, void *data)
39 {
40         if (is_connected_GM()) {
41                 DBG("Setting - language can not change!!");
42
43                 /* automatic freed!! */
44                 struct _toast_data *toast = _create_toast(tmp_ad, _("IDS_ST_TPOP_CHANGE_LANGUAGE_ON_MOBILE_DEVICE"));
45                 if (toast) {
46                         _show_toast(tmp_ad, toast);
47                 }
48                 if (tmp_ad) {
49                         elm_naviframe_item_pop(tmp_ad->nf);
50
51                 }
52         }
53 }
54
55 void _initialize_language(void *data)
56 {
57         g_lang_radio = NULL;
58         tmp_ad = NULL;
59         if (data) {
60                 tmp_ad = data;
61         }
62
63         register_vconf_changing(VCONFKEY_WMS_WMANAGER_CONNECTED, change_language_enabling, NULL);
64 }
65
66 void _set_launguage_update_cb(void (*cb)(void *))
67 {
68         DBG("_set_launguage_update_cb() is called!");
69
70         if (cb == NULL) {
71                 DBG("callback is NULL");
72                 return;
73         }
74
75         lang_update_cb = cb;
76 }
77
78 void _clear_g_lang_menu_items()
79 {
80         DBG("_clear_g_lang_menu_items");
81
82         int i;
83         for (i = 0; i < LANGUAGE_ITEM_COUNT; i++) {
84                 if (lang_menu_its[i].name)
85                         free(lang_menu_its[i].name);
86                 if (lang_menu_its[i].sub_name)
87                         free(lang_menu_its[i].sub_name);
88                 if (lang_menu_its[i].id)
89                         free(lang_menu_its[i].id);
90         }
91 }
92
93 void _clear_lang_cb(void *data , Evas *e, Evas_Object *obj, void *event_info)
94 {
95         DBG("_clear_lang_cb");
96
97         appdata *ad = data;
98         if (ad == NULL) {
99                 return;
100         }
101
102         if (ad->language_rdg) {
103                 ad->language_rdg = NULL;
104         }
105
106         g_lang_radio = NULL;
107
108         _langlist_destroy();
109
110         _clear_g_lang_menu_items();
111
112         unregister_vconf_changing(VCONFKEY_WMS_WMANAGER_CONNECTED, change_language_enabling);
113
114         ad->MENU_TYPE = SETTING_DISPLAY;
115 }
116
117 Ecore_Timer *lang_timer = NULL;
118
119 static Eina_Bool _update_language(void *data)
120 {
121         char *locale = vconf_get_str(VCONFKEY_LANGSET);
122         elm_language_set(locale);
123         /*elm_config_all_flush(); */
124
125         if (lang_update_cb) {
126                 lang_update_cb(tmp_ad);
127         }
128
129         lang_timer = NULL;
130
131         return ECORE_CALLBACK_CANCEL;
132 }
133
134 static int _set_dateformat(const char *region)
135 {
136         char *ret_str = NULL;
137         UChar *uret = NULL;
138         UChar customSkeleton[256] = { 0, };
139         UErrorCode status = U_ZERO_ERROR;
140         UDateTimePatternGenerator *pattern_generator;
141
142         UChar bestPattern[256] = { 0, };
143         char bestPatternString[256] = { 0, };
144         char *skeleton = "yMd";
145
146         uret = u_uastrncpy(customSkeleton, skeleton, strlen(skeleton));
147
148         pattern_generator = udatpg_open(region, &status);
149
150         int32_t bestPatternCapacity =
151                 (int32_t)(sizeof(bestPattern) / sizeof((bestPattern)[0]));
152         (void)udatpg_getBestPattern(pattern_generator, customSkeleton,
153                                                                 u_strlen(customSkeleton), bestPattern,
154                                                                 bestPatternCapacity, &status);
155
156         ret_str = u_austrcpy(bestPatternString, bestPattern);
157
158         int i = 0;
159         int j = 0;
160         int len = strlen(bestPatternString);
161         char region_format[4] = {0, };
162         int ymd[3] = {0, };
163         /*  only save 'y', 'M', 'd' charactor */
164         for (; i < len; i++) {
165                 if (bestPatternString[i] == 'y' && ymd[0] == 0) {
166                         region_format[j++] = bestPatternString[i];
167                         ymd[0] = 1;
168                 } else if (bestPatternString[i] == 'M' && ymd[1] == 0) {
169                         region_format[j++] = bestPatternString[i];
170                         ymd[1] = 1;
171                 } else if (bestPatternString[i] == 'd' && ymd[2] == 0) {
172                         region_format[j++] = bestPatternString[i];
173                         ymd[2] = 1;
174                 }
175         }
176
177         region_format[3] = '\0';
178
179         char *date_format_str[4] = {
180                 "dMy", "Mdy", "yMd", "ydM"
181         };
182         int date_format_vconf_value = 1;        /*  default is "Mdy" */
183         for (i = 0; i < 4; i++) {
184                 if (strlen(region_format) != 0 && !strcmp(region_format, date_format_str[i])) {
185                         date_format_vconf_value = i;
186                 }
187         }
188
189         DBG("bestPatternString : %s, format: %s, index: %d",
190                 bestPatternString, region_format, date_format_vconf_value);
191
192         vconf_set_int(VCONFKEY_SETAPPL_DATE_FORMAT_INT, date_format_vconf_value);
193
194         return 1;
195 }
196
197 void _gl_lang_sel_cb(void *data, Evas_Object *obj, void *event_info)
198 {
199         elm_genlist_item_selected_set((Elm_Object_Item *)event_info, EINA_FALSE);
200
201         int lang_index = (int)data;
202
203         char buf[32] = {0,};
204         snprintf(buf, sizeof(buf) - 1, "%s.UTF-8", lang_menu_its[lang_index].id);
205
206         vconf_set_str(VCONFKEY_LANGSET, buf);
207         vconf_set_str(VCONFKEY_REGIONFORMAT, buf);
208
209         _set_dateformat(lang_menu_its[lang_index].id);
210
211         const char *temp = vconf_get_str(VCONFKEY_LANGSET);
212
213         DBG("Setting - %s", temp);
214
215         if (g_lang_radio) {
216                 elm_radio_value_set(g_lang_radio, lang_index);
217         }
218
219         char *locale = vconf_get_str(VCONFKEY_LANGSET);
220         elm_language_set(locale);
221
222         if (lang_update_cb) {
223                 lang_update_cb(tmp_ad);
224         }
225
226         if (tmp_ad) {
227                 elm_naviframe_item_pop(tmp_ad->nf);
228         }
229 }
230
231 void _lang_sel_changed_cb(void *data, Evas_Object *obj, void *event_info)
232 {
233         /* do nothing */
234 }
235
236 char *_gl_lang_title_get(void *data, Evas_Object *obj, const char *part)
237 {
238         char buf[1024] = {0,};
239         Item_Data *id = data;
240         int index = id->index;
241
242         if (!strcmp(part, "elm.text.2")) {
243                 snprintf(buf, sizeof(buf) - 1, "%s", lang_menu_its[index].sub_name);
244         } else if (!strcmp(part, "elm.text") || !strcmp(part, "elm.text.1")) {
245                 snprintf(buf, sizeof(buf) - 1, "%s", lang_menu_its[index].name);
246         }
247         return strdup(buf);
248 }
249
250 Evas_Object *_gl_lang_ridio_get(void *data, Evas_Object *obj, const char *part)
251 {
252         Evas_Object *radio = NULL;
253         Evas_Object *radio_main = evas_object_data_get(obj, "radio_main");
254         appdata *ad = data;
255
256         Item_Data *id = data;
257         int index = id->index;
258
259         if (!strcmp(part, "elm.icon")) {
260                 radio = elm_radio_add(obj);
261                 elm_object_style_set(radio, "list");
262                 elm_radio_state_value_set(radio, index);
263                 evas_object_smart_callback_add(radio, "changed", _lang_sel_changed_cb, (void *)index);
264                 evas_object_size_hint_align_set(radio, EVAS_HINT_FILL, EVAS_HINT_FILL);
265                 evas_object_size_hint_weight_set(radio, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
266                 evas_object_propagate_events_set(radio, EINA_FALSE);
267                 evas_object_repeat_events_set(radio, EINA_TRUE);
268
269                 elm_radio_group_add(radio, radio_main);
270
271                 const char *lang_set = vconf_get_str(VCONFKEY_LANGSET);
272                 char buf[32] = {0,};
273                 snprintf(buf, sizeof(buf) - 1, "%s.UTF-8", lang_menu_its[index].id);
274                 char *alt_lang_set = strdup(buf);
275
276                 if (!strcasecmp(lang_set, buf)) {
277                         elm_radio_value_set(radio_main, index);
278
279                         if (id->item) {
280                                 elm_genlist_item_show(id->item, ELM_GENLIST_ITEM_SCROLLTO_TOP);
281                         }
282                 }
283                 free(alt_lang_set);
284
285                 snprintf(buf, sizeof(buf) - 1, "%s.UTF8", lang_menu_its[index].id);
286                 char *alt_lang_set2 = strdup(buf);
287                 if (!strcasecmp(lang_set, buf)) {
288                         elm_radio_value_set(radio_main, index);
289
290                         if (id->item) {
291                                 elm_genlist_item_show(id->item, ELM_GENLIST_ITEM_SCROLLTO_TOP);
292                         }
293                 }
294                 free(alt_lang_set2);
295
296                 DBG("Setting - current language is %s", lang_set);
297
298                 index++;
299         }
300
301         return radio;
302 }
303
304 static void _lang_gl_del(void *data, Evas_Object *obj)
305 {
306         /* FIXME: Unrealized callback can be called after this. */
307         /* Accessing Item_Data can be dangerous on unrealized callback. */
308         Item_Data *id = data;
309         if (id)
310                 free(id);
311 }
312
313 Evas_Object *_create_lang_list(void *data)
314 {
315         DBG("_create_lang_list:clear");
316
317         appdata *ad = data;
318         if (ad == NULL) {
319                 DBG("%s", "_create_display_list - appdata is null");
320                 return NULL;
321         }
322         Evas_Object *genlist  = NULL;
323         Elm_Genlist_Item_Class *itc_temp = NULL;
324         struct _lang_menu_item *menu_its = NULL;
325         int idx = 0;
326
327         Evas_Object *layout = elm_layout_add(ad->nf);
328         elm_layout_file_set(layout, EDJE_PATH, "setting/genlist/layout");
329         evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
330         evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
331
332         Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new();
333         itc->item_style = "2text.1icon.1";
334         itc->func.text_get = _gl_lang_title_get;
335         itc->func.content_get = _gl_lang_ridio_get;
336         itc->func.del = _lang_gl_del;
337
338         Elm_Genlist_Item_Class *itc_1line = elm_genlist_item_class_new();
339         itc_1line->item_style = "1text.1icon.1";
340         itc_1line->func.text_get = _gl_lang_title_get;
341         itc_1line->func.content_get = _gl_lang_ridio_get;
342         itc_1line->func.del = _lang_gl_del;
343
344         genlist = elm_genlist_add(layout);
345         elm_genlist_mode_set(genlist, ELM_LIST_COMPRESS);
346 #ifdef O_TYPE
347         Evas_Object *circle_genlist = eext_circle_object_genlist_add(genlist, ad->circle_surface);
348         eext_circle_object_genlist_scroller_policy_set(circle_genlist, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
349         eext_rotary_object_event_activated_set(circle_genlist, EINA_TRUE);
350 #endif
351
352         menu_its = lang_menu_its;
353
354         Eina_List *lang_list = _get_language_list();
355         struct _lang_menu_item *node = NULL;
356         int index = 0;
357
358         int lang_count = eina_list_count(lang_list);
359
360         DBG("Setting - language count: %d", lang_count);
361
362         while (lang_list) {
363                 node = (struct _lang_menu_item *) eina_list_data_get(lang_list);
364                 if (node) {
365                         lang_menu_its[index].name     = strdup(node->name);
366                         if (strlen(node->sub_name) > 0)
367                                 lang_menu_its[index].sub_name = strdup(node->sub_name);
368                         else
369                                 lang_menu_its[index].sub_name = NULL;
370                         lang_menu_its[index].id           = strdup(node->id);
371
372                         index++;
373                 }
374                 lang_list = eina_list_next(lang_list);
375         }
376
377         for (idx = 0; idx < lang_count; idx++) {
378                 if (lang_menu_its[idx].sub_name != NULL) {
379                         itc_temp = itc;
380                 } else {
381                         itc_temp = itc_1line;
382                 }
383                 Item_Data *id = calloc(sizeof(Item_Data), 1);
384                 if (id) {
385                         id->index = idx;
386                         id->item = elm_genlist_item_append(
387                                                    genlist,                             /* genlist object */
388                                                    itc_temp,                            /* item class */
389                                                    id,                          /* data */
390                                                    NULL,
391                                                    ELM_GENLIST_ITEM_NONE,
392                                                    _gl_lang_sel_cb,             /* call back */
393                                                    (const void *)idx);
394                 }
395         }
396
397         ad->language_rdg = elm_radio_add(genlist);
398         elm_radio_state_value_set(ad->language_rdg, lang_count);
399         elm_radio_value_set(ad->language_rdg, lang_count);
400
401         g_lang_radio = ad->language_rdg;
402
403         evas_object_data_set(genlist, "radio_main", ad->language_rdg);
404
405         elm_genlist_item_class_free(itc);
406         elm_genlist_item_class_free(itc_1line);
407
408         elm_object_part_content_set(layout, "elm.genlist", genlist);
409
410         return layout;
411 }
412
413 void _langlist_load()
414 {
415         if (!s_langlist) {
416                 if (is_file_exist(LANGLIST_FILE_PATH_IN_RW)) {
417                         _parseLangListXML(LANGLIST_FILE_PATH_IN_RW);
418                 } else {
419                         _parseLangListXML(LANGLIST_FILE_PATH_IN_RO);
420                 }
421         }
422 }
423
424 Eina_List *_get_language_list()
425 {
426         if (NULL == s_langlist) {
427                 _langlist_load();
428         }
429         return s_langlist;
430 }
431
432 void _langlist_destroy()
433 {
434         Eina_List *list = s_langlist;
435         struct _lang_menu_item *node;
436         while (list) {
437                 node = (struct _lang_menu_item *) eina_list_data_get(list);
438                 if (node) {
439                         if (node->name)
440                                 free(node->name);
441                         if (node->sub_name)
442                                 free(node->sub_name);
443                         if (node->id)
444                                 free(node->id);
445                 }
446                 list = eina_list_next(list);
447         }
448         s_langlist = eina_list_free(s_langlist);
449 }
450
451 static void _parseLangListXML(char *docname)
452 {
453         xmlDocPtr doc;
454         xmlNodePtr cur;
455
456         doc = xmlParseFile(docname);
457         if (doc == NULL) {
458                 DBG("Setting - Documentation is not parsed successfully");
459                 return;
460         }
461
462         cur = xmlDocGetRootElement(doc);
463         if (cur == NULL) {
464                 DBG("Setting - Empty documentation");
465                 xmlFreeDoc(doc);
466                 return;
467         }
468
469         if (xmlStrcmp(cur->name, (const xmlChar *) "langlist")) {
470                 DBG("Setting - Documentation of the wrong type, root node != settings");
471                 xmlFreeDoc(doc);
472                 return;
473         }
474
475         cur = cur->xmlChildrenNode;
476         _tree_walk_langlist(cur);
477
478         if (doc) {
479                 xmlFreeDoc(doc);
480         }
481
482         return;
483 }
484
485 static char *setting_language_string_replace(char *str, char *orig, char *repl)
486 {
487         static char buffer[124];
488         char *ch;
489         if (!(ch = strstr(str, orig))) {
490                 return str;
491         }
492         strncpy(buffer, str, ch - str);
493         buffer[ch - str] = 0;
494         sprintf(buffer + (ch - str), "%s%s", repl, ch + strlen(orig));
495
496         return buffer;
497 }
498
499 static void _tree_walk_langlist(xmlNodePtr cur)
500 {
501         xmlNode *cur_node = NULL;
502         char *id = NULL;                        /* ex. ko_KR */
503         char *name = NULL;
504         char *sub_name = NULL;
505         const char *dim = "(";
506
507         for (cur_node = cur; cur_node; cur_node = cur_node->next) {
508                 if (cur_node->type == XML_ELEMENT_NODE) {
509                         id       = (char *)g_strdup((char *)xmlGetProp(cur_node, (const xmlChar *)"id"));
510                         name = (char *)g_strdup((char *)xmlGetProp(cur_node, (const xmlChar *)"string"));
511                         /*mcc  = (char *)g_strdup((char*) xmlGetProp(cur_node, (const xmlChar *)"mcc")); */
512
513                         struct _lang_menu_item *pitem = (struct _lang_menu_item *)calloc(1, sizeof(struct _lang_menu_item));
514                         if (pitem) {
515                                 pitem->id = id;
516                                 pitem->name = strdup(name);
517
518                                 sub_name = strdup(name);
519                                 if (sub_name && pitem->name)
520                                         pitem->sub_name = (char *)g_strdup(setting_language_string_replace(sub_name, pitem->name, ""));
521
522                                 free(name);
523                                 free(sub_name);
524
525                                 s_langlist = eina_list_append(s_langlist, pitem);
526                         }
527                 }
528         }
529 }
530
531 const char *setting_get_lang_title(void)
532 {
533         DBG("%s", __func__);
534
535         int ret = 0;
536
537         if (s_langlist == NULL) {
538                 _langlist_load();
539         }
540
541         Eina_List *lang_list = s_langlist;
542         Eina_List *elist = NULL;
543
544         struct _lang_menu_item *lang_entry;
545
546         char *title = NULL;
547         char *language = NULL;
548         char buf[32];
549
550         language = vconf_get_str(VCONFKEY_LANGSET);
551
552         DBG("current language : %s", language);
553
554         if (language == NULL) {
555                 return NULL;
556         }
557
558         while (lang_list) {
559                 lang_entry = (struct _lang_menu_item *) eina_list_data_get(lang_list);
560                 if (lang_entry) {
561                         DBG("%s : language -> %s, locale -> %s", __func__, language, lang_entry->id);
562
563                         snprintf(buf, sizeof(buf) - 1, "%s.UTF-8", lang_entry->id);
564                         if (!strcmp(buf, language)) {
565                                 char pull_title_buf[128];
566                                 if (lang_entry->sub_name && strlen(lang_entry->sub_name) > 1)
567                                         snprintf(pull_title_buf, sizeof(pull_title_buf) - 1, "%s %s", lang_entry->name, lang_entry->sub_name);
568                                 else
569                                         snprintf(pull_title_buf, sizeof(pull_title_buf) - 1, "%s", lang_entry->name);
570                                 title = strdup(pull_title_buf);
571                                 break;
572                         }
573                 }
574                 lang_list = eina_list_next(lang_list);
575         }
576
577         return title;
578 }