file selector:Add support mime type filter

This commit is contained in:
Ryuan Choi 2013-06-19 09:00:41 +09:00
parent 8ad4a7f904
commit 2cfa0ce7db
8 changed files with 284 additions and 17 deletions

View File

@ -1450,3 +1450,7 @@
2013-06-23 ChunEon Park (Hermet)
* Apply current ctxpopup style to the list in the ctxpopup.
2013-06-24 Ryuan Choi (ryuan)
* fileselector : Add support mime type filter

View File

@ -75,6 +75,7 @@ Additions:
* Add magnifier to entry.
* Add "focused" and "unfocused" smart callback for panel, video, web, web2, genlist, hover, index, list, map, photocam, progressbar, radio, scroller, slider, slideshow, spinner, toolbar, win, calendar, check, clock, colorselector, datetime, diskselector, flipselector, gengrid, ctxpopup, fileselector_button, naviframe, player, popup, bubble, button.
* Add elm_web_url_set(), elm_web_url_get() and "url,changed" signal for web, web2.
* Add elm_fileselector_mime_type_filter_append and elm_fileselector_filters_clear to support mime type filter.
Improvements:

View File

@ -110,10 +110,27 @@ group { name: "elm/fileselector/base/default";
align: 0.5 1.0;
fixed: 1 1;
rel1 {
to_y: "elm.swallow.ok";
to_y: "elm.swallow.filters";
relative: 0.0 0.0;
offset: 0 -1;
}
rel2 {
to_y: "elm.swallow.filters";
relative: 1.0 0.0;
offset: -1 -1;
}
}
}
part { name: "elm.swallow.filters";
type: SWALLOW;
description { state: "default" 0.0;
align: 1.0 1.0;
fixed: 1 1;
rel1 {
to_y: "elm.swallow.ok";
relative: 1.0 0.0;
offset: 0 -1;
}
rel2 {
to_y: "elm.swallow.ok";
relative: 1.0 0.0;

View File

@ -141,6 +141,7 @@ test_fileselector(void *data __UNUSED__,
setlocale(LC_ALL, "");
elm_need_ethumb();
elm_need_efreet();
win = elm_win_util_standard_add("fileselector", "File Selector");
elm_win_autodel_set(win, EINA_TRUE);
@ -157,6 +158,9 @@ test_fileselector(void *data __UNUSED__,
elm_fileselector_expandable_set(fs, EINA_FALSE);
/* start the fileselector in the home dir */
elm_fileselector_path_set(fs, getenv("HOME"));
elm_fileselector_mime_types_filter_append(fs, "text/*", "Text Files");
elm_fileselector_mime_types_filter_append(fs, "image/*", "Image Files");
/* allow fs to expand in x & y */
evas_object_size_hint_weight_set(fs, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(fs, EVAS_HINT_FILL, EVAS_HINT_FILL);

View File

@ -7,7 +7,8 @@
* - double click to choose a file
* - multi-selection
* - make variable/function names that are sensible
* - Filter support
* - Pattern Filter support
* - Custom Filter support
*/
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
@ -127,6 +128,7 @@ _elm_fileselector_smart_theme(Eo *obj, void *_pd, va_list *list)
SWALLOW("elm.swallow.path", sd->path_entry);
snprintf(buf, sizeof(buf), "fileselector/actions/%s", style);
SWALLOW("elm.swallow.filters", sd->filter_hoversel);
SWALLOW("elm.swallow.cancel", sd->cancel_button);
SWALLOW("elm.swallow.ok", sd->ok_button);
@ -253,6 +255,50 @@ _anchors_do(Evas_Object *obj,
elm_object_text_set(sd->path_entry, buf);
}
static Eina_Bool
_mime_type_matched(const char *mime_filter, const char *mime_type)
{
int i = 0;
while (mime_filter[i] != '\0')
{
if (mime_filter[i] != mime_type[i])
{
if (mime_filter[i] == '*' && mime_filter[i + 1] == '\0')
return EINA_TRUE;
return EINA_FALSE;
}
i++;
}
if (mime_type[i] != '\0') return EINA_FALSE;
return EINA_TRUE;
}
static Eina_Bool
_check_filters(const Elm_Fileselector_Filter *filter, const char *file_name)
{
const char *mime_type = NULL;
int i;
if (!filter) return EINA_TRUE;
#ifdef ELM_EFREET
mime_type = efreet_mime_type_get(file_name);
#endif
if (!mime_type) return EINA_FALSE;
for (i = 0; filter->mime_types[i]; ++i)
{
if (_mime_type_matched(filter->mime_types[i], mime_type))
return EINA_TRUE;
}
return EINA_FALSE;
}
#ifdef HAVE_EIO
static Eina_Bool
_ls_filter_cb(void *data,
@ -267,6 +313,9 @@ _ls_filter_cb(void *data,
if (lreq->sd->only_folder && info->type != EINA_FILE_DIR)
return EINA_FALSE;
if (info->type != EINA_FILE_DIR && !_check_filters(lreq->sd->current_filter, info->path))
return EINA_FALSE;
return EINA_TRUE;
}
@ -452,7 +501,7 @@ _populate(Evas_Object *obj,
filename = eina_stringshare_add(file->path);
if (file->type == EINA_FILE_DIR)
dirs = eina_list_append(dirs, filename);
else if (!sd->only_folder)
else if (!sd->only_folder && _check_filters(sd->current_filter, filename))
files = eina_list_append(files, filename);
}
eina_iterator_free(it);
@ -673,6 +722,21 @@ _home(void *data,
_populate(fs, getenv("HOME"), NULL);
}
static void
_current_filer_changed(void *data,
Evas_Object *obj,
void *event_info __UNUSED__)
{
Elm_Fileselector_Filter *filter = data;
if (filter->sd->current_filter == filter) return;
elm_object_text_set(obj, filter->filter_name);
filter->sd->current_filter = filter;
_populate(filter->sd->obj, filter->sd->path, NULL);
}
static void
_ok(void *data,
Evas_Object *obj __UNUSED__,
@ -881,6 +945,7 @@ _elm_fileselector_smart_del(Eo *obj EINA_UNUSED, void *_pd, va_list *list EINA_U
int i;
Elm_Fileselector_Smart_Data *sd = _pd;
Elm_Fileselector_Filter *filter;
for (i = 0; i < ELM_FILE_LAST; ++i)
{
@ -892,6 +957,16 @@ _elm_fileselector_smart_del(Eo *obj EINA_UNUSED, void *_pd, va_list *list EINA_U
if (sd->current) eio_file_cancel(sd->current);
#endif
EINA_LIST_FREE(sd->filter_list, filter)
{
eina_stringshare_del(filter->filter_name);
free(filter->mime_types[0]);
free(filter->mime_types);
free(filter);
}
sd->files_list = NULL;
sd->files_grid = NULL;
@ -1265,6 +1340,93 @@ clean_up:
free(path);
}
EAPI Eina_Bool
elm_fileselector_mime_types_filter_append(Evas_Object *obj, const char *mime_type, const char *filter_name)
{
ELM_FILESELECTOR_CHECK(obj) EINA_FALSE;
Eina_Bool ret = EINA_FALSE;
eo_do(obj, elm_obj_fileselector_mime_types_filter_append(mime_type, filter_name, &ret));
return ret;
}
static void
_mime_types_filter_append(Eo *obj, void *_pd, va_list *list)
{
const char *mime_types = va_arg(*list, const char *);
const char *filter_name = va_arg(*list, const char *);
Eina_Bool *ret = va_arg(*list, Eina_Bool *);
Elm_Fileselector_Smart_Data *sd;
Elm_Fileselector_Filter *ff;
Eina_Bool int_ret = EINA_FALSE;
Eina_Bool need_theme = EINA_FALSE;
if (!mime_types) goto end;
sd = _pd;
ff = malloc(sizeof(Elm_Fileselector_Filter));
if (!ff) goto end;
if (filter_name)
ff->filter_name = eina_stringshare_add(filter_name);
else
ff->filter_name = eina_stringshare_add(mime_types);
ff->sd = sd;
ff->mime_types = eina_str_split(mime_types, ",", 0);
if (!sd->filter_list)
{
sd->current_filter = ff;
sd->filter_hoversel = elm_hoversel_add(obj);
elm_object_text_set(sd->filter_hoversel, ff->filter_name);
need_theme = EINA_TRUE;
}
elm_hoversel_item_add(sd->filter_hoversel, ff->filter_name, NULL, ELM_ICON_NONE, _current_filer_changed, ff);
sd->filter_list = eina_list_append(sd->filter_list, ff);
_populate(obj, sd->path, NULL);
if (need_theme)
eo_do(obj, elm_wdg_theme(NULL));
int_ret = EINA_TRUE;
end:
if (ret) *ret = int_ret;
}
EAPI void
elm_fileselector_filters_clear(Evas_Object *obj)
{
ELM_FILESELECTOR_CHECK(obj);
eo_do(obj, elm_obj_fileselector_filters_clear());
}
static void
_filters_clear(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
{
Elm_Fileselector_Smart_Data *sd = _pd;
Elm_Fileselector_Filter *filter;
EINA_LIST_FREE(sd->filter_list, filter)
{
eina_stringshare_del(filter->filter_name);
free(filter->mime_types[0]);
free(filter->mime_types);
free(filter);
}
ELM_SAFE_FREE(sd->filter_hoversel, evas_object_del);
_populate(obj, sd->path, NULL);
}
static void
_elm_fileselector_smart_focus_next_manager_is(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED, va_list *list)
{
@ -1308,6 +1470,8 @@ _class_constructor(Eo_Class *klass)
EO_OP_FUNC(ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_MODE_GET), _mode_get),
EO_OP_FUNC(ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_SELECTED_GET), _selected_get),
EO_OP_FUNC(ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_SELECTED_SET), _selected_set),
EO_OP_FUNC(ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_MIME_TYPES_FILTER_APPEND), _mime_types_filter_append),
EO_OP_FUNC(ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_FILTERS_CLEAR), _filters_clear),
EO_OP_FUNC_SENTINEL
};
eo_class_funcs_set(klass, func_desc);
@ -1329,6 +1493,8 @@ static const Eo_Op_Description op_desc[] = {
EO_OP_DESCRIPTION(ELM_OBJ_FILESELECTOR_SUB_ID_MODE_GET, "Get the mode in which a given file selector widget is displaying (layouting) file system entries in its view."),
EO_OP_DESCRIPTION(ELM_OBJ_FILESELECTOR_SUB_ID_SELECTED_GET, "Get the currently selected item's (full) path, in the given file selector widget."),
EO_OP_DESCRIPTION(ELM_OBJ_FILESELECTOR_SUB_ID_SELECTED_SET, "Set, programmatically, the currently selected file/directory in the given file selector widget."),
EO_OP_DESCRIPTION(ELM_OBJ_FILESELECTOR_SUB_ID_MIME_TYPES_FILTER_APPEND, "Append mime type filter"),
EO_OP_DESCRIPTION(ELM_OBJ_FILESELECTOR_SUB_ID_FILTERS_CLEAR, "Clear filters"),
EO_OP_DESCRIPTION_SENTINEL
};
static const Eo_Class_Description class_desc = {

View File

@ -25,6 +25,8 @@ enum
ELM_OBJ_FILESELECTOR_SUB_ID_MODE_GET,
ELM_OBJ_FILESELECTOR_SUB_ID_SELECTED_GET,
ELM_OBJ_FILESELECTOR_SUB_ID_SELECTED_SET,
ELM_OBJ_FILESELECTOR_SUB_ID_MIME_TYPES_FILTER_APPEND,
ELM_OBJ_FILESELECTOR_SUB_ID_FILTERS_CLEAR,
ELM_OBJ_FILESELECTOR_SUB_ID_LAST
};
@ -206,6 +208,32 @@ enum
* @see elm_fileselector_selected_set
*/
#define elm_obj_fileselector_selected_set(_path, ret) ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_SELECTED_SET), EO_TYPECHECK(const char *, _path), EO_TYPECHECK(Eina_Bool *, ret)
/**
* @def elm_obj_fileselector_mime_type_filter_append
* @since 1.8
*
* Append mime type based filter into filter list
*
* @param[in] mime_types
* @param[in] filter_name
* @param[out] ret
*
* @see elm_fileselector_mime_type_filter_append
*/
#define elm_obj_fileselector_mime_types_filter_append(mime_types, filter_name, ret) ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_MIME_TYPES_FILTER_APPEND), EO_TYPECHECK(const char *, mime_types), EO_TYPECHECK(const char *, filter_name), EO_TYPECHECK(Eina_Bool *, ret)
/**
* @def elm_obj_fileselector_filters_clear
* @since 1.8
*
* Clear all filters registered
*
*
* @see elm_fileselector_mime_type_filter_append
*/
#define elm_obj_fileselector_filters_clear() ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_FILTERS_CLEAR)
/**
* @}
*/

View File

@ -242,3 +242,36 @@ EAPI Eina_Bool elm_fileselector_selected_set(Evas_Object *obj, const
* @ingroup Fileselector
*/
EAPI const char *elm_fileselector_selected_get(const Evas_Object *obj);
/**
* Append mime types filter into filter list
*
* @param obj The file selector object
* @param mime_types comma(,) separated mime types to be allowed.
* @param filter_name The name to be displayed, @p mime_types will be displayed if NULL
* @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
*
* @note a sub type of mime can be asterisk(*)
* @note mime type filter is only working with efreet now.
* @note first added filter will be the default filter at the moment.
*
* @see elm_need_efreet()
* @see elm_fileselector_filters_clear()
*
* @ingroup Fileselector
*/
EAPI Eina_Bool elm_fileselector_mime_types_filter_append(Evas_Object *obj, const char *mime_types, const char *filter_name);
/**
* Clear all filters registered
*
* @param obj The file selector object
*
* @note If filter list is empty, file selector assume that all
* files are matched.
*
* @see elm_fileselector_mime_type_filter_append()
*
* @ingroup Fileselector
*/
EAPI void elm_fileselector_filters_clear(Evas_Object *obj);

View File

@ -14,6 +14,8 @@
* widgets which are a fileselector with some more logic on top.
*/
typedef struct _Elm_Fileselector_Filter Elm_Fileselector_Filter;
/**
* Base layout smart data extended with fileselector instance data.
*/
@ -22,24 +24,28 @@ struct _Elm_Fileselector_Smart_Data
{
EINA_REFCOUNT;
Evas_Object *obj;
Evas_Object *path_entry;
Evas_Object *files_list;
Evas_Object *files_grid;
Evas_Object *up_button;
Evas_Object *home_button;
Evas_Object *spinner;
Evas_Object *ok_button;
Evas_Object *cancel_button;
Evas_Object *obj;
Evas_Object *path_entry;
Evas_Object *files_list;
Evas_Object *files_grid;
Evas_Object *up_button;
Evas_Object *home_button;
Evas_Object *spinner;
Evas_Object *filter_hoversel;
Evas_Object *ok_button;
Evas_Object *cancel_button;
const char *path;
const char *selection;
Ecore_Idler *sel_idler;
Eina_List *filter_list;
Elm_Fileselector_Filter *current_filter;
const char *path_separator;
const char *path;
const char *selection;
Ecore_Idler *sel_idler;
const char *path_separator;
#ifdef HAVE_EIO
Eio_File *current;
Eio_File *current;
#endif
Elm_Fileselector_Mode mode;
@ -72,6 +78,14 @@ typedef enum {
ELM_FILE_LAST
} Elm_Fileselector_Type;
struct _Elm_Fileselector_Filter
{
const char *filter_name;
Elm_Fileselector_Smart_Data *sd;
char **mime_types;
};
/**
* @}
*/