fileselector : Add elm_fileselector_custom_filter_append to support custom filter

Summary:
Now, application developers can decide whether files and directories to show in
fileselector view.

Reviewers: seoz, raster

Reviewed By: raster

Differential Revision: https://phab.enlightenment.org/D416
This commit is contained in:
Ryuan Choi 2013-12-29 13:23:17 +09:00 committed by Carsten Haitzler (Rasterman)
parent f464775670
commit e26c97d55c
6 changed files with 195 additions and 30 deletions

View File

@ -474,6 +474,14 @@ _thumbnail_size_option_create(Evas_Object *parent, Evas_Object *fs)
return frame;
}
static Eina_Bool
_all_filter(const char *path EINA_UNUSED,
Eina_Bool dir EINA_UNUSED,
void *data EINA_UNUSED)
{
return EINA_TRUE;
}
void
test_fileselector(void *data EINA_UNUSED,
Evas_Object *obj EINA_UNUSED,
@ -507,6 +515,7 @@ test_fileselector(void *data EINA_UNUSED,
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");
elm_fileselector_custom_filter_append(fs, _all_filter, NULL, "All Files");
/* allow fs to expand in x & y */
evas_object_size_hint_weight_set(fs, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);

View File

@ -4,7 +4,6 @@
* - user defined icon/label cb
* - show/hide/add buttons ???
* - Pattern Filter support
* - Custom Filter support
*/
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
@ -304,20 +303,19 @@ _mime_type_matched(const char *mime_filter, const char *mime_type)
}
static Eina_Bool
_check_filters(const Elm_Fileselector_Filter *filter, const char *file_name)
_check_mime_type_filter(const Elm_Fileselector_Filter *filter,
const char *file_name)
{
const char *mime_type = NULL;
int i;
if (!filter) return EINA_TRUE;
mime_type = efreet_mime_type_get(file_name);
if (!mime_type) return EINA_FALSE;
for (i = 0; filter->mime_types[i]; ++i)
for (i = 0; filter->filter.mime_types[i]; ++i)
{
if (_mime_type_matched(filter->mime_types[i], mime_type))
if (_mime_type_matched(filter->filter.mime_types[i], mime_type))
return EINA_TRUE;
}
return EINA_FALSE;
@ -329,17 +327,34 @@ _ls_filter_cb(void *data,
const Eina_File_Direct_Info *info)
{
Listing_Request *lreq = data;
Elm_Fileselector_Filter *cf;
Eina_Bool dir = EINA_FALSE;
if (!lreq->sd->hidden_visible && info->path[info->name_start] == '.')
return EINA_FALSE;
if (lreq->sd->only_folder && info->type != EINA_FILE_DIR)
if (info->type == EINA_FILE_DIR)
dir = EINA_TRUE;
if (lreq->sd->only_folder && dir)
return EINA_FALSE;
if (info->type != EINA_FILE_DIR && !_check_filters(lreq->sd->current_filter, info->path))
return EINA_FALSE;
cf = lreq->sd->current_filter;
if (!cf)
return EINA_TRUE;
return EINA_TRUE;
switch (cf->filter_type)
{
case ELM_FILESELECTOR_MIME_FILTER:
return dir || _check_mime_type_filter(cf, info->path);
case ELM_FILESELECTOR_CUSTOM_FILTER:
return cf->filter.custom->func(info->path, dir,
cf->filter.custom->data);
default:
return EINA_FALSE;
}
return EINA_FALSE;
}
static const char *
@ -1164,16 +1179,35 @@ _resource_created(void *data, int type, void *ev)
Evas_Object *obj = data;
Eio_Monitor_Event *event = ev;
int itcn = ELM_FILE_UNKNOW;
Eina_Bool dir = EINA_FALSE;
ELM_FILESELECTOR_DATA_GET(obj, sd);
if (type == EIO_MONITOR_DIRECTORY_CREATED)
dir = EINA_TRUE;
Elm_Fileselector_Filter *cf = sd->current_filter;
if (cf)
{
switch (cf->filter_type)
{
case ELM_FILESELECTOR_MIME_FILTER:
if (!dir && !_check_mime_type_filter(cf, event->filename))
return ECORE_CALLBACK_PASS_ON;
break;
case ELM_FILESELECTOR_CUSTOM_FILTER:
if (!cf->filter.custom->func(event->filename, dir, cf->filter.custom->data))
return ECORE_CALLBACK_PASS_ON;
break;
default:
break;
}
}
if (dir)
itcn = ELM_DIRECTORY;
else
{
if (!_check_filters(sd->current_filter, event->filename))
return ECORE_CALLBACK_PASS_ON;
if (evas_object_image_extension_can_load_get(event->filename))
itcn = ELM_FILE_IMAGE;
}
@ -1410,8 +1444,13 @@ _elm_fileselector_smart_del(Eo *obj EINA_UNUSED, void *_pd, va_list *list EINA_U
{
eina_stringshare_del(filter->filter_name);
free(filter->mime_types[0]);
free(filter->mime_types);
if (filter->filter_type == ELM_FILESELECTOR_MIME_FILTER)
{
free(filter->filter.mime_types[0]);
free(filter->filter.mime_types);
}
else
free(filter->filter.custom);
free(filter);
}
@ -1892,6 +1931,18 @@ _selected_paths_get(Eo *obj __UNUSED__, void *_pd, va_list *list)
*ret = NULL;
}
static Elm_Fileselector_Filter *
_filter_add(Elm_Fileselector_Smart_Data *sd, const char *filter_name)
{
Elm_Fileselector_Filter *ff;
ff = malloc(sizeof(Elm_Fileselector_Filter));
ff->filter_name = eina_stringshare_add(filter_name);
ff->sd = sd;
return ff;
}
EAPI Eina_Bool
elm_fileselector_mime_types_filter_append(Evas_Object *obj, const char *mime_type, const char *filter_name)
{
@ -1917,17 +1968,10 @@ _mime_types_filter_append(Eo *obj, void *_pd, va_list *list)
sd = _pd;
ff = malloc(sizeof(Elm_Fileselector_Filter));
if (!ff) goto end;
ff = _filter_add(sd, filter_name ? filter_name : mime_types);
ff->filter_type = ELM_FILESELECTOR_MIME_FILTER;
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);
ff->filter.mime_types = eina_str_split(mime_types, ",", 0);
if (!sd->filter_list)
{
@ -1951,6 +1995,60 @@ end:
if (ret) *ret = int_ret;
}
EAPI Eina_Bool
elm_fileselector_custom_filter_append(Evas_Object *obj, Elm_Fileselector_Filter_Func func, void *data, const char *filter_name)
{
ELM_FILESELECTOR_CHECK(obj) EINA_FALSE;
Eina_Bool ret = EINA_FALSE;
eo_do(obj, elm_obj_fileselector_custom_filter_append(func, data, filter_name, &ret));
return ret;
}
static void
_custom_filter_append(Eo *obj, void *_pd, va_list *list)
{
Elm_Fileselector_Filter_Func func = va_arg(*list, Elm_Fileselector_Filter_Func);
void *data = va_arg(*list, void *);
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 (!func) goto end;
sd = _pd;
ff = _filter_add(sd, filter_name ? filter_name : "custom");
ff->filter_type = ELM_FILESELECTOR_CUSTOM_FILTER;
ff->filter.custom = malloc(sizeof(Elm_Fileselector_Filter_Func));
ff->filter.custom->func = func;
ff->filter.custom->data = data;
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_filter_changed, ff);
sd->filter_list = eina_list_append(sd->filter_list, ff);
_populate(obj, sd->path, NULL, 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)
{
@ -1968,8 +2066,13 @@ _filters_clear(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
{
eina_stringshare_del(filter->filter_name);
free(filter->mime_types[0]);
free(filter->mime_types);
if (filter->filter_type == ELM_FILESELECTOR_MIME_FILTER)
{
free(filter->filter.mime_types[0]);
free(filter->filter.mime_types);
}
else
free(filter->filter.custom);
free(filter);
}
@ -2216,6 +2319,7 @@ _class_constructor(Eo_Class *klass)
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_SELECTED_PATHS_GET), _selected_paths_get),
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_CUSTOM_FILTER_APPEND), _custom_filter_append),
EO_OP_FUNC(ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_FILTERS_CLEAR), _filters_clear),
EO_OP_FUNC(ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_HIDDEN_VISIBLE_SET), _hidden_visible_set),
EO_OP_FUNC(ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_HIDDEN_VISIBLE_GET), _hidden_visible_get),
@ -2282,6 +2386,7 @@ static const Eo_Op_Description op_desc[] = {
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_SELECTED_PATHS_GET, "Get the currently selected item's (full) path, 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_CUSTOM_FILTER_APPEND, "Append custom filter"),
EO_OP_DESCRIPTION(ELM_OBJ_FILESELECTOR_SUB_ID_FILTERS_CLEAR, "Clear filters"),
EO_OP_DESCRIPTION(ELM_OBJ_FILESELECTOR_SUB_ID_HIDDEN_VISIBLE_SET, "Enable or disable visibility of hidden files/directories in the file selector widget."),
EO_OP_DESCRIPTION(ELM_OBJ_FILESELECTOR_SUB_ID_HIDDEN_VISIBLE_GET, "Get if visibility of hidden files/directories in the file selector widget is enabled or disabled."),

View File

@ -21,3 +21,5 @@ typedef enum
ELM_FILESELECTOR_SORT_BY_MODIFIED_DESC,
ELM_FILESELECTOR_SORT_LAST /**< sentinel (helper) value, not used */
} Elm_Fileselector_Sort;
typedef Eina_Bool (*Elm_Fileselector_Filter_Func)(const char *path, Eina_Bool dir, void *data);

