apply FSL(Flora Software License)
[apps/core/preloaded/settings.git] / src / setting.c
1 /*
2   * Copyright 2012  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://www.tizenopensource.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 #include <aul.h>
18 #include <Ecore_X.h>
19 #include <appcore-common.h>
20 #include <ewk_main.h>
21
22 #include "setting.h"
23
24 extern void setting_update_gl_item(void* data);
25
26 static int vconf_key_change_event_listen(struct _vconf_key_change_event* me,void* data);
27 static int vconf_key_change_event_unlisten(struct _vconf_key_change_event* me,void* data);
28
29 /**
30 * The event process when region is changes.
31 */
32 static int setting_main_region_changed_cb(void *data)
33 {
34         setting_main_appdata *ad = data;
35
36         if (ad->ug)
37                 ug_send_event(UG_EVENT_REGION_CHANGE);
38
39         return 0;
40 }
41
42 /**
43 * The event process when win object is destroyed
44 */
45 static void setting_main_del_win(void *data, Evas_Object *obj, void *event)
46 {
47         elm_exit();
48 }
49
50 /**
51 * To create a win object, the win is shared between the App and all its UGs
52 */
53 static Evas_Object *setting_main_create_win(const char *name)
54 {
55         SETTING_TRACE_BEGIN;
56         Evas_Object *eo;
57         int w, h;
58
59         eo = elm_win_add(NULL, name, ELM_WIN_BASIC);
60         if (eo) {
61                 elm_win_title_set(eo, name);
62                 elm_win_borderless_set(eo, EINA_TRUE);
63                 evas_object_smart_callback_add(eo, "delete,request",
64                                                setting_main_del_win, NULL);
65                 ecore_x_window_size_get(ecore_x_window_root_first_get(),
66                                         &w, &h);
67                 evas_object_resize(eo, w, h);
68         }
69
70         return eo;
71 }
72
73 /**
74 * exceptional process, reset the env vars by Setting vconf VCONFKEY_LANGSET
75 */
76 static int setting_main_lang_changed_cb(void *data)
77 {
78         SETTING_TRACE_BEGIN;
79         setting_main_appdata *ad = data;
80
81         int r = appcore_set_i18n(SETTING_PACKAGE, SETTING_LOCALEDIR);
82         if(r == -1) {
83                 SETTING_TRACE_ERROR("call appcore_set_i18n failed");
84         }
85
86         if (ad->data_wifi)
87         {
88             ad->data_wifi->sub_desc = (char *)g_strdup(get_pa_Wi_Fi_on_off_str());
89         }
90         if (ad->data_bt)
91         {
92             ad->data_bt->sub_desc = (char *)g_strdup(get_BT_on_off_str());
93         }
94         if (ad->data_mobileApp)
95         {
96             ad->data_mobileApp->sub_desc = (char *)g_strdup(get_Mobile_AP_on_off_str());
97         }
98         if (ad->data_usbcon)
99         {
100             ad->data_usbcon->sub_desc = get_pa_usb_connect_mode_str();
101         }
102         if (ad->data_theme)
103         {
104             ad->data_theme->sub_desc = get_pa_theme_name_str();
105         }
106
107         if (ad->main_genlist) elm_genlist_realized_items_update(ad->main_genlist);
108         if (ad->genlist_load) elm_genlist_realized_items_update(ad->genlist_load);
109
110         Elm_Object_Item *navi_it = NULL;
111         navi_it = elm_naviframe_bottom_item_get(ad->navibar_main);
112         if (navi_it)
113                 elm_object_item_text_set(navi_it, _("IDS_COM_BODY_SETTINGS"));
114
115         if (ad->edit_item)
116         {
117                 elm_object_item_text_set(ad->edit_item, _(EDIT_PREFERRED_STR));
118         }
119
120
121         if (ad->segment_all) elm_object_item_text_set(ad->segment_all, _(ALL_STR));
122         if (ad->segment_preferred) elm_object_item_text_set(ad->segment_preferred,
123                                            _(PREFERRED_STR));
124
125         if (ad->ug)
126                 ug_send_event(UG_EVENT_LANG_CHANGE);
127
128         return SETTING_RETURN_SUCCESS;
129 }
130
131 /**
132 * the event process when other VCONFS changes
133 */
134 static void setting_other_vconf_change_cb(keynode_t *key, void *data)
135 {
136         setting_main_appdata *ad = data;
137         retm_if(!data, "Invalid argument: data is NULL");
138
139         Setting_GenGroupItem_Data* item_to_update = NULL;
140         char *vconf_name = vconf_keynode_get_name(key);
141         SETTING_TRACE("the value of [ %s ] just changed", vconf_name);
142
143         if (!safeStrCmp(vconf_name, VCONFKEY_SETAPPL_USB_MODE_INT)) {
144                 item_to_update = ad->data_usbcon;
145                 retm_if(!item_to_update, "ad->data_usbcon is NULL");
146
147                 item_to_update->sub_desc = get_pa_usb_connect_mode_str();
148                 if (ad->bAppPause || ad->ug) {
149                         ad->updateItems[GL_ITEM_USB] = EINA_TRUE;
150                 } else { // app is not in pause without ug
151                         elm_object_item_data_set(item_to_update->item, item_to_update);
152                         elm_genlist_item_update(item_to_update->item);
153                 }
154                 return;
155         } else if (!safeStrCmp(vconf_name, VCONFKEY_SETAPPL_WIDGET_THEME_STR)) {
156                 item_to_update = ad->data_theme;
157                 retm_if(!item_to_update, "ad->data_theme is NULL");
158
159                 item_to_update->sub_desc = get_pa_theme_name_str();
160                 if (ad->bAppPause || ad->ug) {
161                         ad->updateItems[GL_ITEM_THEME] = EINA_TRUE;
162                 } else { // app is not in pause without ug
163                         elm_object_item_data_set(item_to_update->item, item_to_update);
164                         elm_genlist_item_update(item_to_update->item);
165                 }
166                 return;
167         } else if (!safeStrCmp(vconf_name, VCONFKEY_SETAPPL_ROTATE_LOCK_BOOL)) {
168                 item_to_update = ad->data_rotationMode;
169                 retm_if(!item_to_update, "ad->data_rotationMode is NULL");
170
171                 int status = 0;
172                 vconf_get_bool(VCONFKEY_SETAPPL_ROTATE_LOCK_BOOL, &status);
173                 item_to_update->chk_status = status;
174                 if (ad->bAppPause || ad->ug) {
175                         ad->updateItems[GL_ITEM_ROTATION] = EINA_TRUE;
176                 } else { // app is not in pause without ug
177                         elm_check_state_set(item_to_update->eo_check, status);
178                 }
179                 return;
180         } else if (!safeStrCmp(vconf_name, VCONFKEY_SETAPPL_STATE_DATA_ROAMING_BOOL)) {
181                 item_to_update = ad->data_roaming;
182                 retm_if(!item_to_update, "ad->data_roaming is NULL");
183
184                 int status = 0;
185                 vconf_get_bool(VCONFKEY_SETAPPL_STATE_DATA_ROAMING_BOOL, &status);
186                 item_to_update->chk_status = status;
187                 if (ad->bAppPause || ad->ug) {
188                         ad->updateItems[GL_ITEM_ROAMING] = EINA_TRUE;
189                 } else { // app is not in pause without ug
190                         elm_check_state_set(item_to_update->eo_check, status);
191                 }
192                 return;
193         }
194 }
195
196 /**
197 * the event process when int VCONFS changes
198 */
199 static void setting_int_vconf_change_cb(keynode_t *key, void *data)
200 {
201         setting_main_appdata *ad = data;
202         retm_if(!data, "Invalid argument: data is NULL");
203
204         int status = vconf_keynode_get_int(key);
205         char *vconf_name = vconf_keynode_get_name(key);
206
207         char *pa_wifi_device = NULL;
208         Setting_GenGroupItem_Data *item_to_update = NULL;
209
210         if (!safeStrCmp(vconf_name, VCONFKEY_WIFI_STATE)) {
211                 item_to_update = ad->data_wifi;
212                 retm_if(!item_to_update, "ad->data_wifi is NULL");
213
214                 switch (status) {
215                 case VCONFKEY_WIFI_OFF:
216                         item_to_update->sub_desc = (char *)g_strdup(_("IDS_COM_BODY_OFF_M_STATUS"));
217                         break;
218
219                 case VCONFKEY_WIFI_UNCONNECTED:
220                 case VCONFKEY_WIFI_CONNECTED:
221                 case VCONFKEY_WIFI_TRANSFER:
222                         pa_wifi_device = vconf_get_str(VCONFKEY_WIFI_CONNECTED_AP_NAME);
223                         if (NULL != pa_wifi_device && '\0' != pa_wifi_device[0]) {
224                                 item_to_update->sub_desc = (char *)g_strdup(pa_wifi_device);
225                         } else {
226                                 item_to_update->sub_desc = (char *)g_strdup(_("IDS_COM_BODY_ON_M_STATUS"));
227                         }
228                         FREE(pa_wifi_device);
229                         break;
230                 default:
231                         SETTING_TRACE_ERROR("Invalid wifi status!");
232                         return;
233                 }
234
235                 if (ad->bAppPause || ad->ug) {
236                         ad->updateItems[GL_ITEM_WIFI] = EINA_TRUE;
237                 } else { // app is not in pause without ug
238                         elm_object_item_data_set(item_to_update->item, item_to_update);
239                         elm_genlist_item_update(item_to_update->item);
240                 }
241         } else if (!safeStrCmp(vconf_name, VCONFKEY_BT_STATUS)) {
242                 item_to_update = ad->data_bt;
243                 retm_if(!item_to_update, "ad->data_bt is NULL");
244
245                 if (FALSE == status) {
246                         item_to_update->sub_desc = (char *)g_strdup(_("IDS_COM_BODY_OFF_M_STATUS"));
247                 } else {
248                         item_to_update->sub_desc = (char *)g_strdup(_("IDS_COM_BODY_ON_M_STATUS"));
249                 }
250
251                 if (ad->bAppPause || ad->ug) {
252                         ad->updateItems[GL_ITEM_BT] = EINA_TRUE;
253                 } else { // app is not in pause without ug
254                         elm_object_item_data_set(item_to_update->item, item_to_update);
255                         elm_genlist_item_update(item_to_update->item);
256                 }
257         } else if (!safeStrCmp(vconf_name, VCONFKEY_MOBILE_HOTSPOT_MODE)) {
258                 item_to_update = ad->data_mobileApp;
259                 retm_if(!item_to_update, "ad->data_mobileApp is NULL");
260
261                 /* For other vconfs */
262                 if (FALSE == status) {
263                         item_to_update->sub_desc = (char *)g_strdup(_("IDS_COM_BODY_OFF_M_STATUS"));
264                 } else {
265                         item_to_update->sub_desc = (char *)g_strdup(_("IDS_COM_BODY_ON_M_STATUS"));
266                 }
267
268                 if (ad->bAppPause || ad->ug) {
269                         ad->updateItems[GL_ITEM_MAP] = EINA_TRUE;
270                 } else { // app is not in pause without ug
271                         elm_object_item_data_set(item_to_update->item, item_to_update);
272                         elm_genlist_item_update(item_to_update->item);
273                 }
274         } else {
275                         SETTING_TRACE_ERROR("vconf_name is bad[%s]", vconf_name);
276         }
277
278         return;
279 }
280
281 /**
282 * the event process when string VCONFS changes
283 */
284 static void setting_string_vconf_change_cb(keynode_t *key, void *data)
285 {
286         SETTING_TRACE_BEGIN;
287         setting_main_appdata *ad = data;
288         retm_if(!data, "Invalid argument: data is NULL");
289
290         char *value = vconf_keynode_get_str(key);
291         char *vconf_name = vconf_keynode_get_name(key);
292         Setting_GenGroupItem_Data *item_to_update = NULL;
293
294         if (!safeStrCmp(vconf_name, VCONFKEY_WIFI_CONNECTED_AP_NAME)) {
295                 int status;
296                 item_to_update = ad->data_wifi;
297                 retm_if(!item_to_update, "ad->data_wifi is NULL");
298
299                 if (0 != vconf_get_int(VCONFKEY_WIFI_STATE, &status)) {
300                         SETTING_TRACE_ERROR("vconf_get err: %s", VCONFKEY_WIFI_STATE);
301                         return;
302                 }
303                 SETTING_TRACE("status:%d", status);
304                 switch (status) {
305                 case VCONFKEY_WIFI_OFF:
306                         item_to_update->sub_desc =
307                                 (char *)g_strdup(_("IDS_COM_BODY_OFF_M_STATUS"));
308                         break;
309
310                 case VCONFKEY_WIFI_UNCONNECTED:
311                 case VCONFKEY_WIFI_CONNECTED:
312                 case VCONFKEY_WIFI_TRANSFER:
313                         if (NULL != value && '\0' != value[0]) {
314                                 SETTING_TRACE("wifi_device:%s", value);
315                                 item_to_update->sub_desc = (char *)g_strdup(value);
316                         } else {
317                                 item_to_update->sub_desc =
318                                         (char *) g_strdup(_("IDS_COM_BODY_ON_M_STATUS"));
319                         }
320                         break;
321                 default:
322                         SETTING_TRACE_ERROR("Invalid wifi status!");
323                         return;
324                 }
325                 if (ad->bAppPause || ad->ug) {
326                         ad->updateItems[GL_ITEM_WIFI] = EINA_TRUE;
327                 } else { // app is not in pause without ug
328                         elm_object_item_data_set(item_to_update->item, item_to_update);
329                         elm_genlist_item_update(item_to_update->item);
330                 }
331         } // vconf_name == VCONFKEY_WIFI_CONNECTED_AP_NAME
332 }
333
334 static int vconf_key_change_event_listen(struct _vconf_key_change_event* me, void* data)
335 {
336         SETTING_TRACE_BEGIN;
337         me->in_key[0] = VCONFKEY_BT_STATUS;
338         me->cb[0] = setting_int_vconf_change_cb;
339
340         me->in_key[1] = VCONFKEY_WIFI_STATE,
341         me->cb[1] = setting_int_vconf_change_cb;
342
343         me->in_key[2] = VCONFKEY_WIFI_CONNECTED_AP_NAME,
344         me->cb[2] = setting_string_vconf_change_cb;
345
346         me->in_key[3] = VCONFKEY_MOBILE_HOTSPOT_MODE,
347         me->cb[3] = setting_int_vconf_change_cb;
348
349         me->in_key[4] = VCONFKEY_SETAPPL_USB_MODE_INT,
350         me->cb[4] = setting_other_vconf_change_cb;
351
352         me->in_key[5] = VCONFKEY_SETAPPL_WIDGET_THEME_STR,
353         me->cb[5] = setting_other_vconf_change_cb;
354
355         me->in_key[6] = VCONFKEY_SETAPPL_ROTATE_LOCK_BOOL,
356         me->cb[6] = setting_other_vconf_change_cb;
357
358         me->in_key[7] = VCONFKEY_SETAPPL_STATE_DATA_ROAMING_BOOL,
359         me->cb[7] = setting_other_vconf_change_cb;
360
361         // notify key event
362         int i, ret;
363         for(i=0;i<VCONF_KEY_EVENT_ARR_SIZE; i++)
364         {
365                 if (me->in_key[i] != NULL && me->cb[i] != NULL) {
366                         ret = vconf_notify_key_changed(me->in_key[i], me->cb[i], data);
367                         if(ret < 0)
368                                 SETTING_TRACE_ERROR(" %dth : %s notifications Failed(%d)",i, (char *)me->in_key[i], ret);
369                 }
370         }
371         SETTING_TRACE_END;
372         return 0;
373 }
374
375 static int vconf_key_change_event_unlisten(struct _vconf_key_change_event* me,void* data)
376 {
377         SETTING_TRACE_BEGIN;
378         // notify key event
379         int i, ret;
380         for(i=0;i<VCONF_KEY_EVENT_ARR_SIZE ; i++) {
381                 if (me->in_key[i] != NULL && me->cb[i] != NULL) {
382                         ret = vconf_ignore_key_changed(me->in_key[i], me->cb[i]);
383                 }
384         }
385         SETTING_TRACE_END;
386         return 0;
387 }
388
389
390 /**
391 * Do the process which cost much time
392 */
393 static Eina_Bool setting_on_idle_lazy(void *data)
394 {
395         SETTING_TRACE_BEGIN;
396         setting_main_appdata *ad = data;
397
398         /* A. add system event callback */
399         appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, setting_main_lang_changed_cb, ad);
400         appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, setting_main_region_changed_cb, ad);
401
402         return FALSE;
403 }
404
405 static int __setting_main_other_app_dead_cb(int pid, void *data)
406 {
407         SETTING_TRACE_BEGIN;
408         setting_retvm_if(NULL == data, -1, "data is NULL");
409         setting_main_appdata *ad = (setting_main_appdata *) data;
410
411         if (ad->isInUGMode && ad->ug) {
412                 bundle *b = NULL;
413                 b = bundle_create();
414                 setting_retvm_if(NULL == b, -1, "b is NULL");
415
416                 char pid_str[SETTING_MAX_PID_LEN] = {0,};
417                 snprintf(pid_str, SETTING_MAX_PID_LEN, "%d", pid);
418                 bundle_add(b, "DEADPID", pid_str);
419                 if (ug_send_message(ad->ug, b) != 0) {
420                         SETTING_TRACE_ERROR("call ug_send_message fail");
421                 }
422                 bundle_free(b);
423         }
424         return 0;
425 }
426
427 /**
428 * The function is called to create Setting view widgets
429 */
430 static int setting_main_app_create(void *data)
431 {
432         SETTING_TRACE_BEGIN;
433
434         ewk_init();
435
436         setting_main_appdata *ad = data;
437
438         ad->data_roaming_popup = NULL;
439
440         /* create window */
441         ad->win_main = setting_main_create_win(SETTING_PACKAGE);
442         setting_retvm_if(ad->win_main == NULL, SETTING_RETURN_FAIL, "window is null");
443         evas_object_show(ad->win_main);
444         UG_INIT_EFL(ad->win_main, UG_OPT_INDICATOR_ENABLE);
445         ad->evas = evas_object_evas_get(ad->win_main);
446
447         /* load config file */
448         int cfg_operation_ret = setting_cfg_init();
449
450         elm_theme_extension_add(NULL, SETTING_THEME_EDJ_NAME);
451
452         elm_win_indicator_mode_set(ad->win_main, ELM_WIN_INDICATOR_SHOW);
453
454         setting_view_create(&setting_view_main, ad);
455         setting_view_node_table_register(&setting_view_main, NULL);
456         setting_view_node_table_register(&setting_view_more_menu,
457                                          &setting_view_main);
458
459         /* error handling */
460         if (Cfg_Error_Type_Sucess != cfg_operation_ret) {
461                 SETTING_TRACE_ERROR("cfg_operation_ret: %d", cfg_operation_ret);
462                 const char *notifyStr = NULL;
463                 switch (cfg_operation_ret) {
464
465                 case Cfg_Error_Type_CreateCfg_Failed:
466                         {
467                                 notifyStr = _("failed to create config file, <br>re-install org.tizen.setting please");
468                                 break;
469                         }
470                 case Cfg_Error_Type_Mkdir_Failed:
471                         {
472                                 notifyStr = _("file system missed<br>/opt/data/setting, <br>re-install org.tizen.setting please");
473                                 break;
474                         }
475                 case Cfg_Error_Type_RemoveCfg_Failed:
476                         {
477                                 notifyStr = _("config file size 0 byte<br>and failed to re-create it.<br>try to startup the app again");
478                                 break;
479                         }
480                 case Cfg_Error_Type_ReadCfg_Failed:
481                         {
482                                 notifyStr = _("failed to read config file, <br>try to startup the app again");
483                                 break;
484                         }
485                 case Cfg_Error_Type_DirPermissionDenied:
486                         {
487                                 notifyStr =
488                                     _("the dir of config file permission denied");
489                                 break;
490                         }
491                 case Cfg_Error_Type_FilePermissionDenied:
492                         {
493                                 notifyStr = _("config file permission denied");
494                                 break;
495                         }
496                 default:
497                         {
498                                 notifyStr = _("Invalid Result, try to startup the app again");
499                                 break;
500                         }
501                 }
502                 setting_create_popup_without_btn(ad, ad->win_main, (char *)notifyStr, NULL, NULL, 10);
503                 return SETTING_RETURN_FAIL;
504         }
505
506         aul_listen_app_dead_signal(__setting_main_other_app_dead_cb, ad);
507         ad->vk_events.listen = vconf_key_change_event_listen;
508         ad->vk_events.unlisten = vconf_key_change_event_unlisten;
509
510         return 0;
511 }
512
513 /**
514 * The function is called when Setting is terminated
515 */
516 static int setting_main_app_terminate(void *data)
517 {
518         SETTING_TRACE_BEGIN;
519         setting_main_appdata *ad = data;
520         setting_cfg_exit();
521
522         ug_destroy_all();
523         ad->ug = NULL;
524
525         SETTING_TRACE("%s*** SETTING APPLICATION CLOSED ***%s",
526                       SETTING_FONT_BGREEN, SETTING_FONT_BLACK);
527
528         ad->vk_events.unlisten(&(ad->vk_events), data);
529
530         setting_view_destroy(&setting_view_more_menu, ad);
531         setting_view_destroy(&setting_view_main, ad);
532         SETTING_TRACE("!!! After setting_view_destroy");
533         if (ad->win_main) {
534                 evas_object_del(ad->win_main);
535                 ad->win_main = NULL;
536         }
537
538         ewk_shutdown();
539         SETTING_TRACE_END;
540         return 0;
541 }
542
543 /**
544 * The function is called when Setting begins run in background from forground
545 */
546 static int setting_main_app_pause(void *data)
547 {
548         SETTING_TRACE_BEGIN;
549         setting_main_appdata *ad = data;
550
551         ad->bAppPause = EINA_TRUE;
552         if (ad->ug)
553                 ug_pause();
554
555         return 0;
556 }
557
558 /**
559 * The function is called when Setting begins run in forground from background
560 */
561 static int setting_main_app_resume(void *data)
562 {
563         SETTING_TRACE_BEGIN;
564         setting_main_appdata *ad = data;
565
566         if (ad->ug)
567                 ug_resume();
568
569         // update main genlist in resuming app.
570         ad->bAppPause = EINA_FALSE;
571         if(!ad->ug) {
572                 SETTING_TRACE("update main genlist in resuming app without UG");
573                 setting_update_gl_item(ad);
574         }
575
576         return 0;
577 }
578
579 /**
580 * The function is called by app-fwk after app_create. It always do the process which cost much time.
581 */
582 static int setting_main_app_reset(bundle *b, void *data)
583 {
584
585         SETTING_TRACE_BEGIN;
586         setting_main_appdata *ad = data;
587
588         ecore_idler_add(setting_on_idle_lazy, ad);
589
590         ad->vk_events.listen(&(ad->vk_events), data);
591
592         if (ad->win_main)
593                 elm_win_activate(ad->win_main);
594
595         return 0;
596 }
597
598 /**
599  * argv[1] != 0 --> Setting app UI
600  * argv[1] == 0 --> SMC test mode
601  */
602 int main(int argc, char *argv[])
603 {
604         int r = 0;
605         setting_main_appdata ad;
606
607         if (!isEmulBin()) {
608                 setenv("ELM_ENGINE", "gl", 1);
609         }
610
611         struct appcore_ops ops = {
612                 .create = setting_main_app_create,
613                 .terminate = setting_main_app_terminate,
614                 .pause = setting_main_app_pause,
615                 .resume = setting_main_app_resume,
616                 .reset = setting_main_app_reset,
617         };
618
619         memset(&ad, 0x0, sizeof(setting_main_appdata));
620         ops.data = &ad;
621
622         setting_main_lang_changed_cb(&ad);
623
624         ecore_main_loop_glib_integrate();
625         r = appcore_efl_main(SETTING_PACKAGE, &argc, &argv, &ops);
626         retv_if(r == -1, -1);
627
628         return 0;
629 }