summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuilherme Lepsch <lepsch@expertisesolutions.com.br>2015-03-24 17:50:11 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2015-09-03 23:06:06 -0300
commit7ea7beffb105a25a586dc6669231da36a160b156 (patch)
tree083ddcf1997d735fc749658712c6c385834731e5
parent01ef11eb56f73af38ba8a3e7f6a5fc2b31a7f53d (diff)
downloadelementary-devs/felipealmeida/elm_prefs.tar.gz
elm_prefs: EFL Data Model integrationdevs/felipealmeida/elm_prefs
-rw-r--r--src/examples/Makefile.am3
-rw-r--r--src/examples/prefs_example_04.c84
-rw-r--r--src/examples/prefs_example_04.epc49
-rw-r--r--src/lib/Elementary.h.in1
-rw-r--r--src/lib/elm_prefs.c436
-rw-r--r--src/lib/elm_prefs.eo55
-rw-r--r--src/lib/elm_prefs.h1
-rw-r--r--src/lib/elm_widget_prefs.h4
8 files changed, 538 insertions, 95 deletions
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 <elementary_config.h>
+#endif
+
+#include <Elementary.h>
+#include <Efl.h>
+#include <Eio.h>
+#include <eio_model.eo.h>
+
+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 <Efreet_Mime.h>
#include <Efreet_Trash.h>
#include <Ethumb_Client.h>
+#include <Eo.h>
#ifdef ELM_ELOCATION
#include <Elocation.h>
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 <Eo.h>
#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 <b>model</b> 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
+ <b>will be written back</b> 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;