file selector:Add support mime type filter
authorRyuan Choi <ryuan.choi@gmail.com>
Wed, 19 Jun 2013 00:00:41 +0000 (09:00 +0900)
committerRyuan Choi <ryuan.choi@gmail.com>
Mon, 24 Jun 2013 06:42:51 +0000 (15:42 +0900)
legacy/elementary/ChangeLog
legacy/elementary/NEWS
legacy/elementary/data/themes/widgets/fileselector.edc
legacy/elementary/src/bin/test_fileselector.c
legacy/elementary/src/lib/elc_fileselector.c
legacy/elementary/src/lib/elc_fileselector_eo.h
legacy/elementary/src/lib/elc_fileselector_legacy.h
legacy/elementary/src/lib/elm_widget_fileselector.h

index f3f38d1..a5d36f2 100644 (file)
 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
index 50a252d..8fb389f 100644 (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:
 
index ccd9e6e..f8d158c 100644 (file)
@@ -110,11 +110,28 @@ 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;
                offset: -1 -1;
index dd532ff..dfa7f02 100644 (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);
index 7aafda5..c774218 100644 (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);
@@ -674,6 +723,21 @@ _home(void *data,
 }
 
 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__,
     void *event_info __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 = {
index 06eba98..38485d1 100644 (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)
+
 /**
  * @}
  */
index 505b787..52edeea 100644 (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);
index d656d0a..ad8c35a 100644 (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;
+
+   Eina_List               *filter_list;
+   Elm_Fileselector_Filter *current_filter;
 
-   const char           *path;
-   const char           *selection;
-   Ecore_Idler          *sel_idler;
+   const char              *path;
+   const char              *selection;
+   Ecore_Idler             *sel_idler;
 
-   const char           *path_separator;
+   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;
+};
+
 /**
  * @}
  */