cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=5fa78a44d883d539364221afc966d0c0e5efe515

commit 5fa78a44d883d539364221afc966d0c0e5efe515
Author: Cedric BAIL <cedric.b...@free.fr>
Date:   Thu Apr 25 15:51:19 2019 -0700

    elementary: move Fileselector to rely on Efl.FilterModel for filtering 
instead of custom logic.
    
    This simply a bit the logic of things, but more refactoring would be nice 
for this widget.
    
    Reviewed-by: SangHyeon Jade Lee <sh10233....@samsung.com>
    Differential Revision: https://phab.enlightenment.org/D8799
---
 src/lib/elementary/elc_fileselector.c | 373 +++++++++++++++++++---------------
 1 file changed, 208 insertions(+), 165 deletions(-)

diff --git a/src/lib/elementary/elc_fileselector.c 
b/src/lib/elementary/elc_fileselector.c
index 9283dc3190..4ebf9cc7e8 100644
--- a/src/lib/elementary/elc_fileselector.c
+++ b/src/lib/elementary/elc_fileselector.c
@@ -96,8 +96,6 @@ EFL_CALLBACKS_ARRAY_DEFINE(monitoring_callbacks,
                           { EFL_MODEL_EVENT_CHILD_ADDED, _resource_created },
                           { EFL_MODEL_EVENT_CHILD_REMOVED, _resource_deleted 
});
 
-static void _properties_changed(void *data, const Efl_Event *ev);
-
 static void
 _focus_chain_update(Eo *obj, Elm_Fileselector_Data *pd)
 {
@@ -194,16 +192,121 @@ _elm_fileselector_replace_model(Elm_Fileselector *fs, 
Elm_Fileselector_Data *sd,
      }
 }
 
