elm: Add support for Efl.Model in Elm.Fileselector
authorVitor Sousa <vitorsousasilva@gmail.com>
Mon, 6 Jun 2016 07:16:57 +0000 (04:16 -0300)
committerVitor Sousa <vitorsousasilva@gmail.com>
Mon, 6 Jun 2016 07:30:22 +0000 (04:30 -0300)
Elm.Interface.Fileselector now supports Efl.Model objects, allowing users
to work with paths from different data models.

Example of model attribution:

ELm_Fileselector *fs = eo_add(EFL_FILESELECTOR_CLASS, NULL);
Efl_Model *model = ...;
elm_interface_fileselector_model_set(fs, model, NULL);

src/lib/elementary/Elementary.h.in
src/lib/elementary/elc_fileselector.c
src/lib/elementary/elc_fileselector_button.c
src/lib/elementary/elc_fileselector_common.h
src/lib/elementary/elc_fileselector_entry.c
src/lib/elementary/elm_fileselector.eo
src/lib/elementary/elm_fileselector_button.eo
src/lib/elementary/elm_fileselector_entry.eo
src/lib/elementary/elm_interface_fileselector.eo
src/lib/elementary/elm_widget_fileselector.h
src/lib/elementary/elm_widget_fileselector_button.h

index 1afc39d..b4f4d44 100644 (file)
@@ -83,6 +83,7 @@
 #include <Efreet_Mime.h>
 #include <Efreet_Trash.h>
 #include <Ethumb_Client.h>
+#include <eio_model.h>
 
 #ifdef ELM_ELOCATION
 #include <Elocation.h>
index 00ecfb1..b7c9fcb 100644 (file)
 static Elm_Genlist_Item_Class *list_itc[ELM_FILE_LAST];
 static Elm_Gengrid_Item_Class *grid_itc[ELM_FILE_LAST];
 
-#define ELM_PRIV_FILESELECTOR_SIGNALS(cmd) \
-   cmd(SIG_ACTIVATED, "activated", "s") \
-   cmd(SIG_DIRECTORY_OPEN, "directory,open", "s") \
-   cmd(SIG_DONE, "done", "s") \
-   cmd(SIG_SELECTED, "selected", "s") \
-   cmd(SIG_SELECTED_INVALID, "selected,invalid", "s")
+static const char _text_activated_model_key[] = "__fs_text_activated_model";
+static const char _text_activated_path_key[] = "__fs_text_activated_path";
+static const char _selected_model_set_promise_owner_key[] = "__fs_selected_model_set_promise_owner";
+static const char _selected_model_set_model_key[] = "__fs_selected_model_set_model";
 
-ELM_PRIV_FILESELECTOR_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
+EAPI Eina_Error ELM_FILESELECTOR_ERROR_UNKNOWN = 0;
+EAPI Eina_Error ELM_FILESELECTOR_ERROR_INVALID_MODEL = 0;
+
+static const char ELM_FILESELECTOR_ERROR_UNKNOWN_STR[]           = "Unknown Error";
+static const char ELM_FILESELECTOR_ERROR_INVALID_MODEL_STR[]     = "Model not set";
 
 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
-   ELM_PRIV_FILESELECTOR_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC)
    {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
    {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
    {NULL, NULL}
 };
-#undef ELM_PRIV_FILESELECTOR_SIGNALS
 
 static Eina_Bool _key_action_select(Evas_Object *obj, const char *params);
 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params);
