2dba8a55cd7eb6605010bbdc2f13f1fd785bd94e
[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 #ifdef O_TYPE
314 static char *
315 _gl_menu_title_text_get(void *data, Evas_Object *obj, const char *part)
316 {
317         char buf[1024];
318
319         snprintf(buf, 1023, "%s", _("IDS_ST_BUTTON_LANGUAGE"));
320         return strdup(buf);
321 }
322 #endif
323 Evas_Object *_create_lang_list(void *data)
324 {
325         DBG("_create_lang_list:clear");
326
327         appdata *ad = data;
328         if (ad == NULL) {
329                 DBG("%s", "_create_display_list - appdata is null");
330                 return NULL;
331         }
332         Evas_Object *genlist  = NULL;
333         Elm_Genlist_Item_Class *itc_temp = NULL;
334         struct _lang_menu_item *menu_its = NULL;
335         int idx = 0;
336
337         Evas_Object *layout = elm_layout_add(ad->nf);
338         elm_layout_file_set(layout, EDJE_PATH, "setting/genlist/layout");
339         evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
340         evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
341
342         Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new();
343         itc->item_style = "2text.1icon.1";
344         itc->func.text_get = _gl_lang_title_get;
345         itc->func.content_get = _gl_lang_ridio_get;
346         itc->func.del = _lang_gl_del;
347
348         Elm_Genlist_Item_Class *itc_1line = elm_genlist_item_class_new();
349         itc_1line->item_style = "1text.1icon.1";
350         itc_1line->func.text_get = _gl_lang_title_get;
351         itc_1line->func.content_get = _gl_lang_ridio_get;
352         itc_1line->func.del = _lang_gl_del;
353
354         genlist = elm_genlist_add(layout);
355         elm_genlist_mode_set(genlist, ELM_LIST_COMPRESS);
356 #ifdef O_TYPE
357         Evas_Object *circle_genlist = eext_circle_object_genlist_add(genlist, ad->circle_surface);
358         eext_circle_object_genlist_scroller_policy_set(circle_genlist, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
359         eext_rotary_object_event_activated_set(circle_genlist, EINA_TRUE);
360 #endif
361
362 #ifdef _CIRCLE
363         Elm_Genlist_Item_Class *title_item = elm_genlist_item_class_new();
364         title_item ->func.text_get = _gl_menu_title_text_get;
365         title_item->item_style = "title";
366         title_item->func.del = _lang_gl_del;
367
368         elm_genlist_item_append(genlist, title_item, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
369
370         elm_genlist_item_class_free(title_item);
371 #endif
372         menu_its = lang_menu_its;
373
374         Eina_List *lang_list = _get_language_list();
375         struct _lang_menu_item *node = NULL;
376         int index = 0;
377
378         int lang_count = eina_list_count(lang_list);
379
380         DBG("Setting - language count: %d", lang_count);
381
382         while (lang_list) {
383                 node = (struct _lang_menu_item *) eina_list_data_get(lang_list);
384                 if (node) {
385                         lang_menu_its[index].name     = strdup(node->name);
386                         if (strlen(node->sub_name) > 0)
387                                 lang_menu_its[index].sub_name = strdup(node->sub_name);
388                         else
389                                 lang_menu_its[index].sub_name = NULL;
390                         lang_menu_its[index].id           = strdup(node->id);
391
392                         index++;
393                 }
394                 lang_list = eina_list_next(lang_list);
395         }
396
397         for (idx = 0; idx < lang_count; idx++) {
398                 if (lang_menu_its[idx].sub_name != NULL) {
399                         itc_temp = itc;
400                 } else {
401                         itc_temp = itc_1line;
402                 }
403                 Item_Data *id = calloc(sizeof(Item_Data), 1);
404                 if (id) {
405                         id->index = idx;
406                         id->item = elm_genlist_item_append(
407                                                    genlist,                             /* genlist object */
408                                                    itc_temp,                            /* item class */
409                                                    id,                          /* data */
410                                                    NULL,
411                                                    ELM_GENLIST_ITEM_NONE,
412                                                    _gl_lang_sel_cb,             /* call back */
413                                                    (const void *)idx);
414                 }
415         }
416
417         ad->language_rdg = elm_radio_add(genlist);
418         elm_radio_state_value_set(ad->language_rdg, lang_count);
419         elm_radio_value_set(ad->language_rdg, lang_count);
420
421         g_lang_radio = ad->language_rdg;
422
423         evas_object_data_set(genlist, "radio_main", ad->language_rdg);
424
425         elm_genlist_item_class_free(itc);
426         elm_genlist_item_class_free(itc_1line);
427
428 #ifdef _CIRCLE
429         Elm_Genlist_Item_Class *padding = elm_genlist_item_class_new();
430         padding->item_style = "padding";
431         padding->func.del = _lang_gl_del;
432
433         elm_genlist_item_append(genlist, padding, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
434         elm_genlist_item_class_free(padding);
435 #endif
436         elm_object_part_content_set(layout, "elm.genlist", genlist);
437
438         return layout;
439 }
440
441 void _langlist_load()
442 {
443         if (!s_langlist) {
444                 if (is_file_exist(LANGLIST_FILE_PATH_IN_RW)) {
445                         _parseLangListXML(LANGLIST_FILE_PATH_IN_RW);
446                 } else {
447                         _parseLangListXML(LANGLIST_FILE_PATH_IN_RO);
448                 }
449         }
450 }
451
452 Eina_List *_get_language_list()
453 {
454         if (NULL == s_langlist) {
455                 _langlist_load();
456         }
457         return s_langlist;
458 }
459
460 void _langlist_destroy()
461 {
462         Eina_List *list = s_langlist;
463         struct _lang_menu_item *node;
464         while (list) {
465                 node = (struct _lang_menu_item *) eina_list_data_get(list);
466                 if (node) {
467                         if (node->name)
468                                 free(node->name);
469                         if (node->sub_name)
470                                 free(node->sub_name);
471                         if (node->id)
472                                 free(node->id);
473                 }
474                 list = eina_list_next(list);
475         }
476         s_langlist = eina_list_free(s_langlist);
477 }
478
479 static void _parseLangListXML(char *docname)
480 {
481         xmlDocPtr doc;
482         xmlNodePtr cur;
483
484         doc = xmlParseFile(docname);
485         if (doc == NULL) {
486                 DBG("Setting - Documentation is not parsed successfully");
487                 return;
488         }
489
490         cur = xmlDocGetRootElement(doc);
491         if (cur == NULL) {
492                 DBG("Setting - Empty documentation");
493                 xmlFreeDoc(doc);
494                 return;
495         }
496
497         if (xmlStrcmp(cur->name, (const xmlChar *) "langlist")) {
498                 DBG("Setting - Documentation of the wrong type, root node != settings");
499                 xmlFreeDoc(doc);
500                 return;
501         }
502
503         cur = cur->xmlChildrenNode;
504         _tree_walk_langlist(cur);
505
506         if (doc) {
507                 xmlFreeDoc(doc);
508         }
509
510         return;
511 }
512
513 static char *setting_language_string_replace(char *str, char *orig, char *repl)
514 {
515         static char buffer[124];
516         char *ch;
517         if (!(ch = strstr(str, orig))) {
518                 return str;
519         }
520         strncpy(buffer, str, ch - str);
521         buffer[ch - str] = 0;
522         sprintf(buffer + (ch - str), "%s%s", repl, ch + strlen(orig));
523
524         return buffer;
525 }
526
527 static void _tree_walk_langlist(xmlNodePtr cur)
528 {
529         xmlNode *cur_node = NULL;
530         char *id = NULL;                        /* ex. ko_KR */
531         char *name = NULL;
532         char *sub_name = NULL;
533         const char *dim = "(";
534
535         for (cur_node = cur; cur_node; cur_node = cur_node->next) {
536                 if (cur_node->type == XML_ELEMENT_NODE) {
537                         id       = (char *)g_strdup((char *)xmlGetProp(cur_node, (const xmlChar *)"id"));
538                         name = (char *)g_strdup((char *)xmlGetProp(cur_node, (const xmlChar *)"string"));
539                         /*mcc  = (char *)g_strdup((char*) xmlGetProp(cur_node, (const xmlChar *)"mcc")); */
540
541                         struct _lang_menu_item *pitem = (struct _lang_menu_item *)calloc(1, sizeof(struct _lang_menu_item));
542                         if (pitem) {
543                                 pitem->id = id;
544                                 pitem->name = strdup(name);
545
546                                 sub_name = strdup(name);
547                                 if (sub_name && pitem->name)
548                                         pitem->sub_name = (char *)g_strdup(setting_language_string_replace(sub_name, pitem->name, ""));
549
550                                 free(name);
551                                 free(sub_name);
552
553                                 s_langlist = eina_list_append(s_langlist, pitem);
554                         }
555                 }
556         }
557 }
558
559 const char *setting_get_lang_title(void)
560 {
561         DBG("%s", __func__);
562
563         int ret = 0;
564
565         if (s_langlist == NULL) {
566                 _langlist_load();
567         }
568
569         Eina_List *lang_list = s_langlist;
570         Eina_List *elist = NULL;
571
572         struct _lang_menu_item *lang_entry;
573
574         char *title = NULL;
575         char *language = NULL;
576         char buf[32];
577
578         language = vconf_get_str(VCONFKEY_LANGSET);
579
580         DBG("current language : %s", language);
581
582         if (language == NULL) {
583                 return NULL;
584         }
585
586         while (lang_list) {
587                 lang_entry = (struct _lang_menu_item *) eina_list_data_get(lang_list);
588                 if (lang_entry) {
589                         DBG("%s : language -> %s, locale -> %s", __func__, language, lang_entry->id);
590
591                         snprintf(buf, sizeof(buf) - 1, "%s.UTF-8", lang_entry->id);
592                         if (!strcmp(buf, language)) {
593                                 char pull_title_buf[128];
594                                 if (lang_entry->sub_name && strlen(lang_entry->sub_name) > 1)
595                                         snprintf(pull_title_buf, sizeof(pull_title_buf) - 1, "%s %s", lang_entry->name, lang_entry->sub_name);
596                                 else
597                                         snprintf(pull_title_buf, sizeof(pull_title_buf) - 1, "%s", lang_entry->name);
598                                 title = strdup(pull_title_buf);
599                                 break;
600                         }
601                 }
602                 lang_list = eina_list_next(lang_list);
603         }
604
605         return title;
606 }