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