]> Pileus Git - ~andy/gtk/blob - gtk/gtkfilefilter.c
Intern type names in code generated by glib-mkenums, too.
[~andy/gtk] / gtk / gtkfilefilter.c
1 /* GTK - The GIMP Toolkit
2  * gtkfilefilter.c: Filters for selecting a file subset
3  * Copyright (C) 2003, Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22 #include <string.h>
23
24 #include "gtkfilefilter.h"
25 #include "gtkobject.h"
26 #include "gtkprivate.h"
27
28 #include "gtkalias.h"
29
30 #ifdef G_OS_UNIX
31 #define XDG_PREFIX _gtk_xdg
32 #include "xdgmime/xdgmime.h"
33 #endif
34
35 typedef struct _GtkFileFilterClass GtkFileFilterClass;
36 typedef struct _FilterRule FilterRule;
37
38 #define GTK_FILE_FILTER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_FILTER, GtkFileFilterClass))
39 #define GTK_IS_FILE_FILTER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_FILTER))
40 #define GTK_FILE_FILTER_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_FILTER, GtkFileFilterClass))
41
42 typedef enum {
43   FILTER_RULE_PATTERN,
44   FILTER_RULE_MIME_TYPE,
45   FILTER_RULE_PIXBUF_FORMATS,
46   FILTER_RULE_CUSTOM
47 } FilterRuleType;
48
49 struct _GtkFileFilterClass
50 {
51   GtkObjectClass parent_class;
52 };
53
54 struct _GtkFileFilter
55 {
56   GtkObject parent_instance;
57   
58   gchar *name;
59   GSList *rules;
60
61   GtkFileFilterFlags needed;
62 };
63
64 struct _FilterRule
65 {
66   FilterRuleType type;
67   GtkFileFilterFlags needed;
68   
69   union {
70     gchar *pattern;
71     gchar *mime_type;
72     GSList *pixbuf_formats;
73     struct {
74       GtkFileFilterFunc func;
75       gpointer data;
76       GDestroyNotify notify;
77     } custom;
78   } u;
79 };
80
81 static void gtk_file_filter_class_init (GtkFileFilterClass *class);
82 static void gtk_file_filter_finalize   (GObject            *object);
83
84 static GObjectClass *parent_class;
85
86 GType
87 gtk_file_filter_get_type (void)
88 {
89   static GType file_filter_type = 0;
90
91   if (!file_filter_type)
92     {
93       static const GTypeInfo file_filter_info =
94       {
95         sizeof (GtkFileFilterClass),
96         NULL,           /* base_init */
97         NULL,           /* base_finalize */
98         (GClassInitFunc) gtk_file_filter_class_init,
99         NULL,           /* class_finalize */
100         NULL,           /* class_data */
101         sizeof (GtkFileFilter),
102         0,              /* n_preallocs */
103         NULL            /* init */
104       };
105       
106       file_filter_type = g_type_register_static (GTK_TYPE_OBJECT, g_intern_static_string ("GtkFileFilter"),
107                                                  &file_filter_info, 0);
108     }
109
110   return file_filter_type;
111 }
112
113 static void
114 gtk_file_filter_class_init (GtkFileFilterClass *class)
115 {
116   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
117
118   parent_class = g_type_class_peek_parent (class);
119
120   gobject_class->finalize = gtk_file_filter_finalize;
121 }
122
123 static void
124 filter_rule_free (FilterRule *rule)
125 {
126   switch (rule->type)
127     {
128     case FILTER_RULE_MIME_TYPE:
129       g_free (rule->u.mime_type);
130       break;
131     case FILTER_RULE_PATTERN:
132       g_free (rule->u.pattern);
133       break;
134     case FILTER_RULE_CUSTOM:
135       if (rule->u.custom.notify)
136         rule->u.custom.notify (rule->u.custom.data);
137       break;
138     case FILTER_RULE_PIXBUF_FORMATS:
139       g_slist_free (rule->u.pixbuf_formats);
140       break;
141     default:
142       g_assert_not_reached ();
143     }
144
145   g_free (rule);
146 }
147
148 static void
149 gtk_file_filter_finalize (GObject  *object)
150 {
151   GtkFileFilter *filter = GTK_FILE_FILTER (object);
152
153   g_slist_foreach (filter->rules, (GFunc)filter_rule_free, NULL);
154   g_slist_free (filter->rules);
155
156   if (filter->name)
157     g_free (filter->name);
158
159   parent_class->finalize (object);
160 }
161
162 /**
163  * gtk_file_filter_new:
164  * 
165  * Creates a new #GtkFileFilter with no rules added to it.
166  * Such a filter doesn't accept any files, so is not
167  * particularly useful until you add rules with
168  * gtk_file_filter_add_mime_type(), gtk_file_filter_add_pattern(),
169  * or gtk_file_filter_add_custom(). To create a filter
170  * that accepts any file, use:
171  *
172  * <informalexample><programlisting>
173  * GtkFileFilter *filter = gtk_file_filter_new (<!-- -->);
174  * gtk_file_filter_add_pattern (filter, "*");
175  * </programlisting></informalexample>
176  * 
177  * Return value: a new #GtkFileFilter
178  * 
179  * Since: 2.4
180  **/
181 GtkFileFilter *
182 gtk_file_filter_new (void)
183 {
184   return g_object_new (GTK_TYPE_FILE_FILTER, NULL);
185 }
186
187 /**
188  * gtk_file_filter_set_name:
189  * @filter: a #GtkFileFilter
190  * @name: the human-readable-name for the filter, or %NULL
191  *   to remove any existing name.
192  * 
193  * Sets the human-readable name of the filter; this is the string
194  * that will be displayed in the file selector user interface if
195  * there is a selectable list of filters.
196  * 
197  * Since: 2.4
198  **/
199 void
200 gtk_file_filter_set_name (GtkFileFilter *filter,
201                           const gchar   *name)
202 {
203   g_return_if_fail (GTK_IS_FILE_FILTER (filter));
204   
205   if (filter->name)
206     g_free (filter->name);
207
208   filter->name = g_strdup (name);
209 }
210
211 /**
212  * gtk_file_filter_get_name:
213  * @filter: a #GtkFileFilter
214  * 
215  * Gets the human-readable name for the filter. See gtk_file_filter_set_name().
216  * 
217  * Return value: The human-readable name of the filter,
218  *   or %NULL. This value is owned by GTK+ and must not
219  *   be modified or freed.
220  * 
221  * Since: 2.4
222  **/
223 G_CONST_RETURN gchar *
224 gtk_file_filter_get_name (GtkFileFilter *filter)
225 {
226   g_return_val_if_fail (GTK_IS_FILE_FILTER (filter), NULL);
227   
228   return filter->name;
229 }
230
231 static void
232 file_filter_add_rule (GtkFileFilter *filter,
233                       FilterRule    *rule)
234 {
235   filter->needed |= rule->needed;
236   filter->rules = g_slist_append (filter->rules, rule);
237 }
238
239 /**
240  * gtk_file_filter_add_mime_type:
241  * @filter: A #GtkFileFilter
242  * @mime_type: name of a MIME type
243  * 
244  * Adds a rule allowing a given mime type to @filter.
245  * 
246  * Since: 2.4
247  **/
248 void
249 gtk_file_filter_add_mime_type (GtkFileFilter *filter,
250                                const gchar   *mime_type)
251 {
252   FilterRule *rule;
253   
254   g_return_if_fail (GTK_IS_FILE_FILTER (filter));
255   g_return_if_fail (mime_type != NULL);
256
257   rule = g_new (FilterRule, 1);
258   rule->type = FILTER_RULE_MIME_TYPE;
259   rule->needed = GTK_FILE_FILTER_MIME_TYPE;
260   rule->u.mime_type = g_strdup (mime_type);
261
262   file_filter_add_rule (filter, rule);
263 }
264
265 /**
266  * gtk_file_filter_add_pattern:
267  * @filter: a #GtkFileFilter
268  * @pattern: a shell style glob
269  * 
270  * Adds a rule allowing a shell style glob to a filter.
271  * 
272  * Since: 2.4
273  **/
274 void
275 gtk_file_filter_add_pattern (GtkFileFilter *filter,
276                              const gchar   *pattern)
277 {
278   FilterRule *rule;
279   
280   g_return_if_fail (GTK_IS_FILE_FILTER (filter));
281   g_return_if_fail (pattern != NULL);
282
283   rule = g_new (FilterRule, 1);
284   rule->type = FILTER_RULE_PATTERN;
285   rule->needed = GTK_FILE_FILTER_DISPLAY_NAME;
286   rule->u.pattern = g_strdup (pattern);
287
288   file_filter_add_rule (filter, rule);
289 }
290
291 /**
292  * gtk_file_filter_add_pixbuf_formats:
293  * @filter: a #GtkFileFilter
294  * 
295  * Adds a rule allowing image files in the formats supported
296  * by GdkPixbuf.
297  * 
298  * Since: 2.6
299  **/
300 void
301 gtk_file_filter_add_pixbuf_formats (GtkFileFilter *filter)
302 {
303   FilterRule *rule;
304   
305   g_return_if_fail (GTK_IS_FILE_FILTER (filter));
306
307   rule = g_new (FilterRule, 1);
308   rule->type = FILTER_RULE_PIXBUF_FORMATS;
309   rule->needed = GTK_FILE_FILTER_MIME_TYPE;
310   rule->u.pixbuf_formats = gdk_pixbuf_get_formats ();
311   file_filter_add_rule (filter, rule);
312 }
313
314
315 /**
316  * gtk_file_filter_add_custom:
317  * @filter: a #GtkFileFilter
318  * @needed: bitfield of flags indicating the information that the custom
319  *          filter function needs.
320  * @func: callback function; if the function returns %TRUE, then
321  *   the file will be displayed.
322  * @data: data to pass to @func
323  * @notify: function to call to free @data when it is no longer needed.
324  * 
325  * Adds rule to a filter that allows files based on a custom callback
326  * function. The bitfield @needed which is passed in provides information
327  * about what sorts of information that the filter function needs;
328  * this allows GTK+ to avoid retrieving expensive information when
329  * it isn't needed by the filter.
330  * 
331  * Since: 2.4
332  **/
333 void
334 gtk_file_filter_add_custom (GtkFileFilter         *filter,
335                             GtkFileFilterFlags     needed,
336                             GtkFileFilterFunc      func,
337                             gpointer               data,
338                             GDestroyNotify         notify)
339 {
340   FilterRule *rule;
341   
342   g_return_if_fail (GTK_IS_FILE_FILTER (filter));
343   g_return_if_fail (func != NULL);
344
345   rule = g_new (FilterRule, 1);
346   rule->type = FILTER_RULE_CUSTOM;
347   rule->needed = needed;
348   rule->u.custom.func = func;
349   rule->u.custom.data = data;
350   rule->u.custom.notify = notify;
351
352   file_filter_add_rule (filter, rule);
353 }
354
355 /**
356  * gtk_file_filter_get_needed:
357  * @filter: a #GtkFileFilter
358  * 
359  * Gets the fields that need to be filled in for the structure
360  * passed to gtk_file_filter_filter()
361  * 
362  * This function will not typically be used by applications; it
363  * is intended principally for use in the implementation of
364  * #GtkFileChooser.
365  * 
366  * Return value: bitfield of flags indicating needed fields when
367  *   calling gtk_file_filter_filter()
368  * 
369  * Since: 2.4
370  **/
371 GtkFileFilterFlags
372 gtk_file_filter_get_needed (GtkFileFilter *filter)
373 {
374   return filter->needed;
375 }
376
377 /**
378  * gtk_file_filter_filter:
379  * @filter: a #GtkFileFilter
380  * @filter_info: a #GtkFileFilterInfo structure containing information
381  *  about a file.
382  * 
383  * Tests whether a file should be displayed according to @filter.
384  * The #GtkFileFilterInfo structure @filter_info should include
385  * the fields returned from gtk_file_filter_get_needed().
386  *
387  * This function will not typically be used by applications; it
388  * is intended principally for use in the implementation of
389  * #GtkFileChooser.
390  * 
391  * Return value: %TRUE if the file should be displayed
392  * 
393  * Since: 2.4
394  **/
395 gboolean
396 gtk_file_filter_filter (GtkFileFilter           *filter,
397                         const GtkFileFilterInfo *filter_info)
398 {
399   GSList *tmp_list;
400
401   for (tmp_list = filter->rules; tmp_list; tmp_list = tmp_list->next)
402     {
403       FilterRule *rule = tmp_list->data;
404
405       if ((filter_info->contains & rule->needed) != rule->needed)
406         continue;
407       
408       switch (rule->type)
409         {
410         case FILTER_RULE_MIME_TYPE:
411           if (filter_info->mime_type != NULL
412 #ifdef G_OS_UNIX
413               && xdg_mime_mime_type_subclass (filter_info->mime_type, rule->u.mime_type))
414 #else
415               && strcmp (rule->u.mime_type, filter_info->mime_type) == 0)
416 #endif
417             return TRUE;
418           break;
419         case FILTER_RULE_PATTERN:
420           if (filter_info->display_name != NULL &&
421               _gtk_fnmatch (rule->u.pattern, filter_info->display_name, FALSE))
422             return TRUE;
423           break;
424         case FILTER_RULE_PIXBUF_FORMATS:
425           {
426             GSList *list;
427
428             for (list = rule->u.pixbuf_formats; list; list = list->next)
429               {
430                 int i;
431                 gchar **mime_types;
432
433                 mime_types = gdk_pixbuf_format_get_mime_types (list->data);
434
435                 for (i = 0; mime_types[i] != NULL; i++)
436                   {
437                     if (strcmp (mime_types[i], filter_info->mime_type) == 0)
438                       {
439                         g_strfreev (mime_types);
440                         return TRUE;
441                       }
442                   }
443
444                 g_strfreev (mime_types);
445               }
446             break;
447           }
448         case FILTER_RULE_CUSTOM:
449           if (rule->u.custom.func (filter_info, rule->u.custom.data))
450             return TRUE;
451           break;
452         }
453     }
454
455   return FALSE;
456 }
457
458 #define __GTK_FILE_FILTER_C__
459 #include "gtkaliasdef.c"