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