From 7ea7beffb105a25a586dc6669231da36a160b156 Mon Sep 17 00:00:00 2001 From: Guilherme Lepsch Date: Tue, 24 Mar 2015 17:50:11 -0300 Subject: elm_prefs: EFL Data Model integration --- src/examples/Makefile.am | 3 + src/examples/prefs_example_04.c | 84 ++++++++ src/examples/prefs_example_04.epc | 49 +++++ src/lib/Elementary.h.in | 1 + src/lib/elm_prefs.c | 436 +++++++++++++++++++++++++++++--------- src/lib/elm_prefs.eo | 55 +++++ src/lib/elm_prefs.h | 1 + src/lib/elm_widget_prefs.h | 4 + 8 files changed, 538 insertions(+), 95 deletions(-) create mode 100644 src/examples/prefs_example_04.c create mode 100644 src/examples/prefs_example_04.epc diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am index bf969e385..87a004284 100644 --- a/src/examples/Makefile.am +++ b/src/examples/Makefile.am @@ -114,6 +114,7 @@ photocam_example_01.c \ prefs_example_01.c \ prefs_example_02.c \ prefs_example_03.c \ +prefs_example_04.c \ popup_example_01.c \ popup_example_02.c \ popup_example_03.c \ @@ -195,6 +196,7 @@ files_DATA += \ prefs_example_02.epb \ prefs_example_03.epb \ prefs_example_03.edj \ + prefs_example_04.epb \ theme_example.edj \ layout_example.edj\ codegen_example.edj \ @@ -292,6 +294,7 @@ photocam_example_01 \ prefs_example_01 \ prefs_example_02 \ prefs_example_03 \ +prefs_example_04 \ popup_example_01 \ popup_example_02 \ popup_example_03 \ diff --git a/src/examples/prefs_example_04.c b/src/examples/prefs_example_04.c new file mode 100644 index 000000000..94a3a23b9 --- /dev/null +++ b/src/examples/prefs_example_04.c @@ -0,0 +1,84 @@ +//Compile with: +//gcc -o prefs_example_04 prefs_example_04.c -g `pkg-config --cflags --libs elementary` + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +static void +_page_saved_cb(void *data, Evas_Object *obj, void *event_info) +{ + const char *page = event_info; + + printf("page %s was saved!\n", page); +} + +static void +_page_loaded_cb(void *data, Evas_Object *obj, void *event_info) +{ + const char *page = event_info; + + printf("page %s was loaded!\n", page); +} + +static void +_item_changed_cb(void *data, Evas_Object *obj, void *event_info) +{ + const char *item = event_info; + + printf("item %s was changed!\n", item); +} + +static Eina_Bool +_filter_cb(void *data EINA_UNUSED, + Eio_File *handler EINA_UNUSED, + const Eina_File_Direct_Info *info) +{ + if (info->type == EINA_FILE_DIR && + info->path[info->name_start] != '.') + return EINA_TRUE; + + return EINA_FALSE; +} + +EAPI_MAIN int +elm_main(int argc, char **argv) +{ + Evas_Object *win, *prefs; + + win = elm_win_util_standard_add("prefs", "Prefs Example 04"); + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + elm_win_autodel_set(win, EINA_TRUE); + + prefs = elm_prefs_add(win); + evas_object_size_hint_weight_set(prefs, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, prefs); + evas_object_show(prefs); + + evas_object_smart_callback_add(prefs, "page,saved", _page_saved_cb, NULL); + evas_object_smart_callback_add(prefs, "page,loaded", _page_loaded_cb, NULL); + evas_object_smart_callback_add(prefs, "item,changed", _item_changed_cb, win); + + Efl_Model_Base *model = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set("test")); + eo_do(model, eio_model_children_filter_set(_filter_cb, NULL)); + eo_do(model, efl_model_load()); + + elm_prefs_file_set(prefs, "prefs_example_04.epb", NULL); + eo_do(prefs, elm_obj_prefs_property_connect("path", "main:text"), + elm_obj_prefs_model_set(model)); + + evas_object_resize(win, 320, 320); + evas_object_show(win); + + elm_run(); + + eo_unref(model); + + return 0; +} +ELM_MAIN() diff --git a/src/examples/prefs_example_04.epc b/src/examples/prefs_example_04.epc new file mode 100644 index 000000000..881861904 --- /dev/null +++ b/src/examples/prefs_example_04.epc @@ -0,0 +1,49 @@ +collection +{ + page + { + name: "main"; + version: 1; + title: "Preferences Widget"; + subtitle: "Example 01"; + widget: "elm/vertical_box"; + + items { + + item { + name: "label"; + type: LABEL; + label: "Filename"; + } + + item { + name: "text"; + type: TEXT; + editable: 1; + + text { + placeholder: "test"; + default: "test"; + deny: "/"; + } + } + + item { + name: "sep"; + type: SEPARATOR; + } + + item { + name: "save"; + type: SAVE; + label: "Save"; + } + + item { + name: "reset"; + type: RESET; + label: "Reset"; + } + } + } +} diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index af3f1229f..cc93cf475 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -84,6 +84,7 @@ #include #include #include +#include #ifdef ELM_ELOCATION #include diff --git a/src/lib/elm_prefs.c b/src/lib/elm_prefs.c index 5b22fd416..c2dac4147 100644 --- a/src/lib/elm_prefs.c +++ b/src/lib/elm_prefs.c @@ -10,7 +10,7 @@ #include "elm_widget_prefs.h" #include "elm_prefs_edd.x" -#include "Eo.h" +#include #define MY_CLASS ELM_PREFS_CLASS @@ -40,10 +40,14 @@ static Eina_Hash *_elm_prefs_item_widgets_map = NULL; static Eina_Hash *_elm_prefs_item_type_widgets_map = NULL; static const Elm_Prefs_Item_Iface *_elm_prefs_item_default_widget = NULL; -static void _elm_prefs_values_get_default(Elm_Prefs_Page_Node *, - Eina_Bool); -static Eina_Bool _prefs_item_widget_value_from_self(Elm_Prefs_Item_Node *, - Eina_Bool); +static void _elm_prefs_values_get_default(Elm_Prefs_Page_Node *, Eina_Bool); +static Eina_Bool _prefs_item_widget_value_from_self(Elm_Prefs_Item_Node *, Eina_Bool); +static Eina_Bool _elm_prefs_value_get(Elm_Prefs_Data *, const char *, Eina_Value *); +static Eina_Bool _elm_prefs_value_set(Elm_Prefs_Data *, const char *, const Elm_Prefs_Item_Type, const Eina_Value *); +static void _elm_prefs_value_restore(Elm_Prefs_Data *, Elm_Prefs_Item_Node *, const char *); +static Eina_Bool _elm_prefs_item_changed(Eo *, Elm_Prefs_Data *, const char *); +static void _elm_prefs_values_get_user(Elm_Prefs_Data *, Elm_Prefs_Page_Node *); +static void _elm_prefs_values_fetch(Eo *, Elm_Prefs_Data *, Eina_Bool); EOLIAN static void _elm_prefs_evas_object_smart_add(Eo *obj, Elm_Prefs_Data *_pd EINA_UNUSED) @@ -245,19 +249,10 @@ _prefs_item_widget_value_from_data(Elm_Prefs_Data *sd, if (!_prefs_data_types_match(t, it->type)) { if (!_prefs_data_type_fix(it, value)) return EINA_FALSE; - else - { - Eina_Bool v_set; - - sd->changing_from_ui = EINA_TRUE; - v_set = elm_prefs_data_value_set(sd->prefs_data, - buf, it->type, value); - - sd->changing_from_ui = EINA_FALSE; - - if (!v_set) return EINA_FALSE; - } + // write-back the type fix only if prefs_data + if (sd->prefs_data && !_elm_prefs_value_set(sd, buf, it->type, value)) + return EINA_FALSE; } if (!it->available) @@ -362,35 +357,121 @@ _elm_prefs_item_list_node_by_name(Elm_Prefs_Data *sd, static void _prefs_data_item_changed_cb(void *cb_data, Elm_Prefs_Data_Event_Type type EINA_UNUSED, - Elm_Prefs_Data *prefs_data, + Elm_Prefs_Data *prefs_data EINA_UNUSED, void *event_info) { Elm_Prefs_Data_Event_Changed *evt = event_info; Eo *obj = cb_data; - Elm_Prefs_Item_Node *it; - Eina_Value value; ELM_PREFS_DATA_GET(obj, sd); if (sd->changing_from_ui) return; - it = _elm_prefs_item_node_by_name(sd, evt->key); - if (!it) return; + if (_elm_prefs_item_changed(obj, sd, evt->key)) + _elm_prefs_mark_as_dirty(obj); +} + +static Eina_Bool +_elm_prefs_item_changed(Eo *obj, + Elm_Prefs_Data *sd, + const char *key) +{ + Elm_Prefs_Item_Node *item = _elm_prefs_item_node_by_name(sd, key); + if (!item) return EINA_FALSE; - if (elm_prefs_data_value_get(prefs_data, evt->key, NULL, &value)) + if (sd->pending_change && strcmp(sd->pending_change, key) == 0) { - if (!_prefs_item_widget_value_from_data(sd, it, &value)) goto end; + free(sd->pending_change); + sd->pending_change = NULL; + return EINA_FALSE; + } - _elm_prefs_item_changed_report(obj, it); - _elm_prefs_mark_as_dirty(obj); + Eina_Value value; + if (!_elm_prefs_value_get(sd, key, &value)) + { + ERR("failed to fetch value from data after changed event: %s", key); + return EINA_FALSE; } - else - ERR("failed to fetch value from data after changed event"); -end: + Eina_Bool changed = _prefs_item_widget_value_from_data(sd, item, &value); + if (changed) + _elm_prefs_item_changed_report(obj, item); + eina_value_flush(&value); - return; + return changed; +} + +static Eina_Bool +_elm_prefs_properties_changed(Eo *obj, + Elm_Prefs_Data *sd, + const Eina_Array *properties) +{ + if (!properties) return EINA_FALSE; + + Eina_Bool changed = EINA_FALSE; + + size_t i; + const char *property; + Eina_Array_Iterator it; + EINA_ARRAY_ITER_NEXT(properties, i, property, it) + { + const char *key = eina_hash_find(sd->property_to_key, property); + if (!key) + key = property; + changed = _elm_prefs_item_changed(obj, sd, key) || changed; + } + + return changed; +} + +static Eina_Bool +_model_property_changed_cb(void *data, + Eo *model EINA_UNUSED, + const Eo_Event_Description *desc EINA_UNUSED, + void *event_info) +{ + const Efl_Model_Property_Event *evt = (Efl_Model_Property_Event*)event_info; + Eo *obj = (Eo*)data; + + ELM_PREFS_DATA_GET(obj, sd); + + Eina_Bool changed = _elm_prefs_properties_changed + (obj, sd, evt->changed_properties); + changed = _elm_prefs_properties_changed + (obj, sd, evt->invalidated_properties) || changed; + if (changed) + _elm_prefs_mark_as_dirty(obj); + + return EO_CALLBACK_CONTINUE; +} + +static Eina_Bool +_model_load_status_change_cb(void *data, + Eo *model EINA_UNUSED, + const Eo_Event_Description *desc EINA_UNUSED, + void *event_info) +{ + const Efl_Model_Load *load = (Efl_Model_Load*)event_info; + Eo *obj = (Eo*)data; + ELM_PREFS_DATA_GET(obj, sd); + + if ((load->status & EFL_MODEL_LOAD_STATUS_ERROR) && sd->pending_change) + { + Elm_Prefs_Item_Node *item = _elm_prefs_item_node_by_name(sd, sd->pending_change); + if (item) + _elm_prefs_value_restore(sd, item, sd->pending_change); + + free(sd->pending_change); + sd->pending_change = NULL; + return EO_CALLBACK_CONTINUE; + } + + Eina_Bool reset_values = !(load->status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES); + _elm_prefs_values_fetch(obj, sd, reset_values); + + return EO_CALLBACK_CONTINUE; } + static void _prefs_data_autosaved_cb(void *cb_data, Elm_Prefs_Data_Event_Type type EINA_UNUSED, @@ -446,6 +527,29 @@ _elm_prefs_data_cbs_del(Eo *obj) "prefs data handle"); } +static Eina_Bool +_elm_prefs_model_cbs_add(Eo *obj, Efl_Model_Base *model) +{ + eo_do(model, eo_event_callback_add(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, + _model_property_changed_cb, obj)); + eo_do(model, eo_event_callback_add(EFL_MODEL_BASE_EVENT_LOAD_STATUS, + _model_load_status_change_cb, obj)); + return EINA_TRUE; +} + +static void +_elm_prefs_model_cbs_del(Eo *obj) +{ + ELM_PREFS_DATA_GET(obj, sd); + + if (!sd->model) return; + + eo_do(sd->model, eo_event_callback_del(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, + _model_property_changed_cb, obj)); + eo_do(sd->model, eo_event_callback_del(EFL_MODEL_BASE_EVENT_LOAD_STATUS, + _model_load_status_change_cb, obj)); +} + EOLIAN static void _elm_prefs_evas_object_smart_del(Eo *obj, Elm_Prefs_Data *sd) { @@ -454,17 +558,24 @@ _elm_prefs_evas_object_smart_del(Eo *obj, Elm_Prefs_Data *sd) if (sd->saving_poller) ecore_poller_del(sd->saving_poller); _elm_prefs_data_cbs_del(obj); + _elm_prefs_model_cbs_del(obj); if (sd->root) { - elm_prefs_data_version_set(sd->prefs_data, sd->root->version); - - _elm_prefs_save(obj); + if (sd->prefs_data) + { + elm_prefs_data_version_set(sd->prefs_data, sd->root->version); + _elm_prefs_save(obj); + } _root_node_free(sd); } + eina_hash_free(sd->key_to_property); + eina_hash_free(sd->property_to_key); + free(sd->pending_change); if (sd->prefs_data) elm_prefs_data_unref(sd->prefs_data); + if (sd->model) eo_unref(sd->model); eina_stringshare_del(sd->file); eina_stringshare_del(sd->page); @@ -512,14 +623,16 @@ elm_prefs_add(Evas_Object *parent) return obj; } -EOLIAN static Eo * -_elm_prefs_eo_base_constructor(Eo *obj, Elm_Prefs_Data *_pd EINA_UNUSED) +EOLIAN static Eo* +_elm_prefs_eo_base_constructor(Eo *obj, Elm_Prefs_Data *pd) { obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor()); eo_do(obj, evas_obj_type_set(MY_CLASS_NAME_LEGACY), evas_obj_smart_callbacks_descriptions_set(_elm_prefs_smart_callbacks), elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_REDUNDANT_OBJECT)); + pd->key_to_property = eina_hash_string_superfast_new(free); + pd->property_to_key = eina_hash_string_superfast_new(free); return obj; } @@ -583,30 +696,12 @@ _item_changed_cb(Evas_Object *it_obj) if (it->w_impl->value_validate && !it->w_impl->value_validate(it->w_obj)) { - if (sd->prefs_data) - { - Eina_Value value; - - // Restoring to the last valid value. - if (!elm_prefs_data_value_get(sd->prefs_data, buf, NULL, &value)) - goto restore_fail; - if (!it->w_impl->value_set(it->w_obj, &value)) - { - eina_value_flush(&value); - goto restore_fail; - } - } - else - { - if (!_prefs_item_widget_value_from_self(it, EINA_FALSE)) - goto restore_fail; - } - + _elm_prefs_value_restore(sd, it, buf); return; } end: - if (sd->prefs_data) + if (sd->prefs_data || sd->model) { Eina_Value value; @@ -614,22 +709,14 @@ end: ERR("failed to fetch value from widget of item %s", buf); else { - sd->changing_from_ui = EINA_TRUE; - elm_prefs_data_value_set(sd->prefs_data, buf, it->type, &value); + _elm_prefs_value_set(sd, buf, it->type, &value); eina_value_flush(&value); - sd->changing_from_ui = EINA_FALSE; } } if (!sd->values_fetching) _elm_prefs_item_changed_report(it->prefs, it); _elm_prefs_mark_as_dirty(it->prefs); - - return; - -restore_fail: - ERR("failed to restore the last valid value from widget of item %s", - buf); } static Eina_Bool @@ -1061,26 +1148,18 @@ _elm_prefs_values_get_user(Elm_Prefs_Data *sd, EINA_LIST_FOREACH(p->items, l, it) { - Eina_Bool get_err = EINA_FALSE, set_err = EINA_FALSE; - if (it->type == ELM_PREFS_TYPE_PAGE) { Elm_Prefs_Page_Node *subp = it->subpage; - if (!elm_prefs_data_value_get - (sd->prefs_data, subp->name, NULL, &value)) + if (!_elm_prefs_value_get(sd, subp->name, &value)) { INF("failed to fetch value for item %s on user data, " "writing UI value back on it", it->name); if (eina_value_setup(&value, EINA_VALUE_TYPE_STRINGSHARE) && eina_value_set(&value, subp->name)) - { - sd->changing_from_ui = EINA_TRUE; - elm_prefs_data_value_set - (sd->prefs_data, subp->name, it->type, &value); - sd->changing_from_ui = EINA_FALSE; - } + _elm_prefs_value_set(sd, subp->name, it->type, &value); } _elm_prefs_values_get_user(sd, subp); @@ -1094,11 +1173,15 @@ _elm_prefs_values_get_user(Elm_Prefs_Data *sd, snprintf(buf, sizeof(buf), "%s:%s", p->name, it->name); - if (!elm_prefs_data_value_get(sd->prefs_data, buf, NULL, &value)) + Eina_Bool get_err = EINA_FALSE, set_err = EINA_FALSE; + if (!_elm_prefs_value_get(sd, buf, &value)) get_err = EINA_TRUE; else if (!_prefs_item_widget_value_from_data(sd, it, &value)) set_err = EINA_TRUE; + if (!get_err) + eina_value_flush(&value); + if (get_err || set_err) { if (get_err) @@ -1113,15 +1196,11 @@ _elm_prefs_values_get_user(Elm_Prefs_Data *sd, it->name); else { - sd->changing_from_ui = EINA_TRUE; - elm_prefs_data_value_set - (sd->prefs_data, buf, it->type, &value); - sd->changing_from_ui = EINA_FALSE; + _elm_prefs_value_set(sd, buf, it->type, &value); + eina_value_flush(&value); } } } - - eina_value_flush(&value); } } @@ -1193,6 +1272,12 @@ _elm_prefs_data_set(Eo *obj, Elm_Prefs_Data *sd, Elm_Prefs_Data *prefs_data) { if (!sd->root) return EINA_FALSE; + if (sd->model) + { + Eina_Bool ret = eo_do_ret(obj, ret, elm_obj_prefs_model_set(NULL)); + if (!ret) return EINA_FALSE; + } + if (prefs_data && !_elm_prefs_data_cbs_add(obj, prefs_data)) return EINA_FALSE; @@ -1205,23 +1290,14 @@ _elm_prefs_data_set(Eo *obj, Elm_Prefs_Data *sd, Elm_Prefs_Data *prefs_data) sd->prefs_data = prefs_data; - if (!sd->prefs_data) + Eina_Bool reset_values = EINA_TRUE; + if (sd->prefs_data) { - INF("resetting prefs to default values"); - _elm_prefs_values_get_default(sd->root, EINA_FALSE); - - goto end; + elm_prefs_data_ref(sd->prefs_data); + reset_values = EINA_FALSE; } - elm_prefs_data_ref(sd->prefs_data); - - sd->values_fetching = EINA_TRUE; - _elm_prefs_values_get_user(sd, sd->root); - sd->values_fetching = EINA_FALSE; - -end: - eo_do(obj, eo_event_callback_call - (ELM_PREFS_EVENT_PAGE_CHANGED, (char *)sd->root->name)); + _elm_prefs_values_fetch(obj, sd, reset_values); return EINA_TRUE; } @@ -1233,6 +1309,50 @@ _elm_prefs_data_get(Eo *obj EINA_UNUSED, Elm_Prefs_Data *sd) else return sd->prefs_data; } +EOLIAN static Eina_Bool +_elm_prefs_model_set(Eo *obj, Elm_Prefs_Data *sd, Efl_Model_Base *model) +{ + if (!sd->root) return EINA_FALSE; + + if (sd->prefs_data) + { + Eina_Bool ret = eo_do_ret(obj, ret, elm_obj_prefs_data_set(NULL)); + if (!ret) return EINA_FALSE; + } + + if (model && !_elm_prefs_model_cbs_add(obj, model)) + return EINA_FALSE; + + if (sd->model) + { + _elm_prefs_model_cbs_del(obj); + eo_unref(sd->model); + } + + sd->model = model; + + Eina_Bool reset_values = EINA_TRUE; + if (sd->model) + { + eo_ref(sd->model); + Efl_Model_Load_Status status; + eo_do(sd->model, status = efl_model_load_status_get()); + reset_values = !(status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES); + } + + _elm_prefs_values_fetch(obj, sd, reset_values); + return EINA_TRUE; +} + +EOLIAN static Efl_Model_Base* +_elm_prefs_model_get(const Eo *obj EINA_UNUSED, Elm_Prefs_Data *sd) +{ + if (!sd->root) + return NULL; + + return sd->model; +} + EOLIAN static void _elm_prefs_autosave_set(Eo *obj, Elm_Prefs_Data *_pd EINA_UNUSED, Eina_Bool autosave) { @@ -1890,4 +2010,130 @@ elm_prefs_file_get(const Eo *obj, const char **file, const char **page) return EINA_TRUE; } +static Eina_Bool +_elm_prefs_value_get(Elm_Prefs_Data *sd, const char *key, Eina_Value *value) +{ + const char *property = eina_hash_find(sd->key_to_property, key); + if (!property) + property = key; + + if (sd->prefs_data) + return elm_prefs_data_value_get(sd->prefs_data, property, NULL, value); + + if (sd->model) + { + Efl_Model_Load_Status status; + const Eina_Value *prop_value; + eo_do(sd->model, status = efl_model_property_get(property, &prop_value)); + if (EFL_MODEL_LOAD_STATUS_ERROR == status || !prop_value) + return EINA_FALSE; + + return eina_value_copy(prop_value, value); + } + + return EINA_FALSE; +} + +static Eina_Bool +_elm_prefs_value_set(Elm_Prefs_Data *sd, + const char *key, + const Elm_Prefs_Item_Type type, + const Eina_Value *value) +{ + const char *property = eina_hash_find(sd->key_to_property, key); + if (!property) + property = key; + + + Eina_Bool result = EINA_FALSE; + if (sd->prefs_data) + { + sd->changing_from_ui = EINA_TRUE; + result = elm_prefs_data_value_set(sd->prefs_data, property, type, value); + sd->changing_from_ui = EINA_FALSE; + } + else + if (sd->model) + { + sd->pending_change = strdup(key); + + // TODO: Convert the value + Efl_Model_Load_Status status; + eo_do(sd->model, status = efl_model_property_set(property, value)); + result = EFL_MODEL_LOAD_STATUS_ERROR != status; + + if (!result) + { + free(sd->pending_change); + sd->pending_change = NULL; + } + } + + return result; +} + +static void +_elm_prefs_value_restore(Elm_Prefs_Data *sd, + Elm_Prefs_Item_Node *it, + const char *key) +{ + if (sd->prefs_data || sd->model) + { + Eina_Value value; + + // Restoring to the last valid value. + if (!_elm_prefs_value_get(sd, key, &value)) + goto on_error; + + Eina_Bool ret = it->w_impl->value_set(it->w_obj, &value); + eina_value_flush(&value); + if (!ret) goto on_error; + } + else + { + if (!_prefs_item_widget_value_from_self(it, EINA_FALSE)) + goto on_error; + } + + return; + +on_error: + ERR("failed to restore the last valid value from widget of item %s", key); +} + +static void +_elm_prefs_property_connect(Eo *obj EINA_UNUSED, + Elm_Prefs_Data *sd, + const char *property, + const char *part) +{ + EINA_SAFETY_ON_NULL_RETURN(sd); + EINA_SAFETY_ON_NULL_RETURN(property); + EINA_SAFETY_ON_NULL_RETURN(part); + + free(eina_hash_set(sd->key_to_property, part, strdup(property))); + free(eina_hash_set(sd->property_to_key, property, strdup(part))); +} + +static void +_elm_prefs_values_fetch(Eo *obj, Elm_Prefs_Data *sd, Eina_Bool reset_values) +{ + if (reset_values) + { + INF("resetting prefs to default values"); + _elm_prefs_values_get_default(sd->root, EINA_FALSE); + } + else + { + elm_prefs_data_ref(sd->prefs_data); + + sd->values_fetching = EINA_TRUE; + _elm_prefs_values_get_user(sd, sd->root); + sd->values_fetching = EINA_FALSE; + } + + eo_do(obj, eo_event_callback_call + (ELM_PREFS_EVENT_PAGE_CHANGED, (char *)sd->root->name)); +} + #include "elm_prefs.eo.c" diff --git a/src/lib/elm_prefs.eo b/src/lib/elm_prefs.eo index fa507a907..80da1dc0b 100644 --- a/src/lib/elm_prefs.eo +++ b/src/lib/elm_prefs.eo @@ -60,6 +60,61 @@ class Elm.Prefs (Elm.Widget, Efl.File) autosave: bool; [[$true to save automatically, $false otherwise.]] } } + model_set { + [[Set user model for a given prefs widget + + Once a prefs widget is created, after elm_prefs_file_set() is + issued on it, all of its UI elements will get default values, when + declared on that file. To fetch an user's own, personal set of + those values, one gets to pair a model handle to the + prefs widget. This is what this call is intended for. + + Model property values from $model model with names matching the ones + present on the file passed on elm_prefs_file_set() to $model obj will + have their values applied to the respective UI elements of the + widget. + + When $model obj dies, the values of the elements declared on its + .epb file (the one set on elm_prefs_file_set()) marked as permanent + will be written back to $model model, if it is writable. + One is also able to make this writing event to take place + automatically after each UI element modification by using + elm_prefs_autosave_set(). + + Note: $model obj will keep a reference of its own for $model model, + but you should still unreference it by yourself, after the widget + is gone. + + see elm_prefs_model_get() + + @since 1.16]] + + return: bool; [[$true, on success, $false otherwise]] + params { + @in model: Efl.Model.Base*; [[A valid model handle]] + } + legacy: null; + } + model_get @const { + [[Get user model for a given prefs widget + + see elm_prefs_model_set() for more details + + @since 1.16]] + + return: Efl.Model.Base *; [[A pointer to the user model of a given prefs widget on success.]] + legacy: null; + } + property_connect { + [[Connect property + + @since 1.16]] + params { + @in property: const(char)*; [[Property name]] + @in part: const(char)*; [[Prefs page:item layout part]] + } + legacy: null; + } reset { [[Reset the values of a given prefs widget to a previous state. diff --git a/src/lib/elm_prefs.h b/src/lib/elm_prefs.h index 466065850..a43f73f41 100644 --- a/src/lib/elm_prefs.h +++ b/src/lib/elm_prefs.h @@ -71,6 +71,7 @@ * @li @ref prefs_example_01 * @li @ref prefs_example_02 * @li @ref prefs_example_03 + * @li @ref prefs_example_04 */ #include "elm_prefs_common.h" diff --git a/src/lib/elm_widget_prefs.h b/src/lib/elm_widget_prefs.h index 728ef3d6c..77960d93d 100644 --- a/src/lib/elm_widget_prefs.h +++ b/src/lib/elm_widget_prefs.h @@ -75,7 +75,11 @@ struct _Elm_Prefs_Data { Elm_Prefs_Page_Node *root; + Eina_Hash *key_to_property; + Eina_Hash *property_to_key; Elm_Prefs_Data *prefs_data; + Efl_Model_Base *model; + char *pending_change; const char *file; const char *page; -- cgit v1.2.1