View File

@ -29,6 +29,7 @@ enum
ELM_OBJ_FILESELECTOR_SUB_ID_SELECTED_SET,
ELM_OBJ_FILESELECTOR_SUB_ID_SELECTED_PATHS_GET,
ELM_OBJ_FILESELECTOR_SUB_ID_MIME_TYPES_FILTER_APPEND,
ELM_OBJ_FILESELECTOR_SUB_ID_CUSTOM_FILTER_APPEND,
ELM_OBJ_FILESELECTOR_SUB_ID_FILTERS_CLEAR,
ELM_OBJ_FILESELECTOR_SUB_ID_HIDDEN_VISIBLE_SET,
ELM_OBJ_FILESELECTOR_SUB_ID_HIDDEN_VISIBLE_GET,
@ -268,6 +269,20 @@ enum
*/
#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_custom_filter_append
* @since 1.9
*
* Append custom filter into filter list
*
* @param[in] mime_types
* @param[in] filter_name
* @param[out] ret
*
* @see elm_fileselector_custom_filter_append
*/
#define elm_obj_fileselector_custom_filter_append(func, data, filter_name, ret) ELM_OBJ_FILESELECTOR_ID(ELM_OBJ_FILESELECTOR_SUB_ID_CUSTOM_FILTER_APPEND), EO_TYPECHECK(Elm_Fileselector_Filter_Func, func), EO_TYPECHECK(void *, data), EO_TYPECHECK(const char *, filter_name), EO_TYPECHECK(Eina_Bool *, ret)
/**
* @def elm_obj_fileselector_filters_clear
* @since 1.8

View File

@ -319,6 +319,22 @@ EAPI const Eina_List *elm_fileselector_selected_paths_get(const Evas_Object
*/
EAPI Eina_Bool elm_fileselector_mime_types_filter_append(Evas_Object *obj, const char *mime_types, const char *filter_name);
/**
* Append custom filter into filter list
*
* @param obj The file selector object
* @param func The function to call when manipulating files and directories.
* @param data The data to be passed to this @p func call.
* @param filter_name The name to be displayed, "custom" will be displayed if NULL
* @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
*
* @note first added filter will be the default filter at the moment.
*
* @since 1.9
* @ingroup Fileselector
*/
EAPI Eina_Bool elm_fileselector_custom_filter_append(Evas_Object *obj, Elm_Fileselector_Filter_Func func, void *data, const char *filter_name);
/**
* Clear all filters registered
*

View File

@ -98,12 +98,30 @@ typedef enum {
ELM_FILE_LAST
} Elm_Fileselector_Type;
typedef enum {
ELM_FILESELECTOR_MIME_FILTER = 0,
ELM_FILESELECTOR_CUSTOM_FILTER,
ELM_FILESELECTOR_FILTER_LAST
} Elm_Fileselector_Filter_Type;
typedef struct _Elm_Fileselector_Custom_Filter Elm_Fileselector_Custom_Filter;
struct _Elm_Fileselector_Custom_Filter
{
Elm_Fileselector_Filter_Func func;
void *data;
};
struct _Elm_Fileselector_Filter
{
const char *filter_name;
Elm_Fileselector_Smart_Data *sd;
const char *filter_name;
Elm_Fileselector_Smart_Data *sd;
char **mime_types;
union {
char **mime_types;
Elm_Fileselector_Custom_Filter *custom;
} filter;
Elm_Fileselector_Filter_Type filter_type;
};
/**