3 * - child elements focusing support
4 * - user defined icon/label cb
5 * - show/hide/add buttons ???
6 * - Pattern Filter support
9 # include "elementary_config.h"
12 #include <Elementary.h>
14 #include "elm_interface_fileselector.h"
15 #include "elm_widget_fileselector.h"
17 #define MY_CLASS ELM_OBJ_FILESELECTOR_CLASS
19 #define MY_CLASS_NAME "Elm_Fileselector"
20 #define MY_CLASS_NAME_LEGACY "elm_fileselector"
22 /* FIXME: need a way to find a gap between the size of item and thumbnail */
23 #define GENGRID_PADDING 16
25 static Elm_Genlist_Item_Class *list_itc[ELM_FILE_LAST];
26 static Elm_Gengrid_Item_Class *grid_itc[ELM_FILE_LAST];
28 #define ELM_PRIV_FILESELECTOR_SIGNALS(cmd) \
29 cmd(SIG_ACTIVATED, "activated", "s") \
30 cmd(SIG_DIRECTORY_OPEN, "directory,open", "s") \
31 cmd(SIG_DONE, "done", "s") \
32 cmd(SIG_SELECTED, "selected", "s") \
33 cmd(SIG_SELECTED_INVALID, "selected,invalid", "s")
35 ELM_PRIV_FILESELECTOR_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
37 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
38 ELM_PRIV_FILESELECTOR_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC)
39 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
40 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
43 #undef ELM_PRIV_FILESELECTOR_SIGNALS
45 static Eina_Bool _key_action_select(Evas_Object *obj, const char *params);
46 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params);
48 static const Elm_Action key_actions[] = {
49 {"select", _key_action_select},
50 {"escape", _key_action_escape},
54 static void _ok(void *data, Evas_Object *obj, void *event_info);
55 static void _canc(void *data, Evas_Object *obj, void *event_info);
57 /* final routine on deletion */
59 _elm_fileselector_smart_del_do(Elc_Fileselector_Data *sd)
61 eina_stringshare_del(sd->path);
62 eina_stringshare_del(sd->selection);
63 free(ecore_idler_del(sd->populate_idler));
65 eo_do_super(sd->obj, MY_CLASS, evas_obj_smart_del());
69 _elc_fileselector_elm_layout_sizing_eval(Eo *obj, Elc_Fileselector_Data *sd EINA_UNUSED)
71 Evas_Coord minw = -1, minh = -1;
73 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
75 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
76 edje_object_size_min_restricted_calc
77 (wd->resize_obj, &minw, &minh, minw, minh);
78 evas_object_size_hint_min_set(obj, minw, minh);
82 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
84 ELM_FILESELECTOR_DATA_GET(obj, sd);
86 elm_widget_mirrored_set(sd->cancel_button, rtl);
87 elm_widget_mirrored_set(sd->ok_button, rtl);
88 elm_widget_mirrored_set(sd->files_view, rtl);
89 elm_widget_mirrored_set(sd->up_button, rtl);
90 elm_widget_mirrored_set(sd->home_button, rtl);
93 EOLIAN static Eina_Bool
94 _elc_fileselector_elm_widget_theme_apply(Eo *obj, Elc_Fileselector_Data *sd)
100 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
102 Eina_Bool int_ret = EINA_FALSE;
103 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
104 if (!int_ret) return EINA_FALSE;
106 style = elm_widget_style_get(obj);
107 _mirrored_set(obj, elm_widget_mirrored_get(obj));
109 data = edje_object_data_get
110 (wd->resize_obj, "path_separator");
111 if (data) sd->path_separator = data;
112 else sd->path_separator = "/";
114 snprintf(buf, sizeof(buf), "fileselector/%s", style);
116 #define SWALLOW(part_name, object_ptn) \
119 elm_widget_style_set(object_ptn, buf); \
120 if (!elm_layout_content_set(obj, part_name, object_ptn)) \
121 evas_object_hide(object_ptn); \
124 SWALLOW("elm.swallow.up", sd->up_button);
125 SWALLOW("elm.swallow.home", sd->home_button);
126 SWALLOW("elm.swallow.spinner", sd->spinner);
127 elm_object_style_set(sd->spinner, "wheel");
129 if (!elm_layout_content_set(obj, "elm.swallow.files", sd->files_view))
130 evas_object_hide(sd->files_view);
132 SWALLOW("elm.swallow.path", sd->path_entry);
133 SWALLOW("elm.swallow.filename", sd->name_entry);
135 snprintf(buf, sizeof(buf), "fileselector/actions/%s", style);
136 SWALLOW("elm.swallow.filters", sd->filter_hoversel);
137 SWALLOW("elm.swallow.cancel", sd->cancel_button);
138 SWALLOW("elm.swallow.ok", sd->ok_button);
142 edje_object_message_signal_process(wd->resize_obj);
144 elm_layout_sizing_eval(obj);
150 _key_action_select(Evas_Object *obj, const char *params EINA_UNUSED)
152 _ok(obj, NULL, NULL);
157 _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
159 _canc(obj, NULL, NULL);
163 EOLIAN static Eina_Bool
164 _elc_fileselector_elm_widget_event(Eo *obj, Elc_Fileselector_Data *sd EINA_UNUSED, Evas_Object *src, Evas_Callback_Type type, void *event_info)
166 Evas_Event_Key_Down *ev = event_info;
169 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
170 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
171 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
173 if (!_elm_config_key_binding_call(obj, ev, key_actions))
176 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
180 /*** GENLIST/GENGRID "MODEL" ***/
182 _itc_text_get(void *data,
183 Evas_Object *obj EINA_UNUSED,
184 const char *source EINA_UNUSED)
186 return elm_entry_utf8_to_markup
187 (ecore_file_file_get(data)); /* NOTE this will be free()'d by
192 _itc_icon_folder_get(void *data EINA_UNUSED,
196 Evas_Object *ic, *grid, *f;
198 if (strcmp(source, "elm.swallow.icon")) return NULL;
200 f = evas_object_data_get(obj, "parent");
201 ELM_FILESELECTOR_DATA_GET(f, sd);
203 ic = elm_icon_add(obj);
204 elm_icon_standard_set(ic, "folder");
205 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
206 evas_object_show(ic);
208 grid = elm_grid_add(obj);
209 elm_grid_size_set(grid, 1, 1);
210 elm_grid_pack(grid, ic, 0, 0, 1, 1);
211 evas_object_size_hint_min_set(grid, sd->thumbnail_size.w, sd->thumbnail_size.h);
212 evas_object_show(grid);
218 _itc_icon_image_get(void *data,
222 const char *filename = data;
223 Evas_Object *ic, *grid, *f;
225 if (strcmp(source, "elm.swallow.icon")) return NULL;
227 f = evas_object_data_get(obj, "parent");
228 ELM_FILESELECTOR_DATA_GET(f, sd);
230 ic = elm_icon_add(obj);
231 elm_icon_standard_set(ic, "image");
232 elm_icon_thumb_set(ic, filename, NULL);
233 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
234 evas_object_show(ic);
236 grid = elm_grid_add(obj);
237 elm_grid_size_set(grid, 1, 1);
238 elm_grid_pack(grid, ic, 0, 0, 1, 1);
239 evas_object_size_hint_min_set(grid, sd->thumbnail_size.w, sd->thumbnail_size.h);
240 evas_object_show(grid);
246 _itc_icon_file_get(void *data EINA_UNUSED,
250 Evas_Object *ic, *grid, *f;
252 if (strcmp(source, "elm.swallow.icon")) return NULL;
254 f = evas_object_data_get(obj, "parent");
255 ELM_FILESELECTOR_DATA_GET(f, sd);
257 ic = elm_icon_add(obj);
258 elm_icon_standard_set(ic, "file");
259 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
260 evas_object_show(ic);
262 grid = elm_grid_add(obj);
263 elm_grid_size_set(grid, 1, 1);
264 elm_grid_pack(grid, ic, 0, 0, 1, 1);
265 evas_object_size_hint_min_set(grid, sd->thumbnail_size.w, sd->thumbnail_size.h);
266 evas_object_show(grid);
272 _itc_state_get(void *data EINA_UNUSED,
273 Evas_Object *obj EINA_UNUSED,
274 const char *source EINA_UNUSED)
281 Evas_Object *obj EINA_UNUSED)
283 eina_stringshare_del(data);
287 _anchors_do(Evas_Object *obj,
290 char **tok, buf[PATH_MAX * 3], *s;
293 ELM_FILESELECTOR_DATA_GET(obj, sd);
295 s = elm_entry_utf8_to_markup(path);
299 tok = eina_str_split(s, "/", 0);
302 eina_strlcat(buf, "<a href='/'>root</a>", sizeof(buf));
303 for (i = 0; tok[i]; i++)
305 if ((!tok[i]) || (!tok[i][0])) continue;
306 eina_strlcat(buf, sd->path_separator, sizeof(buf));
307 eina_strlcat(buf, "<a href=", sizeof(buf));
308 for (j = 0; j <= i; j++)
310 if (strlen(tok[j]) < 1) continue;
311 eina_strlcat(buf, "/", sizeof(buf));
312 eina_strlcat(buf, tok[j], sizeof(buf));
314 eina_strlcat(buf, ">", sizeof(buf));
315 eina_strlcat(buf, tok[i], sizeof(buf));
316 eina_strlcat(buf, "</a>", sizeof(buf));
321 elm_object_text_set(sd->path_entry, buf);
325 _mime_type_matched(const char *mime_filter, const char *mime_type)
329 while (mime_filter[i] != '\0')
331 if (mime_filter[i] != mime_type[i])
333 if (mime_filter[i] == '*' && mime_filter[i + 1] == '\0')
341 if (mime_type[i] != '\0') return EINA_FALSE;
347 _check_mime_type_filter(const Elm_Fileselector_Filter *filter,
348 const char *file_name)
350 const char *mime_type = NULL;
353 mime_type = efreet_mime_type_get(file_name);
355 if (!mime_type) return EINA_FALSE;
357 for (i = 0; filter->filter.mime_types[i]; ++i)
359 if (_mime_type_matched(filter->filter.mime_types[i], mime_type))
366 _ls_filter_cb(void *data,
367 Eio_File *handler EINA_UNUSED,
368 const Eina_File_Direct_Info *info)
370 Listing_Request *lreq = data;
371 Elm_Fileselector_Filter *cf;
372 Eina_Bool dir = EINA_FALSE;
374 if (!lreq->sd->hidden_visible && info->path[info->name_start] == '.')
377 if (info->type == EINA_FILE_DIR)
380 if (lreq->sd->only_folder && !dir)
383 cf = lreq->sd->current_filter;
387 switch (cf->filter_type)
389 case ELM_FILESELECTOR_MIME_FILTER:
390 return dir || _check_mime_type_filter(cf, info->path);
391 case ELM_FILESELECTOR_CUSTOM_FILTER:
392 return cf->filter.custom->func(info->path, dir,
393 cf->filter.custom->data);
402 _file_type(const char *a)
404 char *p = strrchr(a, '.');
411 _strcoll_rev(const char *a, const char *b)
413 return strcoll(b, a);
417 _strcoll_type(const char *a, const char *b)
419 return strcoll(_file_type(a), _file_type(b));
423 _strcoll_type_rev(const char *a, const char *b)
425 return _strcoll_type(b, a);
429 _size_cmp(const char *a, const char *b)
431 return ecore_file_size(a) - ecore_file_size(b);
435 _size_cmp_rev(const char *a, const char *b)
437 return _size_cmp(b, a);
441 _modified_cmp(const char *a, const char *b)
443 if (ecore_file_mod_time(a) > ecore_file_mod_time(b))
450 _modified_cmp_rev(const char *a, const char *b)
452 return _modified_cmp(b, a);
456 _file_grid_cmp(const void *a, const void *b)
460 const Elm_Object_Item *ga = a;
461 const Elm_Object_Item *gb = b;
462 const Elm_Gengrid_Item_Class *ca = elm_gengrid_item_item_class_get(ga);
463 const Elm_Gengrid_Item_Class *cb = elm_gengrid_item_item_class_get(gb);
465 if (ca == grid_itc[ELM_DIRECTORY])
467 if (cb != grid_itc[ELM_DIRECTORY])
470 else if (cb == grid_itc[ELM_DIRECTORY])
475 f = evas_object_data_get(elm_object_item_widget_get(ga), "parent");
476 ELM_FILESELECTOR_DATA_GET(f, sd);
477 return sd->sort_method(elm_object_item_data_get(ga),
478 elm_object_item_data_get(gb));
482 _file_list_cmp(const void *a, const void *b)
486 const Elm_Object_Item *la = a;
487 const Elm_Object_Item *lb = b;
488 const Elm_Genlist_Item_Class *ca = elm_genlist_item_item_class_get(la);
489 const Elm_Genlist_Item_Class *cb = elm_genlist_item_item_class_get(lb);
491 if (ca == list_itc[ELM_DIRECTORY])
493 if (cb != list_itc[ELM_DIRECTORY])
496 else if (cb == list_itc[ELM_DIRECTORY])
501 f = evas_object_data_get(elm_object_item_widget_get(la), "parent");
502 ELM_FILESELECTOR_DATA_GET(f, sd);
503 return sd->sort_method(elm_object_item_data_get(la),
504 elm_object_item_data_get(lb));
508 _signal_first(Listing_Request *lreq)
510 if (!lreq->first) return;
515 EINA_LIST_FREE(lreq->sd->paths, path)
519 evas_object_smart_callback_call
520 (lreq->obj, SIG_DIRECTORY_OPEN, (void *)lreq->path);
522 if (!lreq->parent_it)
524 if (lreq->sd->mode == ELM_FILESELECTOR_LIST)
525 elm_genlist_clear(lreq->sd->files_view);
527 elm_gengrid_clear(lreq->sd->files_view);
528 eina_stringshare_replace(&lreq->sd->path, lreq->path);
529 _anchors_do(lreq->obj, lreq->path);
530 elm_object_text_set(lreq->sd->name_entry, "");
533 lreq->first = EINA_FALSE;
537 _ls_main_cb(void *data,
539 const Eina_File_Direct_Info *info)
541 Listing_Request *lreq = data;
542 Elm_Object_Item *item;
543 int itcn = ELM_FILE_UNKNOW;
545 if (eio_file_check(handler)) return;
547 if (!lreq->sd->files_view || lreq->sd->current != handler)
549 eio_file_cancel(handler);
555 if (info->type == EINA_FILE_DIR)
556 itcn = ELM_DIRECTORY;
559 if (evas_object_image_extension_can_load_get
560 (info->path + info->name_start))
561 itcn = ELM_FILE_IMAGE;
564 if (lreq->sd->mode == ELM_FILESELECTOR_LIST)
566 item = elm_genlist_item_sorted_insert(lreq->sd->files_view, list_itc[itcn],
567 eina_stringshare_add(info->path),
569 ((lreq->sd->expand) && (itcn == ELM_DIRECTORY))
570 ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
571 _file_list_cmp, NULL, NULL);
573 if (lreq->selected && !strcmp(info->path, lreq->selected))
575 elm_genlist_item_selected_set(item, EINA_TRUE);
576 elm_object_text_set(lreq->sd->name_entry, ecore_file_file_get(info->path));
579 else if (lreq->sd->mode == ELM_FILESELECTOR_GRID)
581 item = elm_gengrid_item_sorted_insert(lreq->sd->files_view, grid_itc[itcn],
582 eina_stringshare_add(info->path),
583 _file_grid_cmp, NULL, NULL);
585 if (lreq->selected && !strcmp(info->path, lreq->selected))
587 elm_gengrid_item_selected_set(item, EINA_TRUE);
588 elm_object_text_set(lreq->sd->name_entry, ecore_file_file_get(info->path));
594 _listing_request_cleanup(Listing_Request *lreq)
596 EINA_REFCOUNT_UNREF(lreq->sd) _elm_fileselector_smart_del_do(lreq->sd);
598 eina_stringshare_del(lreq->path);
599 eina_stringshare_del(lreq->selected);
604 _ls_done_cb(void *data, Eio_File *handler EINA_UNUSED)
606 Listing_Request *lreq = data;
609 elm_progressbar_pulse(lreq->sd->spinner, EINA_FALSE);
610 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
612 lreq->sd->current = NULL;
613 _listing_request_cleanup(lreq);
617 _ls_error_cb(void *data, Eio_File *handler, int error EINA_UNUSED)
619 Listing_Request *lreq = data;
621 elm_progressbar_pulse(lreq->sd->spinner, EINA_FALSE);
622 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
624 if (lreq->sd->current == handler)
625 lreq->sd->current = NULL;
626 _listing_request_cleanup(lreq);
630 _populate(Evas_Object *obj,
632 Elm_Object_Item *parent_it,
633 const char *selected)
635 ELM_FILESELECTOR_DATA_GET(obj, sd);
638 Listing_Request *lreq;
640 if (sd->expand && sd->current) return;
642 if (sd->monitor) eio_monitor_del(sd->monitor);
643 if (sd->current) eio_file_cancel(sd->current);
645 lreq = malloc(sizeof (Listing_Request));
649 EINA_REFCOUNT_REF(lreq->sd);
651 lreq->parent_it = parent_it; /* FIXME: should we refcount the parent_it ? */
653 lreq->path = eina_stringshare_add(path);
654 lreq->first = EINA_TRUE;
657 lreq->selected = eina_stringshare_add(selected);
659 lreq->selected = NULL;
661 /* TODO: sub directory should be monitored for expand mode */
662 sd->monitor = eio_monitor_add(path);
663 sd->current = eio_file_stat_ls(path, _ls_filter_cb, _ls_main_cb,
664 _ls_done_cb, _ls_error_cb, lreq);
665 elm_progressbar_pulse(sd->spinner, EINA_TRUE);
666 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,show", "elm");
670 _on_list_expanded(void *data,
671 Evas_Object *obj EINA_UNUSED,
674 Elm_Object_Item *it = event_info;
675 const char *path = elm_object_item_data_get(it);
677 _populate(data, path, it, NULL);
681 _on_list_contracted(void *data EINA_UNUSED,
682 Evas_Object *obj EINA_UNUSED,
685 Elm_Object_Item *it = event_info;
687 elm_genlist_item_subitems_clear(it);
691 _on_list_expand_req(void *data EINA_UNUSED,
692 Evas_Object *obj EINA_UNUSED,
695 Elm_Object_Item *it = event_info;
697 elm_genlist_item_expanded_set(it, EINA_TRUE);
701 _on_list_contract_req(void *data EINA_UNUSED,
702 Evas_Object *obj EINA_UNUSED,
705 Elm_Object_Item *it = event_info;
707 elm_genlist_item_expanded_set(it, EINA_FALSE);
711 _populate_do(void *data)
713 struct sel_data *sdata = data;
716 ELM_FILESELECTOR_DATA_GET(sdata->fs, sd);
718 /* keep a ref to path 'couse it will be destroyed by _populate */
719 p = eina_stringshare_add(sdata->path);
720 _populate(sdata->fs, p, NULL, NULL);
721 eina_stringshare_del(p);
723 sd->populate_idler = NULL;
725 return ECORE_CALLBACK_CANCEL;
729 _on_item_activated(void *data,
730 Evas_Object *obj EINA_UNUSED,
733 //This event_info could be a list or gengrid item
734 Elm_Object_Item *it = event_info;
735 struct sel_data *sdata;
740 ELM_FILESELECTOR_DATA_GET(data, sd);
742 path = elm_object_item_data_get(it);
745 is_dir = ecore_file_is_dir(path);
748 evas_object_smart_callback_call(data, SIG_ACTIVATED, (void *)path);
752 if (!sd->double_tap_navigation) return;
754 sdata = malloc(sizeof(*sdata));
760 if (sd->populate_idler)
762 old_sdata = ecore_idler_del(sd->populate_idler);
765 sd->populate_idler = ecore_idler_add(_populate_do, sdata);
769 _clear_selections(Elc_Fileselector_Data *sd, Elm_Object_Item *last_selected)
772 Elm_Object_Item *sel;
774 if (sd->mode == ELM_FILESELECTOR_LIST)
776 items = eina_list_clone(elm_genlist_selected_items_get(sd->files_view));
778 EINA_LIST_FREE(items, sel)
780 if (sel == last_selected) continue;
781 elm_genlist_item_selected_set(sel, EINA_FALSE);
784 else if (sd->mode == ELM_FILESELECTOR_GRID)
786 items = eina_list_clone(elm_gengrid_selected_items_get(sd->files_view));
788 EINA_LIST_FREE(items, sel)
790 if (sel == last_selected) continue;
791 elm_gengrid_item_selected_set(sel, EINA_FALSE);
797 _on_item_selected(void *data,
798 Evas_Object *obj EINA_UNUSED,
801 //This event_info could be a list or gengrid item
802 Elm_Object_Item *it = event_info;
803 struct sel_data *sdata;
809 ELM_FILESELECTOR_DATA_GET(data, sd);
811 path = elm_object_item_data_get(it);
814 is_dir = ecore_file_is_dir(path);
816 /* We need to send callback when:
817 * - path is dir and mode is ONLY FOLDER
818 * - path is file and mode is NOT ONLY FOLDER */
819 if (is_dir == sd->only_folder)
827 if (sd->dir_selected)
829 _clear_selections(sd, it);
830 sd->dir_selected = EINA_FALSE;
833 buf = eina_strbuf_new();
834 EINA_LIST_FOREACH(sd->paths, li, p)
836 eina_strbuf_append(buf, ecore_file_file_get(p));
837 eina_strbuf_append_length(buf, ", ", 2);
840 sd->paths = eina_list_append(sd->paths, strdup(path));
841 eina_strbuf_append(buf, ecore_file_file_get(path));
843 elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf));
844 eina_strbuf_free(buf);
847 elm_object_text_set(sd->name_entry, ecore_file_file_get(path));
849 evas_object_smart_callback_call(data, SIG_SELECTED, (void *)path);
853 if (sd->multi && is_dir && sd->double_tap_navigation)
855 _clear_selections(sd, it);
856 sd->dir_selected = EINA_TRUE;
859 elm_object_text_set(sd->name_entry, "");
862 /* We need to populate, if path is directory and:
864 * - mode is LIST and 'not expand mode';
865 * in other cases update anchors. */
868 if (sd->expand && sd->mode == ELM_FILESELECTOR_LIST)
872 parent_path = ecore_file_dir_get(path);
873 eina_stringshare_replace(&sd->path, parent_path);
874 _anchors_do(data, parent_path);
879 eina_stringshare_replace(&sd->path, path);
880 _anchors_do(data, path);
885 if (sd->double_tap_navigation) return;
887 sdata = malloc(sizeof(*sdata));
893 if (sd->populate_idler)
895 old_sdata = ecore_idler_del(sd->populate_idler);
898 sd->populate_idler = ecore_idler_add(_populate_do, sdata);
902 _on_item_unselected(void *data,
903 Evas_Object *obj EINA_UNUSED,
908 const char *unselected_path;
910 Elm_Object_Item *it = event_info;
911 Eina_Bool first = EINA_TRUE;
913 ELM_FILESELECTOR_DATA_GET(data, sd);
915 if (!sd->multi) return;
917 unselected_path = elm_object_item_data_get(it);
918 if (!unselected_path) return;
920 buf = eina_strbuf_new();
921 EINA_LIST_FOREACH_SAFE(sd->paths, li, l, path)
923 if (!strcmp(path, unselected_path))
925 sd->paths = eina_list_remove_list(sd->paths, li);
931 eina_strbuf_append_length(buf, ", ", 2);
935 eina_strbuf_append(buf, ecore_file_file_get(path));
939 elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf));
940 eina_strbuf_free(buf);
944 _on_dir_up(void *data,
945 Evas_Object *obj EINA_UNUSED,
946 void *event_info EINA_UNUSED)
948 Evas_Object *fs = data;
951 ELM_FILESELECTOR_DATA_GET(fs, sd);
953 parent = ecore_file_dir_get(sd->path);
954 _populate(fs, parent, NULL, NULL);
960 Evas_Object *obj EINA_UNUSED,
961 void *event_info EINA_UNUSED)
963 Evas_Object *fs = data;
965 _populate(fs, getenv("HOME"), NULL, NULL);
969 _current_filter_changed(void *data,
971 void *event_info EINA_UNUSED)
973 Elm_Fileselector_Filter *filter = data;
975 if (filter->sd->current_filter == filter) return;
977 elm_object_text_set(obj, filter->filter_name);
978 filter->sd->current_filter = filter;
980 _populate(filter->sd->obj, filter->sd->path, NULL, NULL);
985 Evas_Object *obj EINA_UNUSED,
986 void *event_info EINA_UNUSED)
989 const char *selection = NULL;
990 Evas_Object *fs = data;
991 ELM_FILESELECTOR_DATA_GET(fs, sd);
995 evas_object_smart_callback_call(fs, SIG_DONE, NULL);
999 name = elm_object_text_get(sd->name_entry);
1000 if (name && name[0] != '\0')
1002 int len = eina_stringshare_strlen(sd->path);
1003 if (sd->path[len - 1] == '/')
1004 selection = eina_stringshare_printf("%s%s", sd->path, name);
1006 selection = eina_stringshare_printf("%s/%s", sd->path, name);
1009 selection = eina_stringshare_add(elm_fileselector_selected_get(fs));
1011 evas_object_smart_callback_call(fs, SIG_DONE, (void *)selection);
1012 eina_stringshare_del(selection);
1017 Evas_Object *obj EINA_UNUSED,
1018 void *event_info EINA_UNUSED)
1020 Evas_Object *fs = data;
1022 evas_object_smart_callback_call(fs, SIG_DONE, NULL);
1026 _on_text_clicked(void *data EINA_UNUSED,
1028 void *event_info EINA_UNUSED)
1030 ELM_FILESELECTOR_DATA_GET(data, sd);
1032 /* FIXME: When anchor is clicked, current callback is also called.
1033 * But when it is "anchor,clicked" entry should be unfocused, so we remove
1034 * focus in achor_clicked.
1036 * Check if entry is focused.
1037 * It will be so if empty place (not anchor) was clicked. */
1038 if (!elm_object_focus_get(obj)) return;
1040 elm_entry_entry_set(obj, sd->path);
1041 elm_entry_cursor_pos_set(obj, eina_stringshare_strlen(sd->path));
1045 _on_text_activated(void *data,
1047 void *event_info EINA_UNUSED)
1049 Evas_Object *fs = data;
1050 const char *p, *path;
1053 ELM_FILESELECTOR_DATA_GET(fs, sd);
1055 path = elm_widget_part_text_get(obj, NULL);
1057 if (!ecore_file_exists(path))
1059 evas_object_smart_callback_call(fs, SIG_SELECTED, (void *)path);
1060 evas_object_smart_callback_call(fs, SIG_SELECTED_INVALID, (void *)path);
1064 if (ecore_file_is_dir(path))
1066 // keep a ref to path 'couse it will be destroyed by _populate
1067 p = eina_stringshare_add(path);
1068 _populate(fs, p, NULL, NULL);
1069 eina_stringshare_del(p);
1071 if (sd->only_folder)
1072 evas_object_smart_callback_call(fs, SIG_SELECTED, (void *)path);
1077 dir = ecore_file_dir_get(path);
1080 if (strcmp(dir, sd->path))
1082 _populate(fs, dir, NULL, path);
1084 if (sd->only_folder)
1085 evas_object_smart_callback_call(fs, SIG_SELECTED, (void *)path);
1089 if (sd->mode == ELM_FILESELECTOR_LIST)
1091 Elm_Object_Item *item = elm_genlist_first_item_get(sd->files_view);
1094 const char *item_path = elm_widget_item_data_get(item);
1095 if (!strcmp(item_path, path))
1097 elm_genlist_item_selected_set(item, EINA_TRUE);
1098 elm_widget_part_text_set(sd->name_entry, NULL,
1099 ecore_file_file_get(path));
1102 item = elm_genlist_item_next_get(item);
1107 Elm_Object_Item *item = elm_gengrid_first_item_get(sd->files_view);
1110 const char *item_path = elm_object_item_data_get(item);
1111 if (!strcmp(item_path, path))
1113 elm_gengrid_item_selected_set(item, EINA_TRUE);
1114 elm_widget_part_text_set(sd->name_entry, NULL,
1115 ecore_file_file_get(path));
1118 item = elm_gengrid_item_next_get(item);
1125 elm_object_focus_set(obj, EINA_FALSE);
1129 _on_text_unfocused(void *data,
1130 Evas_Object *obj EINA_UNUSED,
1131 void *event_info EINA_UNUSED)
1133 ELM_FILESELECTOR_DATA_GET(data, sd);
1134 _anchors_do(data, sd->path);
1138 _anchor_clicked(void *data,
1139 Evas_Object *obj EINA_UNUSED,
1142 Elm_Entry_Anchor_Info *info = event_info;
1143 Evas_Object *fs = data;
1146 // keep a ref to path 'couse it will be destroyed by _populate
1147 p = eina_stringshare_add(info->name);
1148 _populate(fs, p, NULL, NULL);
1149 eina_stringshare_del(p);
1150 /* After anchor was clicked, entry will be focused, and will be editable.
1151 * It's wrong. So remove focus. */
1152 elm_object_focus_set(obj, EINA_FALSE);
1155 static Evas_Object *
1156 _files_list_add(Evas_Object *obj)
1160 li = elm_genlist_add(obj);
1161 evas_object_data_set(li, "parent", obj);
1162 elm_widget_mirrored_automatic_set(li, EINA_FALSE);
1163 evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
1164 evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1165 evas_object_size_hint_min_set(li, 100, 100);
1167 evas_object_smart_callback_add(li, "selected", _on_item_selected, obj);
1168 evas_object_smart_callback_add(li, "unselected", _on_item_unselected, obj);
1169 evas_object_smart_callback_add(li, "activated", _on_item_activated, obj);
1170 evas_object_smart_callback_add
1171 (li, "expand,request", _on_list_expand_req, obj);
1172 evas_object_smart_callback_add
1173 (li, "contract,request", _on_list_contract_req, obj);
1174 evas_object_smart_callback_add(li, "expanded", _on_list_expanded, obj);
1175 evas_object_smart_callback_add(li, "contracted", _on_list_contracted, obj);
1177 elm_widget_sub_object_add(obj, li);
1182 static Evas_Object *
1183 _files_grid_add(Evas_Object *obj)
1187 ELM_FILESELECTOR_DATA_GET(obj, sd);
1189 grid = elm_gengrid_add(obj);
1190 evas_object_data_set(grid, "parent", obj);
1191 elm_widget_mirrored_automatic_set(grid, EINA_FALSE);
1192 evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
1193 evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1195 elm_gengrid_item_size_set(grid, sd->thumbnail_size.w + GENGRID_PADDING, sd->thumbnail_size.h + GENGRID_PADDING);
1197 elm_gengrid_align_set(grid, 0.0, 0.0);
1199 evas_object_smart_callback_add(grid, "selected", _on_item_selected, obj);
1200 evas_object_smart_callback_add(grid, "unselected", _on_item_unselected, obj);
1201 evas_object_smart_callback_add(grid, "activated", _on_item_activated, obj);
1203 elm_widget_sub_object_add(obj, grid);
1209 _resource_created(void *data, int type, void *ev)
1211 Evas_Object *obj = data;
1212 Eio_Monitor_Event *event = ev;
1213 int itcn = ELM_FILE_UNKNOW;
1214 Eina_Bool dir = EINA_FALSE;
1216 ELM_FILESELECTOR_DATA_GET(obj, sd);
1218 if (type == EIO_MONITOR_DIRECTORY_CREATED)
1221 Elm_Fileselector_Filter *cf = sd->current_filter;
1224 switch (cf->filter_type)
1226 case ELM_FILESELECTOR_MIME_FILTER:
1227 if (!dir && !_check_mime_type_filter(cf, event->filename))
1228 return ECORE_CALLBACK_PASS_ON;
1230 case ELM_FILESELECTOR_CUSTOM_FILTER:
1231 if (!cf->filter.custom->func(event->filename, dir, cf->filter.custom->data))
1232 return ECORE_CALLBACK_PASS_ON;
1240 itcn = ELM_DIRECTORY;
1243 if (evas_object_image_extension_can_load_get(event->filename))
1244 itcn = ELM_FILE_IMAGE;
1247 if (sd->mode == ELM_FILESELECTOR_LIST)
1248 elm_genlist_item_sorted_insert(sd->files_view, list_itc[itcn],
1249 eina_stringshare_add(event->filename),
1251 (sd->expand && itcn == ELM_DIRECTORY)
1252 ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
1253 _file_list_cmp, NULL, NULL);
1255 elm_gengrid_item_sorted_insert(sd->files_view, grid_itc[itcn],
1256 eina_stringshare_add(event->filename),
1257 _file_grid_cmp, NULL, NULL);
1259 return ECORE_CALLBACK_PASS_ON;
1263 _resource_deleted(void *data, int type EINA_UNUSED, void *ev)
1265 Evas_Object *obj = data;
1266 Eio_Monitor_Event *event = ev;
1267 Elm_Object_Item *it = NULL;
1268 Eina_Bool selected = EINA_FALSE;
1270 ELM_FILESELECTOR_DATA_GET(obj, sd);
1272 if (sd->mode == ELM_FILESELECTOR_LIST)
1274 it = elm_genlist_first_item_get(sd->files_view);
1277 if (!strcmp(elm_object_item_data_get(it), event->filename))
1279 selected = elm_genlist_item_selected_get(it);
1282 it = elm_genlist_item_next_get(it);
1287 it = elm_gengrid_first_item_get(sd->files_view);
1290 if (!strcmp(elm_object_item_data_get(it), event->filename))
1292 selected = elm_genlist_item_selected_get(it);
1295 it = elm_gengrid_item_next_get(it);
1299 if (it) elm_object_item_del(it);
1308 Eina_Bool first = EINA_TRUE;
1310 buf = eina_strbuf_new();
1311 EINA_LIST_FOREACH_SAFE(sd->paths, li, l, path)
1313 if (!strcmp(path, event->filename))
1315 sd->paths = eina_list_remove_list(sd->paths, li);
1321 eina_strbuf_append_length(buf, ", ", 2);
1325 eina_strbuf_append(buf, ecore_file_file_get(path));
1329 elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf));
1330 eina_strbuf_free(buf);
1333 elm_object_text_set(sd->name_entry, "");
1336 return ECORE_CALLBACK_PASS_ON;
1340 _name_entry_activated_cb(void *data, Evas_Object *obj EINA_UNUSED,
1341 void *event_info EINA_UNUSED)
1343 _ok(data, NULL, NULL);
1347 _elc_fileselector_evas_smart_add(Eo *obj, Elc_Fileselector_Data *priv)
1349 Evas_Object *ic, *bt, *en, *pb;
1351 EINA_REFCOUNT_INIT(priv);
1353 eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
1354 elm_widget_sub_object_parent_add(obj);
1355 elm_widget_can_focus_set(obj, EINA_TRUE);
1357 priv->expand = !!_elm_config->fileselector_expand_enable;
1358 priv->double_tap_navigation = !!_elm_config->fileselector_double_tap_navigation_enable;
1360 if (!elm_layout_theme_set
1361 (obj, "fileselector", "base", elm_widget_style_get(obj)))
1362 CRI("Failed to set layout!");
1365 ic = elm_icon_add(obj);
1366 elm_icon_standard_set(ic, "arrow_up");
1367 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
1368 bt = elm_button_add(obj);
1369 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1370 elm_object_part_content_set(bt, "icon", ic);
1371 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Up"));
1372 evas_object_size_hint_align_set(bt, 0.0, 0.0);
1373 evas_object_smart_callback_add(bt, "clicked", _on_dir_up, obj);
1375 elm_widget_sub_object_add(obj, bt);
1377 priv->up_button = bt;
1380 ic = elm_icon_add(obj);
1381 elm_icon_standard_set(ic, "home");
1382 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
1383 bt = elm_button_add(obj);
1384 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1385 elm_object_part_content_set(bt, "icon", ic);
1386 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Home"));
1387 evas_object_size_hint_align_set(bt, 0.0, 0.0);
1388 evas_object_smart_callback_add(bt, "clicked", _home, obj);
1390 elm_widget_sub_object_add(obj, bt);
1391 priv->home_button = bt;
1394 pb = elm_progressbar_add(obj);
1395 elm_widget_sub_object_add(obj, pb);
1398 // XXX: will fail for dynamic finger size changing
1399 priv->thumbnail_size.w = elm_config_finger_size_get() * 2 - GENGRID_PADDING;
1400 priv->thumbnail_size.h = priv->thumbnail_size.w;
1402 priv->sort_type = ELM_FILESELECTOR_SORT_BY_FILENAME_ASC;
1403 priv->sort_method = strcoll;
1406 priv->files_view = _files_list_add(obj);
1409 en = elm_entry_add(obj);
1410 elm_entry_scrollable_set(en, EINA_TRUE);
1411 elm_widget_mirrored_automatic_set(en, EINA_FALSE);
1412 elm_entry_single_line_set(en, EINA_TRUE);
1413 elm_entry_line_wrap_set(en, ELM_WRAP_CHAR);
1414 evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1415 evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
1417 evas_object_smart_callback_add(en, "anchor,clicked", _anchor_clicked, obj);
1418 evas_object_smart_callback_add(en, "clicked", _on_text_clicked, obj);
1419 evas_object_smart_callback_add(en, "unfocused", _on_text_unfocused, obj);
1420 evas_object_smart_callback_add(en, "activated", _on_text_activated, obj);
1422 elm_widget_sub_object_add(obj, en);
1423 priv->path_entry = en;
1426 en = elm_entry_add(obj);
1427 elm_entry_scrollable_set(en, EINA_TRUE);
1428 elm_widget_mirrored_automatic_set(en, EINA_FALSE);
1429 elm_entry_editable_set(en, EINA_TRUE);
1430 elm_entry_single_line_set(en, EINA_TRUE);
1431 elm_entry_line_wrap_set(en, ELM_WRAP_CHAR);
1432 evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1433 evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
1434 evas_object_smart_callback_add(en, "activated",
1435 _name_entry_activated_cb, obj);
1437 elm_widget_sub_object_add(obj, en);
1438 priv->name_entry = en;
1440 elm_fileselector_buttons_ok_cancel_set(obj, EINA_TRUE);
1441 elm_fileselector_is_save_set(obj, EINA_FALSE);
1443 #define HANDLER_ADD(e, fn) \
1444 priv->handlers = eina_list_append(priv->handlers, \
1445 ecore_event_handler_add(e, fn, obj));
1447 HANDLER_ADD(EIO_MONITOR_FILE_CREATED, _resource_created);
1448 HANDLER_ADD(EIO_MONITOR_DIRECTORY_CREATED, _resource_created);
1450 HANDLER_ADD(EIO_MONITOR_FILE_DELETED, _resource_deleted);
1451 HANDLER_ADD(EIO_MONITOR_DIRECTORY_DELETED, _resource_deleted);
1454 eo_do(obj, elm_obj_widget_theme_apply());
1458 _elc_fileselector_evas_smart_del(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1460 Elm_Fileselector_Filter *filter;
1462 Ecore_Event_Handler *h;
1464 if (sd->monitor) eio_monitor_del(sd->monitor);
1465 if (sd->current) eio_file_cancel(sd->current);
1467 EINA_LIST_FREE(sd->handlers, h)
1469 ecore_event_handler_del(h);
1472 EINA_LIST_FREE(sd->filter_list, filter)
1474 eina_stringshare_del(filter->filter_name);
1476 if (filter->filter_type == ELM_FILESELECTOR_MIME_FILTER)
1478 free(filter->filter.mime_types[0]);
1479 free(filter->filter.mime_types);
1482 free(filter->filter.custom);
1487 EINA_LIST_FREE(sd->paths, path)
1490 sd->files_view = NULL;
1492 /* this one matching EINA_REFCOUNT_INIT() */
1493 EINA_REFCOUNT_UNREF(sd) _elm_fileselector_smart_del_do(sd);
1497 elm_fileselector_add(Evas_Object *parent)
1499 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1500 Evas_Object *obj = eo_add(MY_CLASS, parent);
1506 _elc_fileselector_eo_base_constructor(Eo *obj, Elc_Fileselector_Data *sd)
1509 eo_do_super(obj, MY_CLASS, eo_constructor());
1511 evas_obj_type_set(MY_CLASS_NAME_LEGACY),
1512 evas_obj_smart_callbacks_descriptions_set(_smart_callbacks));
1516 elm_fileselector_is_save_set(Evas_Object *obj,
1519 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1520 eo_do(obj, elm_interface_fileselector_is_save_set(is_save));
1524 _elc_fileselector_elm_interface_fileselector_is_save_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool is_save)
1526 elm_object_disabled_set(sd->name_entry, !is_save);
1528 if (is_save) elm_layout_signal_emit(obj, "elm,state,save,on", "elm");
1529 else elm_layout_signal_emit(obj, "elm,state,save,off", "elm");
1533 elm_fileselector_is_save_get(const Evas_Object *obj)
1535 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1536 Eina_Bool ret = EINA_FALSE;
1537 eo_do((Eo *) obj, ret = elm_interface_fileselector_is_save_get());
1541 EOLIAN static Eina_Bool
1542 _elc_fileselector_elm_interface_fileselector_is_save_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1544 return !elm_object_disabled_get(sd->name_entry);
1548 elm_fileselector_folder_only_set(Evas_Object *obj,
1551 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1552 eo_do(obj, elm_interface_fileselector_folder_only_set(only));
1556 _elc_fileselector_elm_interface_fileselector_folder_only_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool only)
1558 if (sd->only_folder == only) return;
1560 sd->only_folder = !!only;
1561 if (sd->path) _populate(obj, sd->path, NULL, NULL);
1565 elm_fileselector_folder_only_get(const Evas_Object *obj)
1567 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1568 Eina_Bool ret = EINA_FALSE;
1569 eo_do((Eo *) obj, ret = elm_interface_fileselector_folder_only_get());
1573 EOLIAN static Eina_Bool
1574 _elc_fileselector_elm_interface_fileselector_folder_only_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1576 return sd->only_folder;
1580 _elc_fileselector_buttons_ok_cancel_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool visible)
1584 if (visible && (!sd->ok_button))
1587 bt = elm_button_add(obj);
1588 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1589 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Cancel"));
1591 evas_object_smart_callback_add(bt, "clicked", _canc, obj);
1593 sd->cancel_button = bt;
1596 bt = elm_button_add(obj);
1597 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1598 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("OK"));
1600 evas_object_smart_callback_add(bt, "clicked", _ok, obj);
1604 eo_do(obj, elm_obj_widget_theme_apply());
1608 ELM_SAFE_FREE(sd->cancel_button, evas_object_del);
1609 ELM_SAFE_FREE(sd->ok_button, evas_object_del);
1613 EOLIAN static Eina_Bool
1614 _elc_fileselector_buttons_ok_cancel_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1616 return sd->ok_button ? EINA_TRUE : EINA_FALSE;
1620 elm_fileselector_expandable_set(Evas_Object *obj,
1623 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1624 eo_do(obj, elm_interface_fileselector_expandable_set(expand));
1628 _elc_fileselector_elm_interface_fileselector_expandable_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool expand)
1630 sd->expand = !!expand;
1632 if (sd->path) _populate(obj, sd->path, NULL, NULL);
1636 elm_fileselector_expandable_get(const Evas_Object *obj)
1638 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1639 Eina_Bool ret = EINA_FALSE;
1640 eo_do((Eo *) obj, ret = elm_interface_fileselector_expandable_get());
1644 EOLIAN static Eina_Bool
1645 _elc_fileselector_elm_interface_fileselector_expandable_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1651 elm_fileselector_path_set(Evas_Object *obj,
1654 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1655 eo_do(obj, elm_interface_fileselector_path_set(_path));
1659 _elc_fileselector_elm_interface_fileselector_path_set(Eo *obj, Elc_Fileselector_Data *sd EINA_UNUSED, const char *_path)
1663 path = ecore_file_realpath(_path);
1664 _populate(obj, path, NULL, NULL);
1669 elm_fileselector_path_get(const Evas_Object *obj)
1671 ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
1672 const char *ret = NULL;
1673 eo_do((Eo *) obj, ret = elm_interface_fileselector_path_get());
1677 EOLIAN static const char*
1678 _elc_fileselector_elm_interface_fileselector_path_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1684 elm_fileselector_mode_set(Evas_Object *obj,
1685 Elm_Fileselector_Mode mode)
1687 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1688 eo_do(obj, elm_interface_fileselector_mode_set(mode));
1692 _elc_fileselector_elm_interface_fileselector_mode_set(Eo *obj, Elc_Fileselector_Data *sd, Elm_Fileselector_Mode mode)
1696 if (mode == sd->mode) return;
1698 old = elm_layout_content_unset(obj, "elm.swallow.files");
1700 if (mode == ELM_FILESELECTOR_LIST)
1702 sd->files_view = _files_list_add(obj);
1704 elm_genlist_multi_select_set(sd->files_view, EINA_TRUE);
1708 sd->files_view = _files_grid_add(obj);
1710 elm_gengrid_multi_select_set(sd->files_view, EINA_TRUE);
1713 elm_layout_content_set(obj, "elm.swallow.files", sd->files_view);
1715 evas_object_del(old);
1719 _populate(obj, sd->path, NULL, NULL);
1722 EAPI Elm_Fileselector_Mode
1723 elm_fileselector_mode_get(const Evas_Object *obj)
1725 ELM_FILESELECTOR_INTERFACE_CHECK(obj, ELM_FILESELECTOR_LAST);
1726 Elm_Fileselector_Mode ret = ELM_FILESELECTOR_LAST;
1727 eo_do((Eo *) obj, ret = elm_interface_fileselector_mode_get());
1731 EOLIAN static Elm_Fileselector_Mode
1732 _elc_fileselector_elm_interface_fileselector_mode_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1738 elm_fileselector_multi_select_set(Evas_Object *obj, Eina_Bool multi)
1740 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1741 eo_do(obj, elm_interface_fileselector_multi_select_set(multi));
1745 _elc_fileselector_elm_interface_fileselector_multi_select_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Eina_Bool multi)
1750 if (sd->multi == multi) return;
1753 if (sd->mode == ELM_FILESELECTOR_LIST)
1754 elm_genlist_multi_select_set(sd->files_view, multi);
1756 elm_gengrid_multi_select_set(sd->files_view, multi);
1760 _clear_selections(sd, NULL);
1762 EINA_LIST_FREE(sd->paths, path)
1767 const Eina_List *selected_items, *li;
1768 const Elm_Object_Item *it;
1770 if (sd->mode == ELM_FILESELECTOR_LIST)
1771 selected_items = elm_genlist_selected_items_get(sd->files_view);
1773 selected_items = elm_gengrid_selected_items_get(sd->files_view);
1775 EINA_LIST_FOREACH(selected_items, li, it)
1777 path = elm_object_item_data_get(it);
1778 sd->paths = eina_list_append(sd->paths, strdup(path));
1784 elm_fileselector_multi_select_get(const Evas_Object *obj)
1786 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1787 Eina_Bool ret = EINA_FALSE;
1788 eo_do((Eo *) obj, ret = elm_interface_fileselector_multi_select_get());
1792 EOLIAN static Eina_Bool
1793 _elc_fileselector_elm_interface_fileselector_multi_select_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1799 elm_fileselector_selected_get(const Evas_Object *obj)
1801 ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
1802 const char *ret = NULL;
1803 eo_do((Eo *) obj, ret = elm_interface_fileselector_selected_get());
1807 EOLIAN static const char*
1808 _elc_fileselector_elm_interface_fileselector_selected_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1811 if (!sd->path) return NULL;
1813 fp = elm_object_text_get(sd->path_entry);
1814 if (ecore_file_exists(fp))
1816 eina_stringshare_replace(&sd->selection, fp);
1818 return sd->selection;
1821 if (sd->mode == ELM_FILESELECTOR_LIST)
1823 Elm_Object_Item *gl_it = elm_genlist_selected_item_get(sd->files_view);
1825 if (gl_it) return elm_object_item_data_get(gl_it);
1829 Elm_Object_Item *gg_it = elm_gengrid_selected_item_get(sd->files_view);
1831 if (gg_it) return elm_object_item_data_get(gg_it);
1839 elm_fileselector_selected_set(Evas_Object *obj,
1842 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1843 Eina_Bool ret = EINA_FALSE;
1844 eo_do(obj, ret = elm_interface_fileselector_selected_set(_path));
1848 EOLIAN static Eina_Bool
1849 _elc_fileselector_elm_interface_fileselector_selected_set(Eo *obj, Elc_Fileselector_Data *sd, const char *_path)
1851 Eina_Bool ret = EINA_TRUE;
1855 path = ecore_file_realpath(_path);
1857 if (ecore_file_is_dir(path)) _populate(obj, path, NULL, NULL);
1860 if (!ecore_file_exists(path))
1866 selected = ecore_file_dir_get(path);
1867 _populate(obj, selected, NULL, NULL);
1868 eina_stringshare_replace(&sd->selection, path);
1878 EAPI const Eina_List *
1879 elm_fileselector_selected_paths_get(const Evas_Object* obj)
1881 ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
1882 const Eina_List *ret = NULL;
1883 eo_do((Eo *) obj, ret = elm_interface_fileselector_selected_paths_get());
1887 EOLIAN static const Eina_List*
1888 _elc_fileselector_elm_interface_fileselector_selected_paths_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1896 static Elm_Fileselector_Filter *
1897 _filter_add(Elc_Fileselector_Data *sd, const char *filter_name)
1899 Elm_Fileselector_Filter *ff;
1900 ff = malloc(sizeof(Elm_Fileselector_Filter));
1902 ff->filter_name = eina_stringshare_add(filter_name);
1909 elm_fileselector_mime_types_filter_append(Evas_Object *obj, const char *mime_type, const char *filter_name)
1911 ELM_FILESELECTOR_CHECK(obj) EINA_FALSE;
1912 Eina_Bool ret = EINA_FALSE;
1913 eo_do(obj, ret = elm_interface_fileselector_mime_types_filter_append(mime_type, filter_name));
1917 EOLIAN static Eina_Bool
1918 _elc_fileselector_elm_interface_fileselector_mime_types_filter_append(Eo *obj, Elc_Fileselector_Data *sd, const char *mime_types, const char *filter_name)
1920 Elm_Fileselector_Filter *ff;
1921 Eina_Bool need_theme = EINA_FALSE;
1923 if (!mime_types) return EINA_FALSE;
1925 ff = _filter_add(sd, filter_name ? filter_name : mime_types);
1926 ff->filter_type = ELM_FILESELECTOR_MIME_FILTER;
1928 ff->filter.mime_types = eina_str_split(mime_types, ",", 0);
1930 if (!sd->filter_list)
1932 sd->current_filter = ff;
1933 sd->filter_hoversel = elm_hoversel_add(obj);
1934 elm_object_text_set(sd->filter_hoversel, ff->filter_name);
1935 need_theme = EINA_TRUE;
1937 elm_hoversel_item_add(sd->filter_hoversel, ff->filter_name, NULL, ELM_ICON_NONE, _current_filter_changed, ff);
1939 sd->filter_list = eina_list_append(sd->filter_list, ff);
1941 _populate(obj, sd->path, NULL, NULL);
1944 eo_do(obj, elm_obj_widget_theme_apply());
1950 elm_fileselector_custom_filter_append(Evas_Object *obj, Elm_Fileselector_Filter_Func func, void *data, const char *filter_name)
1952 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1953 Eina_Bool ret = EINA_FALSE;
1954 eo_do(obj, ret = elm_interface_fileselector_custom_filter_append(func, data, filter_name));
1958 EOLIAN static Eina_Bool
1959 _elc_fileselector_elm_interface_fileselector_custom_filter_append(Eo *obj, Elc_Fileselector_Data *sd, Elm_Fileselector_Filter_Func func, void *data, const char *filter_name)
1961 Elm_Fileselector_Filter *ff;
1962 Eina_Bool need_theme = EINA_FALSE;
1964 if (!func) return EINA_FALSE;
1966 ff = _filter_add(sd, filter_name ? filter_name : "custom");
1967 ff->filter_type = ELM_FILESELECTOR_CUSTOM_FILTER;
1969 ff->filter.custom = malloc(sizeof(Elm_Fileselector_Custom_Filter));
1970 ff->filter.custom->func = func;
1971 ff->filter.custom->data = data;
1973 if (!sd->filter_list)
1975 sd->current_filter = ff;
1976 sd->filter_hoversel = elm_hoversel_add(obj);
1977 elm_object_text_set(sd->filter_hoversel, ff->filter_name);
1978 need_theme = EINA_TRUE;
1980 elm_hoversel_item_add(sd->filter_hoversel, ff->filter_name, NULL, ELM_ICON_NONE, _current_filter_changed, ff);
1982 sd->filter_list = eina_list_append(sd->filter_list, ff);
1984 _populate(obj, sd->path, NULL, NULL);
1987 eo_do(obj, elm_obj_widget_theme_apply());
1993 elm_fileselector_filters_clear(Evas_Object *obj)
1995 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1996 eo_do(obj, elm_interface_fileselector_filters_clear());
2000 _elc_fileselector_elm_interface_fileselector_filters_clear(Eo *obj, Elc_Fileselector_Data *sd)
2002 Elm_Fileselector_Filter *filter;
2004 EINA_LIST_FREE(sd->filter_list, filter)
2006 eina_stringshare_del(filter->filter_name);
2008 if (filter->filter_type == ELM_FILESELECTOR_MIME_FILTER)
2010 free(filter->filter.mime_types[0]);
2011 free(filter->filter.mime_types);
2014 free(filter->filter.custom);
2019 ELM_SAFE_FREE(sd->filter_hoversel, evas_object_del);
2021 _populate(obj, sd->path, NULL, NULL);
2025 elm_fileselector_hidden_visible_set(Evas_Object *obj, Eina_Bool visible)
2027 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2028 eo_do(obj, elm_interface_fileselector_hidden_visible_set(visible));
2032 _elc_fileselector_elm_interface_fileselector_hidden_visible_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Eina_Bool visible)
2034 visible = !!visible;
2035 if (sd->hidden_visible == visible) return;
2036 sd->hidden_visible = visible;
2038 _clear_selections(sd, NULL);
2039 _populate(obj, sd->path, NULL, NULL);
2043 elm_fileselector_hidden_visible_get(const Evas_Object *obj)
2045 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
2046 Eina_Bool ret = EINA_FALSE;
2047 eo_do((Eo *) obj, ret = elm_interface_fileselector_hidden_visible_get());
2051 EOLIAN static Eina_Bool
2052 _elc_fileselector_elm_interface_fileselector_hidden_visible_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
2054 return sd->hidden_visible;
2058 elm_fileselector_thumbnail_size_set(Evas_Object *obj,
2062 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2063 eo_do(obj, elm_interface_fileselector_thumbnail_size_set(w, h));
2067 _elc_fileselector_elm_interface_fileselector_thumbnail_size_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Evas_Coord w, Evas_Coord h)
2069 if (sd->thumbnail_size.w == w && sd->thumbnail_size.h == h) return;
2072 w = h = elm_config_finger_size_get() * 2 - GENGRID_PADDING;
2074 sd->thumbnail_size.w = w;
2075 sd->thumbnail_size.h = h;
2077 if (sd->mode == ELM_FILESELECTOR_GRID)
2078 elm_gengrid_item_size_set(sd->files_view, w + GENGRID_PADDING, h + GENGRID_PADDING);
2080 _populate(obj, sd->path, NULL, NULL);
2084 elm_fileselector_thumbnail_size_get(const Evas_Object *obj,
2088 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2089 eo_do((Eo *) obj, elm_interface_fileselector_thumbnail_size_get(w, h));
2093 _elc_fileselector_elm_interface_fileselector_thumbnail_size_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Evas_Coord *w, Evas_Coord *h)
2095 if (w) *w = sd->thumbnail_size.w;
2096 if (h) *h = sd->thumbnail_size.h;
2100 elm_fileselector_sort_method_set(Evas_Object *obj, Elm_Fileselector_Sort sort)
2102 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2103 eo_do(obj, elm_interface_fileselector_sort_method_set(sort));
2107 _elc_fileselector_elm_interface_fileselector_sort_method_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Elm_Fileselector_Sort sort)
2109 if (sd->sort_type == sort) return;
2110 sd->sort_type = sort;
2112 switch (sd->sort_type)
2114 case ELM_FILESELECTOR_SORT_BY_FILENAME_ASC:
2115 sd->sort_method = strcoll;
2117 case ELM_FILESELECTOR_SORT_BY_FILENAME_DESC:
2118 sd->sort_method = _strcoll_rev;
2120 case ELM_FILESELECTOR_SORT_BY_TYPE_ASC:
2121 sd->sort_method = _strcoll_type;
2123 case ELM_FILESELECTOR_SORT_BY_TYPE_DESC:
2124 sd->sort_method = _strcoll_type_rev;
2126 case ELM_FILESELECTOR_SORT_BY_SIZE_ASC:
2127 sd->sort_method = _size_cmp;
2129 case ELM_FILESELECTOR_SORT_BY_SIZE_DESC:
2130 sd->sort_method = _size_cmp_rev;
2132 case ELM_FILESELECTOR_SORT_BY_MODIFIED_ASC:
2133 sd->sort_method = _modified_cmp;
2135 case ELM_FILESELECTOR_SORT_BY_MODIFIED_DESC:
2136 sd->sort_method = _modified_cmp_rev;
2138 case ELM_FILESELECTOR_SORT_LAST:
2140 sd->sort_method = strcoll;
2143 _populate(obj, sd->path, NULL, NULL);
2146 EAPI Elm_Fileselector_Sort
2147 elm_fileselector_sort_method_get(const Evas_Object *obj)
2149 ELM_FILESELECTOR_INTERFACE_CHECK(obj, ELM_FILESELECTOR_SORT_LAST);
2150 Elm_Fileselector_Sort ret = ELM_FILESELECTOR_SORT_LAST;
2151 eo_do((Eo *) obj, ret = elm_interface_fileselector_sort_method_get());
2156 EOLIAN static Elm_Fileselector_Sort
2157 _elc_fileselector_elm_interface_fileselector_sort_method_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
2159 return sd->sort_type;
2162 EOLIAN static Eina_Bool
2163 _elc_fileselector_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd EINA_UNUSED)
2168 EOLIAN static Eina_Bool
2169 _elc_fileselector_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd EINA_UNUSED)
2174 EOLIAN static Eina_Bool
2175 _elc_fileselector_elm_layout_text_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, const char *part, const char *label)
2177 if (!part) return EINA_FALSE;
2179 if (sd->ok_button && !strcmp(part, "ok"))
2181 elm_object_text_set(sd->ok_button, label);
2184 else if (sd->cancel_button && !strcmp(part, "cancel"))
2186 elm_object_text_set(sd->cancel_button, label);
2191 Eina_Bool int_ret = EINA_FALSE;
2192 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_layout_text_set(part, label));
2200 _elc_fileselector_class_constructor(Eo_Class *klass)
2204 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
2206 for (i = 0; i < ELM_FILE_LAST; ++i)
2208 list_itc[i] = elm_genlist_item_class_new();
2209 grid_itc[i] = elm_gengrid_item_class_new();
2211 list_itc[i]->item_style = "default";
2212 list_itc[i]->func.text_get = grid_itc[i]->func.text_get =
2214 list_itc[i]->func.state_get = grid_itc[i]->func.state_get =
2216 list_itc[i]->func.del = grid_itc[i]->func.del = _itc_del;
2219 list_itc[ELM_DIRECTORY]->func.content_get =
2220 grid_itc[ELM_DIRECTORY]->func.content_get = _itc_icon_folder_get;
2221 list_itc[ELM_FILE_IMAGE]->func.content_get =
2222 grid_itc[ELM_FILE_IMAGE]->func.content_get = _itc_icon_image_get;
2223 list_itc[ELM_FILE_UNKNOW]->func.content_get =
2224 grid_itc[ELM_FILE_UNKNOW]->func.content_get = _itc_icon_file_get;
2229 _elc_fileselector_class_destructor(Eo_Class *klass EINA_UNUSED)
2233 for (i = 0; i < ELM_FILE_LAST; ++i)
2235 elm_genlist_item_class_free(list_itc[i]);
2236 elm_gengrid_item_class_free(grid_itc[i]);
2240 #include "elc_fileselector.eo.c"