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 void _ok(void *data, Evas_Object *obj, void *event_info);
46 static void _canc(void *data, Evas_Object *obj, void *event_info);
48 /* final routine on deletion */
50 _elm_fileselector_smart_del_do(Elc_Fileselector_Data *sd)
52 eina_stringshare_del(sd->path);
53 eina_stringshare_del(sd->selection);
54 free(ecore_idler_del(sd->populate_idler));
56 eo_do_super(sd->obj, MY_CLASS, evas_obj_smart_del());
60 _elc_fileselector_elm_layout_sizing_eval(Eo *obj, Elc_Fileselector_Data *sd EINA_UNUSED)
62 Evas_Coord minw = -1, minh = -1;
64 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
66 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
67 edje_object_size_min_restricted_calc
68 (wd->resize_obj, &minw, &minh, minw, minh);
69 evas_object_size_hint_min_set(obj, minw, minh);
73 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
75 ELM_FILESELECTOR_DATA_GET(obj, sd);
77 elm_widget_mirrored_set(sd->cancel_button, rtl);
78 elm_widget_mirrored_set(sd->ok_button, rtl);
79 elm_widget_mirrored_set(sd->files_view, rtl);
80 elm_widget_mirrored_set(sd->up_button, rtl);
81 elm_widget_mirrored_set(sd->home_button, rtl);
84 EOLIAN static Eina_Bool
85 _elc_fileselector_elm_widget_theme_apply(Eo *obj, Elc_Fileselector_Data *sd)
91 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
93 Eina_Bool int_ret = EINA_FALSE;
94 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
95 if (!int_ret) return EINA_FALSE;
97 style = elm_widget_style_get(obj);
98 _mirrored_set(obj, elm_widget_mirrored_get(obj));
100 data = edje_object_data_get
101 (wd->resize_obj, "path_separator");
102 if (data) sd->path_separator = data;
103 else sd->path_separator = "/";
105 snprintf(buf, sizeof(buf), "fileselector/%s", style);
107 #define SWALLOW(part_name, object_ptn) \
110 elm_widget_style_set(object_ptn, buf); \
111 if (!elm_layout_content_set(obj, part_name, object_ptn)) \
112 evas_object_hide(object_ptn); \
115 SWALLOW("elm.swallow.up", sd->up_button);
116 SWALLOW("elm.swallow.home", sd->home_button);
117 SWALLOW("elm.swallow.spinner", sd->spinner);
118 elm_object_style_set(sd->spinner, "wheel");
120 if (!elm_layout_content_set(obj, "elm.swallow.files", sd->files_view))
121 evas_object_hide(sd->files_view);
123 SWALLOW("elm.swallow.path", sd->path_entry);
124 SWALLOW("elm.swallow.filename", sd->name_entry);
126 snprintf(buf, sizeof(buf), "fileselector/actions/%s", style);
127 SWALLOW("elm.swallow.filters", sd->filter_hoversel);
128 SWALLOW("elm.swallow.cancel", sd->cancel_button);
129 SWALLOW("elm.swallow.ok", sd->ok_button);
133 edje_object_message_signal_process(wd->resize_obj);
135 elm_layout_sizing_eval(obj);
140 EOLIAN static Eina_Bool
141 _elc_fileselector_elm_widget_event(Eo *obj, Elc_Fileselector_Data *sd EINA_UNUSED, Evas_Object *src, Evas_Callback_Type type, void *event_info)
143 Evas_Event_Key_Down *ev = event_info;
146 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
147 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
148 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
150 if ((!strcmp(ev->key, "Return")) ||
151 (!strcmp(ev->key, "KP_Enter")))
152 _ok(obj, NULL, NULL);
153 else if (!strcmp(ev->key, "Escape"))
154 _canc(obj, NULL, NULL);
158 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
162 /*** GENLIST/GENGRID "MODEL" ***/
164 _itc_text_get(void *data,
165 Evas_Object *obj EINA_UNUSED,
166 const char *source EINA_UNUSED)
168 return elm_entry_utf8_to_markup
169 (ecore_file_file_get(data)); /* NOTE this will be free()'d by
174 _itc_icon_folder_get(void *data EINA_UNUSED,
178 Evas_Object *ic, *grid, *f;
180 if (strcmp(source, "elm.swallow.icon")) return NULL;
182 f = evas_object_data_get(obj, "parent");
183 ELM_FILESELECTOR_DATA_GET(f, sd);
185 ic = elm_icon_add(obj);
186 elm_icon_standard_set(ic, "folder");
187 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
188 evas_object_show(ic);
190 grid = elm_grid_add(obj);
191 elm_grid_size_set(grid, 1, 1);
192 elm_grid_pack(grid, ic, 0, 0, 1, 1);
193 evas_object_size_hint_min_set(grid, sd->thumbnail_size.w, sd->thumbnail_size.h);
194 evas_object_show(grid);
200 _itc_icon_image_get(void *data,
204 const char *filename = data;
205 Evas_Object *ic, *grid, *f;
207 if (strcmp(source, "elm.swallow.icon")) return NULL;
209 f = evas_object_data_get(obj, "parent");
210 ELM_FILESELECTOR_DATA_GET(f, sd);
212 ic = elm_icon_add(obj);
213 elm_icon_standard_set(ic, "image");
214 elm_icon_thumb_set(ic, filename, NULL);
215 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
216 evas_object_show(ic);
218 grid = elm_grid_add(obj);
219 elm_grid_size_set(grid, 1, 1);
220 elm_grid_pack(grid, ic, 0, 0, 1, 1);
221 evas_object_size_hint_min_set(grid, sd->thumbnail_size.w, sd->thumbnail_size.h);
222 evas_object_show(grid);
228 _itc_icon_file_get(void *data EINA_UNUSED,
232 Evas_Object *ic, *grid, *f;
234 if (strcmp(source, "elm.swallow.icon")) return NULL;
236 f = evas_object_data_get(obj, "parent");
237 ELM_FILESELECTOR_DATA_GET(f, sd);
239 ic = elm_icon_add(obj);
240 elm_icon_standard_set(ic, "file");
241 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
242 evas_object_show(ic);
244 grid = elm_grid_add(obj);
245 elm_grid_size_set(grid, 1, 1);
246 elm_grid_pack(grid, ic, 0, 0, 1, 1);
247 evas_object_size_hint_min_set(grid, sd->thumbnail_size.w, sd->thumbnail_size.h);
248 evas_object_show(grid);
254 _itc_state_get(void *data EINA_UNUSED,
255 Evas_Object *obj EINA_UNUSED,
256 const char *source EINA_UNUSED)
263 Evas_Object *obj EINA_UNUSED)
265 eina_stringshare_del(data);
269 _anchors_do(Evas_Object *obj,
272 char **tok, buf[PATH_MAX * 3], *s;
275 ELM_FILESELECTOR_DATA_GET(obj, sd);
277 s = elm_entry_utf8_to_markup(path);
281 tok = eina_str_split(s, "/", 0);
284 eina_strlcat(buf, "<a href='/'>root</a>", sizeof(buf));
285 for (i = 0; tok[i]; i++)
287 if ((!tok[i]) || (!tok[i][0])) continue;
288 eina_strlcat(buf, sd->path_separator, sizeof(buf));
289 eina_strlcat(buf, "<a href=", sizeof(buf));
290 for (j = 0; j <= i; j++)
292 if (strlen(tok[j]) < 1) continue;
293 eina_strlcat(buf, "/", sizeof(buf));
294 eina_strlcat(buf, tok[j], sizeof(buf));
296 eina_strlcat(buf, ">", sizeof(buf));
297 eina_strlcat(buf, tok[i], sizeof(buf));
298 eina_strlcat(buf, "</a>", sizeof(buf));
303 elm_object_text_set(sd->path_entry, buf);
307 _mime_type_matched(const char *mime_filter, const char *mime_type)
311 while (mime_filter[i] != '\0')
313 if (mime_filter[i] != mime_type[i])
315 if (mime_filter[i] == '*' && mime_filter[i + 1] == '\0')
323 if (mime_type[i] != '\0') return EINA_FALSE;
329 _check_mime_type_filter(const Elm_Fileselector_Filter *filter,
330 const char *file_name)
332 const char *mime_type = NULL;
335 mime_type = efreet_mime_type_get(file_name);
337 if (!mime_type) return EINA_FALSE;
339 for (i = 0; filter->filter.mime_types[i]; ++i)
341 if (_mime_type_matched(filter->filter.mime_types[i], mime_type))
348 _ls_filter_cb(void *data,
349 Eio_File *handler EINA_UNUSED,
350 const Eina_File_Direct_Info *info)
352 Listing_Request *lreq = data;
353 Elm_Fileselector_Filter *cf;
354 Eina_Bool dir = EINA_FALSE;
356 if (!lreq->sd->hidden_visible && info->path[info->name_start] == '.')
359 if (info->type == EINA_FILE_DIR)
362 if (lreq->sd->only_folder && !dir)
365 cf = lreq->sd->current_filter;
369 switch (cf->filter_type)
371 case ELM_FILESELECTOR_MIME_FILTER:
372 return dir || _check_mime_type_filter(cf, info->path);
373 case ELM_FILESELECTOR_CUSTOM_FILTER:
374 return cf->filter.custom->func(info->path, dir,
375 cf->filter.custom->data);
384 _file_type(const char *a)
386 char *p = strrchr(a, '.');
393 _strcoll_rev(const char *a, const char *b)
395 return strcoll(b, a);
399 _strcoll_type(const char *a, const char *b)
401 return strcoll(_file_type(a), _file_type(b));
405 _strcoll_type_rev(const char *a, const char *b)
407 return _strcoll_type(b, a);
411 _size_cmp(const char *a, const char *b)
413 return ecore_file_size(a) - ecore_file_size(b);
417 _size_cmp_rev(const char *a, const char *b)
419 return _size_cmp(b, a);
423 _modified_cmp(const char *a, const char *b)
425 if (ecore_file_mod_time(a) > ecore_file_mod_time(b))
432 _modified_cmp_rev(const char *a, const char *b)
434 return _modified_cmp(b, a);
438 _file_grid_cmp(const void *a, const void *b)
442 const Elm_Object_Item *ga = a;
443 const Elm_Object_Item *gb = b;
444 const Elm_Gengrid_Item_Class *ca = elm_gengrid_item_item_class_get(ga);
445 const Elm_Gengrid_Item_Class *cb = elm_gengrid_item_item_class_get(gb);
447 if (ca == grid_itc[ELM_DIRECTORY])
449 if (cb != grid_itc[ELM_DIRECTORY])
452 else if (cb == grid_itc[ELM_DIRECTORY])
457 f = evas_object_data_get(elm_object_item_widget_get(ga), "parent");
458 ELM_FILESELECTOR_DATA_GET(f, sd);
459 return sd->sort_method(elm_object_item_data_get(ga),
460 elm_object_item_data_get(gb));
464 _file_list_cmp(const void *a, const void *b)
468 const Elm_Object_Item *la = a;
469 const Elm_Object_Item *lb = b;
470 const Elm_Genlist_Item_Class *ca = elm_genlist_item_item_class_get(la);
471 const Elm_Genlist_Item_Class *cb = elm_genlist_item_item_class_get(lb);
473 if (ca == list_itc[ELM_DIRECTORY])
475 if (cb != list_itc[ELM_DIRECTORY])
478 else if (cb == list_itc[ELM_DIRECTORY])
483 f = evas_object_data_get(elm_object_item_widget_get(la), "parent");
484 ELM_FILESELECTOR_DATA_GET(f, sd);
485 return sd->sort_method(elm_object_item_data_get(la),
486 elm_object_item_data_get(lb));
490 _signal_first(Listing_Request *lreq)
492 if (!lreq->first) return;
497 EINA_LIST_FREE(lreq->sd->paths, path)
501 evas_object_smart_callback_call
502 (lreq->obj, SIG_DIRECTORY_OPEN, (void *)lreq->path);
504 if (!lreq->parent_it)
506 if (lreq->sd->mode == ELM_FILESELECTOR_LIST)
507 elm_genlist_clear(lreq->sd->files_view);
509 elm_gengrid_clear(lreq->sd->files_view);
510 eina_stringshare_replace(&lreq->sd->path, lreq->path);
511 _anchors_do(lreq->obj, lreq->path);
512 elm_object_text_set(lreq->sd->name_entry, "");
515 lreq->first = EINA_FALSE;
519 _ls_main_cb(void *data,
521 const Eina_File_Direct_Info *info)
523 Listing_Request *lreq = data;
524 Elm_Object_Item *item;
525 int itcn = ELM_FILE_UNKNOW;
527 if (eio_file_check(handler)) return;
529 if (!lreq->sd->files_view || lreq->sd->current != handler)
531 eio_file_cancel(handler);
537 if (info->type == EINA_FILE_DIR)
538 itcn = ELM_DIRECTORY;
541 if (evas_object_image_extension_can_load_get
542 (info->path + info->name_start))
543 itcn = ELM_FILE_IMAGE;
546 if (lreq->sd->mode == ELM_FILESELECTOR_LIST)
548 item = elm_genlist_item_sorted_insert(lreq->sd->files_view, list_itc[itcn],
549 eina_stringshare_add(info->path),
551 ((lreq->sd->expand) && (itcn == ELM_DIRECTORY))
552 ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
553 _file_list_cmp, NULL, NULL);
555 if (lreq->selected && !strcmp(info->path, lreq->selected))
557 elm_genlist_item_selected_set(item, EINA_TRUE);
558 elm_object_text_set(lreq->sd->name_entry, ecore_file_file_get(info->path));
561 else if (lreq->sd->mode == ELM_FILESELECTOR_GRID)
563 item = elm_gengrid_item_sorted_insert(lreq->sd->files_view, grid_itc[itcn],
564 eina_stringshare_add(info->path),
565 _file_grid_cmp, NULL, NULL);
567 if (lreq->selected && !strcmp(info->path, lreq->selected))
569 elm_gengrid_item_selected_set(item, EINA_TRUE);
570 elm_object_text_set(lreq->sd->name_entry, ecore_file_file_get(info->path));
576 _listing_request_cleanup(Listing_Request *lreq)
578 EINA_REFCOUNT_UNREF(lreq->sd) _elm_fileselector_smart_del_do(lreq->sd);
580 eina_stringshare_del(lreq->path);
581 eina_stringshare_del(lreq->selected);
586 _ls_done_cb(void *data, Eio_File *handler EINA_UNUSED)
588 Listing_Request *lreq = data;
591 elm_progressbar_pulse(lreq->sd->spinner, EINA_FALSE);
592 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
594 lreq->sd->current = NULL;
595 _listing_request_cleanup(lreq);
599 _ls_error_cb(void *data, Eio_File *handler, int error EINA_UNUSED)
601 Listing_Request *lreq = data;
603 elm_progressbar_pulse(lreq->sd->spinner, EINA_FALSE);
604 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
606 if (lreq->sd->current == handler)
607 lreq->sd->current = NULL;
608 _listing_request_cleanup(lreq);
612 _populate(Evas_Object *obj,
614 Elm_Object_Item *parent_it,
615 const char *selected)
617 ELM_FILESELECTOR_DATA_GET(obj, sd);
620 Listing_Request *lreq;
622 if (sd->expand && sd->current) return;
624 if (sd->monitor) eio_monitor_del(sd->monitor);
625 if (sd->current) eio_file_cancel(sd->current);
627 lreq = malloc(sizeof (Listing_Request));
631 EINA_REFCOUNT_REF(lreq->sd);
633 lreq->parent_it = parent_it; /* FIXME: should we refcount the parent_it ? */
635 lreq->path = eina_stringshare_add(path);
636 lreq->first = EINA_TRUE;
639 lreq->selected = eina_stringshare_add(selected);
641 lreq->selected = NULL;
643 /* TODO: sub directory should be monitored for expand mode */
644 sd->monitor = eio_monitor_add(path);
645 sd->current = eio_file_stat_ls(path, _ls_filter_cb, _ls_main_cb,
646 _ls_done_cb, _ls_error_cb, lreq);
647 elm_progressbar_pulse(sd->spinner, EINA_TRUE);
648 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,show", "elm");
652 _on_list_expanded(void *data,
653 Evas_Object *obj EINA_UNUSED,
656 Elm_Object_Item *it = event_info;
657 const char *path = elm_object_item_data_get(it);
659 _populate(data, path, it, NULL);
663 _on_list_contracted(void *data EINA_UNUSED,
664 Evas_Object *obj EINA_UNUSED,
667 Elm_Object_Item *it = event_info;
669 elm_genlist_item_subitems_clear(it);
673 _on_list_expand_req(void *data EINA_UNUSED,
674 Evas_Object *obj EINA_UNUSED,
677 Elm_Object_Item *it = event_info;
679 elm_genlist_item_expanded_set(it, EINA_TRUE);
683 _on_list_contract_req(void *data EINA_UNUSED,
684 Evas_Object *obj EINA_UNUSED,
687 Elm_Object_Item *it = event_info;
689 elm_genlist_item_expanded_set(it, EINA_FALSE);
693 _populate_do(void *data)
695 struct sel_data *sdata = data;
698 ELM_FILESELECTOR_DATA_GET(sdata->fs, sd);
700 /* keep a ref to path 'couse it will be destroyed by _populate */
701 p = eina_stringshare_add(sdata->path);
702 _populate(sdata->fs, p, NULL, NULL);
703 eina_stringshare_del(p);
705 sd->populate_idler = NULL;
707 return ECORE_CALLBACK_CANCEL;
711 _on_item_activated(void *data,
712 Evas_Object *obj EINA_UNUSED,
715 //This event_info could be a list or gengrid item
716 Elm_Object_Item *it = event_info;
717 struct sel_data *sdata;
722 ELM_FILESELECTOR_DATA_GET(data, sd);
724 path = elm_object_item_data_get(it);
727 is_dir = ecore_file_is_dir(path);
730 evas_object_smart_callback_call(data, SIG_ACTIVATED, (void *)path);
734 if (!sd->double_tap_navigation) return;
736 sdata = malloc(sizeof(*sdata));
742 if (sd->populate_idler)
744 old_sdata = ecore_idler_del(sd->populate_idler);
747 sd->populate_idler = ecore_idler_add(_populate_do, sdata);
751 _clear_selections(Elc_Fileselector_Data *sd, Elm_Object_Item *last_selected)
754 Elm_Object_Item *sel;
756 if (sd->mode == ELM_FILESELECTOR_LIST)
758 items = eina_list_clone(elm_genlist_selected_items_get(sd->files_view));
760 EINA_LIST_FREE(items, sel)
762 if (sel == last_selected) continue;
763 elm_genlist_item_selected_set(sel, EINA_FALSE);
766 else if (sd->mode == ELM_FILESELECTOR_GRID)
768 items = eina_list_clone(elm_gengrid_selected_items_get(sd->files_view));
770 EINA_LIST_FREE(items, sel)
772 if (sel == last_selected) continue;
773 elm_gengrid_item_selected_set(sel, EINA_FALSE);
779 _on_item_selected(void *data,
780 Evas_Object *obj EINA_UNUSED,
783 //This event_info could be a list or gengrid item
784 Elm_Object_Item *it = event_info;
785 struct sel_data *sdata;
791 ELM_FILESELECTOR_DATA_GET(data, sd);
793 path = elm_object_item_data_get(it);
796 is_dir = ecore_file_is_dir(path);
798 /* We need to send callback when:
799 * - path is dir and mode is ONLY FOLDER
800 * - path is file and mode is NOT ONLY FOLDER */
801 if (is_dir == sd->only_folder)
809 if (sd->dir_selected)
811 _clear_selections(sd, it);
812 sd->dir_selected = EINA_FALSE;
815 buf = eina_strbuf_new();
816 EINA_LIST_FOREACH(sd->paths, li, p)
818 eina_strbuf_append(buf, ecore_file_file_get(p));
819 eina_strbuf_append_length(buf, ", ", 2);
822 sd->paths = eina_list_append(sd->paths, strdup(path));
823 eina_strbuf_append(buf, ecore_file_file_get(path));
825 elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf));
826 eina_strbuf_free(buf);
829 elm_object_text_set(sd->name_entry, ecore_file_file_get(path));
831 evas_object_smart_callback_call(data, SIG_SELECTED, (void *)path);
835 if (sd->multi && is_dir && sd->double_tap_navigation)
837 _clear_selections(sd, it);
838 sd->dir_selected = EINA_TRUE;
841 elm_object_text_set(sd->name_entry, "");
844 /* We need to populate, if path is directory and:
846 * - mode is LIST and 'not expand mode';
847 * in other cases update anchors. */
850 if (sd->expand && sd->mode == ELM_FILESELECTOR_LIST)
854 parent_path = ecore_file_dir_get(path);
855 eina_stringshare_replace(&sd->path, parent_path);
856 _anchors_do(data, parent_path);
861 eina_stringshare_replace(&sd->path, path);
862 _anchors_do(data, path);
867 if (sd->double_tap_navigation) return;
869 sdata = malloc(sizeof(*sdata));
875 if (sd->populate_idler)
877 old_sdata = ecore_idler_del(sd->populate_idler);
880 sd->populate_idler = ecore_idler_add(_populate_do, sdata);
884 _on_item_unselected(void *data,
885 Evas_Object *obj EINA_UNUSED,
890 const char *unselected_path;
892 Elm_Object_Item *it = event_info;
893 Eina_Bool first = EINA_TRUE;
895 ELM_FILESELECTOR_DATA_GET(data, sd);
897 if (!sd->multi) return;
899 unselected_path = elm_object_item_data_get(it);
900 if (!unselected_path) return;
902 buf = eina_strbuf_new();
903 EINA_LIST_FOREACH_SAFE(sd->paths, li, l, path)
905 if (!strcmp(path, unselected_path))
907 sd->paths = eina_list_remove_list(sd->paths, li);
913 eina_strbuf_append_length(buf, ", ", 2);
917 eina_strbuf_append(buf, ecore_file_file_get(path));
921 elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf));
922 eina_strbuf_free(buf);
926 _on_dir_up(void *data,
927 Evas_Object *obj EINA_UNUSED,
928 void *event_info EINA_UNUSED)
930 Evas_Object *fs = data;
933 ELM_FILESELECTOR_DATA_GET(fs, sd);
935 parent = ecore_file_dir_get(sd->path);
936 _populate(fs, parent, NULL, NULL);
942 Evas_Object *obj EINA_UNUSED,
943 void *event_info EINA_UNUSED)
945 Evas_Object *fs = data;
947 _populate(fs, getenv("HOME"), NULL, NULL);
951 _current_filter_changed(void *data,
953 void *event_info EINA_UNUSED)
955 Elm_Fileselector_Filter *filter = data;
957 if (filter->sd->current_filter == filter) return;
959 elm_object_text_set(obj, filter->filter_name);
960 filter->sd->current_filter = filter;
962 _populate(filter->sd->obj, filter->sd->path, NULL, NULL);
967 Evas_Object *obj EINA_UNUSED,
968 void *event_info EINA_UNUSED)
971 const char *selection = NULL;
972 Evas_Object *fs = data;
973 ELM_FILESELECTOR_DATA_GET(fs, sd);
977 evas_object_smart_callback_call(fs, SIG_DONE, NULL);
981 name = elm_object_text_get(sd->name_entry);
982 if (name && name[0] != '\0')
984 int len = eina_stringshare_strlen(sd->path);
985 if (sd->path[len - 1] == '/')
986 selection = eina_stringshare_printf("%s%s", sd->path, name);
988 selection = eina_stringshare_printf("%s/%s", sd->path, name);
991 selection = eina_stringshare_add(elm_fileselector_selected_get(fs));
993 evas_object_smart_callback_call(fs, SIG_DONE, (void *)selection);
994 eina_stringshare_del(selection);
999 Evas_Object *obj EINA_UNUSED,
1000 void *event_info EINA_UNUSED)
1002 Evas_Object *fs = data;
1004 evas_object_smart_callback_call(fs, SIG_DONE, NULL);
1008 _on_text_clicked(void *data EINA_UNUSED,
1010 void *event_info EINA_UNUSED)
1012 ELM_FILESELECTOR_DATA_GET(data, sd);
1014 /* FIXME: When anchor is clicked, current callback is also called.
1015 * But when it is "anchor,clicked" entry should be unfocused, so we remove
1016 * focus in achor_clicked.
1018 * Check if entry is focused.
1019 * It will be so if empty place (not anchor) was clicked. */
1020 if (!elm_object_focus_get(obj)) return;
1022 elm_entry_entry_set(obj, sd->path);
1023 elm_entry_cursor_pos_set(obj, eina_stringshare_strlen(sd->path));
1027 _on_text_activated(void *data,
1029 void *event_info EINA_UNUSED)
1031 Evas_Object *fs = data;
1032 const char *p, *path;
1035 ELM_FILESELECTOR_DATA_GET(fs, sd);
1037 path = elm_widget_part_text_get(obj, NULL);
1039 if (!ecore_file_exists(path))
1041 evas_object_smart_callback_call(fs, SIG_SELECTED, (void *)path);
1042 evas_object_smart_callback_call(fs, SIG_SELECTED_INVALID, (void *)path);
1046 if (ecore_file_is_dir(path))
1048 // keep a ref to path 'couse it will be destroyed by _populate
1049 p = eina_stringshare_add(path);
1050 _populate(fs, p, NULL, NULL);
1051 eina_stringshare_del(p);
1053 if (sd->only_folder)
1054 evas_object_smart_callback_call(fs, SIG_SELECTED, (void *)path);
1059 dir = ecore_file_dir_get(path);
1062 if (strcmp(dir, sd->path))
1064 _populate(fs, dir, NULL, path);
1066 if (sd->only_folder)
1067 evas_object_smart_callback_call(fs, SIG_SELECTED, (void *)path);
1071 if (sd->mode == ELM_FILESELECTOR_LIST)
1073 Elm_Object_Item *item = elm_genlist_first_item_get(sd->files_view);
1076 const char *item_path = elm_widget_item_data_get(item);
1077 if (!strcmp(item_path, path))
1079 elm_genlist_item_selected_set(item, EINA_TRUE);
1080 elm_widget_part_text_set(sd->name_entry, NULL,
1081 ecore_file_file_get(path));
1084 item = elm_genlist_item_next_get(item);
1089 Elm_Object_Item *item = elm_gengrid_first_item_get(sd->files_view);
1092 const char *item_path = elm_object_item_data_get(item);
1093 if (!strcmp(item_path, path))
1095 elm_gengrid_item_selected_set(item, EINA_TRUE);
1096 elm_widget_part_text_set(sd->name_entry, NULL,
1097 ecore_file_file_get(path));
1100 item = elm_gengrid_item_next_get(item);
1107 elm_object_focus_set(obj, EINA_FALSE);
1111 _on_text_unfocused(void *data,
1112 Evas_Object *obj EINA_UNUSED,
1113 void *event_info EINA_UNUSED)
1115 ELM_FILESELECTOR_DATA_GET(data, sd);
1116 _anchors_do(data, sd->path);
1120 _anchor_clicked(void *data,
1121 Evas_Object *obj EINA_UNUSED,
1124 Elm_Entry_Anchor_Info *info = event_info;
1125 Evas_Object *fs = data;
1128 // keep a ref to path 'couse it will be destroyed by _populate
1129 p = eina_stringshare_add(info->name);
1130 _populate(fs, p, NULL, NULL);
1131 eina_stringshare_del(p);
1132 /* After anchor was clicked, entry will be focused, and will be editable.
1133 * It's wrong. So remove focus. */
1134 elm_object_focus_set(obj, EINA_FALSE);
1137 static Evas_Object *
1138 _files_list_add(Evas_Object *obj)
1142 li = elm_genlist_add(obj);
1143 evas_object_data_set(li, "parent", obj);
1144 elm_widget_mirrored_automatic_set(li, EINA_FALSE);
1145 evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
1146 evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1147 evas_object_size_hint_min_set(li, 100, 100);
1149 evas_object_smart_callback_add(li, "selected", _on_item_selected, obj);
1150 evas_object_smart_callback_add(li, "unselected", _on_item_unselected, obj);
1151 evas_object_smart_callback_add(li, "activated", _on_item_activated, obj);
1152 evas_object_smart_callback_add
1153 (li, "expand,request", _on_list_expand_req, obj);
1154 evas_object_smart_callback_add
1155 (li, "contract,request", _on_list_contract_req, obj);
1156 evas_object_smart_callback_add(li, "expanded", _on_list_expanded, obj);
1157 evas_object_smart_callback_add(li, "contracted", _on_list_contracted, obj);
1159 elm_widget_sub_object_add(obj, li);
1164 static Evas_Object *
1165 _files_grid_add(Evas_Object *obj)
1169 ELM_FILESELECTOR_DATA_GET(obj, sd);
1171 grid = elm_gengrid_add(obj);
1172 evas_object_data_set(grid, "parent", obj);
1173 elm_widget_mirrored_automatic_set(grid, EINA_FALSE);
1174 evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
1175 evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1177 elm_gengrid_item_size_set(grid, sd->thumbnail_size.w + GENGRID_PADDING, sd->thumbnail_size.h + GENGRID_PADDING);
1179 elm_gengrid_align_set(grid, 0.0, 0.0);
1181 evas_object_smart_callback_add(grid, "selected", _on_item_selected, obj);
1182 evas_object_smart_callback_add(grid, "unselected", _on_item_unselected, obj);
1183 evas_object_smart_callback_add(grid, "activated", _on_item_activated, obj);
1185 elm_widget_sub_object_add(obj, grid);
1191 _resource_created(void *data, int type, void *ev)
1193 Evas_Object *obj = data;
1194 Eio_Monitor_Event *event = ev;
1195 int itcn = ELM_FILE_UNKNOW;
1196 Eina_Bool dir = EINA_FALSE;
1198 ELM_FILESELECTOR_DATA_GET(obj, sd);
1200 if (type == EIO_MONITOR_DIRECTORY_CREATED)
1203 Elm_Fileselector_Filter *cf = sd->current_filter;
1206 switch (cf->filter_type)
1208 case ELM_FILESELECTOR_MIME_FILTER:
1209 if (!dir && !_check_mime_type_filter(cf, event->filename))
1210 return ECORE_CALLBACK_PASS_ON;
1212 case ELM_FILESELECTOR_CUSTOM_FILTER:
1213 if (!cf->filter.custom->func(event->filename, dir, cf->filter.custom->data))
1214 return ECORE_CALLBACK_PASS_ON;
1222 itcn = ELM_DIRECTORY;
1225 if (evas_object_image_extension_can_load_get(event->filename))
1226 itcn = ELM_FILE_IMAGE;
1229 if (sd->mode == ELM_FILESELECTOR_LIST)
1230 elm_genlist_item_sorted_insert(sd->files_view, list_itc[itcn],
1231 eina_stringshare_add(event->filename),
1233 (sd->expand && itcn == ELM_DIRECTORY)
1234 ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
1235 _file_list_cmp, NULL, NULL);
1237 elm_gengrid_item_sorted_insert(sd->files_view, grid_itc[itcn],
1238 eina_stringshare_add(event->filename),
1239 _file_grid_cmp, NULL, NULL);
1241 return ECORE_CALLBACK_PASS_ON;
1245 _resource_deleted(void *data, int type EINA_UNUSED, void *ev)
1247 Evas_Object *obj = data;
1248 Eio_Monitor_Event *event = ev;
1249 Elm_Object_Item *it = NULL;
1250 Eina_Bool selected = EINA_FALSE;
1252 ELM_FILESELECTOR_DATA_GET(obj, sd);
1254 if (sd->mode == ELM_FILESELECTOR_LIST)
1256 it = elm_genlist_first_item_get(sd->files_view);
1259 if (!strcmp(elm_object_item_data_get(it), event->filename))
1261 selected = elm_genlist_item_selected_get(it);
1264 it = elm_genlist_item_next_get(it);
1269 it = elm_gengrid_first_item_get(sd->files_view);
1272 if (!strcmp(elm_object_item_data_get(it), event->filename))
1274 selected = elm_genlist_item_selected_get(it);
1277 it = elm_gengrid_item_next_get(it);
1281 if (it) elm_object_item_del(it);
1290 Eina_Bool first = EINA_TRUE;
1292 buf = eina_strbuf_new();
1293 EINA_LIST_FOREACH_SAFE(sd->paths, li, l, path)
1295 if (!strcmp(path, event->filename))
1297 sd->paths = eina_list_remove_list(sd->paths, li);
1303 eina_strbuf_append_length(buf, ", ", 2);
1307 eina_strbuf_append(buf, ecore_file_file_get(path));
1311 elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf));
1312 eina_strbuf_free(buf);
1315 elm_object_text_set(sd->name_entry, "");
1318 return ECORE_CALLBACK_PASS_ON;
1322 _name_entry_activated_cb(void *data, Evas_Object *obj EINA_UNUSED,
1323 void *event_info EINA_UNUSED)
1325 _ok(data, NULL, NULL);
1329 _elc_fileselector_evas_smart_add(Eo *obj, Elc_Fileselector_Data *priv)
1331 Evas_Object *ic, *bt, *en, *pb;
1333 EINA_REFCOUNT_INIT(priv);
1335 eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
1336 elm_widget_sub_object_parent_add(obj);
1337 elm_widget_can_focus_set(obj, EINA_TRUE);
1339 priv->expand = !!_elm_config->fileselector_expand_enable;
1340 priv->double_tap_navigation = !!_elm_config->fileselector_double_tap_navigation_enable;
1342 if (!elm_layout_theme_set
1343 (obj, "fileselector", "base", elm_widget_style_get(obj)))
1344 CRI("Failed to set layout!");
1347 ic = elm_icon_add(obj);
1348 elm_icon_standard_set(ic, "arrow_up");
1349 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
1350 bt = elm_button_add(obj);
1351 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1352 elm_object_part_content_set(bt, "icon", ic);
1353 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Up"));
1354 evas_object_size_hint_align_set(bt, 0.0, 0.0);
1355 evas_object_smart_callback_add(bt, "clicked", _on_dir_up, obj);
1357 elm_widget_sub_object_add(obj, bt);
1359 priv->up_button = bt;
1362 ic = elm_icon_add(obj);
1363 elm_icon_standard_set(ic, "home");
1364 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
1365 bt = elm_button_add(obj);
1366 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1367 elm_object_part_content_set(bt, "icon", ic);
1368 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Home"));
1369 evas_object_size_hint_align_set(bt, 0.0, 0.0);
1370 evas_object_smart_callback_add(bt, "clicked", _home, obj);
1372 elm_widget_sub_object_add(obj, bt);
1373 priv->home_button = bt;
1376 pb = elm_progressbar_add(obj);
1377 elm_widget_sub_object_add(obj, pb);
1380 // XXX: will fail for dynamic finger size changing
1381 priv->thumbnail_size.w = elm_config_finger_size_get() * 2 - GENGRID_PADDING;
1382 priv->thumbnail_size.h = priv->thumbnail_size.w;
1384 priv->sort_type = ELM_FILESELECTOR_SORT_BY_FILENAME_ASC;
1385 priv->sort_method = strcoll;
1388 priv->files_view = _files_list_add(obj);
1391 en = elm_entry_add(obj);
1392 elm_entry_scrollable_set(en, EINA_TRUE);
1393 elm_widget_mirrored_automatic_set(en, EINA_FALSE);
1394 elm_entry_single_line_set(en, EINA_TRUE);
1395 elm_entry_line_wrap_set(en, ELM_WRAP_CHAR);
1396 evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1397 evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
1399 evas_object_smart_callback_add(en, "anchor,clicked", _anchor_clicked, obj);
1400 evas_object_smart_callback_add(en, "clicked", _on_text_clicked, obj);
1401 evas_object_smart_callback_add(en, "unfocused", _on_text_unfocused, obj);
1402 evas_object_smart_callback_add(en, "activated", _on_text_activated, obj);
1404 elm_widget_sub_object_add(obj, en);
1405 priv->path_entry = en;
1408 en = elm_entry_add(obj);
1409 elm_entry_scrollable_set(en, EINA_TRUE);
1410 elm_widget_mirrored_automatic_set(en, EINA_FALSE);
1411 elm_entry_editable_set(en, EINA_TRUE);
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);
1416 evas_object_smart_callback_add(en, "activated",
1417 _name_entry_activated_cb, obj);
1419 elm_widget_sub_object_add(obj, en);
1420 priv->name_entry = en;
1422 elm_fileselector_buttons_ok_cancel_set(obj, EINA_TRUE);
1423 elm_fileselector_is_save_set(obj, EINA_FALSE);
1425 #define HANDLER_ADD(e, fn) \
1426 priv->handlers = eina_list_append(priv->handlers, \
1427 ecore_event_handler_add(e, fn, obj));
1429 HANDLER_ADD(EIO_MONITOR_FILE_CREATED, _resource_created);
1430 HANDLER_ADD(EIO_MONITOR_DIRECTORY_CREATED, _resource_created);
1432 HANDLER_ADD(EIO_MONITOR_FILE_DELETED, _resource_deleted);
1433 HANDLER_ADD(EIO_MONITOR_DIRECTORY_DELETED, _resource_deleted);
1436 eo_do(obj, elm_obj_widget_theme_apply());
1440 _elc_fileselector_evas_smart_del(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1442 Elm_Fileselector_Filter *filter;
1444 Ecore_Event_Handler *h;
1446 if (sd->monitor) eio_monitor_del(sd->monitor);
1447 if (sd->current) eio_file_cancel(sd->current);
1449 EINA_LIST_FREE(sd->handlers, h)
1451 ecore_event_handler_del(h);
1454 EINA_LIST_FREE(sd->filter_list, filter)
1456 eina_stringshare_del(filter->filter_name);
1458 if (filter->filter_type == ELM_FILESELECTOR_MIME_FILTER)
1460 free(filter->filter.mime_types[0]);
1461 free(filter->filter.mime_types);
1464 free(filter->filter.custom);
1469 EINA_LIST_FREE(sd->paths, path)
1472 sd->files_view = NULL;
1474 /* this one matching EINA_REFCOUNT_INIT() */
1475 EINA_REFCOUNT_UNREF(sd) _elm_fileselector_smart_del_do(sd);
1479 elm_fileselector_add(Evas_Object *parent)
1481 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1482 Evas_Object *obj = eo_add(MY_CLASS, parent);
1488 _elc_fileselector_eo_base_constructor(Eo *obj, Elc_Fileselector_Data *sd)
1491 eo_do_super(obj, MY_CLASS, eo_constructor());
1493 evas_obj_type_set(MY_CLASS_NAME_LEGACY),
1494 evas_obj_smart_callbacks_descriptions_set(_smart_callbacks));
1498 elm_fileselector_is_save_set(Evas_Object *obj,
1501 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1502 eo_do(obj, elm_interface_fileselector_is_save_set(is_save));
1506 _elc_fileselector_elm_interface_fileselector_is_save_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool is_save)
1508 elm_object_disabled_set(sd->name_entry, !is_save);
1510 if (is_save) elm_layout_signal_emit(obj, "elm,state,save,on", "elm");
1511 else elm_layout_signal_emit(obj, "elm,state,save,off", "elm");
1515 elm_fileselector_is_save_get(const Evas_Object *obj)
1517 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1518 Eina_Bool ret = EINA_FALSE;
1519 eo_do((Eo *) obj, ret = elm_interface_fileselector_is_save_get());
1523 EOLIAN static Eina_Bool
1524 _elc_fileselector_elm_interface_fileselector_is_save_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1526 return !elm_object_disabled_get(sd->name_entry);
1530 elm_fileselector_folder_only_set(Evas_Object *obj,
1533 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1534 eo_do(obj, elm_interface_fileselector_folder_only_set(only));
1538 _elc_fileselector_elm_interface_fileselector_folder_only_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool only)
1540 if (sd->only_folder == only) return;
1542 sd->only_folder = !!only;
1543 if (sd->path) _populate(obj, sd->path, NULL, NULL);
1547 elm_fileselector_folder_only_get(const Evas_Object *obj)
1549 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1550 Eina_Bool ret = EINA_FALSE;
1551 eo_do((Eo *) obj, ret = elm_interface_fileselector_folder_only_get());
1555 EOLIAN static Eina_Bool
1556 _elc_fileselector_elm_interface_fileselector_folder_only_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1558 return sd->only_folder;
1562 _elc_fileselector_buttons_ok_cancel_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool visible)
1566 if (visible && (!sd->ok_button))
1569 bt = elm_button_add(obj);
1570 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1571 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Cancel"));
1573 evas_object_smart_callback_add(bt, "clicked", _canc, obj);
1575 sd->cancel_button = bt;
1578 bt = elm_button_add(obj);
1579 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1580 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("OK"));
1582 evas_object_smart_callback_add(bt, "clicked", _ok, obj);
1586 eo_do(obj, elm_obj_widget_theme_apply());
1590 ELM_SAFE_FREE(sd->cancel_button, evas_object_del);
1591 ELM_SAFE_FREE(sd->ok_button, evas_object_del);
1595 EOLIAN static Eina_Bool
1596 _elc_fileselector_buttons_ok_cancel_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1598 return sd->ok_button ? EINA_TRUE : EINA_FALSE;
1602 elm_fileselector_expandable_set(Evas_Object *obj,
1605 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1606 eo_do(obj, elm_interface_fileselector_expandable_set(expand));
1610 _elc_fileselector_elm_interface_fileselector_expandable_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool expand)
1612 sd->expand = !!expand;
1614 if (sd->path) _populate(obj, sd->path, NULL, NULL);
1618 elm_fileselector_expandable_get(const Evas_Object *obj)
1620 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1621 Eina_Bool ret = EINA_FALSE;
1622 eo_do((Eo *) obj, ret = elm_interface_fileselector_expandable_get());
1626 EOLIAN static Eina_Bool
1627 _elc_fileselector_elm_interface_fileselector_expandable_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1633 elm_fileselector_path_set(Evas_Object *obj,
1636 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1637 eo_do(obj, elm_interface_fileselector_path_set(_path));
1641 _elc_fileselector_elm_interface_fileselector_path_set(Eo *obj, Elc_Fileselector_Data *sd EINA_UNUSED, const char *_path)
1645 path = ecore_file_realpath(_path);
1646 _populate(obj, path, NULL, NULL);
1651 elm_fileselector_path_get(const Evas_Object *obj)
1653 ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
1654 const char *ret = NULL;
1655 eo_do((Eo *) obj, ret = elm_interface_fileselector_path_get());
1659 EOLIAN static const char*
1660 _elc_fileselector_elm_interface_fileselector_path_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1666 elm_fileselector_mode_set(Evas_Object *obj,
1667 Elm_Fileselector_Mode mode)
1669 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1670 eo_do(obj, elm_interface_fileselector_mode_set(mode));
1674 _elc_fileselector_elm_interface_fileselector_mode_set(Eo *obj, Elc_Fileselector_Data *sd, Elm_Fileselector_Mode mode)
1678 if (mode == sd->mode) return;
1680 old = elm_layout_content_unset(obj, "elm.swallow.files");
1682 if (mode == ELM_FILESELECTOR_LIST)
1684 sd->files_view = _files_list_add(obj);
1686 elm_genlist_multi_select_set(sd->files_view, EINA_TRUE);
1690 sd->files_view = _files_grid_add(obj);
1692 elm_gengrid_multi_select_set(sd->files_view, EINA_TRUE);
1695 elm_layout_content_set(obj, "elm.swallow.files", sd->files_view);
1697 evas_object_del(old);
1701 _populate(obj, sd->path, NULL, NULL);
1704 EAPI Elm_Fileselector_Mode
1705 elm_fileselector_mode_get(const Evas_Object *obj)
1707 ELM_FILESELECTOR_INTERFACE_CHECK(obj, ELM_FILESELECTOR_LAST);
1708 Elm_Fileselector_Mode ret = ELM_FILESELECTOR_LAST;
1709 eo_do((Eo *) obj, ret = elm_interface_fileselector_mode_get());
1713 EOLIAN static Elm_Fileselector_Mode
1714 _elc_fileselector_elm_interface_fileselector_mode_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1720 elm_fileselector_multi_select_set(Evas_Object *obj, Eina_Bool multi)
1722 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1723 eo_do(obj, elm_interface_fileselector_multi_select_set(multi));
1727 _elc_fileselector_elm_interface_fileselector_multi_select_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Eina_Bool multi)
1732 if (sd->multi == multi) return;
1735 if (sd->mode == ELM_FILESELECTOR_LIST)
1736 elm_genlist_multi_select_set(sd->files_view, multi);
1738 elm_gengrid_multi_select_set(sd->files_view, multi);
1742 _clear_selections(sd, NULL);
1744 EINA_LIST_FREE(sd->paths, path)
1749 const Eina_List *selected_items, *li;
1750 const Elm_Object_Item *it;
1752 if (sd->mode == ELM_FILESELECTOR_LIST)
1753 selected_items = elm_genlist_selected_items_get(sd->files_view);
1755 selected_items = elm_gengrid_selected_items_get(sd->files_view);
1757 EINA_LIST_FOREACH(selected_items, li, it)
1759 path = elm_object_item_data_get(it);
1760 sd->paths = eina_list_append(sd->paths, strdup(path));
1766 elm_fileselector_multi_select_get(const Evas_Object *obj)
1768 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1769 Eina_Bool ret = EINA_FALSE;
1770 eo_do((Eo *) obj, ret = elm_interface_fileselector_multi_select_get());
1774 EOLIAN static Eina_Bool
1775 _elc_fileselector_elm_interface_fileselector_multi_select_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1781 elm_fileselector_selected_get(const Evas_Object *obj)
1783 ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
1784 const char *ret = NULL;
1785 eo_do((Eo *) obj, ret = elm_interface_fileselector_selected_get());
1789 EOLIAN static const char*
1790 _elc_fileselector_elm_interface_fileselector_selected_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1793 if (!sd->path) return NULL;
1795 fp = elm_object_text_get(sd->path_entry);
1796 if (ecore_file_exists(fp))
1798 eina_stringshare_replace(&sd->selection, fp);
1800 return sd->selection;
1803 if (sd->mode == ELM_FILESELECTOR_LIST)
1805 Elm_Object_Item *gl_it = elm_genlist_selected_item_get(sd->files_view);
1807 if (gl_it) return elm_object_item_data_get(gl_it);
1811 Elm_Object_Item *gg_it = elm_gengrid_selected_item_get(sd->files_view);
1813 if (gg_it) return elm_object_item_data_get(gg_it);
1821 elm_fileselector_selected_set(Evas_Object *obj,
1824 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1825 Eina_Bool ret = EINA_FALSE;
1826 eo_do(obj, ret = elm_interface_fileselector_selected_set(_path));
1830 EOLIAN static Eina_Bool
1831 _elc_fileselector_elm_interface_fileselector_selected_set(Eo *obj, Elc_Fileselector_Data *sd, const char *_path)
1833 Eina_Bool ret = EINA_TRUE;
1837 path = ecore_file_realpath(_path);
1839 if (ecore_file_is_dir(path)) _populate(obj, path, NULL, NULL);
1842 if (!ecore_file_exists(path))
1848 selected = ecore_file_dir_get(path);
1849 _populate(obj, selected, NULL, NULL);
1850 eina_stringshare_replace(&sd->selection, path);
1860 EAPI const Eina_List *
1861 elm_fileselector_selected_paths_get(const Evas_Object* obj)
1863 ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
1864 const Eina_List *ret = NULL;
1865 eo_do((Eo *) obj, ret = elm_interface_fileselector_selected_paths_get());
1869 EOLIAN static const Eina_List*
1870 _elc_fileselector_elm_interface_fileselector_selected_paths_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1878 static Elm_Fileselector_Filter *
1879 _filter_add(Elc_Fileselector_Data *sd, const char *filter_name)
1881 Elm_Fileselector_Filter *ff;
1882 ff = malloc(sizeof(Elm_Fileselector_Filter));
1884 ff->filter_name = eina_stringshare_add(filter_name);
1891 elm_fileselector_mime_types_filter_append(Evas_Object *obj, const char *mime_type, const char *filter_name)
1893 ELM_FILESELECTOR_CHECK(obj) EINA_FALSE;
1894 Eina_Bool ret = EINA_FALSE;
1895 eo_do(obj, ret = elm_interface_fileselector_mime_types_filter_append(mime_type, filter_name));
1899 EOLIAN static Eina_Bool
1900 _elc_fileselector_elm_interface_fileselector_mime_types_filter_append(Eo *obj, Elc_Fileselector_Data *sd, const char *mime_types, const char *filter_name)
1902 Elm_Fileselector_Filter *ff;
1903 Eina_Bool need_theme = EINA_FALSE;
1905 if (!mime_types) return EINA_FALSE;
1907 ff = _filter_add(sd, filter_name ? filter_name : mime_types);
1908 ff->filter_type = ELM_FILESELECTOR_MIME_FILTER;
1910 ff->filter.mime_types = eina_str_split(mime_types, ",", 0);
1912 if (!sd->filter_list)
1914 sd->current_filter = ff;
1915 sd->filter_hoversel = elm_hoversel_add(obj);
1916 elm_object_text_set(sd->filter_hoversel, ff->filter_name);
1917 need_theme = EINA_TRUE;
1919 elm_hoversel_item_add(sd->filter_hoversel, ff->filter_name, NULL, ELM_ICON_NONE, _current_filter_changed, ff);
1921 sd->filter_list = eina_list_append(sd->filter_list, ff);
1923 _populate(obj, sd->path, NULL, NULL);
1926 eo_do(obj, elm_obj_widget_theme_apply());
1932 elm_fileselector_custom_filter_append(Evas_Object *obj, Elm_Fileselector_Filter_Func func, void *data, const char *filter_name)
1934 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1935 Eina_Bool ret = EINA_FALSE;
1936 eo_do(obj, ret = elm_interface_fileselector_custom_filter_append(func, data, filter_name));
1940 EOLIAN static Eina_Bool
1941 _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)
1943 Elm_Fileselector_Filter *ff;
1944 Eina_Bool need_theme = EINA_FALSE;
1946 if (!func) return EINA_FALSE;
1948 ff = _filter_add(sd, filter_name ? filter_name : "custom");
1949 ff->filter_type = ELM_FILESELECTOR_CUSTOM_FILTER;
1951 ff->filter.custom = malloc(sizeof(Elm_Fileselector_Custom_Filter));
1952 ff->filter.custom->func = func;
1953 ff->filter.custom->data = data;
1955 if (!sd->filter_list)
1957 sd->current_filter = ff;
1958 sd->filter_hoversel = elm_hoversel_add(obj);
1959 elm_object_text_set(sd->filter_hoversel, ff->filter_name);
1960 need_theme = EINA_TRUE;
1962 elm_hoversel_item_add(sd->filter_hoversel, ff->filter_name, NULL, ELM_ICON_NONE, _current_filter_changed, ff);
1964 sd->filter_list = eina_list_append(sd->filter_list, ff);
1966 _populate(obj, sd->path, NULL, NULL);
1969 eo_do(obj, elm_obj_widget_theme_apply());
1975 elm_fileselector_filters_clear(Evas_Object *obj)
1977 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1978 eo_do(obj, elm_interface_fileselector_filters_clear());
1982 _elc_fileselector_elm_interface_fileselector_filters_clear(Eo *obj, Elc_Fileselector_Data *sd)
1984 Elm_Fileselector_Filter *filter;
1986 EINA_LIST_FREE(sd->filter_list, filter)
1988 eina_stringshare_del(filter->filter_name);
1990 if (filter->filter_type == ELM_FILESELECTOR_MIME_FILTER)
1992 free(filter->filter.mime_types[0]);
1993 free(filter->filter.mime_types);
1996 free(filter->filter.custom);
2001 ELM_SAFE_FREE(sd->filter_hoversel, evas_object_del);
2003 _populate(obj, sd->path, NULL, NULL);
2007 elm_fileselector_hidden_visible_set(Evas_Object *obj, Eina_Bool visible)
2009 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2010 eo_do(obj, elm_interface_fileselector_hidden_visible_set(visible));
2014 _elc_fileselector_elm_interface_fileselector_hidden_visible_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Eina_Bool visible)
2016 visible = !!visible;
2017 if (sd->hidden_visible == visible) return;
2018 sd->hidden_visible = visible;
2020 _clear_selections(sd, NULL);
2021 _populate(obj, sd->path, NULL, NULL);
2025 elm_fileselector_hidden_visible_get(const Evas_Object *obj)
2027 ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
2028 Eina_Bool ret = EINA_FALSE;
2029 eo_do((Eo *) obj, ret = elm_interface_fileselector_hidden_visible_get());
2033 EOLIAN static Eina_Bool
2034 _elc_fileselector_elm_interface_fileselector_hidden_visible_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
2036 return sd->hidden_visible;
2040 elm_fileselector_thumbnail_size_set(Evas_Object *obj,
2044 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2045 eo_do(obj, elm_interface_fileselector_thumbnail_size_set(w, h));
2049 _elc_fileselector_elm_interface_fileselector_thumbnail_size_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Evas_Coord w, Evas_Coord h)
2051 if (sd->thumbnail_size.w == w && sd->thumbnail_size.h == h) return;
2054 w = h = elm_config_finger_size_get() * 2 - GENGRID_PADDING;
2056 sd->thumbnail_size.w = w;
2057 sd->thumbnail_size.h = h;
2059 if (sd->mode == ELM_FILESELECTOR_GRID)
2060 elm_gengrid_item_size_set(sd->files_view, w + GENGRID_PADDING, h + GENGRID_PADDING);
2062 _populate(obj, sd->path, NULL, NULL);
2066 elm_fileselector_thumbnail_size_get(const Evas_Object *obj,
2070 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2071 eo_do((Eo *) obj, elm_interface_fileselector_thumbnail_size_get(w, h));
2075 _elc_fileselector_elm_interface_fileselector_thumbnail_size_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Evas_Coord *w, Evas_Coord *h)
2077 if (w) *w = sd->thumbnail_size.w;
2078 if (h) *h = sd->thumbnail_size.h;
2082 elm_fileselector_sort_method_set(Evas_Object *obj, Elm_Fileselector_Sort sort)
2084 ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2085 eo_do(obj, elm_interface_fileselector_sort_method_set(sort));
2089 _elc_fileselector_elm_interface_fileselector_sort_method_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Elm_Fileselector_Sort sort)
2091 if (sd->sort_type == sort) return;
2092 sd->sort_type = sort;
2094 switch (sd->sort_type)
2096 case ELM_FILESELECTOR_SORT_BY_FILENAME_ASC:
2097 sd->sort_method = strcoll;
2099 case ELM_FILESELECTOR_SORT_BY_FILENAME_DESC:
2100 sd->sort_method = _strcoll_rev;
2102 case ELM_FILESELECTOR_SORT_BY_TYPE_ASC:
2103 sd->sort_method = _strcoll_type;
2105 case ELM_FILESELECTOR_SORT_BY_TYPE_DESC:
2106 sd->sort_method = _strcoll_type_rev;
2108 case ELM_FILESELECTOR_SORT_BY_SIZE_ASC:
2109 sd->sort_method = _size_cmp;
2111 case ELM_FILESELECTOR_SORT_BY_SIZE_DESC:
2112 sd->sort_method = _size_cmp_rev;
2114 case ELM_FILESELECTOR_SORT_BY_MODIFIED_ASC:
2115 sd->sort_method = _modified_cmp;
2117 case ELM_FILESELECTOR_SORT_BY_MODIFIED_DESC:
2118 sd->sort_method = _modified_cmp_rev;
2120 case ELM_FILESELECTOR_SORT_LAST:
2122 sd->sort_method = strcoll;
2125 _populate(obj, sd->path, NULL, NULL);
2128 EAPI Elm_Fileselector_Sort
2129 elm_fileselector_sort_method_get(const Evas_Object *obj)
2131 ELM_FILESELECTOR_INTERFACE_CHECK(obj, ELM_FILESELECTOR_SORT_LAST);
2132 Elm_Fileselector_Sort ret = ELM_FILESELECTOR_SORT_LAST;
2133 eo_do((Eo *) obj, ret = elm_interface_fileselector_sort_method_get());
2138 EOLIAN static Elm_Fileselector_Sort
2139 _elc_fileselector_elm_interface_fileselector_sort_method_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
2141 return sd->sort_type;
2144 EOLIAN static Eina_Bool
2145 _elc_fileselector_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd EINA_UNUSED)
2150 EOLIAN static Eina_Bool
2151 _elc_fileselector_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd EINA_UNUSED)
2156 EOLIAN static Eina_Bool
2157 _elc_fileselector_elm_layout_text_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, const char *part, const char *label)
2159 if (!part) return EINA_FALSE;
2161 if (sd->ok_button && !strcmp(part, "ok"))
2163 elm_object_text_set(sd->ok_button, label);
2166 else if (sd->cancel_button && !strcmp(part, "cancel"))
2168 elm_object_text_set(sd->cancel_button, label);
2173 Eina_Bool int_ret = EINA_FALSE;
2174 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_layout_text_set(part, label));
2182 _elc_fileselector_class_constructor(Eo_Class *klass)
2186 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
2188 for (i = 0; i < ELM_FILE_LAST; ++i)
2190 list_itc[i] = elm_genlist_item_class_new();
2191 grid_itc[i] = elm_gengrid_item_class_new();
2193 list_itc[i]->item_style = "default";
2194 list_itc[i]->func.text_get = grid_itc[i]->func.text_get =
2196 list_itc[i]->func.state_get = grid_itc[i]->func.state_get =
2198 list_itc[i]->func.del = grid_itc[i]->func.del = _itc_del;
2201 list_itc[ELM_DIRECTORY]->func.content_get =
2202 grid_itc[ELM_DIRECTORY]->func.content_get = _itc_icon_folder_get;
2203 list_itc[ELM_FILE_IMAGE]->func.content_get =
2204 grid_itc[ELM_FILE_IMAGE]->func.content_get = _itc_icon_image_get;
2205 list_itc[ELM_FILE_UNKNOW]->func.content_get =
2206 grid_itc[ELM_FILE_UNKNOW]->func.content_get = _itc_icon_file_get;
2211 _elc_fileselector_class_destructor(Eo_Class *klass EINA_UNUSED)
2215 for (i = 0; i < ELM_FILE_LAST; ++i)
2217 elm_genlist_item_class_free(list_itc[i]);
2218 elm_gengrid_item_class_free(grid_itc[i]);
2222 #include "elc_fileselector.eo.c"