@@ -59,15 +59,52 @@ static const Elm_Action key_actions[] = {
 static Eina_Bool _ok(void *data, const Eo_Event *event);
 static Eina_Bool _canc(void *data, const Eo_Event *event);
 static Eina_Bool _on_dir_up(void *data, const Eo_Event *event);
-static void _populate(Evas_Object *obj, const char *path, Elm_Object_Item *parent_it, const char *selected);
+static void _populate(Evas_Object *obj, Efl_Model *model, Elm_Object_Item *parent_it, Efl_Model *selected);
+static Elm_Fileselector_Item_Data *_selected_item_data_get(Elm_Fileselector_Data *sd);
+
+static Eina_Bool _resource_created(void *, const Eo_Event *);
+static Eina_Bool _resource_deleted(void *, const Eo_Event *);
+static void _listing_request_cleanup(Listing_Request *);
+
+static void
+_model_free_eo_cb(void *data)
+{
+   Eo *eo = data;
+   eo_unref(eo);
+}
+
+static void
+_elm_fileselector_replace_model(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, Efl_Model *model, const char *path)
+{
+   if (sd->model)
+     {
+        eo_event_callback_del(sd->model, EFL_MODEL_EVENT_CHILD_ADDED, _resource_created, fs);
+        eo_event_callback_del(sd->model, EFL_MODEL_EVENT_CHILD_REMOVED, _resource_deleted, fs);
+        eo_unref(sd->model);
+     }
+
+   if (model && path)
+     {
+        sd->model = model ? eo_ref(model) : NULL;
+        eina_stringshare_replace(&sd->path, path);
+        eo_event_callback_add(sd->model, EFL_MODEL_EVENT_CHILD_ADDED, _resource_created, fs);
+        eo_event_callback_add(sd->model, EFL_MODEL_EVENT_CHILD_REMOVED, _resource_deleted, fs);
+        /* TODO: sub directory should be monitored for expand mode */
+     }
+   else
+     {
+        sd->model = NULL;
+        eina_stringshare_replace(&sd->path, NULL);
+     }
+}
 
 /* final routine on deletion */
 static void
-_elm_fileselector_smart_del_do(Elm_Fileselector_Data *sd)
+_elm_fileselector_smart_del_do(Elm_Fileselector *fs, Elm_Fileselector_Data *sd)
 {
-   eina_stringshare_del(sd->path);
-   eina_stringshare_del(sd->prev_path);
-   eina_stringshare_del(sd->selection);
+   _elm_fileselector_replace_model(fs, sd, NULL, NULL);
+   if (sd->prev_model)
+     eo_unref(sd->prev_model);
    free(ecore_idler_del(sd->populate_idler));
    ecore_idler_del(sd->path_entry_idler);
 
@@ -86,6 +123,30 @@ _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
    elm_widget_mirrored_set(sd->home_button, rtl);
 }
 
+static Eina_Bool
+_iterator_next_value_get(Eina_Iterator *it, void *res)
+{
+   Eina_Value *v = NULL;
+   if (eina_iterator_next(it, (void **)&v) && v)
+     {
+        eina_value_get(v, res);
+        return EINA_TRUE;
+     }
+   return EINA_FALSE;
+}
+
+static void
+_model_str_property_set(Efl_Model *model, const char *property_name, const char *property_value, Eina_Promise **promise)
+{
+   Eina_Value v;
+   eina_value_setup(&v, EINA_VALUE_TYPE_STRING);
+   eina_value_set(&v, property_value);
+
+   efl_model_property_set(model, property_name, &v, promise);
+
+   eina_value_flush(&v);
+}
+
 EOLIAN static Eina_Bool
 _elm_fileselector_elm_widget_theme_apply(Eo *obj, Elm_Fileselector_Data *sd)
 {
@@ -151,14 +212,15 @@ static Eina_Bool
 _key_action_backspace(Evas_Object *obj, const char *params EINA_UNUSED)
 {
    ELM_FILESELECTOR_DATA_GET(obj, sd);
-   if (sd->prev_path)
-     _populate(obj, sd->prev_path, NULL, NULL);
+   if (sd->prev_model)
+     {
+        _populate(obj, sd->prev_model, NULL, NULL);
+        eo_unref(sd->prev_model);
+        sd->prev_model = NULL;
+     }
    else
      _on_dir_up(obj, NULL);
 
-   eina_stringshare_del(sd->prev_path);
-   sd->prev_path = NULL;
-
    return EINA_TRUE;
 }
 
@@ -184,8 +246,9 @@ _itc_text_get(void *data,
               Evas_Object *obj   EINA_UNUSED,
               const char *source EINA_UNUSED)
 {
+   Elm_Fileselector_Item_Data *it_data = data;
    return elm_entry_utf8_to_markup
-            (ecore_file_file_get(data)); /* NOTE this will be free()'d by
+            (it_data->filename);        /* NOTE this will be free()'d by
                                           * the caller */
 }
 
@@ -220,7 +283,7 @@ _itc_icon_image_get(void *data,
                     Evas_Object *obj,
                     const char *source)
 {
-   const char *filename = data;
+   Elm_Fileselector_Item_Data *it_data = data;
    Evas_Object *ic, *grid, *f;
 
    if (strcmp(source, "elm.swallow.icon")) return NULL;
@@ -230,7 +293,8 @@ _itc_icon_image_get(void *data,
 
    ic = elm_icon_add(obj);
    elm_icon_standard_set(ic, "image");
-   elm_icon_thumb_set(ic, filename, NULL);
+   // FIXME: maybe use Efl.Model.connect
+   elm_icon_thumb_set(ic, it_data->path, NULL);
    evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
    evas_object_show(ic);
 
@@ -281,7 +345,14 @@ static void
 _itc_del(void *data,
          Evas_Object *obj EINA_UNUSED)
 {
-   eina_stringshare_del(data);
+   Elm_Fileselector_Item_Data *it_data = data;
+   eo_unref(it_data->model);
+   eina_stringshare_del(it_data->path);
+   eina_stringshare_del(it_data->filename);
+   eina_stringshare_del(it_data->mime_type);
+   eo_unref(it_data->parent_model);
+   eina_stringshare_del(it_data->parent_path);
+   free(it_data);
 }
 
 static void
@@ -345,14 +416,9 @@ _mime_type_matched(const char *mime_filter, const char *mime_type)
 }
 
 static Eina_Bool
-_check_mime_type_filter(const Elm_Fileselector_Filter *filter,
-                        const char *file_name)
+_is_in_filter(const Elm_Fileselector_Filter *filter, const char *mime_type)
 {
-   const char *mime_type = NULL;
    int i;
-
-   mime_type = efreet_mime_type_get(file_name);
-
    if (!mime_type) return EINA_FALSE;
 
    for (i = 0; filter->filter.mime_types[i]; ++i)
@@ -364,23 +430,20 @@ _check_mime_type_filter(const Elm_Fileselector_Filter *filter,
 }
 
 static Eina_Bool
-_ls_filter_cb(void *data,
-              Eio_File *handler EINA_UNUSED,
-              const Eina_File_Direct_Info *info)
+_filter_child(Elm_Fileselector_Data* sd,
+              const char *path,
+              const char *filename,
+              Eina_Bool dir,
+              const char *mime_type)
 {
-   Listing_Request *lreq = data;
    Elm_Fileselector_Filter *cf;
-   Eina_Bool dir = EINA_FALSE;
    char *pch = NULL, *temp = NULL;
    char temp_path[EINA_PATH_MAX];
-   ELM_FILESELECTOR_DATA_GET(lreq->obj, sd);
 
    if (!sd) return EINA_FALSE;
-   if (!sd->hidden_visible && info->path[info->name_start] == '.')
-     return EINA_FALSE;
 
-   if (info->type == EINA_FILE_DIR)
-     dir = EINA_TRUE;
+   if (!sd->hidden_visible && filename[0] == '.')
+     return EINA_FALSE;
 
    if (sd->only_folder && !dir)
      return EINA_FALSE;
@@ -388,7 +451,7 @@ _ls_filter_cb(void *data,
    //Search entry filter
    if ((sd->search_string) && (sd->search_string[0] != '\0'))
      {
-        strcpy(temp_path, info->path);
+        strcpy(temp_path, path);
         pch = strchr(temp_path, '/');
         while (pch != NULL)
           {
@@ -408,9 +471,9 @@ _ls_filter_cb(void *data,
    switch (cf->filter_type)
      {
       case ELM_FILESELECTOR_MIME_FILTER:
-         return dir || _check_mime_type_filter(cf, info->path);
+         return dir || _is_in_filter(cf, mime_type);
       case ELM_FILESELECTOR_CUSTOM_FILTER:
-         return cf->filter.custom->func(info->path, dir,
+         return cf->filter.custom->func(path, dir,
                                         cf->filter.custom->data);
       default:
          return EINA_FALSE;
@@ -429,46 +492,52 @@ _file_type(const char *a)
 }
 
 static int
-_strcoll_rev(const char *a, const char *b)
+_filename_cmp(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b)
 {
-   return strcoll(b, a);
+   return strcoll(a->filename, b->filename);
 }
 
 static int
-_strcoll_type(const char *a, const char *b)
+_filename_cmp_rev(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b)
 {
-   return strcoll(_file_type(a), _file_type(b));
+   return _filename_cmp(b, a);
 }
 
 static int
-_strcoll_type_rev(const char *a, const char *b)
+_type_cmp(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b)
 {
-   return _strcoll_type(b, a);
+   return strcoll(_file_type(a->filename), _file_type(b->filename));
 }
 
 static int
-_size_cmp(const char *a, const char *b)
+_type_cmp_rev(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b)
 {
-   return ecore_file_size(a) - ecore_file_size(b);
+   return _type_cmp(b, a);
 }
 
 static int
-_size_cmp_rev(const char *a, const char *b)
+_size_cmp(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b)
+{
+   return a->size - b->size;
+}
+
+static int
+_size_cmp_rev(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b)
 {
    return _size_cmp(b, a);
 }
 
 static int
-_modified_cmp(const char *a, const char *b)
+_modified_cmp(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b)
 {
-   if (ecore_file_mod_time(a) > ecore_file_mod_time(b))
+   if (a->mtime > b->mtime)
      return 1;
 
    return -1;
 }
 
 static int
-_modified_cmp_rev(const char *a, const char *b)
+_modified_cmp_rev(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b)
 {
    return _modified_cmp(b, a);
 }
@@ -528,19 +597,20 @@ _file_list_cmp(const void *a, const void *b)
 static void
 _signal_first(Listing_Request *lreq)
 {
-   ELM_FILESELECTOR_DATA_GET(lreq->obj, sd);
-
+   Elm_Fileselector_Data *sd = lreq->sd;
    if (!lreq->first) return;
    if (!sd) return;
 
    if (sd->multi)
      {
-        char *path;
-        EINA_LIST_FREE(sd->paths, path) free(path);
+        sd->multi_selection = eina_list_free(sd->multi_selection);
      }
 
-   eo_event_callback_call
-     (lreq->obj, ELM_FILESELECTOR_EVENT_DIRECTORY_OPEN, (void *)lreq->path);
+   // EVENTS: should not call legacy
+   //eo_event_callback_call
+   //  (lreq->obj, ELM_FILESELECTOR_EVENT_DIRECTORY_OPEN, (void *)lreq->model);
+
+   evas_object_smart_callback_call(lreq->obj, "directory,open", (void *)lreq->path);
 
    if (!lreq->parent_it)
      {
@@ -548,7 +618,7 @@ _signal_first(Listing_Request *lreq)
           elm_genlist_clear(sd->files_view);
         else
           elm_gengrid_clear(sd->files_view);
-        eina_stringshare_replace(&sd->path, lreq->path);
+        _elm_fileselector_replace_model(lreq->obj, sd, lreq->model, lreq->path);
         _anchors_do(lreq->obj, lreq->path);
      }
 
@@ -556,139 +626,299 @@ _signal_first(Listing_Request *lreq)
 }
 
 static void
-_ls_main_cb(void *data,
-            Eio_File *handler,
-            const Eina_File_Direct_Info *info)
+_process_last(Listing_Request *lreq)
+{
+   Elm_Fileselector_Data *sd = lreq->sd;
+   elm_progressbar_pulse(sd->spinner, EINA_FALSE);
+   elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
+
+   _listing_request_cleanup(lreq);
+
+   sd->current_populate_lreq = NULL;
+}
+
+static Eina_Bool
+_process_child(Elm_Fileselector_Item_Data *it_data, Eina_Iterator *value_itt)
 {
-   Listing_Request *lreq = data;
    Elm_Object_Item *item;
+   Listing_Request *lreq = it_data->user_data;
    int itcn = ELM_FILE_UNKNOW;
-   ELM_FILESELECTOR_DATA_GET(lreq->obj, sd);
-   
-   if (eio_file_check(handler)) return;
-   if (!sd) return;
+   const char *path = NULL;
+   const char *filename = NULL;
+   const char *mime_type = NULL;
+   int64_t size = 0;
+   double mtime = 0;
+   Eina_Bool dir = EINA_FALSE;
+   Elm_Fileselector_Data *sd = lreq->sd;
+   it_data->user_data = NULL;
+
+   if (!sd->files_view)
+     return EINA_FALSE;
 
-   if (!sd->files_view || sd->current != handler)
+   if (!_iterator_next_value_get(value_itt, &path) ||
+       !_iterator_next_value_get(value_itt, &filename) ||
+       !path || !filename ||
+       !_iterator_next_value_get(value_itt, &dir) ||
+       !_iterator_next_value_get(value_itt, &size) ||
+       !_iterator_next_value_get(value_itt, &mtime) ||
+       !_iterator_next_value_get(value_itt, &mime_type))
      {
-        eio_file_cancel(handler);
-        return;
+        ERR("missing child Efl.Model data");
+        return EINA_FALSE;
      }
 
+   if (!_filter_child(sd, path, filename, dir, mime_type))
+     return EINA_FALSE;
+
    _signal_first(lreq);
 
-   if (info->type == EINA_FILE_DIR)
+   it_data->path = eina_stringshare_add(path);
+   it_data->filename = eina_stringshare_add(filename);
+   it_data->size = size;
+   it_data->mtime = mtime;
+   it_data->mime_type = eina_stringshare_add(mime_type);
+   it_data->parent_model = eo_ref(lreq->model);
+   it_data->parent_path = eina_stringshare_add(lreq->path);
+   it_data->is_dir = dir;
+
+   if (it_data->is_dir)
      itcn = ELM_DIRECTORY;
    else
      {
-        if (evas_object_image_extension_can_load_get
-              (info->path + info->name_start))
+        if (evas_object_image_extension_can_load_get(it_data->filename))
           itcn = ELM_FILE_IMAGE;
      }
 
    if (sd->mode == ELM_FILESELECTOR_LIST)
      {
         item = elm_genlist_item_sorted_insert(sd->files_view, list_itc[itcn],
-                                              eina_stringshare_add(info->path),
+                                              it_data,
                                               lreq->parent_it,
                                               ((sd->expand) && (itcn == ELM_DIRECTORY))
                                               ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
                                               _file_list_cmp, NULL, NULL);
 
-        if (lreq->selected && !strcmp(info->path, lreq->selected))
+        if (lreq->selected_path && it_data->path == lreq->selected_path)
           {
              elm_genlist_item_selected_set(item, EINA_TRUE);
-             elm_object_text_set(sd->name_entry, ecore_file_file_get(info->path));
+             elm_object_text_set(sd->name_entry, it_data->filename);
           }
      }
    else if (sd->mode == ELM_FILESELECTOR_GRID)
      {
         item = elm_gengrid_item_sorted_insert(sd->files_view, grid_itc[itcn],
-                                              eina_stringshare_add(info->path),
+                                              it_data,
                                               _file_grid_cmp, NULL, NULL);
 
-        if (lreq->selected && !strcmp(info->path, lreq->selected))
+        if (lreq->selected_path && it_data->path == lreq->selected_path)
           {
              elm_gengrid_item_selected_set(item, EINA_TRUE);
-             elm_object_text_set(sd->name_entry, ecore_file_file_get(info->path));
+             elm_object_text_set(sd->name_entry, it_data->filename);
           }
      }
+   return EINA_TRUE;
+}
+
+static void
+_process_child_cb(void *data, void *values)
+{
+   Elm_Fileselector_Item_Data *it_data = data;
+   Listing_Request *lreq = it_data->user_data;
+   Eina_Iterator *value_itt = values;
+
+   if (!lreq->valid ||
+       !_process_child(it_data, value_itt))
+     {
+        eo_unref(it_data->model);
+        free(it_data);
+     }
+
+   ++(lreq->item_processed_count);
+   if (lreq->item_processed_count >= lreq->item_total)
+     {
+        if (!lreq->valid)
+          {
+             _listing_request_cleanup(lreq);
+             return;
+          }
+        _signal_first(lreq);
+        _process_last(lreq);
+     }
+}
+
+static void
+_process_child_error_cb(void *data, Eina_Error err EINA_UNUSED)
+{
+   Elm_Fileselector_Item_Data *it_data = data;
+   Listing_Request *lreq = it_data->user_data;
+
+   eo_unref(it_data->model);
+   free(it_data);
+
+   WRN("could not get data from child Efl.Model");
+
+   ++(lreq->item_processed_count);
+   if (lreq->item_processed_count >= lreq->item_total)
+     {
+        if (!lreq->valid)
+          {
+             _listing_request_cleanup(lreq);
+             return;
+          }
+        _signal_first(lreq);
+        _process_last(lreq);
+     }
 }
 
 static void
 _listing_request_cleanup(Listing_Request *lreq)
 {
+   if (lreq->parent_it)
+     eo_unref(lreq->parent_it);
+   eo_unref(lreq->obj);
+   eo_unref(lreq->model);
+   if (lreq->selected)
+     eo_unref(lreq->selected);
    eina_stringshare_del(lreq->path);
-   eina_stringshare_del(lreq->selected);
+   eina_stringshare_del(lreq->selected_path);
    free(lreq);
 }
 
 static void
-_ls_done_cb(void *data, Eio_File *handler EINA_UNUSED)
+_process_children_cb(void *data, void *values)
 {
    Listing_Request *lreq = data;
-   ELM_FILESELECTOR_DATA_GET(lreq->obj, sd);
+   Eina_Iterator *value_itt = values;
+   Eina_Accessor *children_accessor = NULL;
+   Elm_Fileselector_Item_Data *it_data = NULL;
+   const char *path = NULL;
+   const char *selected_path = NULL;
+   void *child = NULL;
+   unsigned int i = 0;
+   Elm_Fileselector_Data *sd = lreq->sd;
+
+   if (!lreq->valid)
+     {
+        _listing_request_cleanup(lreq);
+        return;
+     }
 
-   _signal_first(lreq);
-   if (sd)
+   if (_iterator_next_value_get(value_itt, &path) &&
+       eina_iterator_next(value_itt, (void **)&children_accessor) &&
+       path)
+   {
+        if (lreq->selected)
+          {
+             if (!_iterator_next_value_get(value_itt, &selected_path) ||
+                 !selected_path)
+               {
+                  ERR("missing selected Efl.Model path information");
+                  _listing_request_cleanup(lreq);
+                  sd->current_populate_lreq = NULL;
+                  return;
+               }
+             lreq->selected_path = eina_stringshare_add(selected_path);
+          }
+        lreq->path = eina_stringshare_add(path);
+        if (children_accessor)
+          {
+             EINA_ACCESSOR_FOREACH(children_accessor, i, child)
+               {
+                  Eina_Promise *promises[7] = {NULL,};
+                  Eina_Promise *promise_all = NULL;
+                  it_data = calloc(1, sizeof(Elm_Fileselector_Item_Data));
+                  if (!it_data)
+                    {
+                       ERR("insufficient memory");
+                       break;
+                    }
+
+                  it_data->model = eo_ref(child);
+                  it_data->user_data = lreq;
+
+                  efl_model_property_get(child, "path", &promises[0]);
+                  efl_model_property_get(child, "filename", &promises[1]);
+                  efl_model_property_get(child, "is_dir", &promises[2]);
+                  efl_model_property_get(child, "size", &promises[3]);
+                  efl_model_property_get(child, "mtime", &promises[4]);
+                  efl_model_property_get(child, "mime_type", &promises[5]);
+
+                  promise_all = eina_promise_all(eina_carray_iterator_new((void**)promises));
+                  ++(lreq->item_total);
+                  eina_promise_then(promise_all, _process_child_cb, _process_child_error_cb, it_data);
+               }
+          }
+        if (lreq->item_total == 0)
+          {
+             _signal_first(lreq);
+             _process_last(lreq);
+          }
+     }
+   else
      {
-        elm_progressbar_pulse(sd->spinner, EINA_FALSE);
-        elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
-        sd->current = NULL;
+        ERR("missing Efl.Model information");
+        _listing_request_cleanup(lreq);
+        sd->current_populate_lreq = NULL;
      }
-
-   _listing_request_cleanup(lreq);
 }
 
 static void
-_ls_error_cb(void *data, Eio_File *handler, int error EINA_UNUSED)
+_process_children_error_cb(void *data, Eina_Error error)
 {
    Listing_Request *lreq = data;
-   ELM_FILESELECTOR_DATA_GET(lreq->obj, sd);
+   Elm_Fileselector_Data *sd = lreq->sd;
+
+   if (error != EINA_ERROR_PROMISE_CANCEL)
+     {
+        ERR("failed to get information from Efl.Model");
+     }
 
-   if (sd)
+   if (lreq->valid)
      {
         elm_progressbar_pulse(sd->spinner, EINA_FALSE);
         elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
-        if (sd->current == handler) sd->current = NULL;
+        sd->current_populate_lreq = NULL;
      }
    _listing_request_cleanup(lreq);
 }
 
 static void
 _populate(Evas_Object *obj,
-          const char *path,
+          Efl_Model *model,
           Elm_Object_Item *parent_it,
-          const char *selected)
+          Efl_Model *selected)
 {
    ELM_FILESELECTOR_DATA_GET(obj, sd);
-   if (!path) return;
+   if (!model) return;
 
    Listing_Request *lreq;
 
-   if (sd->expand && sd->current) return;
+   if (sd->expand && sd->current_populate_lreq)
+     return;
 
-   if (sd->monitor) eio_monitor_del(sd->monitor);
-   if (sd->current) eio_file_cancel(sd->current);
-   sd->monitor = NULL;
-   sd->current = NULL;
+   if (sd->current_populate_lreq)
+     {
+        sd->current_populate_lreq->valid = EINA_FALSE;
+        sd->current_populate_lreq = NULL;
+     }
 
-   lreq = malloc(sizeof (Listing_Request));
+   lreq = calloc(1, sizeof (Listing_Request));
    if (!lreq) return;
 
-   lreq->parent_it = parent_it; /* FIXME: should we refcount the parent_it ? */
-   lreq->obj = obj;
-   lreq->path = eina_stringshare_add(path);
+   lreq->sd = sd;
+   lreq->parent_it = (parent_it ? eo_ref(parent_it) : NULL);
+   lreq->obj = eo_ref(obj);
+   lreq->model = eo_ref(model);
+   lreq->selected = (selected ? eo_ref(selected) : NULL);
+   lreq->path = NULL;
+   lreq->selected_path = NULL;
+   lreq->item_total = 0;
+   lreq->item_processed_count = 0;
    lreq->first = EINA_TRUE;
+   lreq->valid = EINA_TRUE;
 
-   if (selected)
-     lreq->selected = eina_stringshare_add(selected);
-   else
-     lreq->selected = NULL;
+   sd->current_populate_lreq = lreq;
 
-   /* TODO: sub directory should be monitored for expand mode */
-   sd->monitor = eio_monitor_add(path);
-   sd->current = eio_file_stat_ls(path, _ls_filter_cb, _ls_main_cb,
-                                  _ls_done_cb, _ls_error_cb, lreq);
    elm_progressbar_pulse(sd->spinner, EINA_TRUE);
    elm_layout_signal_emit(lreq->obj, "elm,action,spinner,show", "elm");
 
@@ -696,15 +926,24 @@ _populate(Evas_Object *obj,
    if (elm_object_disabled_get(sd->name_entry))
      elm_object_text_set(sd->name_entry, "");
 
+   Eina_Promise *promises[4] = {NULL,};
+   Eina_Promise *promise_all = NULL;
+   efl_model_property_get(model, "path", &promises[0]);
+   efl_model_children_slice_get(model, 0, 0, &promises[1]);
+   if (selected)
+     efl_model_property_get(selected, "path", &promises[2]);
+
+   promise_all = eina_promise_all(eina_carray_iterator_new((void**)&promises[0]));
+   eina_promise_then(promise_all, _process_children_cb, _process_children_error_cb, lreq);
 }
 
 static Eina_Bool
 _on_list_expanded(void *data, const Eo_Event *event)
 {
    Elm_Object_Item *it = event->info;
-   const char *path = elm_object_item_data_get(it);
+   const Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(it);
 
-   _populate(data, path, it, NULL);
+   _populate(data, it_data->model, it, NULL);
 
    return EINA_TRUE;
 }
@@ -744,10 +983,11 @@ _populate_do(void *data)
 {
    struct sel_data *sdata = data;
    ELM_FILESELECTOR_DATA_GET(sdata->fs, sd);
-
-   _populate(sdata->fs, sdata->path, NULL, sdata->selected);
-   eina_stringshare_del(sdata->path);
-   eina_stringshare_del(sdata->selected);
+   _populate(sdata->fs, sdata->model, NULL, sdata->selected);
+   if (sdata->model)
+     eo_unref(sdata->model);
+   if (sdata->selected)
+     eo_unref(sdata->selected);
 
    sd->populate_idler = NULL;
 
@@ -758,23 +998,28 @@ _populate_do(void *data)
 static void
 _schedule_populate(Evas_Object *fs,
                    Elm_Fileselector_Data *sd,
-                   Eina_Stringshare *path,
-                   Eina_Stringshare *selected)
+                   Efl_Model *model,
+                   Efl_Model *selected)
 {
    struct sel_data *sdata;
-   sdata = malloc(sizeof(*sdata));
+   sdata = calloc(1, sizeof(*sdata));
    if (!sdata) return;
 
    sdata->fs = fs;
-   sdata->path = path;
+   sdata->model = model;
    sdata->selected = selected;
 
+   if (model) eo_ref(model);
+   if (selected) eo_ref(selected);
+
    if (sd->populate_idler)
      {
         struct sel_data *old_sdata;
         old_sdata = ecore_idler_del(sd->populate_idler);
-        eina_stringshare_del(old_sdata->path);
-        eina_stringshare_del(old_sdata->selected);
+        if (old_sdata->model)
+          eo_unref(old_sdata->model);
+        if (old_sdata->selected)
+          eo_unref(old_sdata->selected);
         free(old_sdata);
      }
    sd->populate_idler = ecore_idler_add(_populate_do, sdata);
@@ -785,25 +1030,25 @@ _on_item_activated(void *data, const Eo_Event *event)
 {
    //This event_info could be a list or gengrid item
    Elm_Object_Item *it = event->info;
-   const char *path;
-   Eina_Bool is_dir;
+   const Elm_Fileselector_Item_Data *it_data;
 
    ELM_FILESELECTOR_DATA_GET(data, sd);
 
-   path = elm_object_item_data_get(it);
-   if (!path) return EINA_TRUE;
+   it_data = elm_object_item_data_get(it);
+   if (!it_data) return EINA_TRUE;
 
-   is_dir = ecore_file_is_dir(path);
-   if (!is_dir)
+   if (!it_data->is_dir)
      {
-        eo_event_callback_call
-          (data, ELM_FILESELECTOR_EVENT_ACTIVATED, (void *)path);
+        // EVENTS: should not call legacy
+        //eo_event_callback_call
+        //  (data, ELM_FILESELECTOR_EVENT_ACTIVATED, (void *)it_data->model);
+        evas_object_smart_callback_call(data, "activated", (void *)it_data->path);
         return EINA_TRUE;
      }
 
    if (!sd->double_tap_navigation) return EINA_TRUE;
 
-   _schedule_populate(data, sd, eina_stringshare_add(path), NULL);
+   _schedule_populate(data, sd, it_data->model, NULL);
 
    return EINA_TRUE;
 }
@@ -841,26 +1086,22 @@ _on_item_selected(void *data, const Eo_Event *event)
 {
    //This event_info could be a list or gengrid item
    Elm_Object_Item *it = event->info;
-   const char *path;
-   char *parent_path;
-   Eina_Bool is_dir;
+   Elm_Fileselector_Item_Data *it_data = NULL;
 
    ELM_FILESELECTOR_DATA_GET(data, sd);
 
-   path = elm_object_item_data_get(it);
-   if (!path) return EINA_TRUE;
-
-   is_dir = ecore_file_is_dir(path);
+   it_data = elm_object_item_data_get(it);
+   if (!it_data) return EINA_TRUE;
 
    /* We need to send callback when:
     * - path is dir and mode is ONLY FOLDER
     * - path is file and mode is NOT ONLY FOLDER */
-   if (is_dir == sd->only_folder)
+   if (it_data->is_dir == sd->only_folder)
      {
         if (sd->multi)
           {
              Eina_List *li;
-             const char *p;
+             Elm_Object_Item *it2;
              Eina_Strbuf *buf;
 
              if (sd->dir_selected)
@@ -870,25 +1111,28 @@ _on_item_selected(void *data, const Eo_Event *event)
                }
 
              buf = eina_strbuf_new();
-             EINA_LIST_FOREACH(sd->paths, li, p)
+             EINA_LIST_FOREACH(sd->multi_selection, li, it2)
                {
-                  eina_strbuf_append(buf, ecore_file_file_get(p));
+                  Elm_Fileselector_Item_Data *it2_data = elm_object_item_data_get(it2);
+                  eina_strbuf_append(buf, it2_data->filename);
                   eina_strbuf_append_length(buf, ", ", 2);
                }
 
-             sd->paths = eina_list_append(sd->paths, strdup(path));
-             eina_strbuf_append(buf, ecore_file_file_get(path));
+             sd->multi_selection = eina_list_append(sd->multi_selection, it);
+             eina_strbuf_append(buf, it_data->filename);
 
              elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf));
              eina_strbuf_free(buf);
           }
         else
-          elm_object_text_set(sd->name_entry, ecore_file_file_get(path));
+          elm_object_text_set(sd->name_entry, it_data->filename);
 
-        eo_event_callback_call
-          (data, EVAS_SELECTABLE_INTERFACE_EVENT_SELECTED, (void *)path);
+        // EVENTS: should not call legacy
+        //eo_event_callback_call
+        //  (data, EVAS_SELECTABLE_INTERFACE_EVENT_SELECTED, (void *)it_data->model);
+        evas_object_smart_callback_call(data, "selected", (void *)it_data->path);
      }
-   else if (sd->multi && is_dir && sd->double_tap_navigation)
+   else if (sd->multi && it_data->is_dir && sd->double_tap_navigation)
      {
         _clear_selections(sd, it);
         sd->dir_selected = EINA_TRUE;
@@ -898,28 +1142,36 @@ _on_item_selected(void *data, const Eo_Event *event)
     * - mode is GRID;
     * - mode is LIST and 'not expand mode';
     *   in other cases update anchors. */
-   if (!is_dir) return EINA_TRUE;
 
    if (sd->expand && sd->mode == ELM_FILESELECTOR_LIST)
      {
+        if (!it_data->is_dir)
+          {
+             _elm_fileselector_replace_model(data, sd, it_data->parent_model, it_data->parent_path);
+             _anchors_do(data, it_data->parent_path);
+             return EINA_TRUE;
+          }
         if (sd->only_folder)
           {
-             parent_path = ecore_file_dir_get(path);
-             eina_stringshare_replace(&sd->path, parent_path);
-             _anchors_do(data, parent_path);
-             free(parent_path);
+             _elm_fileselector_replace_model(data, sd, it_data->parent_model, it_data->parent_path);
+             _anchors_do(data, it_data->parent_path);
           }
         else
           {
-             eina_stringshare_replace(&sd->path, path);
-             _anchors_do(data, path);
+             _elm_fileselector_replace_model(data, sd, it_data->model, it_data->path);
+             _anchors_do(data, it_data->path);
           }
+        // Clear name entry not in case of save mode.
+        if (elm_object_disabled_get(sd->name_entry))
+          elm_object_text_set(sd->name_entry, "");
         return EINA_TRUE;
      }
 
+   if (!it_data->is_dir) return EINA_TRUE;
+
    if (sd->double_tap_navigation) return EINA_TRUE;
 
-   _schedule_populate(data, sd, eina_stringshare_add(path), NULL);
+   _schedule_populate(data, sd, it_data->model, NULL);
 
    return EINA_TRUE;
 }
@@ -928,35 +1180,37 @@ static Eina_Bool
 _on_item_unselected(void *data, const Eo_Event *event)
 {
    Eina_List *li, *l;
-   char *path;
-   const char *unselected_path;
+   const Elm_Fileselector_Item_Data *it_data;
    Eina_Strbuf *buf;
    Elm_Object_Item *it = event->info;
+   Elm_Object_Item *it2 = NULL;
    Eina_Bool first = EINA_TRUE;
 
    ELM_FILESELECTOR_DATA_GET(data, sd);
 
    if (!sd->multi) return EINA_TRUE;
 
-   unselected_path = elm_object_item_data_get(it);
-   if (!unselected_path) return EINA_TRUE;
+   it_data = elm_object_item_data_get(it);
+   if (!it_data) return EINA_TRUE;
 
    buf = eina_strbuf_new();
-   EINA_LIST_FOREACH_SAFE(sd->paths, li, l, path)
+   EINA_LIST_FOREACH_SAFE(sd->multi_selection, li, l, it2)
      {
-        if (!strcmp(path, unselected_path))
+        if (it2 == it)
           {
-             sd->paths = eina_list_remove_list(sd->paths, li);
-             free(path);
+             sd->multi_selection = eina_list_remove_list(sd->multi_selection, li);
           }
         else
           {
+             Elm_Fileselector_Item_Data *it2_data = elm_object_item_data_get(it2);
+             if (!it2_data)
+               continue;
              if (!first)
                eina_strbuf_append_length(buf, ", ", 2);
              else
                first = EINA_FALSE;
 
-             eina_strbuf_append(buf, ecore_file_file_get(path));
+             eina_strbuf_append(buf, it2_data->path);
           }
      }
 
@@ -970,13 +1224,14 @@ static Eina_Bool
 _on_dir_up(void *data, const Eo_Event *event EINA_UNUSED)
 {
    Evas_Object *fs = data;
-   char *parent;
+   Efl_Model *parent = NULL;
 
    ELM_FILESELECTOR_DATA_GET(fs, sd);
 
-   parent = ecore_file_dir_get(sd->path);
+   parent = eo_parent_get(sd->model);
+   if (!parent)
+     return EINA_TRUE;
    _populate(fs, parent, NULL, NULL);
-   free(parent);
 
    return EINA_TRUE;
 }
@@ -985,8 +1240,16 @@ static Eina_Bool
 _home(void *data, const Eo_Event *event EINA_UNUSED)
 {
    Evas_Object *fs = data;
+   ELM_FILESELECTOR_DATA_GET(fs, sd);
 
-   _populate(fs, eina_environment_home_get(), NULL, NULL);
+   // FIXME: maybe use vpath
+   if (!sd->model || eo_isa(sd->model, EIO_MODEL_CLASS))
+     {
+        Eio_Model *model = eo_add(EIO_MODEL_CLASS, NULL,
+                                  eio_model_path_set(eo_self, eina_environment_home_get()));
+        _populate(fs, model, NULL, NULL);
+        eo_unref(model);
+     }
 
    return EINA_TRUE;
 }
@@ -1003,7 +1266,7 @@ _current_filter_changed(void *data,
    elm_object_text_set(obj, filter->filter_name);
    filter->sd->current_filter = filter;
 
-   _populate(filter->sd->obj, filter->sd->path, NULL, NULL);
+   _populate(filter->sd->obj, filter->sd->model, NULL, NULL);
 }
 
 static Eina_Bool
@@ -1014,27 +1277,50 @@ _ok(void *data, const Eo_Event *event EINA_UNUSED)
    Evas_Object *fs = data;
    ELM_FILESELECTOR_DATA_GET(fs, sd);
 
-   if (!sd->path)
+   if (!sd->model || !sd->path)
      {
-        eo_event_callback_call(fs, ELM_FILESELECTOR_EVENT_DONE, NULL);
-         return EINA_TRUE;
+        // EVENTS: should not call legacy
+        //eo_event_callback_call(fs, ELM_FILESELECTOR_EVENT_DONE, NULL);
+        evas_object_smart_callback_call(fs, "done", NULL);
+        return EINA_TRUE;
      }
 
    name = elm_object_text_get(sd->name_entry);
    if (name && name[0] != '\0')
      {
+        Efl_Model *selected_model = NULL;
         int len = eina_stringshare_strlen(sd->path);
         if (sd->path[len - 1] == '/')
           selection = eina_stringshare_printf("%s%s", sd->path, name);
         else
           selection = eina_stringshare_printf("%s/%s", sd->path, name);
+
+        selected_model = eo_add(eo_class_get(sd->model), NULL);
+        _model_str_property_set(selected_model, "path", selection, NULL);
+
+        // EVENTS: should not call legacy
+        //eo_event_callback_call
+        //  (fs, ELM_FILESELECTOR_EVENT_DONE, selected_model);
+        evas_object_smart_callback_call(fs, "done", (void *) selection);
+
+        eo_unref(selected_model);
+        eina_stringshare_del(selection);
      }
    else
-     selection = eina_stringshare_add(elm_fileselector_selected_get(fs));
-
-   eo_event_callback_call
-     (fs, ELM_FILESELECTOR_EVENT_DONE, (void *)selection);
-   eina_stringshare_del(selection);
+     {
+        Elm_Fileselector_Item_Data *it_data = _selected_item_data_get(sd);
+        if (it_data)
+          {
+             // EVENTS: should not call legacy
+             //eo_event_callback_call
+             //  (fs, ELM_FILESELECTOR_EVENT_DONE, it_data->model);
+             evas_object_smart_callback_call(fs, "done", (void *) it_data->path);
+          }
+        // EVENTS: should not call legacy
+        //eo_event_callback_call
+        //  (fs, ELM_FILESELECTOR_EVENT_DONE, sd->model);
+        evas_object_smart_callback_call(fs, "done", (void *) sd->path);
+     }
 
    return EINA_TRUE;
 }
@@ -1044,96 +1330,145 @@ _canc(void *data, const Eo_Event *event EINA_UNUSED)
 {
    Evas_Object *fs = data;
 
-   eo_event_callback_call(fs, ELM_FILESELECTOR_EVENT_DONE, NULL);
+   // EVENTS: should not call legacy
+   //eo_event_callback_call(fs, ELM_FILESELECTOR_EVENT_DONE, NULL);
+   evas_object_smart_callback_call(fs, "done", NULL);
 
    return EINA_TRUE;
 }
 
-static Eina_Bool
-_on_text_activated(void *data, const Eo_Event *event)
+static void
+_text_activated_free_fs_data(Elm_Fileselector *fs)
 {
-   Evas_Object *fs = data;
-   const char *p, *path;
-   char *dir;
+   Eina_Stringshare *str = eo_key_data_get(fs, _text_activated_path_key);
+   eina_stringshare_del(str);
+   eo_key_data_set(fs, _text_activated_path_key, NULL);
+   eo_key_obj_set(fs, _text_activated_model_key, NULL);
+   eo_unref(fs);
+}
 
+static void
+_text_activated_is_dir_then(void *data, void *value)
+{
+   Evas_Object *fs = data;
+   Eina_Bool is_dir = EINA_FALSE;
    ELM_FILESELECTOR_DATA_GET(fs, sd);
 
-   path = elm_widget_part_text_get(event->object, NULL);
-
-   if (!ecore_file_exists(path))
-     {
-        eo_event_callback_call
-          (fs, EVAS_SELECTABLE_INTERFACE_EVENT_SELECTED, (void *)path);
-        eo_event_callback_call
-          (fs, ELM_FILESELECTOR_EVENT_SELECTED_INVALID, (void *)path);
-        goto end;
-     }
+   Efl_Model *model = eo_key_obj_get(fs, _text_activated_model_key);
+   Eina_Stringshare *str = eo_key_data_get(fs, _text_activated_path_key);
 
-   if (ecore_file_is_dir(path))
+   eina_value_get(value, &is_dir);
+   if (is_dir)
      {
         // keep previous path for backspace key action
-        eina_stringshare_replace(&sd->prev_path, sd->path);
-        // keep a ref to path 'couse it will be destroyed by _populate
-        p = eina_stringshare_add(path);
-        _populate(fs, p, NULL, NULL);
-        eina_stringshare_del(p);
-
-        if (sd->only_folder)
-          eo_event_callback_call
-            (fs, EVAS_SELECTABLE_INTERFACE_EVENT_SELECTED, (void *)path);
-
-        goto end;
-     }
+        if (sd->prev_model)
+          eo_unref(sd->prev_model);
+        sd->prev_model = eo_ref(sd->model);
 
-   dir = ecore_file_dir_get(path);
-   if (!dir) goto end;
-
-   if (strcmp(dir, sd->path))
-     {
-        _populate(fs, dir, NULL, path);
+        _populate(fs, model, NULL, NULL);
 
         if (sd->only_folder)
-          eo_event_callback_call
-            (fs, EVAS_SELECTABLE_INTERFACE_EVENT_SELECTED, (void *)path);
+          {
+             // EVENTS: should not call legacy
+             //eo_event_callback_call
+             //  (fs, EVAS_SELECTABLE_INTERFACE_EVENT_SELECTED, (void *)model);
+             evas_object_smart_callback_call(fs, "selected", (void *) str);
+          }
      }
    else
      {
-        if (sd->mode == ELM_FILESELECTOR_LIST)
+        Efl_Model *parent = eo_parent_get(model);
+        if (!parent)
           {
-             Elm_Object_Item *item = elm_genlist_first_item_get(sd->files_view);
-             while (item)
-               {
-                  const char *item_path = WIDGET_ITEM_DATA_GET(item);
-                  if (!strcmp(item_path, path))
-                    {
-                       elm_genlist_item_selected_set(item, EINA_TRUE);
-                       elm_widget_part_text_set(sd->name_entry, NULL,
-                                                ecore_file_file_get(path));
-                       break;
-                    }
-                  item = elm_genlist_item_next_get(item);
-               }
+             ERR("Efl.Model allocation error");
           }
         else
           {
-             Elm_Object_Item *item = elm_gengrid_first_item_get(sd->files_view);
-             while (item)
+             _populate(fs, parent, NULL, model);
+
+             if (sd->only_folder)
                {
-                  const char *item_path = elm_object_item_data_get(item);
-                  if (!strcmp(item_path, path))
-                    {
-                       elm_gengrid_item_selected_set(item, EINA_TRUE);
-                       elm_widget_part_text_set(sd->name_entry, NULL,
-                                                ecore_file_file_get(path));
-                       break;
-                    }
-                  item = elm_gengrid_item_next_get(item);
+                  // EVENTS: should not call legacy
+                  //eo_event_callback_call
+                  //  (fs, EVAS_SELECTABLE_INTERFACE_EVENT_SELECTED, (void *)model);
+                  evas_object_smart_callback_call(fs, "selected", (void *) str);
                }
           }
      }
-   free(dir);
 
-end:
+   _text_activated_free_fs_data(fs);
+}
+
+static void
+_text_activated_is_dir_then_error(void *data, Eina_Error err EINA_UNUSED)
+{
+   ERR("could not get information from Efl.Model");
+   _text_activated_free_fs_data(data);
+}
+
+static void
+_on_text_activated_set_path_then(void *data, void *value EINA_UNUSED)
+{
+   Evas_Object *fs = data;
+   Eina_Promise *promise = NULL;
+   ELM_FILESELECTOR_DATA_GET(fs, sd);
+
+   if (!sd->model) return ;
+
+   efl_model_property_get(sd->model, "is_dir", &promise);
+   eina_promise_then
+     (promise, _text_activated_is_dir_then, _text_activated_is_dir_then_error, data);
+}
+
+static void
+_on_text_activated_set_path_then_error(void *data, Eina_Error err EINA_UNUSED)
+{
+   Evas_Object *fs = data;
+   Efl_Model *model = eo_key_data_get(fs, _text_activated_model_key);
+   Eina_Stringshare *str = eo_key_data_get(fs, _text_activated_path_key);
+
+   // EVENTS: should not call legacy
+   //eo_event_callback_call
+   //  (fs, EVAS_SELECTABLE_INTERFACE_EVENT_SELECTED, (void *)model);
+   evas_object_smart_callback_call(fs, "selected", (void *)str);
+
+   // EVENTS: should not call legacy
+   //eo_event_callback_call
+   //  (fs, ELM_FILESELECTOR_EVENT_SELECTED_INVALID, (void *)model);
+   evas_object_smart_callback_call(fs, "selected,invalid", (void *)str);
+
+   _text_activated_free_fs_data(fs);
+}
+
+static Eina_Bool
+_on_text_activated(void *data, const Eo_Event *event)
+{
+   Evas_Object *fs = data;
+   const char *path;
+   Efl_Model *model;
+   Eina_Promise *promise = NULL;
+
+   ELM_FILESELECTOR_DATA_GET(fs, sd);
+
+   if (!sd->model)
+     return EINA_TRUE;
+
+   path = elm_widget_part_text_get(event->object, NULL);
+   model = eo_add(eo_class_get(sd->model), NULL);
+   if (!model)
+     return EINA_TRUE;
+
+   _model_str_property_set(model, "path", path, &promise);
+
+   eo_key_data_set(fs, _text_activated_path_key, eina_stringshare_add(path));
+   eo_key_obj_set(fs, _text_activated_model_key, model);
+   eo_ref(fs);
+   eina_promise_then(promise,
+                     _on_text_activated_set_path_then,
+                     _on_text_activated_set_path_then_error,
+                     fs);
+
+   eo_unref(model);
    elm_object_focus_set(event->object, EINA_FALSE);
 
    return EINA_TRUE;
@@ -1177,14 +1512,20 @@ _anchor_clicked(void *data, const Eo_Event *event)
 {
    Elm_Entry_Anchor_Info *info = event->info;
    Evas_Object *fs = data;
-   const char *p;
+   Efl_Model *model = NULL;
 
    ELM_FILESELECTOR_DATA_GET(fs, sd);
 
-   // keep a ref to path 'couse it will be destroyed by _populate
-   p = eina_stringshare_add(info->name);
-   _populate(fs, p, NULL, NULL);
-   eina_stringshare_del(p);
+   if (!sd->model)
+     return EINA_TRUE;
+
+   model = eo_add(eo_class_get(sd->model), NULL);
+   if (!model)
+     return EINA_TRUE;
+   _model_str_property_set(model, "path", info->name, NULL);
+
+   _populate(fs, model, NULL, NULL);
+   eo_unref(model);
    /* After anchor was clicked, entry will be focused, and will be editable.
     * It's wrong. So remove focus. */
    elm_object_focus_set(event->object, EINA_FALSE);
@@ -1293,76 +1634,139 @@ _files_grid_add(Evas_Object *obj)
    return grid;
 }
 
-static Eina_Bool
-_resource_created(void *data, int type, void *ev)
+static void
+_resource_then_error(void *data, Eina_Error err EINA_UNUSED)
 {
-   Evas_Object *obj = data;
-   Eio_Monitor_Event *event = ev;
+   Elm_Fileselector_Item_Data *it_data = data;
+   WRN("could not get information from Efl.Model");
+   eo_unref(it_data->user_data);
+   eo_unref(it_data->model);
+   free(it_data);
+}
+
+static void
+_resource_created_then(void *data, void *values)
+{
+   Elm_Fileselector_Item_Data *it_data = data;
+   Evas_Object *obj = it_data->user_data;
+   Eina_Iterator *value_itt = values;
    int itcn = ELM_FILE_UNKNOW;
+   const char *path = NULL;
+   const char *filename = NULL;
+   const char *mime_type = NULL;
+   int64_t size = 0;
+   double mtime = 0;
    Eina_Bool dir = EINA_FALSE;
+   it_data->user_data = NULL;
 
    ELM_FILESELECTOR_DATA_GET(obj, sd);
 
-   if (type == EIO_MONITOR_DIRECTORY_CREATED)
-     dir = EINA_TRUE;
-
-   Elm_Fileselector_Filter *cf = sd->current_filter;
-   if (cf)
-     {
-        switch (cf->filter_type)
-          {
-           case ELM_FILESELECTOR_MIME_FILTER:
-              if (!dir && !_check_mime_type_filter(cf, event->filename))
-                return ECORE_CALLBACK_PASS_ON;
-              break;
-           case ELM_FILESELECTOR_CUSTOM_FILTER:
-              if (!cf->filter.custom->func(event->filename, dir, cf->filter.custom->data))
-                return ECORE_CALLBACK_PASS_ON;
-              break;
-           default:
-              break;
-          }
+   if (!_iterator_next_value_get(value_itt, &path) ||
+       !_iterator_next_value_get(value_itt, &filename) ||
+       !path || !filename ||
+       !_iterator_next_value_get(value_itt, &dir) ||
+       !_iterator_next_value_get(value_itt, &size) ||
+       !_iterator_next_value_get(value_itt, &mtime) ||
+       !_iterator_next_value_get(value_itt, &mime_type) ||
+       !_filter_child(sd, path, filename, dir, mime_type))
+     {
+        ERR("missing Efl.Model data");
+        eo_unref(it_data->model);
+        free(it_data);
+        goto end;
      }
 
+   it_data->path = eina_stringshare_add(path);
+   it_data->filename = eina_stringshare_add(filename);
+   it_data->size = size;
+   it_data->mtime = mtime;
+   it_data->mime_type = eina_stringshare_add(mime_type);
+   it_data->parent_model = eo_ref(sd->model);
+   it_data->parent_path = eina_stringshare_add(sd->path);
+   it_data->is_dir = dir;
+
    if (dir)
      itcn = ELM_DIRECTORY;
    else
      {
-        if (evas_object_image_extension_can_load_get(event->filename))
+        if (evas_object_image_extension_can_load_get(filename))
           itcn = ELM_FILE_IMAGE;
      }
 
    if (sd->mode == ELM_FILESELECTOR_LIST)
      elm_genlist_item_sorted_insert(sd->files_view, list_itc[itcn],
-                                    eina_stringshare_add(event->filename),
+                                    it_data,
                                     NULL,
                                     (sd->expand && itcn == ELM_DIRECTORY)
                                     ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
                                     _file_list_cmp, NULL, NULL);
    else
      elm_gengrid_item_sorted_insert(sd->files_view, grid_itc[itcn],
-                                    eina_stringshare_add(event->filename),
+                                    it_data,
                                     _file_grid_cmp, NULL, NULL);
 
+end:
+   eo_unref(obj);
+}
+
+static Eina_Bool
+_resource_created(void *data, const Eo_Event *event)
+{
+   Elm_Fileselector *fs = data;
+   Efl_Model_Children_Event* evt = event->info;
+   Efl_Model *child = evt->child;
+   Eina_Promise *promises[7] = {NULL,};
+   Eina_Promise *promise_all = NULL;
+   Elm_Fileselector_Item_Data *it_data = NULL;
+
+   ELM_FILESELECTOR_DATA_GET(fs, sd);
+
+   if (sd->model != event->object)
+     return ECORE_CALLBACK_PASS_ON;
+
+   it_data = calloc(1, sizeof(Elm_Fileselector_Item_Data));
+   if (!it_data)
+     return ECORE_CALLBACK_PASS_ON;
+
+   it_data->model = eo_ref(child);
+   it_data->user_data = eo_ref(fs);
+
+   efl_model_property_get(child, "path", &promises[0]);
+   efl_model_property_get(child, "filename", &promises[1]);
+   efl_model_property_get(child, "is_dir", &promises[2]);
+   efl_model_property_get(child, "size", &promises[3]);
+   efl_model_property_get(child, "mtime", &promises[4]);
+   efl_model_property_get(child, "mime_type", &promises[5]);
+
+
+   promise_all = eina_promise_all(eina_carray_iterator_new((void**)promises));
+
+   eina_promise_then(promise_all, _resource_created_then, _resource_then_error, it_data);
+
    return ECORE_CALLBACK_PASS_ON;
 }
 
 static Eina_Bool
-_resource_deleted(void *data, int type EINA_UNUSED, void *ev)
+_resource_deleted(void *data, const Eo_Event *event)
 {
    Evas_Object *obj = data;
-   Eio_Monitor_Event *event = ev;
+   Efl_Model_Children_Event* evt = event->info;
+   Efl_Model *child = evt->child;
    Elm_Object_Item *it = NULL;
    Eina_Bool selected = EINA_FALSE;
 
    ELM_FILESELECTOR_DATA_GET(obj, sd);
 
+   if (sd->model != event->object)
+     return ECORE_CALLBACK_PASS_ON;
+
    if (sd->mode == ELM_FILESELECTOR_LIST)
      {
         it = elm_genlist_first_item_get(sd->files_view);
         while (it)
           {
-             if (!strcmp(elm_object_item_data_get(it), event->filename))
+             Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(it);
+             if (child == it_data->model)
                {
                   selected = elm_genlist_item_selected_get(it);
                   break;
@@ -1375,7 +1779,8 @@ _resource_deleted(void *data, int type EINA_UNUSED, void *ev)
         it = elm_gengrid_first_item_get(sd->files_view);
         while (it)
           {
-             if (!strcmp(elm_object_item_data_get(it), event->filename))
+             Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(it);
+             if (child == it_data->model)
                {
                   selected = elm_genlist_item_selected_get(it);
                   break;
@@ -1391,17 +1796,17 @@ _resource_deleted(void *data, int type EINA_UNUSED, void *ev)
         if (sd->multi)
           {
              Eina_List *li, *l;
-             char *path;
+             Elm_Object_Item *item;
              Eina_Strbuf *buf;
              Eina_Bool first = EINA_TRUE;
 
              buf = eina_strbuf_new();
-             EINA_LIST_FOREACH_SAFE(sd->paths, li, l, path)
+             EINA_LIST_FOREACH_SAFE(sd->multi_selection, li, l, item)
                {
-                  if (!strcmp(path, event->filename))
+                  Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(item);
+                  if (child == it_data->model)
                     {
-                       sd->paths = eina_list_remove_list(sd->paths, li);
-                       free(path);
+                       sd->multi_selection = eina_list_remove_list(sd->multi_selection, li);
                     }
                   else
                     {
@@ -1410,7 +1815,7 @@ _resource_deleted(void *data, int type EINA_UNUSED, void *ev)
                        else
                          first = EINA_FALSE;
 
-                       eina_strbuf_append(buf, ecore_file_file_get(path));
+                       eina_strbuf_append(buf, it_data->filename);
                     }
                }
 
@@ -1431,8 +1836,8 @@ _preedit_cb(void *data, const Eo_Event *event)
 
    sd->search_string = elm_entry_entry_get(event->object);
 
-   if (sd->search_string && sd->path)
-     _populate(data, sd->path, NULL, NULL);
+   if (sd->search_string && sd->model)
+     _populate(data, sd->model, NULL, NULL);
 
    return EINA_TRUE;
 }
@@ -1526,7 +1931,7 @@ _elm_fileselector_evas_object_smart_add(Eo *obj, Elm_Fileselector_Data *priv)
    priv->thumbnail_size.h = priv->thumbnail_size.w;
 
    priv->sort_type = ELM_FILESELECTOR_SORT_BY_FILENAME_ASC;
-   priv->sort_method = strcoll;
+   priv->sort_method = _filename_cmp;
 
    // path entry
    en = elm_entry_add(obj);
@@ -1568,36 +1973,17 @@ _elm_fileselector_evas_object_smart_add(Eo *obj, Elm_Fileselector_Data *priv)
    priv->files_view = _files_list_add(obj);
    elm_object_part_content_set(obj, "elm.swallow.files", priv->files_view);
 
-#define HANDLER_ADD(e, fn) \
-   priv->handlers = eina_list_append(priv->handlers, \
-                                     ecore_event_handler_add(e, fn, obj));
-
-   HANDLER_ADD(EIO_MONITOR_FILE_CREATED, _resource_created);
-   HANDLER_ADD(EIO_MONITOR_DIRECTORY_CREATED, _resource_created);
-
-   HANDLER_ADD(EIO_MONITOR_FILE_DELETED, _resource_deleted);
-   HANDLER_ADD(EIO_MONITOR_DIRECTORY_DELETED, _resource_deleted);
-#undef HANDLER_ADD
-
    elm_obj_layout_sizing_eval(obj);
 }
 
 EOLIAN static void
-_elm_fileselector_evas_object_smart_del(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd)
+_elm_fileselector_evas_object_smart_del(Eo *obj, Elm_Fileselector_Data *sd)
 {
    Elm_Fileselector_Filter *filter;
-   char *path;
-   Ecore_Event_Handler *h;
-
-   if (sd->monitor) eio_monitor_del(sd->monitor);
-   if (sd->current) eio_file_cancel(sd->current);
-   sd->monitor = NULL;
-   sd->current = NULL;
 
-   EINA_LIST_FREE(sd->handlers, h)
-     {
-        ecore_event_handler_del(h);
-     }
+   if (sd->current_populate_lreq)
+     sd->current_populate_lreq->valid = EINA_FALSE;
+   sd->current_populate_lreq = NULL;
 
    EINA_LIST_FREE(sd->filter_list, filter)
      {
@@ -1614,13 +2000,13 @@ _elm_fileselector_evas_object_smart_del(Eo *obj EINA_UNUSED, Elm_Fileselector_Da
         free(filter);
      }
 
-   EINA_LIST_FREE(sd->paths, path)
-     free(path);
+   sd->multi_selection = eina_list_free(sd->multi_selection);
+   sd->multi_selection_tmp = eina_list_free(sd->multi_selection_tmp);
 
    sd->files_view = NULL;
 
    /* this one matching EINA_REFCOUNT_INIT() */
-   EINA_REFCOUNT_UNREF(sd) _elm_fileselector_smart_del_do(sd);
+   EINA_REFCOUNT_UNREF(sd) _elm_fileselector_smart_del_do(obj, sd);
 }
 
 EAPI Evas_Object *
@@ -1689,10 +2075,9 @@ _elm_fileselector_elm_interface_fileselector_folder_only_set(Eo *obj, Elm_Filese
    if (sd->only_folder == only) return;
 
    sd->only_folder = !!only;
-   if (sd->path)
+   if (sd->model)
      {
-        eina_stringshare_ref(sd->path);
-        _schedule_populate(obj, sd, sd->path, NULL);
+        _schedule_populate(obj, sd, sd->model, NULL);
      }
 }
 
@@ -1770,10 +2155,9 @@ _elm_fileselector_elm_interface_fileselector_expandable_set(Eo *obj, Elm_Filesel
 {
    sd->expand = !!expand;
 
-   if (sd->path)
+   if (sd->model)
      {
-        eina_stringshare_ref(sd->path);
-        _schedule_populate(obj, sd, sd->path, NULL);
+        _schedule_populate(obj, sd, sd->model, NULL);
      }
 }
 
@@ -1797,32 +2181,34 @@ elm_fileselector_path_set(Evas_Object *obj,
                           const char *_path)
 {
    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
-   elm_interface_fileselector_path_set(obj, _path);
+   Eio_Model *model = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(eo_self, _path));
+   if (!model)
+     {
+        ERR("Efl.Model allocation error");
+        return;
+     }
+   elm_interface_fileselector_model_set(obj, model);
+   eo_unref(model);
 }
 
 EOLIAN static void
-_elm_fileselector_elm_interface_fileselector_path_set(Eo *obj, Elm_Fileselector_Data *sd, const char *_path)
+_elm_fileselector_elm_interface_fileselector_model_set(Eo *obj, Elm_Fileselector_Data *sd, Efl_Model *model)
 {
-   char *path;
-
-   path = ecore_file_realpath(_path);
-   _schedule_populate(obj, sd, eina_stringshare_add(path), NULL);
-   free(path);
+   _schedule_populate(obj, sd, model, NULL);
 }
 
 EAPI const char *
 elm_fileselector_path_get(const Evas_Object *obj)
 {
    ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
-   const char *ret = NULL;
-   ret = elm_interface_fileselector_path_get((Eo *) obj);
-   return ret;
+   ELM_FILESELECTOR_DATA_GET(obj, sd);
+   return sd->path;
 }
 
-EOLIAN static const char*
-_elm_fileselector_elm_interface_fileselector_path_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd)
+EOLIAN static Efl_Model *
+_elm_fileselector_elm_interface_fileselector_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd)
 {
-   return sd->path;
+   return sd->model;
 }
 
 EAPI void
@@ -1861,10 +2247,9 @@ _elm_fileselector_elm_interface_fileselector_mode_set(Eo *obj, Elm_Fileselector_
 
    sd->mode = mode;
 
-   if (sd->path)
+   if (sd->model)
      {
-        eina_stringshare_ref(sd->path);
-        _schedule_populate(obj, sd, sd->path, NULL);
+        _schedule_populate(obj, sd, sd->model, NULL);
      }
 }
 
@@ -1893,8 +2278,6 @@ elm_fileselector_multi_select_set(Evas_Object *obj, Eina_Bool multi)
 EOLIAN static void
 _elm_fileselector_elm_interface_fileselector_multi_select_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd, Eina_Bool multi)
 {
-   char *path;
-
    multi = !!multi;
    if (sd->multi == multi) return;
    sd->multi = multi;
@@ -1908,8 +2291,7 @@ _elm_fileselector_elm_interface_fileselector_multi_select_set(Eo *obj EINA_UNUSE
      {
         _clear_selections(sd, NULL);
 
-        EINA_LIST_FREE(sd->paths, path)
-          free(path);
+        sd->multi_selection = eina_list_free(sd->multi_selection);
      }
    else
      {
@@ -1923,8 +2305,7 @@ _elm_fileselector_elm_interface_fileselector_multi_select_set(Eo *obj EINA_UNUSE
 
         EINA_LIST_FOREACH(selected_items, li, it)
           {
-             path = elm_object_item_data_get(it);
-             sd->paths = eina_list_append(sd->paths, strdup(path));
+             sd->multi_selection = eina_list_append(sd->multi_selection, it);
           }
      }
 }
@@ -1944,29 +2325,9 @@ _elm_fileselector_elm_interface_fileselector_multi_select_get(Eo *obj EINA_UNUSE
    return sd->multi;
 }
 
-EAPI const char *
-elm_fileselector_selected_get(const Evas_Object *obj)
+static Elm_Fileselector_Item_Data *
+_selected_item_data_get(Elm_Fileselector_Data *sd)
 {
-   ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
-   const char *ret = NULL;
-   ret = elm_interface_fileselector_selected_get((Eo *) obj);
-   return ret;
-}
-
-EOLIAN static const char*
-_elm_fileselector_elm_interface_fileselector_selected_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd)
-{
-   const char *fp;
-   if (!sd->path) return NULL;
-
-   fp = elm_object_text_get(sd->path_entry);
-   if (ecore_file_exists(fp))
-     {
-        eina_stringshare_replace(&sd->selection, fp);
-
-        return sd->selection;
-     }
-
    if (sd->mode == ELM_FILESELECTOR_LIST)
      {
         Elm_Object_Item *gl_it = elm_genlist_selected_item_get(sd->files_view);
@@ -1979,45 +2340,89 @@ _elm_fileselector_elm_interface_fileselector_selected_get(Eo *obj EINA_UNUSED, E
 
         if (gg_it) return elm_object_item_data_get(gg_it);
      }
+   return NULL;
+}
+
+EAPI const char *
+elm_fileselector_selected_get(const Evas_Object *obj)
+{
+   ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
+   ELM_FILESELECTOR_DATA_GET(obj, sd);
+   if (!sd->path) return NULL;
 
+   Elm_Fileselector_Item_Data *it_data = _selected_item_data_get(sd);
+   if (it_data)
+     return it_data->path;
 
    return sd->path;
 }
 
+EOLIAN static Efl_Model *
+_elm_fileselector_elm_interface_fileselector_selected_model_get(Eo *fs EINA_UNUSED, Elm_Fileselector_Data *sd)
+{
+   if (!sd->model)
+     {
+        return NULL;
+     }
+
+   Elm_Fileselector_Item_Data *it_data = _selected_item_data_get(sd);
+   if (it_data)
+     return it_data->model;
+
+   return sd->model;
+}
+
 EAPI Eina_Bool
 elm_fileselector_selected_set(Evas_Object *obj,
                               const char *_path)
 {
    ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
    Eina_Bool ret = EINA_FALSE;
-   ret = elm_interface_fileselector_selected_set(obj, _path);
-   return ret;
-}
-
-EOLIAN static Eina_Bool
-_elm_fileselector_elm_interface_fileselector_selected_set(Eo *obj, Elm_Fileselector_Data *sd, const char *_path)
-{
-   Eina_Bool ret = EINA_TRUE;
    char *dir;
    char *path;
+   Eio_Model *model = NULL;
+   Eio_Model *parent = NULL;
+   ELM_FILESELECTOR_DATA_GET(obj, sd);
 
    path = ecore_file_realpath(_path);
 
    if (ecore_file_is_dir(path))
-     _schedule_populate(obj, sd, eina_stringshare_add(path), NULL);
+     {
+         model = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(eo_self, path));
+         if (!model)
+           {
+              ERR("Efl.Model allocation error");
+              goto clean_up;
+           }
+
+        _schedule_populate(obj, sd, model, NULL);
+        eo_unref(model);
+        ret = EINA_TRUE;
+     }
    else
      {
         if (!ecore_file_exists(path))
           {
-             ret = EINA_FALSE;
+             goto clean_up;
+          }
+
+        model = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(eo_self, path));
+        if (!model)
+          {
+             ERR("Efl.Model allocation error");
              goto clean_up;
           }
 
         dir = ecore_file_dir_get(path);
-        eina_stringshare_replace(&sd->selection, path);
-        eina_stringshare_ref(sd->selection);
-        _schedule_populate(obj, sd, eina_stringshare_add(dir), sd->selection);
+        parent = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(eo_self, dir));
+        if (parent)
+          {
+             _schedule_populate(obj, sd, parent, model);
+             eo_unref(parent);
+             ret = EINA_TRUE;
+          }
         free(dir);
+        eo_unref(model);
      }
 
 clean_up:
@@ -2026,22 +2431,126 @@ clean_up:
    return ret;
 }
 
+static void
+_selected_model_set_free_fs_data(Elm_Fileselector *fs)
+{
+   eo_key_obj_set(fs, _selected_model_set_model_key, NULL);
+   eo_key_data_set(fs, _selected_model_set_promise_owner_key, NULL);
+   eo_unref(fs);
+}
+
+static void
+_selected_model_set_then_error(void *data, Eina_Error err)
+{
+   Eina_Promise_Owner *promise_owner = eo_key_data_get(data, _selected_model_set_promise_owner_key);
+   if (promise_owner)
+     eina_promise_owner_error_set(promise_owner, err);
+   _selected_model_set_free_fs_data(data);
+}
+
+static void
+_selected_model_set_is_dir_then(void *data, void *value)
+{
+   Elm_Fileselector *fs = data;
+   Eina_Bool is_dir = EINA_FALSE;
+   Efl_Model *model = eo_key_obj_get(fs, _selected_model_set_model_key);
+   Eina_Promise_Owner *promise_owner = eo_key_data_get(fs, _selected_model_set_promise_owner_key);
+   ELM_FILESELECTOR_DATA_GET(fs, sd);
+
+   eina_value_get(value, &is_dir);
+   if (is_dir)
+     {
+        _schedule_populate(fs, sd, model, NULL);
+        if (promise_owner)
+          {
+             eo_ref(model);
+             eina_promise_owner_value_set(promise_owner, model, _model_free_eo_cb);
+          }
+     }
+   else
+     {
+        Efl_Model *parent = eo_parent_get(model);
+        if (parent)
+          {
+             _schedule_populate(fs, sd, parent, model);
+
+             if (promise_owner)
+               {
+                  eo_ref(model);
+                  eina_promise_owner_value_set(promise_owner, model, _model_free_eo_cb);
+               }
+          }
+        else
+          {
+             if (promise_owner)
+               eina_promise_owner_error_set(promise_owner, ELM_FILESELECTOR_ERROR_UNKNOWN);
+          }
+     }
+   _selected_model_set_free_fs_data(fs);
+}
+
+EOLIAN static void
+_elm_fileselector_elm_interface_fileselector_selected_model_set(Eo *obj, Elm_Fileselector_Data *sd EINA_UNUSED, Efl_Model *model, Eina_Promise_Owner *promise_owner)
+{
+   Eina_Promise *promise = NULL;
+   if (!model)
+     {
+        if (promise_owner)
+          eina_promise_owner_error_set(promise_owner, ELM_FILESELECTOR_ERROR_INVALID_MODEL);
+        return;
+     }
+   efl_model_property_get(model, "is_dir", &promise);
+
+   eo_key_obj_set(obj, _selected_model_set_model_key, model);
+   if (promise_owner)
+     eo_key_data_set(obj, _selected_model_set_promise_owner_key, promise_owner);
+
+   eina_promise_then(promise, _selected_model_set_is_dir_then, _selected_model_set_then_error, eo_ref(obj));
+}
+
 EAPI const Eina_List *
 elm_fileselector_selected_paths_get(const Evas_Object* obj)
 {
    ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
-   const Eina_List *ret = NULL;
-   ret = elm_interface_fileselector_selected_paths_get((Eo *) obj);
-   return ret;
+   Eina_List *l;
+   Elm_Object_Item *item;
+   ELM_FILESELECTOR_DATA_GET(obj, sd);
+
+   if (!sd->multi)
+     return NULL;
+
+   if (sd->multi_selection_tmp)
+     {
+        sd->multi_selection_tmp = eina_list_free(sd->multi_selection_tmp);
+     }
+
+   EINA_LIST_FOREACH(sd->multi_selection, l, item)
+     {
+        Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(item);
+        sd->multi_selection_tmp = eina_list_append(sd->multi_selection_tmp, it_data->path);
+     }
+   return sd->multi_selection_tmp;
 }
 
 EOLIAN static const Eina_List*
-_elm_fileselector_elm_interface_fileselector_selected_paths_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd)
+_elm_fileselector_elm_interface_fileselector_selected_models_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd)
 {
-   if (sd->multi)
-     return sd->paths;
-   else
+   Eina_List *l;
+   Elm_Object_Item *item;
+   if (!sd->multi)
      return NULL;
+
+   if (sd->multi_selection_tmp)
+     {
+        sd->multi_selection_tmp = eina_list_free(sd->multi_selection_tmp);
+     }
+
+   EINA_LIST_FOREACH(sd->multi_selection, l, item)
+     {
+        Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(item);
+        sd->multi_selection_tmp = eina_list_append(sd->multi_selection_tmp, it_data->model);
+     }
+   return sd->multi_selection_tmp;
 }
 
 EAPI const char *
@@ -2077,7 +2586,7 @@ static Elm_Fileselector_Filter *
 _filter_add(Elm_Fileselector_Data *sd, const char *filter_name)
 {
    Elm_Fileselector_Filter *ff;
-   ff = malloc(sizeof(Elm_Fileselector_Filter));
+   ff = calloc(1, sizeof(Elm_Fileselector_Filter));
    if (!ff) return NULL;
 
    ff->filter_name = eina_stringshare_add(filter_name);
@@ -2123,10 +2632,9 @@ _elm_fileselector_elm_interface_fileselector_mime_types_filter_append(Eo *obj, E
 
    sd->filter_list = eina_list_append(sd->filter_list, ff);
 
-   if (sd->path)
+   if (sd->model)
      {
-        eina_stringshare_ref(sd->path);
-        _schedule_populate(obj, sd, sd->path, NULL);
+        _schedule_populate(obj, sd, sd->model, NULL);
      }
 
    return EINA_TRUE;
@@ -2150,7 +2658,7 @@ _elm_fileselector_elm_interface_fileselector_custom_filter_append(Eo *obj, Elm_F
 
    if (!func) return EINA_FALSE;
 
-   custom_filter = malloc(sizeof(Elm_Fileselector_Custom_Filter));
+   custom_filter = calloc(1, sizeof(Elm_Fileselector_Custom_Filter));
    if (!custom_filter) return EINA_FALSE;
 
    ff = _filter_add(sd, filter_name ? filter_name : "custom");
@@ -2178,10 +2686,9 @@ _elm_fileselector_elm_interface_fileselector_custom_filter_append(Eo *obj, Elm_F
 
    sd->filter_list = eina_list_append(sd->filter_list, ff);
 
-   if (sd->path)
+   if (sd->model)
      {
-        eina_stringshare_ref(sd->path);
-        _schedule_populate(obj, sd, sd->path, NULL);
+        _schedule_populate(obj, sd, sd->model, NULL);
      }
 
    return EINA_TRUE;
@@ -2216,10 +2723,9 @@ _elm_fileselector_elm_interface_fileselector_filters_clear(Eo *obj, Elm_Filesele
 
    ELM_SAFE_FREE(sd->filter_hoversel, evas_object_del);
 
-   if (sd->path)
+   if (sd->model)
      {
-        eina_stringshare_ref(sd->path);
-        _schedule_populate(obj, sd, sd->path, NULL);
+        _schedule_populate(obj, sd, sd->model, NULL);
      }
 }
 
@@ -2239,10 +2745,9 @@ _elm_fileselector_elm_interface_fileselector_hidden_visible_set(Eo *obj EINA_UNU
 
    _clear_selections(sd, NULL);
 
-   if (sd->path)
+   if (sd->model)
      {
-        eina_stringshare_ref(sd->path);
-        _schedule_populate(obj, sd, sd->path, NULL);
+        _schedule_populate(obj, sd, sd->model, NULL);
      }
 }
 
@@ -2284,10 +2789,9 @@ _elm_fileselector_elm_interface_fileselector_thumbnail_size_set(Eo *obj EINA_UNU
    if (sd->mode == ELM_FILESELECTOR_GRID)
      elm_gengrid_item_size_set(sd->files_view, w + GENGRID_PADDING, h + GENGRID_PADDING);
 
-   if (sd->path)
+   if (sd->model)
      {
-        eina_stringshare_ref(sd->path);
-        _schedule_populate(obj, sd, sd->path, NULL);
+        _schedule_populate(obj, sd, sd->model, NULL);
      }
 }
 
@@ -2323,16 +2827,16 @@ _elm_fileselector_elm_interface_fileselector_sort_method_set(Eo *obj EINA_UNUSED
    switch (sd->sort_type)
      {
       case ELM_FILESELECTOR_SORT_BY_FILENAME_ASC:
-         sd->sort_method = strcoll;
+         sd->sort_method = _filename_cmp;
          break;
       case ELM_FILESELECTOR_SORT_BY_FILENAME_DESC:
-         sd->sort_method = _strcoll_rev;
+         sd->sort_method = _filename_cmp_rev;
          break;
       case ELM_FILESELECTOR_SORT_BY_TYPE_ASC:
-         sd->sort_method = _strcoll_type;
+         sd->sort_method = _type_cmp;
          break;
       case ELM_FILESELECTOR_SORT_BY_TYPE_DESC:
-         sd->sort_method = _strcoll_type_rev;
+         sd->sort_method = _type_cmp_rev;
          break;
       case ELM_FILESELECTOR_SORT_BY_SIZE_ASC:
          sd->sort_method = _size_cmp;
@@ -2348,13 +2852,12 @@ _elm_fileselector_elm_interface_fileselector_sort_method_set(Eo *obj EINA_UNUSED
          break;
       case ELM_FILESELECTOR_SORT_LAST:
       default:
-         sd->sort_method = strcoll;
+         sd->sort_method = _filename_cmp;
      }
 
-   if (sd->path)
+   if (sd->model)
      {
-        eina_stringshare_ref(sd->path);
-        _schedule_populate(obj, sd, sd->path, NULL);
+        _schedule_populate(obj, sd, sd->model, NULL);
      }
 }
 
@@ -2465,6 +2968,9 @@ _elm_fileselector_class_constructor(Eo_Class *klass)
 
    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
 
+   ELM_FILESELECTOR_ERROR_UNKNOWN = eina_error_msg_static_register(ELM_FILESELECTOR_ERROR_UNKNOWN_STR);
+   ELM_FILESELECTOR_ERROR_INVALID_MODEL = eina_error_msg_static_register(ELM_FILESELECTOR_ERROR_INVALID_MODEL_STR);
+
    for (i = 0; i < ELM_FILE_LAST; ++i)
      {
         list_itc[i] = elm_genlist_item_class_new();
index 3f726a7..6007b17 100644 (file)
@@ -34,6 +34,12 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = {
 };
 #undef ELM_PRIV_FILESELECTOR_BUTTON_SIGNALS
 
+static void
+_model_free_eo_cb(void *eo)
+{
+   eo_unref(eo);
+}
+
 EOLIAN static Eina_Bool
 _elm_fileselector_button_elm_widget_theme_apply(Eo *obj, Elm_Fileselector_Button_Data *sd EINA_UNUSED)
 {
@@ -61,26 +67,68 @@ _elm_fileselector_button_elm_widget_theme_apply(Eo *obj, Elm_Fileselector_Button
    return EINA_TRUE;
 }
 
+static void
+_replace_path_then(void *data, void *value)
+{
+   Elm_Fileselector_Button_Data *sd = data;
+   const char *path = NULL;
+   eina_value_get(value, &path);
+   eina_stringshare_replace(&sd->fsd.path, path);
+}
+
+static void
+_replace_path_then_error(void *data, Eina_Error err EINA_UNUSED)
+{
+   Elm_Fileselector_Button_Data *sd = data;
+   ERR("could not get information from Efl.Model");
+   eina_stringshare_replace(&sd->fsd.path, NULL);
+}
+
 static Eina_Bool
 _selection_done(void *data, const Eo_Event *event)
 {
    Elm_Fileselector_Button_Data *sd = data;
-   const char *file = event->info;
+   Efl_Model *model = event->info;
    Evas_Object *del;
 
-   if (file) eina_stringshare_replace(&sd->fsd.path, file);
+   if (model)
+     {
+        Eina_Promise *promise = NULL;
+        if (sd->fsd.model)
+          eo_unref(sd->fsd.model);
+        sd->fsd.model = eo_ref(model);
+        efl_model_property_get(model, "path", &promise);
+        eina_promise_then(promise, _replace_path_then, _replace_path_then_error, sd);
+     }
 
    del = sd->fsw;
    sd->fs = NULL;
    sd->fsw = NULL;
    evas_object_del(del);
 
-   eo_event_callback_call
-     (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, (void *)file);
+   // EVENTS: should not call legacy
+   //eo_event_callback_call
+   //  (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, (void *)model);
 
    return EINA_TRUE;
 }
 
+
+static void
+_selection_done_path(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Elm_Fileselector_Button_Data *sd = data;
+   const char *path = event_info;
+
+   evas_object_smart_callback_call(sd->obj, "file,chosen", (void *) path);
+
+   // EVENTS: code above should not be needed
+   Eo_Event e = {0,};
+   if (path)
+      e.info = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(eo_self, path));
+   _selection_done(data, &e);
+}
+
 static Evas_Object *
 _new_window_add(Elm_Fileselector_Button_Data *sd)
 {
@@ -139,12 +187,14 @@ _activate(Elm_Fileselector_Button_Data *sd)
    elm_fileselector_expandable_set(sd->fs, sd->fsd.expandable);
    elm_fileselector_folder_only_set(sd->fs, sd->fsd.folder_only);
    elm_fileselector_is_save_set(sd->fs, sd->fsd.is_save);
-   elm_fileselector_selected_set(sd->fs, sd->fsd.path);
+   elm_interface_fileselector_selected_model_set(sd->fs, sd->fsd.model, NULL);
    evas_object_size_hint_weight_set
      (sd->fs, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    evas_object_size_hint_align_set(sd->fs, EVAS_HINT_FILL, EVAS_HINT_FILL);
-   eo_event_callback_add
-         (sd->fs, ELM_FILESELECTOR_EVENT_DONE, _selection_done, sd);
+   // EVENTS: should not call legacy
+   //eo_event_callback_add
+   //      (sd->fs, ELM_FILESELECTOR_EVENT_DONE, _selection_done, sd);
+   evas_object_smart_callback_add(sd->fs, "done", _selection_done_path, sd);
    evas_object_show(sd->fs);
 
    if (is_inwin)
@@ -180,6 +230,8 @@ _elm_fileselector_button_evas_object_smart_add(Eo *obj, Elm_Fileselector_Button_
    if (path) priv->fsd.path = eina_stringshare_add(path);
    else priv->fsd.path = eina_stringshare_add("/");
 
+   priv->fsd.model = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(eo_self, priv->fsd.path));
+
    priv->fsd.expandable = _elm_config->fileselector_expand_enable;
    priv->inwin_mode = _elm_config->inwin_dialogs_enable;
    priv->w = 400;
@@ -197,9 +249,12 @@ _elm_fileselector_button_evas_object_smart_add(Eo *obj, Elm_Fileselector_Button_
 EOLIAN static void
 _elm_fileselector_button_evas_object_smart_del(Eo *obj, Elm_Fileselector_Button_Data *sd)
 {
+   if (sd->fsd.model)
+     eo_unref(sd->fsd.model);
    eina_stringshare_del(sd->window_title);
    eina_stringshare_del(sd->fsd.path);
-   eina_stringshare_del(sd->fsd.selection);
+   if (sd->fsd.selection)
+     eo_unref(sd->fsd.selection);
    evas_object_del(sd->fsw);
 
    evas_obj_smart_del(eo_super(obj, MY_CLASS));
@@ -275,30 +330,58 @@ elm_fileselector_button_path_set(Evas_Object *obj,
                                  const char *path)
 {
    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
-   elm_interface_fileselector_path_set(obj, path);
+   ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN(obj, sd);
+
+   Efl_Model *model = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(eo_self, path));
+   if (!model)
+     {
+        ERR("Efl.Model allocation error");
+        return;
+     }
+
+   if (sd->fsd.model)
+     eo_unref(sd->fsd.model);
+   sd->fsd.model = eo_ref(model);
+
+   eina_stringshare_replace(&sd->fsd.path, path);
+
+   if (sd->fs) elm_interface_fileselector_selected_model_set(sd->fs, model, NULL);
 }
 
 EOLIAN static void
-_elm_fileselector_button_elm_interface_fileselector_path_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, const char *path)
+_elm_fileselector_button_elm_interface_fileselector_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Efl_Model *model)
 {
-   eina_stringshare_replace(&sd->fsd.path, path);
+   if (sd->fsd.model)
+     eo_unref(sd->fsd.model);
+
+   if (model)
+     {
+        Eina_Promise *promise = NULL;
+        sd->fsd.model = eo_ref(model);
+        efl_model_property_get(model, "path", &promise);
+        eina_promise_then(promise, _replace_path_then, _replace_path_then_error, sd);
+     }
+   else
+     {
+        sd->fsd.model = NULL;
+        eina_stringshare_replace(&sd->fsd.path, NULL);
+     }
 
-   if (sd->fs) elm_fileselector_selected_set(sd->fs, sd->fsd.path);
+   if (sd->fs) elm_interface_fileselector_selected_model_set(sd->fs, model, NULL);
 }
 
 EINA_DEPRECATED EAPI const char *
 elm_fileselector_button_path_get(const Evas_Object *obj)
 {
    ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
-   const char *ret = NULL;
-   ret = elm_interface_fileselector_path_get((Eo *) obj);
-   return ret;
+   ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
+   return sd->fsd.path;
 }
 
-EOLIAN static const char *
-_elm_fileselector_button_elm_interface_fileselector_path_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd)
+EOLIAN static Efl_Model *
+_elm_fileselector_button_elm_interface_fileselector_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd)
 {
-   return sd->fsd.path;
+   return sd->fsd.model;
 }
 
 EINA_DEPRECATED EAPI void
@@ -437,41 +520,48 @@ _elm_fileselector_button_elm_interface_fileselector_multi_select_get(Eo *obj EIN
 }
 
 EOLIAN static const Eina_List*
-_elm_fileselector_button_elm_interface_fileselector_selected_paths_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd)
+_elm_fileselector_button_elm_interface_fileselector_selected_models_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd)
 {
-   if (sd->fs) return elm_fileselector_selected_paths_get(sd->fs);
+   if (sd->fs) return elm_interface_fileselector_selected_models_get(sd->fs);
 
    return NULL;
 }
 
-EOLIAN static const char*
-_elm_fileselector_button_elm_interface_fileselector_selected_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd)
+EOLIAN static Efl_Model *
+_elm_fileselector_button_elm_interface_fileselector_selected_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd)
 {
-   if (sd->fs) return elm_fileselector_selected_get(sd->fs);
+   if (sd->fs) return elm_interface_fileselector_selected_model_get(sd->fs);
 
-   return sd->fsd.selection;
+   return NULL;
 }
 
-EOLIAN static Eina_Bool
-_elm_fileselector_button_elm_interface_fileselector_selected_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, const char *_path)
+static void
+_selected_model_then(void *data, void *v)
 {
-   Eina_Bool ret = EINA_TRUE;
+   Eina_Promise_Owner *owner = data;
+   eina_promise_owner_value_set(owner, eo_ref(v), _model_free_eo_cb);
+}
 
-   if (sd->fs) ret = elm_fileselector_selected_set(sd->fs, _path);
-   else
+static void
+_selected_model_then_error(void *data, Eina_Error err)
+{
+   Eina_Promise_Owner *owner = data;
+   eina_promise_owner_error_set(owner, err);
+}
+
+EOLIAN static void
+_elm_fileselector_button_elm_interface_fileselector_selected_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Efl_Model *model, Eina_Promise_Owner *promise_owner)
+{
+   if (sd->fs)
      {
-        char *path = ecore_file_realpath(_path);
-        if (!ecore_file_is_dir(path) && !ecore_file_exists(path))
-          {
-             free(path);
-             return EINA_FALSE;
-          }
-        free(path);
+        Eina_Promise *promise = NULL;
+        elm_interface_fileselector_selected_model_set(sd->fs, model, &promise);
+        eina_promise_then(promise, _selected_model_then, _selected_model_then_error, promise_owner);
      }
 
-   eina_stringshare_replace(&sd->fsd.selection, _path);
-
-   return ret;
+   if (sd->fsd.selection)
+     eo_unref(sd->fsd.selection);
+   sd->fsd.selection = model ? eo_ref(model) : NULL;
 }
 
 EOLIAN static void
index 2202a96..e3647f0 100644 (file)
@@ -1,3 +1,7 @@
 typedef Eina_Bool (*Elm_Fileselector_Filter_Func)(const char *path, /**< File path */
                                                   Eina_Bool dir, /**< A flag to show if path is a directory or not. True if the path is a directory. */
                                                   void *data /**< A user data that was given by elm_fileselector_custom_filter_append. */);
+
+EAPI extern Eina_Error ELM_FILESELECTOR_ERROR_UNKNOWN;
+EAPI extern Eina_Error ELM_FILESELECTOR_ERROR_INVALID_MODEL;
+
index 1941eb8..f0bdb2b 100644 (file)
@@ -33,7 +33,6 @@ EAPI const char ELM_FILESELECTOR_ENTRY_SMART_NAME[] = "elm_fileselector_entry";
    cmd(SIG_SELECTION_COPY, "selection,copy", "") \
    cmd(SIG_SELECTION_CUT, "selection,cut", "") \
    cmd(SIG_UNPRESSED, "unpressed", "") \
-   cmd(SIG_FILE_CHOSEN, "file,chosen", "s") \
 
 ELM_PRIV_FILESELECTOR_ENTRY_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
 
@@ -67,39 +66,88 @@ SIG_FWD(SELECTION_CUT, EVAS_SELECTABLE_INTERFACE_EVENT_SELECTION_CUT)
 SIG_FWD(UNPRESSED, EVAS_CLICKABLE_INTERFACE_EVENT_UNPRESSED)
 #undef SIG_FWD
 
-static Eina_Bool
-_FILE_CHOSEN_fwd(void *data, const Eo_Event *event)
+static void
+_file_chosen_path_then(void *data, void *v)
 {
-   const char *file = event->info;
+   const char *file = NULL;
    char *s;
 
-   if (!file) return EINA_TRUE;
+   eina_value_get(v, &file);
+
+   if (!file) return;
    ELM_FILESELECTOR_ENTRY_DATA_GET(data, sd);
 
+   evas_object_smart_callback_call(data, "file,chosen", (void *) file);
+
    s = elm_entry_utf8_to_markup(file);
    elm_object_text_set(sd->entry, s);
    free(s);
-   eo_event_callback_call
-     (data, ELM_FILESELECTOR_ENTRY_EVENT_FILE_CHOSEN, event->info);
+}
+
+static Eina_Bool
+_FILE_CHOSEN_fwd(void *data, const Eo_Event *event)
+{
+   Efl_Model *model = event->info;
+   Eina_Promise *promise = NULL;
+
+   if (!model) return EINA_TRUE;
+
+   efl_model_property_get(model, "path", &promise);
+   eina_promise_then(promise, _file_chosen_path_then, NULL, data);
+
+   // EVENTS: should not call legacy
+   //eo_event_callback_call
+   //  (data, ELM_FILESELECTOR_ENTRY_EVENT_FILE_CHOSEN, event->info);
 
    return EINA_TRUE;
 }
 
+// EVENTS: should not need this function
+static void
+_FILE_CHOSEN_fwd_path(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   const char *path = event_info;
+
+   Eo_Event e = {0,};
+   if (path)
+     e.info = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(eo_self, path));
+   _FILE_CHOSEN_fwd(data, &e);
+}
+
 static Eina_Bool
 _ACTIVATED_fwd(void *data, const Eo_Event *event)
 {
    const char *file;
+   Efl_Model *bmodel, *model;
+   Eina_Value path;
 
    ELM_FILESELECTOR_ENTRY_DATA_GET(data, sd);
 
    file = elm_object_text_get(sd->entry);
-   elm_fileselector_path_set(sd->button, file);
+
+   bmodel = elm_interface_fileselector_model_get(sd->button);
+   if (bmodel)
+     {
+         model = eo_add(eo_class_get(bmodel), NULL);
+         eina_value_setup(&path, EINA_VALUE_TYPE_STRING);
+         eina_value_set(&path, file);
+         efl_model_property_set(model, "path", &path, NULL);
+         eina_value_flush(&path);
+         elm_interface_fileselector_model_set(sd->button, model);
+     }
+
    eo_event_callback_call
      (data, ELM_FILESELECTOR_ENTRY_EVENT_ACTIVATED, event->info);
 
    return EINA_TRUE;
 }
 
+static void
+_model_free_eo_cb(void *eo)
+{
+   eo_unref(eo);
+}
+
 EOLIAN static void
 _elm_fileselector_entry_elm_layout_sizing_eval(Eo *obj, Elm_Fileselector_Entry_Data *sd EINA_UNUSED)
 {
@@ -286,8 +334,11 @@ _elm_fileselector_entry_evas_object_smart_add(Eo *obj, Elm_Fileselector_Entry_Da
   eo_event_callback_add(priv->button, event, _##name##_fwd, obj)
    SIG_FWD(CLICKED, EVAS_CLICKABLE_INTERFACE_EVENT_CLICKED);
    SIG_FWD(UNPRESSED, EVAS_CLICKABLE_INTERFACE_EVENT_UNPRESSED);
-   SIG_FWD(FILE_CHOSEN, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN);
+   // EVENTS: should not call legacy
+   //SIG_FWD(FILE_CHOSEN, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN);
 #undef SIG_FWD
+   // EVENTS: should not need this "callback_add"
+   evas_object_smart_callback_add(priv->button, "file,chosen", _FILE_CHOSEN_fwd_path, obj);
 
    priv->entry = elm_entry_add(obj);
    elm_entry_scrollable_set(priv->entry, EINA_TRUE);
@@ -352,31 +403,35 @@ _elm_fileselector_entry_eo_base_constructor(Eo *obj, Elm_Fileselector_Entry_Data
 }
 
 EINA_DEPRECATED EAPI void
-elm_fileselector_entry_selected_set(Evas_Object *obj,
-                                    const char *path)
+elm_fileselector_entry_selected_set(Evas_Object *obj, const char *path)
 {
    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
-   elm_interface_fileselector_selected_set(obj, path);
+   ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN(obj, sd);
+   elm_fileselector_button_path_set(sd->button, path);
 }
 
-EOLIAN static Eina_Bool
-_elm_fileselector_entry_elm_interface_fileselector_selected_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, const char *path)
+EOLIAN static void
+_elm_fileselector_entry_elm_interface_fileselector_selected_model_set(Eo *obj EINA_UNUSED,
+                                                                      Elm_Fileselector_Entry_Data *sd,
+                                                                      Efl_Model *model,
+                                                                      Eina_Promise_Owner *promise_owner)
 {
-   elm_fileselector_path_set(sd->button, path);
-   return EINA_TRUE;
+   elm_interface_fileselector_model_set(sd->button, model);
+   eina_promise_owner_value_set(promise_owner, eo_ref(model), _model_free_eo_cb);
 }
 
 EINA_DEPRECATED EAPI const char *
 elm_fileselector_entry_selected_get(const Evas_Object *obj)
 {
    ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
-   return elm_interface_fileselector_selected_get((Eo *) obj);
+   ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
+   return elm_fileselector_button_path_get(sd->button);
 }
 
-EOLIAN static const char *
-_elm_fileselector_entry_elm_interface_fileselector_selected_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd)
+EOLIAN static Efl_Model *
+_elm_fileselector_entry_elm_interface_fileselector_selected_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd)
 {
-   return elm_fileselector_path_get(sd->button);
+   return elm_interface_fileselector_model_get(sd->button);
 }
 
 EAPI void
@@ -418,15 +473,28 @@ elm_fileselector_entry_path_set(Evas_Object *obj,
                                 const char *path)
 {
    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
-   elm_interface_fileselector_path_set(obj, path);
+   ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN(obj, sd);
+   char *s = elm_entry_utf8_to_markup(path);
+   if (s)
+     {
+        elm_object_text_set(sd->entry, s);
+        free(s);
+     }
+
+   elm_fileselector_button_path_set(sd->button, path);
 }
 
-EOLIAN static void
-_elm_fileselector_entry_elm_interface_fileselector_path_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, const char *path)
+static void
+_fs_entry_model_path_get_then(void *data, void *v)
 {
+   Elm_Fileselector_Entry_Data *sd = data;
+   char *path = NULL;
    char *s;
 
-   elm_fileselector_path_set(sd->button, path);
+   if (!v)
+     return;
+
+   eina_value_get(v, &path);
    s = elm_entry_utf8_to_markup(path);
    if (s)
      {
@@ -435,19 +503,47 @@ _elm_fileselector_entry_elm_interface_fileselector_path_set(Eo *obj EINA_UNUSED,
      }
 }
 
+EOLIAN static void
+_elm_fileselector_entry_elm_interface_fileselector_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, Efl_Model *model)
+{
+   Eina_Promise *p = NULL;
+   elm_interface_fileselector_model_set(sd->button, model);
+
+   efl_model_property_get(model, "path", &p);
+   eina_promise_then(p, _fs_entry_model_path_get_then, NULL, sd);
+}
+
 EINA_DEPRECATED EAPI const char *
 elm_fileselector_entry_path_get(const Evas_Object *obj)
 {
    ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
-   return elm_interface_fileselector_path_get((Eo *) obj);
+   ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
+   free(sd->path);
+   sd->path = elm_entry_markup_to_utf8(elm_object_text_get(sd->entry));
+   return sd->path;
 }
 
-EOLIAN static const char *
-_elm_fileselector_entry_elm_interface_fileselector_path_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd)
+EOLIAN static Efl_Model *
+_elm_fileselector_entry_elm_interface_fileselector_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd)
 {
+   Efl_Model *bmodel, *ret;
+   Eina_Value path;
+   bmodel = elm_interface_fileselector_model_get(sd->button);
+   if (!bmodel)
+     {
+        WRN("no base Efl.Model");
+        return NULL;
+     }
+
+   ret = eo_add(eo_class_get(bmodel), NULL);
    free(sd->path);
    sd->path = elm_entry_markup_to_utf8(elm_object_text_get(sd->entry));
-   return sd->path;
+   eina_value_setup(&path, EINA_VALUE_TYPE_STRING);
+   eina_value_set(&path, sd->path);
+   efl_model_property_set(ret, "path", &path, NULL);
+   eina_value_flush(&path);
+
+   return ret;
 }
 
 EINA_DEPRECATED EAPI void
index d41300d..5d111b3 100644 (file)
@@ -38,21 +38,22 @@ class Elm.Fileselector (Elm.Layout, Elm.Interface.Fileselector,
       Evas.Object.Smart.del;
       Elm.Widget.focus_next;
       Elm.Widget.focus_direction_manager_is;
-      Elm.Widget.focus_direction;      
+      Elm.Widget.focus_direction;
       Elm.Widget.event;
       Elm.Widget.theme_apply;
       Elm.Widget.focus_next_manager_is;
       Elm.Layout.text.set;
-      Elm.Interface.Fileselector.selected_paths.get;
+      Elm.Interface.Fileselector.selected_models.get;
+      Elm.Interface.Fileselector.selected_model_get;
+      Elm.Interface.Fileselector.selected_model_set;
       Elm.Interface.Fileselector.custom_filter_append;
       Elm.Interface.Fileselector.expandable;
       Elm.Interface.Fileselector.thumbnail_size;
-      Elm.Interface.Fileselector.selected;
       Elm.Interface.Fileselector.mime_types_filter_append;
       Elm.Interface.Fileselector.hidden_visible;
       Elm.Interface.Fileselector.filters_clear;
       Elm.Interface.Fileselector.is_save;
-      Elm.Interface.Fileselector.path;
+      Elm.Interface.Fileselector.model;
       Elm.Interface.Fileselector.sort_method;
       Elm.Interface.Fileselector.multi_select;
       Elm.Interface.Fileselector.folder_only;
index dc81ec0..5cdd97e 100644 (file)
@@ -7,13 +7,14 @@ class Elm.Fileselector_Button (Elm.Button, Elm.Interface.Fileselector)
       Evas.Object.Smart.del;
       Elm.Widget.theme_apply;
       Elm.Button.admits_autorepeat.get;
-      Elm.Interface.Fileselector.selected_paths.get;
+      Elm.Interface.Fileselector.selected_models.get;
       Elm.Interface.Fileselector.expandable;
       Elm.Interface.Fileselector.thumbnail_size;
-      Elm.Interface.Fileselector.selected;
+      Elm.Interface.Fileselector.selected_model_get;
+      Elm.Interface.Fileselector.selected_model_set;
       Elm.Interface.Fileselector.hidden_visible;
       Elm.Interface.Fileselector.is_save;
-      Elm.Interface.Fileselector.path;
+      Elm.Interface.Fileselector.model;
       Elm.Interface.Fileselector.sort_method;
       Elm.Interface.Fileselector.multi_select;
       Elm.Interface.Fileselector.folder_only;
index 0b369df..a1561b8 100644 (file)
@@ -16,10 +16,11 @@ class Elm.Fileselector_Entry (Elm.Layout, Elm.Interface.Fileselector,
       Elm.Layout.text.set;
       Elm.Layout.text.get;
       Elm.Layout.sizing_eval;
-      Elm.Interface.Fileselector.selected;
+      Elm.Interface.Fileselector.selected_model_get;
+      Elm.Interface.Fileselector.selected_model_set;
       Elm.Interface.Fileselector.folder_only;
       Elm.Interface.Fileselector.is_save;
-      Elm.Interface.Fileselector.path;
+      Elm.Interface.Fileselector.model;
       Elm.Interface.Fileselector.expandable;
       Efl.Part.part;
    }
index 389857e..82dc00f 100644 (file)
@@ -41,18 +41,6 @@ interface Elm.Interface.Fileselector ()
             only: bool;
          }
       }
-      @property selected {
-         set {
-            [[Set, programmatically, the currently selected file/directory in the given file selector widget]]
-            return: bool;
-         }
-         get {
-            [[Get the currently selected item's (full) path, in the given file the given file selector widget]]
-         }
-         values {
-            path: string;
-         }
-      }
       @property thumbnail_size {
          set {
             [[Set the size for the thumbnail of the file selector widget's view.]]
@@ -109,15 +97,15 @@ interface Elm.Interface.Fileselector ()
             expand: bool;
          }
       }
-      @property path {
+      @property model {
          set {
             [[Set, programmatically, the directory that a given file selector widget will display contents from]]
          }
          get {
-            [[Get the parent directory's path that a given file selector selector widget will display contents from]]
+            [[Get the directory's model that a given file selector selector widget display contents from]]
          }
          values {
-            path: string;
+            model: Efl.Model;
          }
       }
       @property mode {
@@ -142,12 +130,12 @@ interface Elm.Interface.Fileselector ()
             is_save: bool;
          }
       }
-      @property selected_paths {
+      @property selected_models {
          get {
-            [[Get a list of selected paths in the fileselector.]]
+            [[Get a list of models selected in the fileselector.]]
          }
          values {
-            ret: const(list<string>);
+            ret: const(list<Efl.Model>);
          }
       }
       @property current_name {
@@ -159,6 +147,17 @@ interface Elm.Interface.Fileselector ()
             name: string;
          }
       }
+      selected_model_set {
+         [[Set, programmatically, the currently selected file/directory in the given file selector widget]]
+         params {
+            @in model: Efl.Model; [[Model to be set]]
+            @inout promise: promise<Efl.Model>; [[Promise returning the recorded selected model or error]]
+         }
+      }
+      selected_model_get {
+         [[Get the currently selected item's model, in the given file the given file selector widget]]
+         return: Efl.Model;
+      }
       custom_filter_append {
          [[Append custom filter into filter list]]
          params {
index e3f7c76..c352887 100644 (file)
@@ -21,6 +21,8 @@
  */
 
 typedef struct _Elm_Fileselector_Filter Elm_Fileselector_Filter;
+typedef struct _Listing_Request Listing_Request;
+typedef struct _Elm_Fileselector_Item_Data Elm_Fileselector_Item_Data;
 
 /**
  * Base layout smart data extended with fileselector instance data.
@@ -42,29 +44,30 @@ struct _Elm_Fileselector_Data
    Evas_Object             *ok_button;
    Evas_Object             *cancel_button;
 
+   Eina_List               *files_item_data;
+
    Eina_List               *filter_list;
    Elm_Fileselector_Filter *current_filter;
 
    /* a list of selected paths. only for multi selection */
-   Eina_List               *paths;
+   Eina_List               *multi_selection;
+   Eina_List               *multi_selection_tmp;
 
    const char              *path;
-   const char              *prev_path;
-   const char              *selection;
+   Efl_Model               *model;
+   Efl_Model               *prev_model;
    Ecore_Idler             *populate_idler;
    Ecore_Idler             *path_entry_idler;
 
    const char              *path_separator;
    const char              *search_string;
 
-   Eio_File                *current;
-   Eio_Monitor             *monitor;
-   Eina_List               *handlers;
+   Listing_Request         *current_populate_lreq;
 
    Evas_Coord_Size          thumbnail_size;
 
    /* a sort method to decide orders of files/directories */
-   int                    (*sort_method)(const char *, const char *);
+   int                    (*sort_method)(const Elm_Fileselector_Item_Data *, const Elm_Fileselector_Item_Data *);
 
    Elm_Fileselector_Mode    mode;
    Elm_Fileselector_Sort    sort_type;
@@ -86,20 +89,38 @@ struct _Elm_Fileselector_Data
 struct sel_data
 {
    Evas_Object      *fs;
-   Eina_Stringshare *path;
-   Eina_Stringshare *selected;
+   Efl_Model        *model;
+   Efl_Model        *selected;
 };
 
-typedef struct _Listing_Request Listing_Request;
 struct _Listing_Request
 {
    Elm_Fileselector_Data *sd;
    Elm_Object_Item             *parent_it;
 
    Evas_Object                 *obj;
-   const char                  *path;
-   const char                  *selected;
+   Efl_Model                   *model;
+   Efl_Model                   *selected;
+   Eina_Stringshare            *path;
+   Eina_Stringshare            *selected_path;
+   int                          item_total;
+   int                          item_processed_count;
    Eina_Bool                    first : 1;
+   Eina_Bool                    valid : 1;
+};
+
+struct _Elm_Fileselector_Item_Data
+{
+   void                        *user_data;
+   Efl_Model                   *model;
+   Eina_Stringshare            *path;
+   Eina_Stringshare            *filename;
+   int64_t                      size;
+   double                       mtime;
+   Eina_Stringshare            *mime_type;
+   Efl_Model                   *parent_model;
+   const char                  *parent_path;
+   Eina_Bool                    is_dir : 1;
 };
 
 typedef enum {
index a328989..23a15f6 100644 (file)
@@ -37,8 +37,9 @@ struct _Elm_Fileselector_Button_Data
 
    struct
    {
+      Efl_Model              *model;
       const char             *path;
-      const char             *selection;
+      Efl_Model              *selection;
       Evas_Coord_Size         thumbnail_size;
       Elm_Fileselector_Mode   mode;
       Elm_Fileselector_Sort   sort_type;