summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/elementary/elc_fileselector.c1108
-rw-r--r--src/lib/elementary/elc_fileselector_button.c118
-rw-r--r--src/lib/elementary/elc_fileselector_entry.c96
-rw-r--r--src/lib/elementary/elm_fileselector.eo3
-rw-r--r--src/lib/elementary/elm_fileselector_button.eo3
-rw-r--r--src/lib/elementary/elm_fileselector_entry.eo3
-rw-r--r--src/lib/elementary/elm_interface_fileselector.c4
-rw-r--r--src/lib/elementary/elm_interface_fileselector.eo19
-rw-r--r--src/lib/elementary/elm_widget_fileselector.h9
9 files changed, 568 insertions, 795 deletions
diff --git a/src/lib/elementary/elc_fileselector.c b/src/lib/elementary/elc_fileselector.c
index e09ff15fd6..092679efdb 100644
--- a/src/lib/elementary/elc_fileselector.c
+++ b/src/lib/elementary/elc_fileselector.c
@@ -11,8 +11,10 @@
11 11
12#define EFL_ACCESS_OBJECT_PROTECTED 12#define EFL_ACCESS_OBJECT_PROTECTED
13#define EFL_ACCESS_WIDGET_ACTION_PROTECTED 13#define EFL_ACCESS_WIDGET_ACTION_PROTECTED
14#define ELM_INTERFACE_FILESELECTOR_BETA
14 15
15#include <Elementary.h> 16#include <Elementary.h>
17#include "Eio_Eo.h"
16#include "elm_priv.h" 18#include "elm_priv.h"
17#include "elm_fileselector_button.eo.h" 19#include "elm_fileselector_button.eo.h"
18#include "elm_fileselector_entry.eo.h" 20#include "elm_fileselector_entry.eo.h"
@@ -45,8 +47,6 @@ static Elm_Gengrid_Item_Class *grid_itc[ELM_FILE_LAST];
45 47
46static const char _text_activated_model_key[] = "__fs_text_activated_model"; 48static const char _text_activated_model_key[] = "__fs_text_activated_model";
47static const char _text_activated_path_key[] = "__fs_text_activated_path"; 49static const char _text_activated_path_key[] = "__fs_text_activated_path";
48static const char _selected_model_set_promise_owner_key[] = "__fs_selected_model_set_promise_owner";
49static const char _selected_model_set_model_key[] = "__fs_selected_model_set_model";
50 50
51EAPI Eina_Error ELM_FILESELECTOR_ERROR_UNKNOWN = 0; 51EAPI Eina_Error ELM_FILESELECTOR_ERROR_UNKNOWN = 0;
52EAPI Eina_Error ELM_FILESELECTOR_ERROR_INVALID_MODEL = 0; 52EAPI Eina_Error ELM_FILESELECTOR_ERROR_INVALID_MODEL = 0;
@@ -120,14 +120,6 @@ _focus_chain_update(Eo *obj, Elm_Fileselector_Data *pd)
120 efl_ui_focus_manager_calc_update_order(efl_ui_focus_object_focus_manager_get(obj), obj, tmp); 120 efl_ui_focus_manager_calc_update_order(efl_ui_focus_object_focus_manager_get(obj), obj, tmp);
121} 121}
122 122
123static void
124_model_free_eo_cb(void *data)
125{
126 Eo *eo = data;
127 efl_unref(eo);
128}
129
130
131void 123void
132_event_to_legacy_call(Eo *obj, const Efl_Event_Description *evt_desc, void *event_info) 124_event_to_legacy_call(Eo *obj, const Efl_Event_Description *evt_desc, void *event_info)
133{ 125{
@@ -160,23 +152,16 @@ static void
160_elm_fileselector_replace_model(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, Efl_Model *model, const char *path) 152_elm_fileselector_replace_model(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, Efl_Model *model, const char *path)
161{ 153{
162 if (sd->model) 154 if (sd->model)
163 { 155 _monitoring_stop(fs, sd, sd->model);
164 _monitoring_stop(fs, sd, sd->model); 156
165 efl_unref(sd->model); 157 efl_replace(&sd->model, model);
166 } 158 eina_stringshare_replace(&sd->path, path);
167 159
168 if (model && path) 160 if (model && path)
169 { 161 {
170 sd->model = efl_ref(model);
171 eina_stringshare_replace(&sd->path, path);
172 _monitoring_start(fs, sd, sd->model); 162 _monitoring_start(fs, sd, sd->model);
173 /* TODO: sub directory should be monitored for expand mode */ 163 /* TODO: sub directory should be monitored for expand mode */
174 } 164 }
175 else
176 {
177 sd->model = NULL;
178 eina_stringshare_replace(&sd->path, NULL);
179 }
180} 165}
181 166
182/* final routine on deletion */ 167/* final routine on deletion */
@@ -204,31 +189,10 @@ _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
204 efl_ui_mirrored_set(sd->home_button, rtl); 189 efl_ui_mirrored_set(sd->home_button, rtl);
205} 190}
206 191
207static Eina_Bool 192static Eina_Future *
208_accessor_value_get(Eina_Accessor *acc, int id, void *res)
209{
210 Eina_Value *v = NULL;
211
212 if (!eina_accessor_data_get(acc, id, (void **) &v))
213 return EINA_FALSE;
214
215 eina_value_get(v, res);
216 return EINA_TRUE;
217}
218
219static Efl_Future*
220_model_str_property_set(Efl_Model *model, const char *property_name, const char *property_value) 193_model_str_property_set(Efl_Model *model, const char *property_name, const char *property_value)
221{ 194{
222 Efl_Future* r; 195 return efl_model_property_set(model, property_name, eina_value_string_new(property_value));
223 Eina_Value v;
224 eina_value_setup(&v, EINA_VALUE_TYPE_STRING);
225 eina_value_set(&v, property_value);
226
227 r = efl_model_property_set(model, property_name, &v);
228
229 eina_value_flush(&v);
230
231 return r;
232} 196}
233 197
234EOLIAN static Efl_Ui_Theme_Apply 198EOLIAN static Efl_Ui_Theme_Apply
@@ -408,7 +372,6 @@ _itc_del(void *data,
408 eina_stringshare_del(it_data->path); 372 eina_stringshare_del(it_data->path);
409 eina_stringshare_del(it_data->filename); 373 eina_stringshare_del(it_data->filename);
410 eina_stringshare_del(it_data->mime_type); 374 eina_stringshare_del(it_data->mime_type);
411 efl_unref(it_data->parent_model);
412 eina_stringshare_del(it_data->parent_path); 375 eina_stringshare_del(it_data->parent_path);
413 free(it_data); 376 free(it_data);
414} 377}
@@ -657,6 +620,7 @@ static void
657_signal_first(Listing_Request *lreq) 620_signal_first(Listing_Request *lreq)
658{ 621{
659 Elm_Fileselector_Data *sd = lreq->sd; 622 Elm_Fileselector_Data *sd = lreq->sd;
623
660 if (!lreq->first) return; 624 if (!lreq->first) return;
661 if (!sd) return; 625 if (!sd) return;
662 626
@@ -685,59 +649,199 @@ static void
685_process_last(Listing_Request *lreq) 649_process_last(Listing_Request *lreq)
686{ 650{
687 Elm_Fileselector_Data *sd = lreq->sd; 651 Elm_Fileselector_Data *sd = lreq->sd;
688 elm_progressbar_pulse(sd->spinner, EINA_FALSE);
689 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
690 652
691 _listing_request_cleanup(lreq); 653 if (lreq->valid)
654 {
655 elm_progressbar_pulse(sd->spinner, EINA_FALSE);
656 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
657 }
692 658
659 _listing_request_cleanup(lreq);
693 sd->current_populate_lreq = NULL; 660 sd->current_populate_lreq = NULL;
694} 661}
695 662
663static void
664_listing_request_cleanup(Listing_Request *lreq)
665{
666 if (!lreq) return ;
667 if (lreq->parent_it)
668 efl_unref(lreq->parent_it);
669 efl_unref(lreq->obj);
670 efl_unref(lreq->model);
671 if (lreq->selected)
672 efl_unref(lreq->selected);
673 eina_stringshare_del(lreq->path);
674 eina_stringshare_del(lreq->selected_path);
675 free(lreq);
676}
677
678static Eina_Bool
679_check_again(Eina_Value *fetch)
680{
681 Eina_Error err = 0;
682 char *str;
683
684 if (eina_value_type_get(fetch) != EINA_VALUE_TYPE_ERROR)
685 return EINA_FALSE;
686
687 eina_value_error_get(fetch, &err);
688 if (err == EAGAIN) return EINA_TRUE;
689
690 str = eina_value_to_string(fetch);
691 ERR("Unexpected error: '%s'.", str);
692 free(str);
693
694 return EINA_TRUE;
695}
696
696static Eina_Bool 697static Eina_Bool
697_process_child(Elm_Fileselector_Item_Data *it_data, Eina_Accessor *values_acc) 698_fetch_string_value(Efl_Model *child, const char *name, char **str)
698{ 699{
700 Eina_Value *fetch;
701 Eina_Bool r = EINA_FALSE;
702
703 *str = NULL;
704
705 fetch = efl_model_property_get(child, name);
706 if (_check_again(fetch)) goto on_error;
707
708 *str = eina_value_to_string(fetch);
709 r = EINA_TRUE;
710
711 on_error:
712 eina_value_free(fetch);
713 return r;
714}
715
716static Eina_Bool
717_fetch_bool_value(Efl_Model *child, const char *name, Eina_Bool *b)
718{
719 Eina_Value *fetch;
720 Eina_Bool r = EINA_FALSE;
721
722 fetch = efl_model_property_get(child, name);
723 if (_check_again(fetch)) goto on_error;
724 if (!eina_value_bool_get(fetch, b)) goto on_error;
725
726 r = EINA_TRUE;
727
728 on_error:
729 eina_value_free(fetch);
730 return r;
731}
732
733static Eina_Bool
734_fetch_double_value(Efl_Model *child, const char *name, double *d)
735{
736 Eina_Value convert = EINA_VALUE_EMPTY;
737 Eina_Value *fetch;
738 Eina_Bool r = EINA_FALSE;
739
740 fetch = efl_model_property_get(child, name);
741 if (_check_again(fetch)) goto on_error;
742 if (!eina_value_setup(&convert, EINA_VALUE_TYPE_DOUBLE))
743 goto on_error;
744 if (!eina_value_convert(fetch, &convert))
745 goto on_error;
746 if (!eina_value_double_get(&convert, d)) goto on_error;
747
748 r = EINA_TRUE;
749
750 on_error:
751 eina_value_flush(&convert);
752 eina_value_free(fetch);
753 return r;
754}
755
756static Eina_Bool
757_fetch_int64_value(Efl_Model *child, const char *name, int64_t *i)
758{
759 Eina_Value convert = EINA_VALUE_EMPTY;
760 Eina_Value *fetch;
761 Eina_Bool r = EINA_FALSE;
762
763 fetch = efl_model_property_get(child, name);
764 if (_check_again(fetch)) goto on_error;
765 if (!eina_value_setup(&convert, EINA_VALUE_TYPE_INT64))
766 goto on_error;
767 if (!eina_value_convert(fetch, &convert))
768 goto on_error;
769 if (!eina_value_int64_get(&convert, i)) goto on_error;
770
771 r = EINA_TRUE;
772
773 on_error:
774 eina_value_free(fetch);
775 return r;
776}
777
778static void _invalidate(void *data, const Efl_Event *ev);
779static void _properties_changed(void *data, const Efl_Event *ev);
780
781EFL_CALLBACKS_ARRAY_DEFINE(child_model_callbacks,
782 { EFL_MODEL_EVENT_PROPERTIES_CHANGED, _properties_changed },
783 { EFL_EVENT_INVALIDATE, _invalidate });
784
785static void
786_process_model(Elm_Fileselector_Data *sd, Efl_Model *child)
787{
788 Elm_Fileselector_Item_Data *it_data;
699 Elm_Object_Item *item; 789 Elm_Object_Item *item;
700 Listing_Request *lreq = it_data->user_data;
701 int itcn = ELM_FILE_UNKNOW; 790 int itcn = ELM_FILE_UNKNOW;
702 const char *path = NULL; 791
703 const char *filename = NULL; 792 Efl_Model *parent = efl_parent_get(child);
704 const char *mime_type = NULL; 793 char *parent_path = NULL;
794 // FIXME: This could be only needed with ELM_FILESELECTOR_MIME_FILTER
795 char *mime_type = NULL;
796 char *filename = NULL;
797 char *path = NULL;
705 int64_t size = 0; 798 int64_t size = 0;
706 double mtime = 0; 799 double mtime = 0;
707 Eina_Bool dir = EINA_FALSE; 800 Eina_Bool dir = EINA_FALSE;
708 Elm_Fileselector_Data *sd = lreq->sd;
709 it_data->user_data = NULL;
710 801
711 if (!sd->files_view) 802 if (!_fetch_string_value(parent, "path", &parent_path) ||
712 return EINA_FALSE; 803 !_fetch_string_value(child, "path", &path) ||
804 !_fetch_string_value(child, "filename", &filename) ||
805 !_fetch_string_value(child, "mime_type", &mime_type) ||
806 !_fetch_double_value(child, "mtime", &mtime) ||
807 !_fetch_int64_value(child, "size", &size) ||
808 !_fetch_bool_value(child, "is_dir", &dir))
809 {
810 // SETUP listener to retry fetching all data when ready
811 efl_event_callback_array_add(efl_ref(child), child_model_callbacks(), sd);
812 goto cleanup;
813 }
713 814
714 if (!_accessor_value_get(values_acc, 0, &path) || !path || 815 if (!path || !filename || !mime_type)
715 !_accessor_value_get(values_acc, 1, &filename) || !filename ||
716 !_accessor_value_get(values_acc, 2, &dir) ||
717 !_accessor_value_get(values_acc, 3, &size) ||
718 !_accessor_value_get(values_acc, 4, &mtime) ||
719 !_accessor_value_get(values_acc, 5, &mime_type))
720 { 816 {
721 ERR("missing child Efl.Model data"); 817 ERR("Wrong file info ('%s', '%s', '%s').", path, filename, mime_type);
722 return EINA_FALSE; 818 goto cleanup;
723 } 819 }
724 820
725 if (!_filter_child(sd, path, filename, dir, mime_type)) 821 if (!_filter_child(sd, path, filename, dir, mime_type))
726 return EINA_FALSE; 822 goto cleanup;
727 823
728 _signal_first(lreq); 824 it_data = calloc(1, sizeof(Elm_Fileselector_Item_Data));
825 if (!it_data)
826 {
827 ERR("Not enough memory.");
828 goto cleanup;
829 }
729 830
831 it_data->model = efl_ref(child);
832 it_data->parent_model = efl_parent_get(child);
833 it_data->parent_path = eina_stringshare_add(parent_path);
730 it_data->path = eina_stringshare_add(path); 834 it_data->path = eina_stringshare_add(path);
731 it_data->filename = eina_stringshare_add(filename); 835 it_data->filename = eina_stringshare_add(filename);
732 it_data->size = size; 836 it_data->size = size;
733 it_data->mtime = mtime; 837 it_data->mtime = mtime;
734 it_data->mime_type = eina_stringshare_add(mime_type); 838 it_data->mime_type = eina_stringshare_add(mime_type);
735 it_data->parent_model = efl_ref(lreq->model);
736 it_data->parent_path = eina_stringshare_add(lreq->path);
737 it_data->is_dir = dir; 839 it_data->is_dir = dir;
738 840
739 if (it_data->is_dir) 841 if (dir)
740 itcn = ELM_DIRECTORY; 842 {
843 itcn = ELM_DIRECTORY;
844 }
741 else 845 else
742 { 846 {
743 if (evas_object_image_extension_can_load_get(it_data->filename)) 847 if (evas_object_image_extension_can_load_get(it_data->filename))
@@ -745,210 +849,78 @@ _process_child(Elm_Fileselector_Item_Data *it_data, Eina_Accessor *values_acc)
745 } 849 }
746 850
747 if (sd->mode == ELM_FILESELECTOR_LIST) 851 if (sd->mode == ELM_FILESELECTOR_LIST)
852 item = elm_genlist_item_sorted_insert(sd->files_view, list_itc[itcn],
853 it_data,
854 NULL,
855 (sd->expand && itcn == ELM_DIRECTORY) ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
856 _file_list_cmp, NULL, NULL);
857 else
858 item = elm_gengrid_item_sorted_insert(sd->files_view, grid_itc[itcn],
859 it_data,
860 _file_grid_cmp, NULL, NULL);
861 efl_key_data_set(child, ".item.data", item);
862
863 // Is this item selected
864 if (sd->target)
748 { 865 {
749 item = elm_genlist_item_sorted_insert(sd->files_view, list_itc[itcn], 866 const char *target_path = eio_model_path_get(sd->target);
750 it_data,
751 lreq->parent_it,
752 ((sd->expand) && (itcn == ELM_DIRECTORY))
753 ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
754 _file_list_cmp, NULL, NULL);
755 867
756 if (lreq->selected_path && it_data->path == lreq->selected_path) 868 if (!strcmp(it_data->path, target_path))
757 { 869 {
758 elm_genlist_item_selected_set(item, EINA_TRUE); 870 elm_genlist_item_selected_set(item, EINA_TRUE);
759 elm_object_text_set(sd->name_entry, it_data->filename); 871 elm_object_text_set(sd->name_entry, it_data->filename);
760 }
761 }
762 else if (sd->mode == ELM_FILESELECTOR_GRID)
763 {
764 item = elm_gengrid_item_sorted_insert(sd->files_view, grid_itc[itcn],
765 it_data,
766 _file_grid_cmp, NULL, NULL);
767 872
768 if (lreq->selected_path && it_data->path == lreq->selected_path) 873 efl_replace(&sd->target, NULL);
769 {
770 elm_gengrid_item_selected_set(item, EINA_TRUE);
771 elm_object_text_set(sd->name_entry, it_data->filename);
772 } 874 }
773 } 875 }
774 return EINA_TRUE;
775}
776
777static void
778_process_child_cb(void *data, Efl_Event const*event)
779{
780 Elm_Fileselector_Item_Data *it_data = data;
781 Listing_Request *lreq = it_data->user_data;
782 Efl_Future_Event_Success *ev = event->info;
783 Eina_Accessor *values_acc = ev->value;
784
785 if (!lreq->valid || !_process_child(it_data, values_acc))
786 {
787 efl_unref(it_data->model);
788 free(it_data);
789 }
790 876
791 ++(lreq->item_processed_count); 877 cleanup:
792 if (lreq->item_processed_count >= lreq->item_total) 878 free(mime_type);
793 { 879 free(filename);
794 if (!lreq->valid) 880 free(path);
795 { 881 free(parent_path);
796 _listing_request_cleanup(lreq);
797 return;
798 }
799 _signal_first(lreq);
800 _process_last(lreq);
801 }
802} 882}
803 883
804static void 884static void
805_process_child_error_cb(void *data, Efl_Event const* event EINA_UNUSED) 885_invalidate(void *data EINA_UNUSED, const Efl_Event *ev)
806{ 886{
807 Elm_Fileselector_Item_Data *it_data = data; 887 efl_unref(ev->object);
808 Listing_Request *lreq = it_data->user_data;
809
810 efl_unref(it_data->model);
811 free(it_data);
812
813 ERR("Failed to access to a model property");
814
815 ++(lreq->item_processed_count);
816 if (lreq->item_processed_count >= lreq->item_total)
817 {
818 if (!lreq->valid)
819 {
820 _listing_request_cleanup(lreq);
821 return;
822 }
823 _signal_first(lreq);
824 _process_last(lreq);
825 }
826} 888}
827 889
828static void 890static void
829_listing_request_cleanup(Listing_Request *lreq) 891_properties_changed(void *data, const Efl_Event *ev)
830{ 892{
831 if (lreq->parent_it) 893 Elm_Fileselector_Data *sd = data;
832 efl_unref(lreq->parent_it); 894 Efl_Model *child = ev->object;
833 efl_unref(lreq->obj); 895
834 efl_unref(lreq->model); 896 efl_event_callback_array_del(child, child_model_callbacks(), sd);
835 if (lreq->selected) 897 _process_model(sd, child);
836 efl_unref(lreq->selected); 898 efl_unref(child);
837 eina_stringshare_del(lreq->path);
838 eina_stringshare_del(lreq->selected_path);
839 free(lreq);
840} 899}
841 900
842static void 901static Eina_Value
843_process_children_cb(void *data, Efl_Event const *event) 902_process_children_cb(void *data, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED)
844{ 903{
845 Listing_Request *lreq = data; 904 Listing_Request *lreq = data;
846 Efl_Future_Event_Success *ev = event->info; 905 Efl_Model *child = NULL;
847 Eina_Accessor *all_promises = ev->value; 906 unsigned int i, len;
848 Eina_Accessor *children_accessor = NULL;
849 Elm_Fileselector_Item_Data *it_data = NULL;
850 const char *path = NULL;
851 const char *selected_path = NULL;
852 unsigned int count = 0;
853 Elm_Fileselector_Data *sd = lreq->sd;
854
855 if (!lreq->valid)
856 {
857 _listing_request_cleanup(lreq);
858 return;
859 }
860
861 if (_accessor_value_get(all_promises, 0, &path) && path &&
862 eina_accessor_data_get(all_promises, 1, (void **) &children_accessor))
863 {
864 if (lreq->selected)
865 {
866 if (!_accessor_value_get(all_promises, 2, &selected_path) ||
867 !selected_path)
868 {
869 ERR("missing selected Efl.Model path information");
870 _listing_request_cleanup(lreq);
871 sd->current_populate_lreq = NULL;
872 return;
873 }
874 lreq->selected_path = eina_stringshare_add(selected_path);
875 }
876 lreq->path = eina_stringshare_add(path);
877 if (children_accessor)
878 {
879 Eina_List *children = NULL;
880 void *child = NULL;
881 EINA_ACCESSOR_FOREACH(children_accessor, count, child)
882 {
883 children = eina_list_append(children, child);
884 }
885 907
886 lreq->item_total = count; 908 if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ERROR)
909 goto end;
887 910
888 EINA_LIST_FREE(children, child) 911 if (!lreq->valid) goto end;
889 {
890 Efl_Future *futures[7];
891 Efl_Future *future_all = NULL;
892 const char *prop[6] = {
893 "path", "filename", "is_dir", "size", "mtime", "mime_type"
894 };
895 unsigned int i;
896
897 it_data = calloc(1, sizeof(Elm_Fileselector_Item_Data));
898 if (!it_data)
899 {
900 ERR("insufficient memory");
901 break;
902 }
903
904 it_data->model = efl_ref(child);
905 it_data->user_data = lreq;
906
907 for (i = 0; i != 6; i++)
908 {
909 futures[i] = efl_model_property_get(child, prop[i]);
910 }
911 912
912 future_all = efl_future_all(futures[0], futures[1], futures[2], futures[3], futures[4], futures[5]); 913 EINA_VALUE_ARRAY_FOREACH(&v, len, i, child)
913 efl_future_then(future_all, _process_child_cb, _process_child_error_cb, NULL, it_data); 914 _process_model(lreq->sd, child);
914 }
915 915
916 // NOTE: lreq may have been deallocated in the previous loop 916 lreq->item_total = len;
917 lreq = NULL;
918 }
919 if (count == 0)
920 {
921 _signal_first(lreq);
922 _process_last(lreq);
923 }
924 }
925 else
926 {
927 ERR("missing Efl.Model information");
928 _listing_request_cleanup(lreq);
929 sd->current_populate_lreq = NULL;
930 }
931}
932 917
933static void 918 _signal_first(lreq);
934_process_children_error_cb(void *data, Efl_Event const* event)
935{
936 Eina_Error error = ((Efl_Future_Event_Failure*)event->info)->error;
937 Listing_Request *lreq = data;
938 Elm_Fileselector_Data *sd = lreq->sd;
939 919
940 if (error != EINA_ERROR_FUTURE_CANCEL) 920 end:
941 { 921 _process_last(lreq);
942 ERR("failed to get information from Efl.Model");
943 }
944 922
945 if (lreq->valid) 923 return v;
946 {
947 elm_progressbar_pulse(sd->spinner, EINA_FALSE);
948 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
949 sd->current_populate_lreq = NULL;
950 }
951 _listing_request_cleanup(lreq);
952} 924}
953 925
954static void 926static void
@@ -958,9 +930,12 @@ _populate(Evas_Object *obj,
958 Efl_Model *selected) 930 Efl_Model *selected)
959{ 931{
960 ELM_FILESELECTOR_DATA_GET(obj, sd); 932 ELM_FILESELECTOR_DATA_GET(obj, sd);
961 if (!model) return;
962
963 Listing_Request *lreq; 933 Listing_Request *lreq;
934 Eina_Future *future;
935 Eina_Value *fetch;
936 char *string;
937
938 if (!model) return;
964 939
965 if (sd->expand && sd->current_populate_lreq) 940 if (sd->expand && sd->current_populate_lreq)
966 return; 941 return;
@@ -998,15 +973,26 @@ _populate(Evas_Object *obj,
998 if (elm_object_disabled_get(sd->name_entry)) 973 if (elm_object_disabled_get(sd->name_entry))
999 elm_object_text_set(sd->name_entry, ""); 974 elm_object_text_set(sd->name_entry, "");
1000 975
1001 Efl_Future *futures[4] = {NULL,}; 976 fetch = efl_model_property_get(model, "path");
1002 Efl_Future *future_all = NULL; 977 string = eina_value_to_string(fetch);
1003 futures[0] = efl_model_property_get(model, "path"); 978 lreq->path = eina_stringshare_add(string);
1004 futures[1] = efl_model_children_slice_get(model, 0, 0); 979 eina_value_free(fetch);
980 free(string);
981
1005 if (selected) 982 if (selected)
1006 futures[2] = efl_model_property_get(selected, "path"); 983 {
984 fetch = efl_model_property_get(selected, "path");
985 string = eina_value_to_string(fetch);
986 lreq->selected_path = eina_stringshare_add(string);
987 eina_value_free(fetch);
988 free(string);
989 }
990
991 future = efl_model_children_slice_get(model, 0, efl_model_children_count_get(model));
992 future = eina_future_then(future, _process_children_cb, lreq);
993 efl_future_Eina_FutureXXX_then(obj, future);
1007 994
1008 future_all = efl_future_all(futures[0], futures[1], futures[2]); 995 _signal_first(lreq);
1009 efl_future_then(future_all, _process_children_cb, _process_children_error_cb, NULL, lreq);
1010} 996}
1011 997
1012static void 998static void
@@ -1066,15 +1052,13 @@ _schedule_populate(Evas_Object *fs,
1066 Efl_Model *selected) 1052 Efl_Model *selected)
1067{ 1053{
1068 struct sel_data *sdata; 1054 struct sel_data *sdata;
1055
1069 sdata = calloc(1, sizeof(*sdata)); 1056 sdata = calloc(1, sizeof(*sdata));
1070 if (!sdata) return; 1057 if (!sdata) return;
1071 1058
1072 sdata->fs = fs; 1059 sdata->fs = fs;
1073 sdata->model = model; 1060 sdata->model = model ? efl_ref(model) : NULL;
1074 sdata->selected = selected; 1061 sdata->selected = selected ? efl_ref(selected) : NULL;
1075
1076 if (model) efl_ref(model);
1077 if (selected) efl_ref(selected);
1078 1062
1079 if (sd->populate_idler) 1063 if (sd->populate_idler)
1080 { 1064 {
@@ -1283,25 +1267,35 @@ _on_dir_up(void *data, const Efl_Event *event EINA_UNUSED)
1283 ELM_FILESELECTOR_DATA_GET(fs, sd); 1267 ELM_FILESELECTOR_DATA_GET(fs, sd);
1284 1268
1285 parent = efl_parent_get(sd->model); 1269 parent = efl_parent_get(sd->model);
1286 if (!parent) 1270 if (!parent) return;
1287 return; 1271
1288 _populate(fs, parent, NULL, NULL); 1272 if (!efl_isa(parent, EIO_MODEL_CLASS))
1273 {
1274 const char *path = eio_model_path_get(sd->model);
1275 char dir[PATH_MAX] = "";
1276 char *r;
1277
1278 eina_strlcpy(dir, path, sizeof (dir));
1279 r = dirname(dir);
1280
1281 // In case we have reached '/'
1282 if (!strcmp(r, path)) return ;
1283
1284 elm_fileselector_path_set(fs, r);
1285 }
1286 else
1287 {
1288 _populate(fs, parent, NULL, NULL);
1289 }
1289} 1290}
1290 1291
1291static void 1292static void
1292_home(void *data, const Efl_Event *event) 1293_home(void *data, const Efl_Event *event EINA_UNUSED)
1293{ 1294{
1294 Evas_Object *fs = data; 1295 Evas_Object *fs = data;
1295 ELM_FILESELECTOR_DATA_GET(fs, sd);
1296 1296
1297 // FIXME: maybe use vpath 1297 // FIXME: maybe use vpath
1298 if (!sd->model || efl_isa(sd->model, EIO_MODEL_CLASS)) 1298 elm_fileselector_path_set(fs, eina_environment_home_get());
1299 {
1300 Eio_Model *model = efl_add(EIO_MODEL_CLASS, efl_provider_find(event->object, EFL_LOOP_CLASS),
1301 eio_model_path_set(efl_added, eina_environment_home_get()));
1302 _populate(fs, model, NULL, NULL);
1303 efl_unref(model);
1304 }
1305} 1299}
1306 1300
1307static void 1301static void
@@ -1320,7 +1314,7 @@ _current_filter_changed(void *data,
1320} 1314}
1321 1315
1322static void 1316static void
1323_ok(void *data, const Efl_Event *event EINA_UNUSED) 1317_ok(void *data, const Efl_Event *event)
1324{ 1318{
1325 const char *name; 1319 const char *name;
1326 const char *selection = NULL; 1320 const char *selection = NULL;
@@ -1343,7 +1337,7 @@ _ok(void *data, const Efl_Event *event EINA_UNUSED)
1343 else 1337 else
1344 selection = eina_stringshare_printf("%s/%s", sd->path, name); 1338 selection = eina_stringshare_printf("%s/%s", sd->path, name);
1345 1339
1346 selected_model = efl_add(efl_class_get(sd->model), NULL); 1340 selected_model = efl_add(efl_class_get(sd->model), event->object);
1347 _model_str_property_set(selected_model, "path", selection); 1341 _model_str_property_set(selected_model, "path", selection);
1348 1342
1349 _model_event_call 1343 _model_event_call
@@ -1386,119 +1380,77 @@ _text_activated_free_fs_data(Elm_Fileselector *fs)
1386 efl_unref(fs); 1380 efl_unref(fs);
1387} 1381}
1388 1382
1389static void 1383static Eina_Value
1390_text_activated_is_dir_then(void *data, Efl_Event const *event) 1384_on_text_activated_set_path_then(void *data, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED)
1391{ 1385{
1392 Evas_Object *fs = data; 1386 Evas_Object *fs = data;
1393 Eina_Bool is_dir = EINA_FALSE; 1387 Eina_Value *fetch = NULL;
1394 ELM_FILESELECTOR_DATA_GET(fs, sd); 1388 Efl_Model *parent;
1395
1396 Efl_Model *model = efl_key_ref_get(fs, _text_activated_model_key); 1389 Efl_Model *model = efl_key_ref_get(fs, _text_activated_model_key);
1397 Eina_Stringshare *str = efl_key_data_get(fs, _text_activated_path_key); 1390 Eina_Stringshare *str = efl_key_data_get(fs, _text_activated_path_key);
1391 Eina_Bool dir = EINA_FALSE;
1392 ELM_FILESELECTOR_DATA_GET(fs, sd);
1393
1394 if (!sd->model) goto end;
1398 1395
1399 eina_value_get((Eina_Value*)((Efl_Future_Event_Success*)event->info)->value, &is_dir); 1396 if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ERROR)
1400 if (is_dir)
1401 { 1397 {
1402 // keep previous path for backspace key action 1398 _model_event_call(fs, ELM_FILESELECTOR_EVENT_SELECTED_INVALID, model, str);
1403 if (sd->prev_model) 1399 goto selected;
1404 efl_unref(sd->prev_model); 1400 }
1405 sd->prev_model = efl_ref(sd->model);
1406 1401
1407 _populate(fs, model, NULL, NULL); 1402 fetch = efl_model_property_get(sd->model, "is_dir");
1403 eina_value_bool_get(fetch, &dir);
1408 1404
1409 if (sd->only_folder) 1405 if (dir)
1410 { 1406 {
1411 _model_event_call 1407 efl_replace(&sd->prev_model, sd->model);
1412 (fs, EFL_UI_EVENT_SELECTED, model, str); 1408
1413 } 1409 parent = model;
1410 model = NULL;
1414 } 1411 }
1415 else 1412 else
1416 { 1413 {
1417 Efl_Model *parent = efl_parent_get(model); 1414 parent = efl_parent_get(model);
1418 if (!parent)
1419 {
1420 ERR("Efl.Model allocation error");
1421 }
1422 else
1423 {
1424 _populate(fs, parent, NULL, model);
1425 1415
1426 if (sd->only_folder) 1416 if (!parent || efl_isa(parent, EFL_MODEL_INTERFACE))
1427 { 1417 goto end;
1428 _model_event_call
1429 (fs, EFL_UI_EVENT_SELECTED, model, str);
1430 }
1431 }
1432 } 1418 }
1433 1419
1434 _text_activated_free_fs_data(fs); 1420 _populate(fs, parent, NULL, model);
1435}
1436
1437static void
1438_text_activated_is_dir_then_error(void *data, Efl_Event const* event EINA_UNUSED)
1439{
1440 ERR("could not get information from Efl.Model");
1441 _text_activated_free_fs_data(data);
1442}
1443
1444static void
1445_on_text_activated_set_path_then(void *data, Efl_Event const * event EINA_UNUSED)
1446{
1447 Evas_Object *fs = data;
1448 Efl_Future *future = NULL;
1449 ELM_FILESELECTOR_DATA_GET(fs, sd);
1450
1451 if (!sd->model) return ;
1452
1453 future = efl_model_property_get(sd->model, "is_dir");
1454 efl_future_then
1455 (future, _text_activated_is_dir_then, _text_activated_is_dir_then_error, NULL, data);
1456}
1457
1458static void
1459_on_text_activated_set_path_then_error(void *data, Efl_Event const* event EINA_UNUSED)
1460{
1461 Evas_Object *fs = data;
1462 Efl_Model *model = efl_key_data_get(fs, _text_activated_model_key);
1463 Eina_Stringshare *str = efl_key_data_get(fs, _text_activated_path_key);
1464
1465 _model_event_call
1466 (fs, EFL_UI_EVENT_SELECTED, model, str);
1467 1421
1468 _model_event_call 1422 selected:
1469 (fs, ELM_FILESELECTOR_EVENT_SELECTED_INVALID, model, str); 1423 if (sd->only_folder)
1424 _model_event_call(fs, EFL_UI_EVENT_SELECTED, model, str);
1470 1425
1426 end:
1471 _text_activated_free_fs_data(fs); 1427 _text_activated_free_fs_data(fs);
1428
1429 return v;
1472} 1430}
1473 1431
1474static void 1432static void
1475_on_text_activated(void *data, const Efl_Event *event) 1433_on_text_activated(void *data, const Efl_Event *event)
1476{ 1434{
1435 Eina_Future *future = NULL;
1477 Evas_Object *fs = data; 1436 Evas_Object *fs = data;
1478 const char *path; 1437 const char *path;
1479 Efl_Model *model; 1438 Efl_Model *model;
1480 Efl_Future *future = NULL;
1481 1439
1482 ELM_FILESELECTOR_DATA_GET(fs, sd); 1440 ELM_FILESELECTOR_DATA_GET(fs, sd);
1483 1441
1484 if (!sd->model) 1442 if (!sd->model) return;
1485 return;
1486 1443
1487 path = elm_widget_part_text_get(event->object, NULL); 1444 path = elm_widget_part_text_get(event->object, NULL);
1488 model = efl_add(efl_class_get(sd->model), NULL); 1445 model = efl_add(efl_class_get(sd->model), event->object);
1489 if (!model) 1446 if (!model) return;
1490 return;
1491 1447
1492 future = _model_str_property_set(model, "path", path); 1448 future = _model_str_property_set(model, "path", path);
1493 1449
1494 efl_key_data_set(fs, _text_activated_path_key, eina_stringshare_add(path)); 1450 efl_key_data_set(fs, _text_activated_path_key, eina_stringshare_add(path));
1495 efl_key_ref_set(fs, _text_activated_model_key, model); 1451 efl_key_ref_set(fs, _text_activated_model_key, model);
1496 efl_ref(fs); 1452 efl_ref(fs);
1497 efl_future_then(future, 1453 eina_future_then(future, _on_text_activated_set_path_then, fs);
1498 _on_text_activated_set_path_then,
1499 _on_text_activated_set_path_then_error,
1500 NULL,
1501 fs);
1502 1454
1503 efl_unref(model); 1455 efl_unref(model);
1504 elm_object_focus_set(event->object, EINA_FALSE); 1456 elm_object_focus_set(event->object, EINA_FALSE);
@@ -1545,7 +1497,7 @@ _anchor_clicked(void *data, const Efl_Event *event)
1545 if (!sd->model) 1497 if (!sd->model)
1546 return; 1498 return;
1547 1499
1548 model = efl_add(efl_class_get(sd->model), NULL); 1500 model = efl_add(efl_class_get(sd->model), event->object);
1549 if (!model) 1501 if (!model)
1550 return; 1502 return;
1551 _model_str_property_set(model, "path", info->name); 1503 _model_str_property_set(model, "path", info->name);
@@ -1655,87 +1607,23 @@ _files_grid_add(Evas_Object *obj)
1655 return grid; 1607 return grid;
1656} 1608}
1657 1609
1658static void 1610static Eina_Value
1659_resource_then_error(void *data, Efl_Event const* event EINA_UNUSED) 1611_resource_created_then(void *data, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED)
1660{ 1612{
1661 Elm_Fileselector_Item_Data *it_data = data; 1613 Evas_Object *fs = data;
1662 WRN("could not get information from Efl.Model"); 1614 Efl_Model *child = NULL;
1663 efl_unref(it_data->user_data); 1615 unsigned int len, i;
1664 efl_unref(it_data->model);
1665 free(it_data);
1666}
1667
1668static void
1669_resource_created_then(void *data, Efl_Event const*event)
1670{
1671 Elm_Fileselector_Item_Data *it_data = data;
1672 Evas_Object *obj = it_data->user_data;
1673 Efl_Future_Event_Success *ev = event->info;
1674 Eina_Accessor *values_acc = ev->value;
1675 int itcn = ELM_FILE_UNKNOW;
1676 const char *path = NULL;
1677 const char *filename = NULL;
1678 const char *mime_type = NULL;
1679 int64_t size = 0;
1680 double mtime = 0;
1681 Eina_Bool dir = EINA_FALSE;
1682 it_data->user_data = NULL;
1683
1684 ELM_FILESELECTOR_DATA_GET(obj, sd);
1685
1686 if (!sd || !sd->monitoring || sd->model != it_data->parent_model)
1687 goto cancel;
1688
1689 if (!_accessor_value_get(values_acc, 0, &path) || !path ||
1690 !_accessor_value_get(values_acc, 1, &filename) || !filename ||
1691 !_accessor_value_get(values_acc, 2, &dir) ||
1692 !_accessor_value_get(values_acc, 3, &size) ||
1693 !_accessor_value_get(values_acc, 4, &mtime) ||
1694 !_accessor_value_get(values_acc, 5, &mime_type))
1695 {
1696 ERR("missing Efl.Model data");
1697 goto cancel;
1698 }
1699
1700 if (!_filter_child(sd, path, filename, dir, mime_type))
1701 goto cancel;
1702
1703 it_data->path = eina_stringshare_add(path);
1704 it_data->filename = eina_stringshare_add(filename);
1705 it_data->size = size;
1706 it_data->mtime = mtime;
1707 it_data->mime_type = eina_stringshare_add(mime_type);
1708 it_data->is_dir = dir;
1709 1616
1710 if (dir) 1617 if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ERROR)
1711 itcn = ELM_DIRECTORY; 1618 goto end;
1712 else
1713 {
1714 if (evas_object_image_extension_can_load_get(filename))
1715 itcn = ELM_FILE_IMAGE;
1716 }
1717 1619
1718 if (sd->mode == ELM_FILESELECTOR_LIST) 1620 ELM_FILESELECTOR_DATA_GET(fs, sd);
1719 elm_genlist_item_sorted_insert(sd->files_view, list_itc[itcn],
1720 it_data,
1721 NULL,
1722 (sd->expand && itcn == ELM_DIRECTORY)
1723 ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
1724 _file_list_cmp, NULL, NULL);
1725 else
1726 elm_gengrid_item_sorted_insert(sd->files_view, grid_itc[itcn],
1727 it_data,
1728 _file_grid_cmp, NULL, NULL);
1729 1621
1730 efl_unref(obj); 1622 EINA_VALUE_ARRAY_FOREACH(&v, len, i, child)
1731 return; 1623 _process_model(sd, child);
1732 1624
1733cancel: 1625 end:
1734 efl_unref(obj); 1626 return v;
1735 efl_unref(it_data->model);
1736 efl_unref(it_data->parent_model);
1737 eina_stringshare_del(it_data->parent_path);
1738 free(it_data);
1739} 1627}
1740 1628
1741static void 1629static void
@@ -1743,38 +1631,16 @@ _resource_created(void *data, const Efl_Event *event)
1743{ 1631{
1744 Elm_Fileselector *fs = data; 1632 Elm_Fileselector *fs = data;
1745 Efl_Model_Children_Event* evt = event->info; 1633 Efl_Model_Children_Event* evt = event->info;
1746 Efl_Model *child = evt->child; 1634 Eina_Future *f;
1747 Efl_Future *futures[7] = {NULL,};
1748 Efl_Future *future_all = NULL;
1749 Elm_Fileselector_Item_Data *it_data = NULL;
1750 1635
1751 ELM_FILESELECTOR_DATA_GET(fs, sd); 1636 ELM_FILESELECTOR_DATA_GET(fs, sd);
1752 1637
1753 if (!sd || !sd->monitoring || sd->model != event->object) 1638 if (!sd || !sd->monitoring || sd->model != event->object)
1754 return; 1639 return;
1755 1640
1756 it_data = calloc(1, sizeof(Elm_Fileselector_Item_Data)); 1641 f = efl_model_children_slice_get(sd->model, evt->index, 1);
1757 if (!it_data) 1642 f = eina_future_then(f, _resource_created_then, fs);
1758 return; 1643 efl_future_Eina_FutureXXX_then(fs, f);
1759
1760 it_data->model = efl_ref(child);
1761 it_data->user_data = efl_ref(fs);
1762 it_data->parent_model = efl_ref(sd->model);
1763 it_data->parent_path = eina_stringshare_add(sd->path);
1764
1765 future_all = efl_future_all
1766 (
1767 futures[0] = efl_model_property_get(child, "path"),
1768 futures[1] = efl_model_property_get(child, "filename"),
1769 futures[2] = efl_model_property_get(child, "is_dir"),
1770 futures[3] = efl_model_property_get(child, "size"),
1771 futures[4] = efl_model_property_get(child, "mtime"),
1772 futures[5] = efl_model_property_get(child, "mime_type")
1773 );
1774
1775 efl_future_then(future_all, _resource_created_then, _resource_then_error, NULL, it_data);
1776
1777 return;
1778} 1644}
1779 1645
1780static void 1646static void
@@ -1782,7 +1648,6 @@ _resource_deleted(void *data, const Efl_Event *event)
1782{ 1648{
1783 Evas_Object *obj = data; 1649 Evas_Object *obj = data;
1784 Efl_Model_Children_Event* evt = event->info; 1650 Efl_Model_Children_Event* evt = event->info;
1785 Efl_Model *child = evt->child;
1786 Elm_Object_Item *it = NULL; 1651 Elm_Object_Item *it = NULL;
1787 Eina_Bool selected = EINA_FALSE; 1652 Eina_Bool selected = EINA_FALSE;
1788 1653
@@ -1791,36 +1656,12 @@ _resource_deleted(void *data, const Efl_Event *event)
1791 if (!sd || !sd->monitoring || sd->model != event->object) 1656 if (!sd || !sd->monitoring || sd->model != event->object)
1792 return; 1657 return;
1793 1658
1794 if (sd->mode == ELM_FILESELECTOR_LIST) 1659 if (!evt->child) return ;
1795 {
1796 it = elm_genlist_first_item_get(sd->files_view);
1797 while (it)
1798 {
1799 Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(it);
1800 if (child == it_data->model)
1801 {
1802 selected = elm_genlist_item_selected_get(it);
1803 break;
1804 }
1805 it = elm_genlist_item_next_get(it);
1806 }
1807 }
1808 else
1809 {
1810 it = elm_gengrid_first_item_get(sd->files_view);
1811 while (it)
1812 {
1813 Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(it);
1814 if (child == it_data->model)
1815 {
1816 selected = elm_genlist_item_selected_get(it);
1817 break;
1818 }
1819 it = elm_gengrid_item_next_get(it);
1820 }
1821 }
1822 1660
1823 if (it) efl_del(it); 1661 it = efl_key_data_get(evt->child, ".item.data");
1662 if (!it) return ;
1663
1664 selected = elm_genlist_item_selected_get(it);
1824 1665
1825 if (selected) 1666 if (selected)
1826 { 1667 {
@@ -1834,13 +1675,14 @@ _resource_deleted(void *data, const Efl_Event *event)
1834 buf = eina_strbuf_new(); 1675 buf = eina_strbuf_new();
1835 EINA_LIST_FOREACH_SAFE(sd->multi_selection, li, l, item) 1676 EINA_LIST_FOREACH_SAFE(sd->multi_selection, li, l, item)
1836 { 1677 {
1837 Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(item); 1678 if (item == it)
1838 if (child == it_data->model)
1839 { 1679 {
1840 sd->multi_selection = eina_list_remove_list(sd->multi_selection, li); 1680 sd->multi_selection = eina_list_remove_list(sd->multi_selection, li);
1841 } 1681 }
1842 else 1682 else
1843 { 1683 {
1684 Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(item);
1685
1844 if (!first) 1686 if (!first)
1845 eina_strbuf_append_length(buf, ", ", 2); 1687 eina_strbuf_append_length(buf, ", ", 2);
1846 else 1688 else
@@ -1857,6 +1699,8 @@ _resource_deleted(void *data, const Efl_Event *event)
1857 elm_object_text_set(sd->name_entry, ""); 1699 elm_object_text_set(sd->name_entry, "");
1858 } 1700 }
1859 1701
1702 if (it) efl_del(it);
1703
1860 return; 1704 return;
1861} 1705}
1862 1706
@@ -2056,39 +1900,22 @@ _elm_fileselector_efl_object_constructor(Eo *obj, Elm_Fileselector_Data *sd)
2056 return obj; 1900 return obj;
2057} 1901}
2058 1902
2059static void
2060_legacy_smart_callback_caller_path_then(void *data, Efl_Event const *event)
2061{
2062 Legacy_Event_Path_Then_Data *evt_data = data;
2063 _event_to_legacy_call(evt_data->eo_obj, evt_data->evt_desc, ((Efl_Future_Event_Success*)event->info)->value);
2064 free(data);
2065}
2066
2067static void
2068_legacy_smart_callback_caller_path_then_error(void *data, Efl_Event const* event)
2069{
2070 Eina_Error err = ((Efl_Future_Event_Failure*)event->info)->error;
2071 ERR("Efl.Model property \"path\" error: %s", eina_error_msg_get(err));
2072 free(data);
2073}
2074
2075static Eina_Bool 1903static Eina_Bool
2076_from_efl_event_call(Elm_Fileselector *fs, const Efl_Event_Description *evt_desc, Efl_Model *model) 1904_from_efl_event_call(Elm_Fileselector *fs, const Efl_Event_Description *evt_desc, Efl_Model *model)
2077{ 1905{
2078 Efl_Future *future;
2079 Legacy_Event_Path_Then_Data *evt_data; 1906 Legacy_Event_Path_Then_Data *evt_data;
1907 Eina_Value *fetch;
1908 char *path;
2080 1909
2081 evt_data = calloc(1, sizeof(Legacy_Event_Path_Then_Data)); 1910 evt_data = calloc(1, sizeof(Legacy_Event_Path_Then_Data));
2082 evt_data->eo_obj = fs; 1911 evt_data->eo_obj = fs;
2083 evt_data->evt_desc = evt_desc; 1912 evt_data->evt_desc = evt_desc;
2084 1913
2085 // Call legacy smart callback with path 1914 // Call legacy smart callback with path
2086 future = efl_model_property_get(model, "path"); 1915 fetch = efl_model_property_get(model, "path");
2087 efl_future_then(future, 1916 path = eina_value_to_string(fetch);
2088 _legacy_smart_callback_caller_path_then, 1917
2089 _legacy_smart_callback_caller_path_then_error, 1918 _event_to_legacy_call(evt_data->eo_obj, evt_data->evt_desc, path);
2090 NULL,
2091 evt_data);
2092 1919
2093 // Call Eo event with model 1920 // Call Eo event with model
2094 return efl_event_callback_call(fs, evt_desc, model); 1921 return efl_event_callback_call(fs, evt_desc, model);
@@ -2103,13 +1930,13 @@ _from_legacy_event_call(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, const E
2103 else 1930 else
2104 model_cls = efl_class_get(sd->model); 1931 model_cls = efl_class_get(sd->model);
2105 1932
2106 Efl_Model *model = efl_add(model_cls, efl_provider_find(sd->obj, EFL_LOOP_CLASS)); 1933 Efl_Model *model = efl_add(model_cls, fs);
2107 _model_str_property_set(model, "path", path); 1934 _model_str_property_set(model, "path", path);
2108 1935
2109 // Call Eo event with model 1936 // Call Eo event with model
2110 efl_event_callback_call(fs, evt_desc, model); 1937 efl_event_callback_call(fs, evt_desc, model);
2111 1938
2112 efl_unref(model); 1939 efl_del(model);
2113 1940
2114 // Call legacy smart callback with path 1941 // Call legacy smart callback with path
2115 return efl_event_callback_call(fs, legacy_desc, (void *)path); 1942 return efl_event_callback_call(fs, legacy_desc, (void *)path);
@@ -2312,14 +2139,13 @@ elm_fileselector_path_set(Evas_Object *obj,
2312void 2139void
2313_elm_fileselector_path_set_internal(Evas_Object *obj, const char *_path) 2140_elm_fileselector_path_set_internal(Evas_Object *obj, const char *_path)
2314{ 2141{
2315 Eio_Model *model = efl_add(EIO_MODEL_CLASS, efl_provider_find(obj, EFL_LOOP_CLASS), eio_model_path_set(efl_added, _path)); 2142 Eio_Model *model = efl_add(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, _path));
2316 if (!model) 2143 if (!model)
2317 { 2144 {
2318 ERR("Efl.Model allocation error"); 2145 ERR("Efl.Model allocation error");
2319 return; 2146 return;
2320 } 2147 }
2321 efl_ui_view_model_set(obj, model); 2148 efl_ui_view_model_set(obj, model);
2322 efl_unref(model);
2323} 2149}
2324 2150
2325EOLIAN static void 2151EOLIAN static void
@@ -2512,6 +2338,10 @@ _elm_fileselector_selected_get_internal(const Evas_Object *obj)
2512{ 2338{
2513 ELM_FILESELECTOR_DATA_GET(obj, sd); 2339 ELM_FILESELECTOR_DATA_GET(obj, sd);
2514 if (!sd->path) return NULL; 2340 if (!sd->path) return NULL;
2341 if (sd->target)
2342 {
2343 return eio_model_path_get(sd->target);
2344 }
2515 2345
2516 Elm_Fileselector_Item_Data *it_data = _selected_item_data_get(sd); 2346 Elm_Fileselector_Item_Data *it_data = _selected_item_data_get(sd);
2517 if (it_data) 2347 if (it_data)
@@ -2521,7 +2351,7 @@ _elm_fileselector_selected_get_internal(const Evas_Object *obj)
2521} 2351}
2522 2352
2523EOLIAN static Efl_Model * 2353EOLIAN static Efl_Model *
2524_elm_fileselector_elm_interface_fileselector_selected_model_get(Eo *fs EINA_UNUSED, Elm_Fileselector_Data *sd) 2354_elm_fileselector_elm_interface_fileselector_selected_model_get(const Eo *fs EINA_UNUSED, Elm_Fileselector_Data *sd)
2525{ 2355{
2526 if (!sd->model) 2356 if (!sd->model)
2527 { 2357 {
@@ -2555,140 +2385,172 @@ elm_fileselector_selected_set(Evas_Object *obj,
2555 } 2385 }
2556} 2386}
2557 2387
2388static void
2389_properties_ready(void *data, const Efl_Event *ev)
2390{
2391 Evas_Object *obj = data;
2392 Efl_Model_Property_Event *event = ev->info;
2393 const char *property = NULL;
2394 Eina_Array_Iterator iterator;
2395 unsigned int i;
2396
2397 ELM_FILESELECTOR_DATA_GET(obj, pd);
2398
2399 EINA_ARRAY_ITER_NEXT(event->changed_properties, i, property, iterator)
2400 if (!strcmp(property, "is_dir"))
2401 {
2402 Eina_Value *value;
2403 Eina_Bool is_dir = EINA_FALSE;
2404
2405 value = efl_model_property_get(pd->target, "is_dir");
2406 if (eina_value_type_get(value) != EINA_VALUE_TYPE_BOOL)
2407 {
2408 ERR("Unexpected type for 'is_dir': '%s' with value '%s'.", eina_value_type_get(value)->name, eina_value_to_string(value));
2409 return ;
2410 }
2411
2412 efl_event_callback_del(pd->target, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _properties_ready, obj);
2413
2414 eina_value_bool_get(value, &is_dir);
2415
2416 if (!is_dir)
2417 {
2418 Efl_Model *parent;
2419 const char *path = eio_model_path_get(pd->target);
2420 char *dir = ecore_file_dir_get(path);
2421
2422 parent = efl_add(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, dir));
2423 if (!parent)
2424 {
2425 ERR("Could not create model for '%s'.", dir);
2426 efl_replace(&pd->target, NULL);
2427 free(dir);
2428 return ;
2429 }
2430 efl_model_children_count_get(parent);
2431
2432 _schedule_populate(obj, pd, parent, pd->target);
2433 free(dir);
2434 }
2435 else
2436 {
2437 efl_model_children_count_get(pd->target);
2438 _schedule_populate(obj, pd, pd->target, NULL);
2439 }
2440 return ;
2441 }
2442}
2443
2558Eina_Bool 2444Eina_Bool
2559_elm_fileselector_selected_set_internal(Evas_Object *obj, const char *_path) 2445_elm_fileselector_selected_set_internal(Evas_Object *obj, const char *path)
2560{ 2446{
2447 Eina_Value *value;
2448 struct stat st;
2449
2561 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); 2450 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
2562 Eina_Bool ret = EINA_FALSE; 2451 ELM_FILESELECTOR_DATA_GET(obj, pd);
2563 char *dir;
2564 char *path;
2565 Eio_Model *model = NULL;
2566 Eio_Model *parent = NULL;
2567 ELM_FILESELECTOR_DATA_GET(obj, sd);
2568 2452
2569 path = ecore_file_realpath(_path); 2453 efl_replace(&pd->target, NULL);
2570 2454
2571 if (ecore_file_is_dir(path)) 2455 if (stat(path, &st)) return EINA_FALSE;
2572 {
2573 model = efl_add(EIO_MODEL_CLASS, efl_provider_find(obj, EFL_LOOP_CLASS), eio_model_path_set(efl_added, path));
2574 if (!model)
2575 {
2576 ERR("Efl.Model allocation error");
2577 goto clean_up;
2578 }
2579 2456
2580 _schedule_populate(obj, sd, model, NULL); 2457 pd->target = efl_add(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, path));
2581 efl_unref(model); 2458 if (!pd->target)
2582 ret = EINA_TRUE; 2459 {
2460 ERR("Could not create model for '%s'.", path);
2461 return EINA_FALSE;
2583 } 2462 }
2584 else 2463
2464 efl_event_callback_add(pd->target, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _properties_ready, obj);
2465 value = efl_model_property_get(pd->target, "is_dir");
2466 if (eina_value_type_get(value) == EINA_VALUE_TYPE_ERROR)
2585 { 2467 {
2586 if (!ecore_file_exists(path)) 2468 Eina_Error err = 0;
2587 {
2588 goto clean_up;
2589 }
2590 2469
2591 model = efl_add(EIO_MODEL_CLASS, efl_provider_find(obj, EFL_LOOP_CLASS), eio_model_path_set(efl_added, path)); 2470 eina_value_error_get(value, &err);
2592 if (!model) 2471 if (err != EAGAIN)
2593 { 2472 {
2594 ERR("Efl.Model allocation error"); 2473 ERR("Unexpected error '%s' when setting path '%s'.", eina_value_to_string(value), path);
2595 goto clean_up; 2474 goto clean_up;
2596 } 2475 }
2597 2476
2598 dir = ecore_file_dir_get(path); 2477 return EINA_TRUE;
2599 parent = efl_add(EIO_MODEL_CLASS, efl_provider_find(obj, EFL_LOOP_CLASS), eio_model_path_set(efl_added, dir));
2600 if (parent)
2601 {
2602 _schedule_populate(obj, sd, parent, model);
2603 efl_unref(parent);
2604 ret = EINA_TRUE;
2605 }
2606 free(dir);
2607 efl_unref(model);
2608 } 2478 }
2609 2479
2610clean_up: 2480 ERR("Unexpected value '%s' when setting path '%s'.", eina_value_to_string(value), path);
2611 free(path);
2612 2481
2613 return ret; 2482clean_up:
2483 efl_replace(&pd->target, NULL);
2484 return EINA_FALSE;
2614} 2485}
2615 2486
2616static void 2487EOLIAN static Eina_Bool
2617_selected_model_set_free_fs_data(Elm_Fileselector *fs) 2488_elm_fileselector_elm_interface_fileselector_selected_model_set(Eo *obj, Elm_Fileselector_Data *pd, Efl_Model *model)
2618{ 2489{
2619 efl_key_ref_set(fs, _selected_model_set_model_key, NULL); 2490 Eina_Value *value = NULL;
2620 efl_key_data_set(fs, _selected_model_set_promise_owner_key, NULL); 2491 Eina_Bool dir = EINA_FALSE;
2621 efl_unref(fs);
2622}
2623 2492
2624static void 2493 if (!efl_isa(model, EIO_MODEL_CLASS)) return EINA_FALSE;
2625_selected_model_set_then_error(void *data, Efl_Event const* event)
2626{
2627 Eina_Error err = ((Efl_Future_Event_Failure*)event->info)->error;
2628 Efl_Promise *promise_owner = efl_key_data_get(data, _selected_model_set_promise_owner_key);
2629 if (promise_owner)
2630 efl_promise_failed_set(promise_owner, err);
2631 _selected_model_set_free_fs_data(data);
2632}
2633 2494
2634static void 2495 efl_replace(&pd->target, model);
2635_selected_model_set_is_dir_then(void *data, Efl_Event const *event)
2636{
2637 Elm_Fileselector *fs = data;
2638 Eina_Bool is_dir = EINA_FALSE;
2639 Efl_Model *model = efl_key_ref_get(fs, _selected_model_set_model_key);
2640 Efl_Promise *promise_owner = efl_key_data_get(fs, _selected_model_set_promise_owner_key);
2641 ELM_FILESELECTOR_DATA_GET(fs, sd);
2642 2496
2643 eina_value_get((Eina_Value*)((Efl_Future_Event_Success*)event->info)->value, &is_dir); 2497 if (!model) return EINA_TRUE;
2644 if (is_dir)
2645 {
2646 _schedule_populate(fs, sd, model, NULL);
2647 if (promise_owner)
2648 {
2649 efl_ref(model);
2650 efl_promise_value_set(promise_owner, model, _model_free_eo_cb);
2651 }
2652 }
2653 else
2654 {
2655 Efl_Model *parent = efl_parent_get(model);
2656 if (parent)
2657 {
2658 _schedule_populate(fs, sd, parent, model);
2659 2498
2660 if (promise_owner) 2499 efl_event_callback_add(pd->target, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _properties_ready, obj);
2661 { 2500 value = efl_model_property_get(pd->target, "is_dir");
2662 efl_ref(model); 2501 if (eina_value_type_get(value) == EINA_VALUE_TYPE_ERROR)
2663 efl_promise_value_set(promise_owner, model, _model_free_eo_cb); 2502 {
2664 } 2503 Eina_Error err = 0;
2665 }
2666 else
2667 {
2668 if (promise_owner)
2669 efl_promise_failed_set(promise_owner, ELM_FILESELECTOR_ERROR_UNKNOWN);
2670 }
2671 }
2672 _selected_model_set_free_fs_data(fs);
2673}
2674 2504
2675EOLIAN static Efl_Future* 2505 eina_value_error_get(value, &err);
2676_elm_fileselector_elm_interface_fileselector_selected_model_set(Eo *obj, Elm_Fileselector_Data *sd EINA_UNUSED, Efl_Model *model) 2506 if (err != EAGAIN)
2677{ 2507 {
2678 Efl_Future *future = NULL; 2508 ERR("Unexpected error '%s' when setting path '%s'.", eina_value_to_string(value), eio_model_path_get(pd->target));
2679 Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj); 2509 goto clean_up;
2680 if (!model) 2510 }
2681 {
2682 efl_promise_failed_set(promise, ELM_FILESELECTOR_ERROR_INVALID_MODEL);
2683 return efl_promise_future_get(promise);
2684 }
2685 future = efl_model_property_get(model, "is_dir");
2686 2511
2687 efl_key_ref_set(obj, _selected_model_set_model_key, model); 2512 return EINA_TRUE;
2688 efl_key_data_set(obj, _selected_model_set_promise_owner_key, promise); 2513 }
2514
2515 if (eina_value_type_get(value) != EINA_VALUE_TYPE_BOOL)
2516 {
2517 ERR("Unexpected type for 'is_dir': '%s' with value '%s'.", eina_value_type_get(value)->name, eina_value_to_string(value));
2518 goto clean_up;
2519 }
2520
2521 efl_event_callback_del(pd->target, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _properties_ready, obj);
2522
2523 eina_value_bool_get(value, &dir);
2689 2524
2690 efl_future_then(future, _selected_model_set_is_dir_then, _selected_model_set_then_error, NULL, efl_ref(obj)); 2525 if (!dir)
2691 return efl_promise_future_get(promise); 2526 {
2527 Efl_Model *parent;
2528 const char *path = eio_model_path_get(pd->target);
2529 char *d = ecore_file_dir_get(path);
2530
2531 parent = efl_add(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, d));
2532 if (!parent)
2533 {
2534 ERR("Could not create model for '%s'.", d);
2535 free(d);
2536 goto clean_up;
2537 }
2538 efl_model_children_count_get(parent);
2539
2540 _schedule_populate(obj, pd, parent, pd->target);
2541 free(d);
2542 }
2543 else
2544 {
2545 efl_model_children_count_get(pd->target);
2546 _schedule_populate(obj, pd, pd->target, NULL);
2547 }
2548
2549 return EINA_TRUE;
2550
2551 clean_up:
2552 efl_replace(&pd->target, NULL);
2553 return EINA_FALSE;
2692} 2554}
2693 2555
2694EAPI const Eina_List * 2556EAPI const Eina_List *
diff --git a/src/lib/elementary/elc_fileselector_button.c b/src/lib/elementary/elc_fileselector_button.c
index edf8a90e47..b1d263b6c8 100644
--- a/src/lib/elementary/elc_fileselector_button.c
+++ b/src/lib/elementary/elc_fileselector_button.c
@@ -3,8 +3,10 @@
3#endif 3#endif
4 4
5#define EFL_ACCESS_OBJECT_PROTECTED 5#define EFL_ACCESS_OBJECT_PROTECTED
6#define ELM_INTERFACE_FILESELECTOR_BETA
6 7
7#include <Elementary.h> 8#include <Elementary.h>
9#include "Eio_Eo.h"
8#include "elm_priv.h" 10#include "elm_priv.h"
9#include "elm_fileselector_button.eo.h" 11#include "elm_fileselector_button.eo.h"
10#include "elm_fileselector_entry.eo.h" 12#include "elm_fileselector_entry.eo.h"
@@ -37,12 +39,6 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = {
37}; 39};
38#undef ELM_PRIV_FILESELECTOR_BUTTON_SIGNALS 40#undef ELM_PRIV_FILESELECTOR_BUTTON_SIGNALS
39 41
40static void
41_model_free_eo_cb(void *eo)
42{
43 efl_unref(eo);
44}
45
46EOLIAN static Efl_Ui_Theme_Apply 42EOLIAN static Efl_Ui_Theme_Apply
47_elm_fileselector_button_efl_ui_widget_theme_apply(Eo *obj, Elm_Fileselector_Button_Data *sd EINA_UNUSED) 43_elm_fileselector_button_efl_ui_widget_theme_apply(Eo *obj, Elm_Fileselector_Button_Data *sd EINA_UNUSED)
48{ 44{
@@ -71,30 +67,6 @@ _elm_fileselector_button_efl_ui_widget_theme_apply(Eo *obj, Elm_Fileselector_But
71} 67}
72 68
73static void 69static void
74_replace_path_then(void *data, Efl_Event const *event)
75{
76 Elm_Fileselector_Button_Data *sd = data;
77 Efl_Future_Event_Success *ev = event->info;
78 Eina_Value *v = ev->value;
79 const char *path = NULL;
80
81 eina_value_get(v, &path);
82 eina_stringshare_replace(&sd->fsd.path, path);
83 _event_to_legacy_call
84 (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, (void *)path);
85}
86
87static void
88_replace_path_then_error(void *data, Efl_Event const* event EINA_UNUSED)
89{
90 Elm_Fileselector_Button_Data *sd = data;
91 ERR("could not get information from Efl.Model");
92 eina_stringshare_replace(&sd->fsd.path, NULL);
93 _event_to_legacy_call
94 (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, NULL);
95}
96
97static void
98_selection_done(void *data, const Efl_Event *event) 70_selection_done(void *data, const Efl_Event *event)
99{ 71{
100 Elm_Fileselector_Button_Data *sd = data; 72 Elm_Fileselector_Button_Data *sd = data;
@@ -103,15 +75,22 @@ _selection_done(void *data, const Efl_Event *event)
103 75
104 if (model) 76 if (model)
105 { 77 {
106 Efl_Future *future = NULL; 78 Eina_Value *path;
107 if (sd->fsd.model) 79 char *file;
108 efl_unref(sd->fsd.model); 80
109 // XXX: the efl_ref here smells wrong. fsd.model is only unreffed ONCE so this obj leaks... 81 efl_replace(&sd->fsd.model, model);
110 sd->fsd.model = efl_ref(model); 82
111 future = efl_model_property_get(model, "path"); 83 path = efl_model_property_get(model, "path");
112 efl_future_then(future, _replace_path_then, _replace_path_then_error, NULL, sd); 84 file = eina_value_to_string(path);
85 eina_stringshare_replace(&sd->fsd.path, file);
86
113 efl_event_callback_call 87 efl_event_callback_call
114 (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, model); 88 (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, model);
89 _event_to_legacy_call
90 (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, file);
91
92 eina_value_free(path);
93 free(file);
115 } 94 }
116 else 95 else
117 { 96 {
@@ -322,17 +301,15 @@ _elm_fileselector_button_path_set_internal(Evas_Object *obj, const char *path)
322{ 301{
323 ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN(obj, sd); 302 ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN(obj, sd);
324 303
325 Efl_Model *model = efl_add(EIO_MODEL_CLASS, efl_provider_find(obj, EFL_LOOP_CLASS), eio_model_path_set(efl_added, path)); 304 Efl_Model *model = efl_add(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, path));
326 if (!model) 305 if (!model)
327 { 306 {
328 ERR("Efl.Model allocation error"); 307 ERR("Efl.Model allocation error");
329 return; 308 return;
330 } 309 }
331 310
332 if (sd->fsd.model)
333 efl_unref(sd->fsd.model);
334 // XXX: the efl_ref here smells wrong. fsd.model is only unreffed ONCE so this obj leaks... 311 // XXX: the efl_ref here smells wrong. fsd.model is only unreffed ONCE so this obj leaks...
335 sd->fsd.model = efl_ref(model); 312 efl_replace(&sd->fsd.model, model);
336 313
337 eina_stringshare_replace(&sd->fsd.path, path); 314 eina_stringshare_replace(&sd->fsd.path, path);
338 315
@@ -349,21 +326,26 @@ elm_fileselector_button_path_set(Evas_Object *obj, const char *path)
349EOLIAN static void 326EOLIAN static void
350_elm_fileselector_button_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Efl_Model *model) 327_elm_fileselector_button_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Efl_Model *model)
351{ 328{
352 if (sd->fsd.model) 329 char *file = NULL;
353 efl_unref(sd->fsd.model); 330
331 efl_replace(&sd->fsd.model, model);
354 332
355 if (model) 333 if (model)
356 { 334 {
357 sd->fsd.model = efl_ref(model); 335 Eina_Value *path;
358 efl_future_then(efl_model_property_get(model, "path"), 336
359 _replace_path_then, _replace_path_then_error, NULL, sd); 337 path = efl_model_property_get(model, "path");
360 } 338 file = eina_value_to_string(path);
361 else 339 eina_value_free(path);
362 {
363 sd->fsd.model = NULL;
364 eina_stringshare_replace(&sd->fsd.path, NULL);
365 } 340 }
366 341
342 eina_stringshare_replace(&sd->fsd.path, file);
343
344 _event_to_legacy_call
345 (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, file);
346
347 free(file);
348
367 if (sd->fs) elm_interface_fileselector_selected_model_set(sd->fs, model); 349 if (sd->fs) elm_interface_fileselector_selected_model_set(sd->fs, model);
368} 350}
369 351
@@ -551,7 +533,7 @@ _elm_fileselector_button_selected_get_internal(const Evas_Object *obj)
551} 533}
552 534
553EOLIAN static Efl_Model * 535EOLIAN static Efl_Model *
554_elm_fileselector_button_elm_interface_fileselector_selected_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) 536_elm_fileselector_button_elm_interface_fileselector_selected_model_get(const Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd)
555{ 537{
556 if (sd->fs) return elm_interface_fileselector_selected_model_get(sd->fs); 538 if (sd->fs) return elm_interface_fileselector_selected_model_get(sd->fs);
557 539
@@ -581,37 +563,15 @@ _elm_fileselector_button_selected_set_internal(Evas_Object *obj, const char *_pa
581 return ret; 563 return ret;
582} 564}
583 565
584static void 566EOLIAN static Eina_Bool
585_selected_model_then(void *data, Efl_Event const *event)
586{
587 Eo* v = (Eo*)((Efl_Future_Event_Success*)event->info)->value;
588 Efl_Promise *owner = data;
589 efl_promise_value_set(owner, efl_ref(v), _model_free_eo_cb);
590}
591
592static void
593_selected_model_then_error(void *data, Efl_Event const* event)
594{
595 Efl_Promise *owner = data;
596 efl_promise_failed_set(owner, ((Efl_Future_Event_Failure*)event->info)->error);
597}
598
599EOLIAN static Efl_Future*
600_elm_fileselector_button_elm_interface_fileselector_selected_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Efl_Model *model) 567_elm_fileselector_button_elm_interface_fileselector_selected_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Efl_Model *model)
601{ 568{
602 Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj);
603 if (sd->fs) 569 if (sd->fs)
604 { 570 elm_interface_fileselector_selected_model_set(sd->fs, model);
605 efl_future_then(elm_interface_fileselector_selected_model_set(sd->fs, model),
606 _selected_model_then, _selected_model_then_error, NULL, promise);
607 }
608 else
609 efl_promise_failed_set(promise, EINA_ERROR_FUTURE_CANCEL);
610 571
611 if (sd->fsd.selection) 572 efl_replace(&sd->fsd.selection, model);
612 efl_unref(sd->fsd.selection); 573
613 sd->fsd.selection = model ? efl_ref(model) : NULL; 574 return EINA_TRUE;
614 return efl_promise_future_get(promise);
615} 575}
616 576
617EOLIAN static void 577EOLIAN static void
diff --git a/src/lib/elementary/elc_fileselector_entry.c b/src/lib/elementary/elc_fileselector_entry.c
index d8f43e5cc5..59108cd7aa 100644
--- a/src/lib/elementary/elc_fileselector_entry.c
+++ b/src/lib/elementary/elc_fileselector_entry.c
@@ -4,8 +4,10 @@
4#endif 4#endif
5 5
6#define EFL_ACCESS_OBJECT_PROTECTED 6#define EFL_ACCESS_OBJECT_PROTECTED
7#define ELM_INTERFACE_FILESELECTOR_BETA
7 8
8#include <Elementary.h> 9#include <Elementary.h>
10#include "Eio_Eo.h"
9#include "elm_priv.h" 11#include "elm_priv.h"
10#include "elm_fileselector_button.eo.h" 12#include "elm_fileselector_button.eo.h"
11#include "elm_fileselector_entry.eo.h" 13#include "elm_fileselector_entry.eo.h"
@@ -66,53 +68,25 @@ SIG_FWD(UNPRESSED, EFL_UI_EVENT_UNPRESSED)
66#undef SIG_FWD 68#undef SIG_FWD
67 69
68static void 70static void
69_file_chosen_path_then(void *data, Efl_Event const* event) 71_FILE_CHOSEN_fwd(void *data, const Efl_Event *event)
70{ 72{
71 Eina_Array *args = data; 73 Efl_Model *model = event->info;
72 const char *file = NULL; 74 Eo *fs = data;
73 char *s; 75 Eina_Value *path;
74 Eo *fs = eina_array_data_get(args, 0); 76 char *file = NULL;
75 Efl_Model *model = eina_array_data_get(args, 1);
76
77 eina_array_free(args);
78
79 eina_value_get((Eina_Value*)((Efl_Future_Event_Success*)event->info)->value, &file);
80
81 if (!file) return;
82 ELM_FILESELECTOR_ENTRY_DATA_GET(fs, sd); 77 ELM_FILESELECTOR_ENTRY_DATA_GET(fs, sd);
83 78
84 s = elm_entry_utf8_to_markup(file); 79 efl_ui_view_model_set(sd->entry, model);
85 elm_object_text_set(sd->entry, s); 80 efl_ui_model_connect(sd->entry, "default", "path");
86 free(s); 81
82 path = efl_model_property_get(model, "path");
83 file = eina_value_to_string(path);
87 84
88 _model_event_call 85 _model_event_call
89 (fs, ELM_FILESELECTOR_ENTRY_EVENT_FILE_CHOSEN, model, file); 86 (fs, ELM_FILESELECTOR_ENTRY_EVENT_FILE_CHOSEN, model, file);
90}
91
92static void
93_file_chosen_path_then_error(void *data, Efl_Event const* event)
94{
95 Eina_Error err = ((Efl_Future_Event_Failure*)event->info)->error;
96 ERR("Efl.Model property \"path\" error: %s", eina_error_msg_get(err));
97 eina_array_free(data);
98}
99
100static void
101_FILE_CHOSEN_fwd(void *data, const Efl_Event *event)
102{
103 Efl_Model *model = event->info;
104 Efl_Future *future = NULL;
105 Eina_Array *args = NULL;
106
107 if (!model) return;
108 87
109 args = eina_array_new(2); 88 eina_value_free(path);
110 eina_array_push(args, data); 89 free(file);
111 eina_array_push(args, model);
112
113 future = efl_model_property_get(model, "path");
114 efl_future_then
115 (future, _file_chosen_path_then, _file_chosen_path_then_error, NULL, args);
116} 90}
117 91
118static void 92static void
@@ -141,12 +115,6 @@ _ACTIVATED_fwd(void *data, const Efl_Event *event)
141 (data, ELM_FILESELECTOR_ENTRY_EVENT_ACTIVATED, event->info); 115 (data, ELM_FILESELECTOR_ENTRY_EVENT_ACTIVATED, event->info);
142} 116}
143 117
144static void
145_model_free_eo_cb(void *eo)
146{
147 efl_unref(eo);
148}
149
150EOLIAN static void 118EOLIAN static void
151_elm_fileselector_entry_elm_layout_sizing_eval(Eo *obj, Elm_Fileselector_Entry_Data *sd EINA_UNUSED) 119_elm_fileselector_entry_elm_layout_sizing_eval(Eo *obj, Elm_Fileselector_Entry_Data *sd EINA_UNUSED)
152{ 120{
@@ -358,16 +326,14 @@ _elm_fileselector_entry_selected_set_internal(Evas_Object *obj, const char *path
358 return EINA_TRUE; 326 return EINA_TRUE;
359} 327}
360 328
361EOLIAN static Efl_Future* 329EOLIAN static Eina_Bool
362_elm_fileselector_entry_elm_interface_fileselector_selected_model_set(Eo *obj EINA_UNUSED, 330_elm_fileselector_entry_elm_interface_fileselector_selected_model_set(Eo *obj EINA_UNUSED,
363 Elm_Fileselector_Entry_Data *sd, 331 Elm_Fileselector_Entry_Data *sd,
364 Efl_Model *model) 332 Efl_Model *model)
365{ 333{
366 Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj);
367 Efl_Future* future = efl_promise_future_get(promise);
368 efl_ui_view_model_set(sd->button, model); 334 efl_ui_view_model_set(sd->button, model);
369 efl_promise_value_set(promise, efl_ref(model), _model_free_eo_cb); 335
370 return future; 336 return EINA_TRUE;
371} 337}
372 338
373EINA_DEPRECATED EAPI const char * 339EINA_DEPRECATED EAPI const char *
@@ -385,7 +351,7 @@ _elm_fileselector_entry_selected_get_internal(const Evas_Object *obj)
385} 351}
386 352
387EOLIAN static Efl_Model * 353EOLIAN static Efl_Model *
388_elm_fileselector_entry_elm_interface_fileselector_selected_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd) 354_elm_fileselector_entry_elm_interface_fileselector_selected_model_get(const Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd)
389{ 355{
390 return efl_ui_view_model_get(sd->button); 356 return efl_ui_view_model_get(sd->button);
391} 357}
@@ -448,34 +414,12 @@ _elm_fileselector_entry_path_set_internal(Evas_Object *obj, const char *path)
448 } 414 }
449} 415}
450 416
451static void
452_fs_entry_model_path_get_then(void *data, Efl_Event const *event)
453{
454 Elm_Fileselector_Entry_Data *sd = data;
455 char *path = NULL;
456 char *s;
457 Eina_Value* v = (Eina_Value*)((Efl_Future_Event_Success*)event->info)->value;
458
459 if (!v)
460 return;
461
462 eina_value_get(v, &path);
463 s = elm_entry_utf8_to_markup(path);
464 if (s)
465 {
466 elm_object_text_set(sd->entry, s);
467 free(s);
468 }
469}
470
471EOLIAN static void 417EOLIAN static void
472_elm_fileselector_entry_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, Efl_Model *model) 418_elm_fileselector_entry_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, Efl_Model *model)
473{ 419{
474 Efl_Future *p = NULL;
475 efl_ui_view_model_set(sd->button, model); 420 efl_ui_view_model_set(sd->button, model);
476 421 efl_ui_view_model_set(sd->entry, model);
477 p = efl_model_property_get(model, "path"); 422 efl_ui_model_connect(sd->entry, "default", "path");
478 efl_future_then(p, _fs_entry_model_path_get_then, NULL, NULL, sd);
479} 423}
480 424
481EINA_DEPRECATED EAPI const char * 425EINA_DEPRECATED EAPI const char *
diff --git a/src/lib/elementary/elm_fileselector.eo b/src/lib/elementary/elm_fileselector.eo
index 166ee078c1..3ef8a517af 100644
--- a/src/lib/elementary/elm_fileselector.eo
+++ b/src/lib/elementary/elm_fileselector.eo
@@ -39,8 +39,7 @@ class Elm.Fileselector (Efl.Ui.Layout.Object, Elm.Interface.Fileselector,
39 Efl.Ui.Widget.theme_apply; 39 Efl.Ui.Widget.theme_apply;
40 Efl.Ui.Widget.focus_state_apply; 40 Efl.Ui.Widget.focus_state_apply;
41 Elm.Interface.Fileselector.selected_models { get; } 41 Elm.Interface.Fileselector.selected_models { get; }
42 Elm.Interface.Fileselector.selected_model_get; 42 Elm.Interface.Fileselector.selected_model { get; set; }
43 Elm.Interface.Fileselector.selected_model_set;
44 Elm.Interface.Fileselector.custom_filter_append; 43 Elm.Interface.Fileselector.custom_filter_append;
45 Elm.Interface.Fileselector.expandable { get; set; } 44 Elm.Interface.Fileselector.expandable { get; set; }
46 Elm.Interface.Fileselector.thumbnail_size { get; set; } 45 Elm.Interface.Fileselector.thumbnail_size { get; set; }
diff --git a/src/lib/elementary/elm_fileselector_button.eo b/src/lib/elementary/elm_fileselector_button.eo
index c9b2ba8091..37f7c141e2 100644
--- a/src/lib/elementary/elm_fileselector_button.eo
+++ b/src/lib/elementary/elm_fileselector_button.eo
@@ -10,8 +10,7 @@ class Elm.Fileselector_Button (Efl.Ui.Button, Elm.Interface.Fileselector,
10 Elm.Interface.Fileselector.selected_models { get; } 10 Elm.Interface.Fileselector.selected_models { get; }
11 Elm.Interface.Fileselector.expandable { get; set; } 11 Elm.Interface.Fileselector.expandable { get; set; }
12 Elm.Interface.Fileselector.thumbnail_size { get; set; } 12 Elm.Interface.Fileselector.thumbnail_size { get; set; }
13 Elm.Interface.Fileselector.selected_model_get; 13 Elm.Interface.Fileselector.selected_model { get; set; }
14 Elm.Interface.Fileselector.selected_model_set;
15 Elm.Interface.Fileselector.hidden_visible { get; set; } 14 Elm.Interface.Fileselector.hidden_visible { get; set; }
16 Elm.Interface.Fileselector.is_save { get; set; } 15 Elm.Interface.Fileselector.is_save { get; set; }
17 Efl.Ui.View.model { get; set; } 16 Efl.Ui.View.model { get; set; }
diff --git a/src/lib/elementary/elm_fileselector_entry.eo b/src/lib/elementary/elm_fileselector_entry.eo
index 45e8fc6dd0..c3afba8e37 100644
--- a/src/lib/elementary/elm_fileselector_entry.eo
+++ b/src/lib/elementary/elm_fileselector_entry.eo
@@ -8,8 +8,7 @@ class Elm.Fileselector_Entry (Efl.Ui.Layout.Object, Elm.Interface.Fileselector,
8 Efl.Object.constructor; 8 Efl.Object.constructor;
9 Efl.Ui.Widget.theme_apply; 9 Efl.Ui.Widget.theme_apply;
10 Efl.Ui.Widget.on_disabled_update; 10 Efl.Ui.Widget.on_disabled_update;
11 Elm.Interface.Fileselector.selected_model_get; 11 Elm.Interface.Fileselector.selected_model { get; set; }
12 Elm.Interface.Fileselector.selected_model_set;
13 Elm.Interface.Fileselector.folder_only { get; set; } 12 Elm.Interface.Fileselector.folder_only { get; set; }
14 Elm.Interface.Fileselector.is_save { get; set; } 13 Elm.Interface.Fileselector.is_save { get; set; }
15 Efl.Ui.View.model { get; set; } 14 Efl.Ui.View.model { get; set; }
diff --git a/src/lib/elementary/elm_interface_fileselector.c b/src/lib/elementary/elm_interface_fileselector.c
index aaa7cdae2e..091911100a 100644
--- a/src/lib/elementary/elm_interface_fileselector.c
+++ b/src/lib/elementary/elm_interface_fileselector.c
@@ -2,7 +2,11 @@
2# include "elementary_config.h" 2# include "elementary_config.h"
3#endif 3#endif
4 4
5#define ELM_INTERFACE_FILESELECTOR_BETA
6
5#include <Elementary.h> 7#include <Elementary.h>
8#include "Eio_Eo.h"
9
6#include "elm_interface_fileselector.h" 10#include "elm_interface_fileselector.h"
7 11
8#include "elm_interface_fileselector.eo.c" 12#include "elm_interface_fileselector.eo.c"
diff --git a/src/lib/elementary/elm_interface_fileselector.eo b/src/lib/elementary/elm_interface_fileselector.eo
index a197e6fbf8..fb35f6264a 100644
--- a/src/lib/elementary/elm_interface_fileselector.eo
+++ b/src/lib/elementary/elm_interface_fileselector.eo
@@ -137,16 +137,17 @@ interface Elm.Interface.Fileselector (Efl.Ui.View)
137 name: string; [[Name]] 137 name: string; [[Name]]
138 } 138 }
139 } 139 }
140 selected_model_set { 140 @property selected_model @beta {
141 [[Set, programmatically, the currently selected file/directory in the given file selector widget]] 141 set {
142 params { 142 [[Set, programmatically, the currently selected file/directory in the given file selector widget]]
143 @in model: Efl.Model; [[Model to be set]] 143 return: bool; [[$true on success, $false otherwise]]
144 }
145 get {
146 [[Get the currently selected item's model, in the given file the given file selector widget]]
147 }
148 values {
149 model: Eio.Model; [[Model to be set, NULL reset it.]]
144 } 150 }
145 return: future<Efl.Model>; [[Promise returning the recorded selected model or error]]
146 }
147 selected_model_get {
148 [[Get the currently selected item's model, in the given file the given file selector widget]]
149 return: Efl.Model; [[Selected model]]
150 } 151 }
151 custom_filter_append { 152 custom_filter_append {
152 [[Append custom filter into filter list]] 153 [[Append custom filter into filter list]]
diff --git a/src/lib/elementary/elm_widget_fileselector.h b/src/lib/elementary/elm_widget_fileselector.h
index db0de2c492..1ebf33c0ca 100644
--- a/src/lib/elementary/elm_widget_fileselector.h
+++ b/src/lib/elementary/elm_widget_fileselector.h
@@ -57,6 +57,8 @@ struct _Elm_Fileselector_Data
57 Ecore_Idler *populate_idler; 57 Ecore_Idler *populate_idler;
58 Ecore_Idler *path_entry_idler; 58 Ecore_Idler *path_entry_idler;
59 59
60 Efl_Model *target;
61
60 const char *path_separator; 62 const char *path_separator;
61 const char *search_string; 63 const char *search_string;
62 64
@@ -104,6 +106,7 @@ struct _Listing_Request
104 Eina_Stringshare *selected_path; 106 Eina_Stringshare *selected_path;
105 int item_total; 107 int item_total;
106 int item_processed_count; 108 int item_processed_count;
109
107 Eina_Bool first : 1; 110 Eina_Bool first : 1;
108 Eina_Bool valid : 1; 111 Eina_Bool valid : 1;
109}; 112};
@@ -114,11 +117,13 @@ struct _Elm_Fileselector_Item_Data
114 Efl_Model *model; 117 Efl_Model *model;
115 Eina_Stringshare *path; 118 Eina_Stringshare *path;
116 Eina_Stringshare *filename; 119 Eina_Stringshare *filename;
117 int64_t size;
118 double mtime;
119 Eina_Stringshare *mime_type; 120 Eina_Stringshare *mime_type;
120 Efl_Model *parent_model; 121 Efl_Model *parent_model;
121 const char *parent_path; 122 const char *parent_path;
123
124 int64_t size;
125 double mtime;
126
122 Eina_Bool is_dir : 1; 127 Eina_Bool is_dir : 1;
123}; 128};
124 129