+static const char *
+_io_path_get(Efl_Model *model)
+{
+   if (!model) return NULL;
+   if (efl_isa(model, EFL_IO_MODEL_CLASS)) return efl_io_model_path_get(model);
+   return _io_path_get(efl_ui_view_model_get(model));
+}
+
+static Eina_Bool
+_check_again(Eina_Value *fetch)
+{
+   Eina_Error err = 0;
+   char *str;
+
+   if (eina_value_type_get(fetch) != EINA_VALUE_TYPE_ERROR)
+     return EINA_FALSE;
+
+   eina_value_error_get(fetch, &err);
+   if (err == EAGAIN) return EINA_TRUE;
+
+   str = eina_value_to_string(fetch);
+   ERR("Unexpected error: '%s'.", str);
+   free(str);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_fetch_string_value(Efl_Model *child, const char *name, char **str)
+{
+   Eina_Value *fetch;
+   Eina_Bool r = EINA_FALSE;
+
+   *str = NULL;
+
+   fetch = efl_model_property_get(child, name);
+   if (_check_again(fetch)) goto on_error;
+
+   *str = eina_value_to_string(fetch);
+   r = EINA_TRUE;
+
+ on_error:
+   eina_value_free(fetch);
+   return r;
+}
+
+static Eina_Bool
+_fetch_bool_value(Efl_Model *child, const char *name, Eina_Bool *b)
+{
+   Eina_Value *fetch;
+   Eina_Bool r = EINA_FALSE;
+
+   fetch = efl_model_property_get(child, name);
+   if (_check_again(fetch)) goto on_error;
+   if (!eina_value_bool_get(fetch, b)) goto on_error;
+
+   r = EINA_TRUE;
+
+ on_error:
+   eina_value_free(fetch);
+   return r;
+}
+
+static Eina_Bool
+_fetch_double_value(Efl_Model *child, const char *name, double *d)
+{
+   Eina_Value convert = EINA_VALUE_EMPTY;
+   Eina_Value *fetch;
+   Eina_Bool r = EINA_FALSE;
+
+   fetch = efl_model_property_get(child, name);
+   if (_check_again(fetch)) goto on_error;
+   if (!eina_value_setup(&convert, EINA_VALUE_TYPE_DOUBLE))
+     goto on_error;
+   if (!eina_value_convert(fetch, &convert))
+     goto on_error;
+   if (!eina_value_double_get(&convert, d)) goto on_error;
+
+   r = EINA_TRUE;
+
+ on_error:
+   eina_value_flush(&convert);
+   eina_value_free(fetch);
+   return r;
+}
+
+static Eina_Bool
+_fetch_int64_value(Efl_Model *child, const char *name, int64_t *i)
+{
+   Eina_Value convert = EINA_VALUE_EMPTY;
+   Eina_Value *fetch;
+   Eina_Bool r = EINA_FALSE;
+
+   fetch = efl_model_property_get(child, name);
+   if (_check_again(fetch)) goto on_error;
+   if (!eina_value_setup(&convert, EINA_VALUE_TYPE_INT64))
+     goto on_error;
+   if (!eina_value_convert(fetch, &convert))
+     goto on_error;
+   if (!eina_value_int64_get(&convert, i)) goto on_error;
+
+   r = EINA_TRUE;
+
+ on_error:
+   eina_value_free(fetch);
+   return r;
+}
+
 /* final routine on deletion */
 static void
 _elm_fileselector_smart_del_do(Elm_Fileselector *fs, Elm_Fileselector_Data *sd)
 {
    Eo *child;
    EINA_LIST_FREE(sd->children, child)
-     {
-        efl_event_callback_del(child, EFL_MODEL_EVENT_PROPERTIES_CHANGED, 
_properties_changed, sd);
-        efl_unref(child);
-     }
+     efl_unref(child);
    _elm_fileselector_replace_model(fs, sd, NULL, NULL);
    efl_replace(&sd->prev_model, NULL);
    ecore_idler_del(sd->path_entry_idler);
@@ -536,6 +639,77 @@ _filter_child(Elm_Fileselector_Data* sd,
    return EINA_FALSE;
 }
 
+static Eina_Value
+_filter_do(Eo *child, void *data, const Eina_Value v EINA_UNUSED)
+{
+   Elm_Fileselector_Data* sd = data;
+   // FIXME: This could be only needed with ELM_FILESELECTOR_MIME_FILTER
+   char *mime_type = NULL;
+   char *filename = NULL;
+   char *path = NULL;
+   int64_t size = 0;
+   double mtime = 0;
+   Eina_Bool dir = EINA_FALSE;
+   Eina_Bool r = EINA_FALSE;
+
+   if (!_fetch_string_value(child, "path", &path) ||
+       !_fetch_string_value(child, "filename", &filename) ||
+       !_fetch_string_value(child, "mime_type", &mime_type) ||
+       !_fetch_double_value(child, "mtime", &mtime) ||
+       !_fetch_int64_value(child, "size", &size) ||
+       !_fetch_bool_value(child, "is_dir", &dir))
+     goto cleanup;
+
+   if (!path || !filename || !mime_type)
+    {
+       ERR("Wrong file info ('%s', '%s', '%s').", path, filename, mime_type);
+       goto cleanup;
+    }
+
+   if (!_filter_child(sd, path, filename, dir, mime_type))
+     goto cleanup;
+
+   r = EINA_TRUE;
+
+ cleanup:
+   free(mime_type);
+   free(filename);
+   free(path);
+
+   return eina_value_bool_init(r);
+}
+
+static void
+_filter_free(Eo *o, void *data EINA_UNUSED, const Eina_Future *dead_future 
EINA_UNUSED)
+{
+   efl_unref(o);
+}
+
+static Eina_Future *
+_filter_simple(void *data, Efl_Filter_Model *parent, Efl_Model *child)
+{
+   Elm_Fileselector_Data* sd = data;
+   Eina_Future *request[8];
+   Eina_Future *f;
+
+   request[0] = efl_model_property_ready_get(parent, "path");
+   request[1] = efl_model_property_ready_get(child, "path");
+   request[2] = efl_model_property_ready_get(child, "filename");
+   request[3] = efl_model_property_ready_get(child, "mime_type");
+   request[4] = efl_model_property_ready_get(child, "mtime");
+   request[5] = efl_model_property_ready_get(child, "size");
+   request[6] = efl_model_property_ready_get(child, "is_dir");
+   request[7] = EINA_FUTURE_SENTINEL;
+
+   f = eina_future_all_array(request);
+   f = efl_future_then(efl_ref(child), f,
+                       .success = _filter_do,
+                       .free = _filter_free,
+                       .data = sd);
+
+   return f;
+}
+
 static const char *
 _file_type(const char *a)
 {
@@ -706,106 +880,6 @@ _listing_request_cleanup(Listing_Request *lreq)
    free(lreq);
 }
 
-static Eina_Bool
-_check_again(Eina_Value *fetch)
-{
-   Eina_Error err = 0;
-   char *str;
-
-   if (eina_value_type_get(fetch) != EINA_VALUE_TYPE_ERROR)
-     return EINA_FALSE;
-
-   eina_value_error_get(fetch, &err);
-   if (err == EAGAIN) return EINA_TRUE;
-
-   str = eina_value_to_string(fetch);
-   ERR("Unexpected error: '%s'.", str);
-   free(str);
-
-   return EINA_TRUE;
-}
-
-static Eina_Bool
-_fetch_string_value(Efl_Model *child, const char *name, char **str)
-{
-   Eina_Value *fetch;
-   Eina_Bool r = EINA_FALSE;
-
-   *str = NULL;
-
-   fetch = efl_model_property_get(child, name);
-   if (_check_again(fetch)) goto on_error;
-
-   *str = eina_value_to_string(fetch);
-   r = EINA_TRUE;
-
- on_error:
-   eina_value_free(fetch);
-   return r;
-}
-
-static Eina_Bool
-_fetch_bool_value(Efl_Model *child, const char *name, Eina_Bool *b)
-{
-   Eina_Value *fetch;
-   Eina_Bool r = EINA_FALSE;
-
-   fetch = efl_model_property_get(child, name);
-   if (_check_again(fetch)) goto on_error;
-   if (!eina_value_bool_get(fetch, b)) goto on_error;
-
-   r = EINA_TRUE;
-
- on_error:
-   eina_value_free(fetch);
-   return r;
-}
-
-static Eina_Bool
-_fetch_double_value(Efl_Model *child, const char *name, double *d)
-{
-   Eina_Value convert = EINA_VALUE_EMPTY;
-   Eina_Value *fetch;
-   Eina_Bool r = EINA_FALSE;
-
-   fetch = efl_model_property_get(child, name);
-   if (_check_again(fetch)) goto on_error;
-   if (!eina_value_setup(&convert, EINA_VALUE_TYPE_DOUBLE))
-     goto on_error;
-   if (!eina_value_convert(fetch, &convert))
-     goto on_error;
-   if (!eina_value_double_get(&convert, d)) goto on_error;
-
-   r = EINA_TRUE;
-
- on_error:
-   eina_value_flush(&convert);
-   eina_value_free(fetch);
-   return r;
-}
-
-static Eina_Bool
-_fetch_int64_value(Efl_Model *child, const char *name, int64_t *i)
-{
-   Eina_Value convert = EINA_VALUE_EMPTY;
-   Eina_Value *fetch;
-   Eina_Bool r = EINA_FALSE;
-
-   fetch = efl_model_property_get(child, name);
-   if (_check_again(fetch)) goto on_error;
-   if (!eina_value_setup(&convert, EINA_VALUE_TYPE_INT64))
-     goto on_error;
-   if (!eina_value_convert(fetch, &convert))
-     goto on_error;
-   if (!eina_value_int64_get(&convert, i)) goto on_error;
-
-   r = EINA_TRUE;
-
- on_error:
-   eina_value_free(fetch);
-   return r;
-}
-
 static void
 _process_model(Elm_Fileselector_Data *sd, Efl_Model *child)
 {
@@ -826,7 +900,7 @@ _process_model(Elm_Fileselector_Data *sd, Efl_Model *child)
    // In case we are shutting down, there might be an error being gnerated
    if (!parent) return ;
 
-   // We should be good now
+   // We should be good now and already filtered
    if (!_fetch_string_value(parent, "path", &parent_path) ||
        !_fetch_string_value(child, "path", &path) ||
        !_fetch_string_value(child, "filename", &filename) ||
@@ -834,31 +908,6 @@ _process_model(Elm_Fileselector_Data *sd, Efl_Model *child)
        !_fetch_double_value(child, "mtime", &mtime) ||
        !_fetch_int64_value(child, "size", &size) ||
        !_fetch_bool_value(child, "is_dir", &dir))
-     {
-        Eina_Value *check_error = efl_model_property_get(child, "mtime");
-        Eina_Error err = EAGAIN;
-
-        if (eina_value_type_get(check_error) == EINA_VALUE_TYPE_ERROR)
-          {
-             // If the error is different from EAGAIN, we should definitively 
drop this one.
-             eina_value_error_get(check_error, &err);
-          }
-        // SETUP listener to retry fetching all data when ready
-        if (err == EAGAIN)
-          {
-             efl_event_callback_add(efl_ref(child), 
EFL_MODEL_EVENT_PROPERTIES_CHANGED, _properties_changed, sd);
-             sd->children = eina_list_append(sd->children, child);
-          }
-        goto cleanup;
-     }
-
-   if (!path || !filename || !mime_type)
-     {
-        ERR("Wrong file info ('%s', '%s', '%s').", path, filename, mime_type);
-        goto cleanup;
-     }
-
-   if (!_filter_child(sd, path, filename, dir, mime_type))
      goto cleanup;
 
    it_data = calloc(1, sizeof(Elm_Fileselector_Item_Data));
@@ -905,7 +954,7 @@ _process_model(Elm_Fileselector_Data *sd, Efl_Model *child)
    // Is this item selected
    if (sd->target && sd->target_ready)
      {
-        const char *target_path = efl_io_model_path_get(sd->target);
+        const char *target_path = _io_path_get(sd->target);
 
         if (!strcmp(it_data->path, target_path))
           {
@@ -923,18 +972,6 @@ _process_model(Elm_Fileselector_Data *sd, Efl_Model *child)
    free(parent_path);
 }
 
-static void
-_properties_changed(void *data, const Efl_Event *ev)
-{
-   Elm_Fileselector_Data *sd = data;
-   Efl_Model *child = ev->object;
-
-   sd->children = eina_list_remove(sd->children, child);
-   efl_event_callback_del(child, EFL_MODEL_EVENT_PROPERTIES_CHANGED, 
_properties_changed, sd);
-   _process_model(sd, child);
-   efl_unref(child);
-}
-
 static Eina_Value
 _process_children_cb(Eo *model EINA_UNUSED, void *data, const Eina_Value v)
 {
@@ -999,7 +1036,13 @@ _populate(Evas_Object *obj,
    lreq->sd = sd;
    lreq->parent_it = (parent_it ? efl_ref(parent_it) : NULL);
    lreq->obj = efl_ref(obj);
-   lreq->model = efl_ref(model);
+   if (efl_isa(model, EFL_FILTER_MODEL_CLASS))
+     model = efl_ui_view_model_get(model);
+
+   lreq->model = efl_add_ref(EFL_FILTER_MODEL_CLASS, obj,
+                             efl_ui_view_model_set(efl_added, model),
+                             efl_filter_model_filter_set(efl_added, sd, 
_filter_simple, NULL),
+                             efl_loop_model_volatile_make(efl_added));
    lreq->selected = (selected ? efl_ref(selected) : NULL);
    lreq->path = NULL;
    lreq->selected_path = NULL;
@@ -1034,11 +1077,11 @@ _populate(Evas_Object *obj,
 
    _signal_first(lreq);
 
-   if (efl_model_children_count_get(model))
+   if (efl_model_children_count_get(lreq->model))
      {
-        future = efl_model_children_slice_get(model, 0, 
efl_model_children_count_get(model));
+        future = efl_model_children_slice_get(lreq->model, 0, 
efl_model_children_count_get(model));
         future = efl_future_then(obj, future);
-        efl_future_then(model, future,
+        efl_future_then(lreq->model, future,
                         .success = _process_children_cb,
                         .error = _process_children_error,
                         .data = lreq);
@@ -1102,7 +1145,8 @@ _on_item_activated(void *data, const Efl_Event *event)
 
    if (!sd->double_tap_navigation) return;
 
-   efl_parent_set(it_data->model, data);
+   // Set the Efl.Io.Model parent to be the fileselector to prevent death when 
populate
+   efl_parent_set(efl_ui_view_model_get(it_data->model), data);
    _populate(data, it_data->model, NULL, NULL);
 }
 
@@ -1279,7 +1323,7 @@ _on_dir_up(void *data, const Efl_Event *event EINA_UNUSED)
 
    if (!efl_isa(parent, EFL_IO_MODEL_CLASS))
      {
-        const char *path = efl_io_model_path_get(sd->model);
+        const char *path = _io_path_get(sd->model);
         char dir[PATH_MAX] = "";
         char *r;
 
@@ -1345,7 +1389,7 @@ _ok(void *data, const Efl_Event *event EINA_UNUSED)
         else
           selection = eina_stringshare_printf("%s/%s", sd->path, name);
 
-        selected_model = efl_add_ref(efl_class_get(sd->model), fs,
+        selected_model = 
efl_add_ref(efl_class_get(efl_ui_view_model_get(sd->model)), fs,
                                      efl_event_callback_array_add(efl_added, 
noref_death(), NULL),
                                      efl_io_model_path_set(efl_added, 
selection));
 
@@ -1394,13 +1438,13 @@ _on_text_activated(void *data, const Efl_Event *event)
         _model_event_call(fs, ELM_FILESELECTOR_EVENT_SELECTED_INVALID,
                           ELM_FILESELECTOR_EVENT_SELECTED_INVALID->name, NULL, 
path);
 
-        elm_widget_part_text_set(event->object, NULL, 
efl_io_model_path_get(sd->model));
+        elm_widget_part_text_set(event->object, NULL, _io_path_get(sd->model));
         goto end;
      }
 
    if (!ecore_file_is_dir(path))
      {
-        model = efl_add_ref(efl_class_get(sd->model), fs,
+        model = efl_add_ref(efl_class_get(efl_ui_view_model_get(sd->model)), 
fs,
                             efl_io_model_path_set(efl_added, path),
                             efl_event_callback_array_add(efl_added, 
noref_death(), NULL));
 
@@ -1411,7 +1455,7 @@ _on_text_activated(void *data, const Efl_Event *event)
         dir = EINA_TRUE;
      }
 
-   parent = efl_add_ref(efl_class_get(sd->model), fs,
+   parent = efl_add_ref(efl_class_get(efl_ui_view_model_get(sd->model)), fs,
                         efl_io_model_path_set(efl_added, path),
                         efl_event_callback_array_add(efl_added, noref_death(), 
NULL));
    if (!parent) goto end;
@@ -1465,7 +1509,7 @@ _anchor_clicked(void *data, const Efl_Event *event)
 
    if (!sd->model) return;
 
-   model = efl_add_ref(efl_class_get(sd->model), fs,
+   model = efl_add_ref(efl_class_get(efl_ui_view_model_get(sd->model)), fs,
                        efl_event_callback_array_add(efl_added, noref_death(), 
NULL),
                        efl_io_model_path_set(efl_added, info->name));
    if (!model) return;
@@ -1581,9 +1625,7 @@ _resource_created_then(Eo *model EINA_UNUSED, void *data, 
const Eina_Value v)
    ELM_FILESELECTOR_DATA_GET(fs, sd);
 
    EINA_VALUE_ARRAY_FOREACH(&v, len, i, child)
-     {
-        _process_model(sd, child);
-     }
+     _process_model(sd, child);
 
    return v;
 }
@@ -1889,7 +1931,7 @@ _from_legacy_event_call(Elm_Fileselector *fs, 
Elm_Fileselector_Data *sd, const E
    if (!sd->model)
      model_cls = EFL_IO_MODEL_CLASS;
    else
-     model_cls = efl_class_get(sd->model);
+     model_cls = efl_class_get(efl_ui_view_model_get(sd->model));
 
    Efl_Model *model = efl_add_ref(model_cls, fs,
                                   efl_event_callback_array_add(efl_added, 
noref_death(), NULL),
@@ -2306,7 +2348,7 @@ _elm_fileselector_selected_get_internal(const Evas_Object 
*obj)
    if (!sd->path) return NULL;
    if (sd->target)
      {
-        return efl_io_model_path_get(sd->target);
+        return _io_path_get(sd->target);
      }
 
    Elm_Fileselector_Item_Data *it_data = _selected_item_data_get(sd);
@@ -2382,10 +2424,11 @@ _properties_ready(void *data, const Efl_Event *ev)
           if (!is_dir)
             {
                Efl_Model *parent;
-               const char *path = efl_io_model_path_get(ev->object);
+               const char *path = _io_path_get(ev->object);
                char *dir = ecore_file_dir_get(path);
 
-               parent = efl_add_ref(EFL_IO_MODEL_CLASS, obj, 
efl_io_model_path_set(efl_added, dir),
+               parent = efl_add_ref(EFL_IO_MODEL_CLASS, obj,
+                                    efl_io_model_path_set(efl_added, dir),
                                     efl_event_callback_array_add(efl_added, 
noref_death(), NULL));
                if (!parent)
                  {
@@ -2476,7 +2519,7 @@ 
_elm_fileselector_elm_interface_fileselector_selected_model_set(Eo *obj, Elm_Fil
           eina_value_error_get(value, &err);
           if (err != EAGAIN)
             {
-               ERR("Unexpected error '%s' when setting path '%s'.", 
eina_value_to_string(value), efl_io_model_path_get(pd->target));
+               ERR("Unexpected error '%s' when setting path '%s'.", 
eina_value_to_string(value), _io_path_get(pd->target));
                goto clean_up;
             }
 
@@ -2496,7 +2539,7 @@ 
_elm_fileselector_elm_interface_fileselector_selected_model_set(Eo *obj, Elm_Fil
     if (!dir)
       {
          Efl_Model *parent;
-         const char *path = efl_io_model_path_get(pd->target);
+         const char *path = _io_path_get(pd->target);
          char *d = ecore_file_dir_get(path);
 
          parent = efl_add_ref(EFL_IO_MODEL_CLASS, obj, 
efl_io_model_path_set(efl_added, d),

-- 


Reply via email to