From b02dd546a4ebda9d29a6c224cb1baf707656029c Mon Sep 17 00:00:00 2001 From: Gustavo Lima Chaves Date: Mon, 25 Oct 2010 13:08:19 +0000 Subject: [PATCH] Profile selection at Elementary config app. New heading for persistent profile changes/editions. SVN revision: 53868 --- legacy/elementary/src/bin/config.c | 254 +++++++++++++++++++++- legacy/elementary/src/lib/Elementary.h.in | 7 + legacy/elementary/src/lib/elm_config.c | 147 ++++++++++++- legacy/elementary/src/lib/elm_main.c | 97 +++++++++ legacy/elementary/src/lib/elm_priv.h | 4 + 5 files changed, 505 insertions(+), 4 deletions(-) diff --git a/legacy/elementary/src/bin/config.c b/legacy/elementary/src/bin/config.c index ee5e95bb7a..89ff8b9913 100644 --- a/legacy/elementary/src/bin/config.c +++ b/legacy/elementary/src/bin/config.c @@ -249,6 +249,21 @@ _cf_caches(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) _flip_to(data, "caches"); } +static void +_profile_use(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *li; + const char *selection; + + li = data; + selection = elm_list_item_data_get(elm_list_selected_item_get(li)); + + if (!strcmp(elm_profile_current_get(), selection)) + return; + + elm_profile_all_set(selection); +} + static void _theme_use(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { @@ -659,10 +674,247 @@ _status_config_fonts(Evas_Object *win, Evas_Object *holder) _unimplemented(win, holder, "fonts"); } +static void +_profiles_list_item_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + free(data); +} + +static void +_profiles_list_selected_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) +{ + const char *cur_profile = NULL; + Efreet_Desktop *desk = NULL; + char *pdir, buf[PATH_MAX]; + const char *sel_profile; + Eina_Bool cur_selected; + const char *prof_name; + Evas_Object *en; + + sel_profile = data; + if (!sel_profile) + return; + + cur_profile = elm_profile_current_get(); + cur_selected = !strcmp(cur_profile, sel_profile); + + elm_object_disabled_set(evas_object_data_get(obj, "prof_del_btn"), + cur_selected); + + /* TODO */ + /* e_config_dialog_changed_set(cfdata->cfd, !v); /\* just a flag to say */ + /* user selected */ + /* other profile */ + /* other than curr *\/ */ + + pdir = elm_profile_dir_get(sel_profile); + snprintf(buf, sizeof(buf), "%s/profile.desktop", pdir); + desk = efreet_desktop_new(buf); + + if ((desk) && (desk->name)) + prof_name = desk->name; + else + prof_name = cur_profile; + + snprintf(buf, sizeof(buf), "Selected profile: %s
", + prof_name); + elm_label_label_set(evas_object_data_get(obj, "prof_name_lbl"), buf); + + en = evas_object_data_get(obj, "prof_desc_entry"); + if (desk) + elm_scrolled_entry_entry_set(en, desk->comment); + else + elm_scrolled_entry_entry_set(en, "Unknown"); + + if (desk) + efreet_desktop_free(desk); +} + +static void +_profiles_list_fill(Evas_Object *l_widget, Eina_List *p_names) +{ + const char *cur_profile = NULL; + const char *profile; + void *sel_it = NULL; + + if (!p_names) + return; + + elm_list_clear(l_widget); + efreet_init(); + + cur_profile = elm_profile_current_get(); + + EINA_LIST_FREE(p_names, profile) + { + Efreet_Desktop *desk = NULL; + char buf[PATH_MAX], *pdir; + const char *label, *ext; + Evas_Object *ic; + Elm_List_Item *it; + + pdir = elm_profile_dir_get(profile); + snprintf(buf, sizeof(buf), "%s/profile.desktop", pdir); + + desk = efreet_desktop_new(buf); + label = profile; + + if ((desk) && (desk->name)) + label = desk->name; + + buf[0] = 0; + if (pdir) + snprintf(buf, sizeof(buf), "%s/icon.edj", pdir); + if ((desk) && (desk->icon) && (pdir)) + snprintf(buf, sizeof(buf), "%s/%s", pdir, desk->icon); + ic = elm_icon_add(l_widget); + + ext = strrchr(buf, '.'); + if (ext) + { + if (!strcmp(ext, ".edj")) + elm_icon_file_set(ic, buf, "icon"); + else + elm_icon_file_set(ic, buf, NULL); + } + + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, + 1, 1); + evas_object_show(ic); + + it = elm_list_item_append(l_widget, label, ic, NULL, + _profiles_list_selected_cb, strdup(profile)); + elm_list_item_del_cb_set(it, _profiles_list_item_del_cb); + if (cur_profile && !strcmp(profile, cur_profile)) + sel_it = it; + + if (pdir) + free(pdir); + free((void *)profile); + + if (desk) + efreet_desktop_free(desk); + } + + efreet_shutdown(); + + if (sel_it) + elm_list_item_selected_set(sel_it, EINA_TRUE); + elm_list_go(l_widget); +} + static void _status_config_profiles(Evas_Object *win, Evas_Object *holder) { - _unimplemented(win, holder, "profiles"); + Evas_Object *li, *bx, *fr_bx, *btn_bx, *fr, *lb, *en, *sp, *pd, *bt; + char buf[PATH_MAX]; + Eina_List *profs; + Evas *evas; + + bx = elm_box_add(win); + evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL); + + fr_bx = elm_box_add(win); + evas_object_size_hint_weight_set(fr_bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(fr_bx, EVAS_HINT_FILL, EVAS_HINT_FILL); + + fr = elm_frame_add(win); + elm_frame_label_set(fr, "Available Profiles"); + evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_frame_content_set(fr, fr_bx); + elm_box_pack_end(bx, fr); + evas_object_show(fr); + + li = elm_list_add(win); + evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL); + + profs = elm_profile_list_get(); + + evas_object_show(li); + elm_box_pack_end(fr_bx, li); + + lb = elm_label_add(win); + evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, 0.5); + + elm_label_label_set(lb, buf); + evas_object_show(lb); + + en = elm_scrolled_entry_add(win); + evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5); + evas_object_size_hint_min_set(en, 0, 60); + evas_object_show(en); + + evas_object_data_set(li, "prof_name_lbl", lb); + evas_object_data_set(li, "prof_desc_entry", en); + + elm_box_pack_end(fr_bx, lb); + elm_box_pack_end(fr_bx, en); + + ///////////////////////////////////////////// + sp = elm_separator_add(win); + elm_separator_horizontal_set(sp, EINA_TRUE); + evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5); + elm_box_pack_end(bx, sp); + evas_object_show(sp); + + pd = elm_frame_add(win); + elm_object_style_set(pd, "pad_medium"); + evas_object_size_hint_weight_set(pd, 0.0, 0.0); + evas_object_size_hint_align_set(pd, 0.5, 0.5); + elm_box_pack_end(bx, pd); + evas_object_show(pd); + + btn_bx = elm_box_add(win); + elm_box_horizontal_set(btn_bx, EINA_TRUE); + evas_object_size_hint_weight_set(btn_bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(btn_bx, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(btn_bx); + + bt = elm_button_add(win); + evas_object_smart_callback_add(bt, "clicked", _profile_use, li); + elm_button_label_set(bt, "Use profile"); + evas_object_size_hint_weight_set(bt, 0.0, 0.0); + evas_object_size_hint_align_set(bt, 0.5, 0.5); + elm_box_pack_end(btn_bx, bt); + evas_object_show(bt); + + bt = elm_button_add(win); + evas_object_smart_callback_add(bt, "clicked", NULL, NULL); /* TODO */ + elm_button_label_set(bt, "Delete profile"); + evas_object_size_hint_weight_set(bt, 0.0, 0.0); + evas_object_size_hint_align_set(bt, 0.5, 0.5); + elm_box_pack_end(btn_bx, bt); + evas_object_show(bt); + + evas_object_data_set(li, "prof_del_btn", bt); + + bt = elm_button_add(win); + evas_object_smart_callback_add(bt, "clicked", NULL, NULL); /* TODO */ + elm_button_label_set(bt, "Add new"); + evas_object_size_hint_weight_set(bt, 0.0, 0.0); + evas_object_size_hint_align_set(bt, 0.5, 0.5); + elm_box_pack_end(btn_bx, bt); + evas_object_show(bt); + + elm_frame_content_set(pd, btn_bx); + + evas = evas_object_evas_get(li); + evas_event_freeze(evas); + edje_freeze(); + + _profiles_list_fill(li, profs); + + edje_thaw(); + evas_event_thaw(evas); + + evas_object_data_set(win, "profiles", bx); + elm_table_pack(holder, bx, 0, 0, 1, 1); } static void diff --git a/legacy/elementary/src/lib/Elementary.h.in b/legacy/elementary/src/lib/Elementary.h.in index b7e22dee5c..df8f70bebb 100644 --- a/legacy/elementary/src/lib/Elementary.h.in +++ b/legacy/elementary/src/lib/Elementary.h.in @@ -330,6 +330,13 @@ extern "C" { EAPI double elm_scale_get(void); EAPI void elm_scale_set(double scale); EAPI void elm_scale_all_set(double scale); + + EAPI const char *elm_profile_current_get(void); + EAPI char *elm_profile_dir_get(const char *profile); + EAPI Eina_List *elm_profile_list_get(void); + EAPI void elm_profile_set(const char *profile); + EAPI void elm_profile_all_set(const char *profile); + EAPI Evas_Coord elm_finger_size_get(void); EAPI void elm_finger_size_set(Evas_Coord size); EAPI void elm_finger_size_all_set(Evas_Coord size); diff --git a/legacy/elementary/src/lib/elm_config.c b/legacy/elementary/src/lib/elm_config.c index f29d07eb1b..87ce3f736d 100644 --- a/legacy/elementary/src/lib/elm_config.c +++ b/legacy/elementary/src/lib/elm_config.c @@ -15,7 +15,7 @@ static Eet_Data_Descriptor *_config_edd = NULL; static void _desc_init(void); static void _desc_shutdown(void); -static void _profile_get(void); +static void _profile_fetch_from_conf(void); static void _config_free(void); static void _config_apply(void); static Elm_Config * _config_user_load(void); @@ -283,8 +283,125 @@ _desc_shutdown(void) _config_edd = NULL; } +static int _cb_sort_files(char *f1, char *f2) +{ + return strcmp(f1, f2); +} + +const char * +_elm_config_current_profile_get(void) +{ + return _elm_profile; +} + +char * +_elm_config_profile_dir_get(const char *prof) +{ + char buf[PATH_MAX]; + const char *home = NULL; + + home = getenv("HOME"); + if (!home) + home = "/"; + + snprintf(buf, sizeof(buf), "%s/.elementary/config/%s", home, prof); + + if (ecore_file_is_dir(buf)) + return strdup(buf); + + snprintf(buf, sizeof(buf), "%s/config/%s", _elm_data_dir, prof); + + if (ecore_file_is_dir(buf)) + return strdup(buf); + + return NULL; +} + +Eina_List * +_elm_config_profiles_list(void) +{ + const char *home = NULL; + Eina_List *flist = NULL; + char buf[PATH_MAX], *p; + Eina_List *files; + size_t len; + + home = getenv("HOME"); + if (!home) + home = "/"; + + len = eina_str_join_len(buf, sizeof(buf), '/', home, strlen(home), + ".elementary/config", + sizeof(".elementary/config") - 1); + + files = ecore_file_ls(buf); + + buf[len] = '/'; + len++; + + p = buf + len; + len = sizeof(buf) - len; + if (files) + { + char *file; + + files = eina_list_sort(files, 0, (Eina_Compare_Cb)_cb_sort_files); + EINA_LIST_FREE(files, file) + { + if (eina_strlcpy(p, file, len) >= len) + { + free(file); + continue; + } + if (ecore_file_is_dir(buf)) + flist = eina_list_append(flist, file); + else + free(file); + } + } + + len = eina_str_join_len(buf, sizeof(buf), '/', _elm_data_dir, + strlen(_elm_data_dir), "config", + sizeof("config") - 1); + + files = ecore_file_ls(buf); + + buf[len] = '/'; + len++; + + p = buf + len; + len = sizeof(buf) - len; + if (files) + { + char *file; + files = eina_list_sort(files, 0, (Eina_Compare_Cb)_cb_sort_files); + EINA_LIST_FREE(files, file) + { + if (eina_strlcpy(p, file, len) >= len) + { + free(file); + continue; + } + if (ecore_file_is_dir(buf)) + { + const Eina_List *l; + const char *tmp; + EINA_LIST_FOREACH(flist, l, tmp) + if (!strcmp(file, tmp)) break; + + if (!l) + flist = eina_list_append(flist, file); + else free(file); + } + else + free(file); + } + } + return flist; +} + static void -_profile_get(void) +_profile_fetch_from_conf(void) { Eet_File *ef = NULL; const char *home = NULL; @@ -691,7 +808,7 @@ void _elm_config_init(void) { _desc_init(); - _profile_get(); + _profile_fetch_from_conf(); _config_load(); _env_get(); _config_apply(); @@ -788,6 +905,30 @@ _elm_config_sub_init(void) _config_sub_apply(); } +/* TODO: dump old profile's entries to disk? keep default values, for + reset action? */ +void +_elm_config_profile_set(const char *profile) +{ + Eina_Bool changed = EINA_FALSE; + + if (_elm_profile) + { + if (strcmp(_elm_profile, profile)) + changed = 1; + free(_elm_profile); + } + _elm_profile = strdup(profile); + + if (changed) + { + _config_free(); + _config_load(); + _config_apply(); + _elm_rescale(); + } +} + void _elm_config_shutdown(void) { diff --git a/legacy/elementary/src/lib/elm_main.c b/legacy/elementary/src/lib/elm_main.c index 232342c654..4a7f3cee64 100644 --- a/legacy/elementary/src/lib/elm_main.c +++ b/legacy/elementary/src/lib/elm_main.c @@ -1198,6 +1198,103 @@ elm_scale_all_set(double scale) #endif } + +/** + * @defgroup Profile Elementary Profile + * + * Profiles are pre-set options that affect the whole look-and-feel of + * Elementary-based applications. There are, for example, profiles + * aimed at desktop computer applications and others aimed at mobile, + * touchscreen-based ones. You probably don't want to use the + * functions in this group unlees you're writing an elementary + * configuration manager. + */ + +/** + * Get Elementary's profile in use. + * + * This gets the global profile that is applied to all Elementary + * applications. + * + * @return The profile's name + * @ingroup Profile + */ +EAPI const char * +elm_profile_current_get(void) +{ + return _elm_config_current_profile_get(); +} + +/** + * Get an Elementary's profile directory path in the filesystem. + * + * @param profile The profile's name + * @return The profile's directory path. + * @ingroup Profile + * + * @note You must free() the return value after usage. + */ +EAPI char * +elm_profile_dir_get(const char *profile) +{ + return _elm_config_profile_dir_get(profile); +} + +/** + * Get Elementary's list of available profiles. + * + * @return The profiles list. + * @ingroup Profile + * + * @note You must free() the strings which came as list data after + * usage of the return value. Consider using the @c EINA_LIST_FREE() + * macro. + */ +EAPI Eina_List * +elm_profile_list_get(void) +{ + return _elm_config_profiles_list(); +} + +/** + * Set Elementary's profile. + * + * This sets the global profile that is applied to Elementary + * applications. Just the instance the call comes from will be + * affected. + * + * @param profile The profile's name + * @ingroup Scaling + * + */ +EAPI void +elm_profile_set(const char *profile) +{ + _elm_config_profile_set(profile); +} + +/** + * Set Elementary's profile. + * + * This sets the global profile that is applied to all Elementary + * applications. All running Elementary windows will be affected. + * + * @param profile The profile's name + * @ingroup Scaling + * + */ +EAPI void +elm_profile_all_set(const char *profile) +{ +#ifdef HAVE_ELEMENTARY_X + static Ecore_X_Atom atom = 0; + + if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_PROFILE"); + ecore_x_window_prop_string_set(ecore_x_window_root_first_get(), + atom, profile); +#endif +} + /** * @defgroup Fingers Fingers * diff --git a/legacy/elementary/src/lib/elm_priv.h b/legacy/elementary/src/lib/elm_priv.h index 1c8897dbcf..17755838c7 100644 --- a/legacy/elementary/src/lib/elm_priv.h +++ b/legacy/elementary/src/lib/elm_priv.h @@ -145,6 +145,10 @@ void _elm_rescale(void); void _elm_config_init(void); void _elm_config_sub_init(void); void _elm_config_shutdown(void); +const char *_elm_config_current_profile_get(void); +char *_elm_config_profile_dir_get(const char *prof); +Eina_List *_elm_config_profiles_list(void); +void _elm_config_profile_set(const char *profile); void elm_tooltip_theme(Elm_Tooltip *tt); void elm_object_sub_tooltip_content_cb_set(Evas_Object *eventarea, Evas_Object *owner, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb);