]> Pileus Git - ~andy/gtk/blob - gtk/gtkfilefilter.c
[annotations] Add allow-none
[~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 "gtkintl.h"
26 #include "gtkprivate.h"
27
28 #include "gtkalias.h"
29
30 typedef struct _GtkFileFilterClass GtkFileFilterClass;
31 typedef struct _FilterRule FilterRule;
32
33 #define GTK_FILE_FILTER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_FILTER, GtkFileFilterClass))
34 #define GTK_IS_FILE_FILTER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_FILTER))
35 #define GTK_FILE_FILTER_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_FILTER, GtkFileFilterClass))
36
37 typedef enum {
38   FILTER_RULE_PATTERN,
39   FILTER_RULE_MIME_TYPE,
40   FILTER_RULE_PIXBUF_FORMATS,
41   FILTER_RULE_CUSTOM
42 } FilterRuleType;
43
44 struct _GtkFileFilterClass
45 {
46   GtkObjectClass parent_class;
47 };
48
49 struct _GtkFileFilter
50 {
51   GtkObject parent_instance;
52   
53   gchar *name;
54   GSList *rules;
55
56   GtkFileFilterFlags needed;
57 };
58
59 struct _FilterRule
60 {
61   FilterRuleType type;
62   GtkFileFilterFlags needed;
63   
64   union {
65     gchar *pattern;
66     gchar *mime_type;
67     GSList *pixbuf_formats;
68     struct {
69       GtkFileFilterFunc func;
70       gpointer data;
71       GDestroyNotify notify;
72     } custom;
73   } u;
74 };
75
76 static void gtk_file_filter_finalize   (GObject            *object);
77
78
79 G_DEFINE_TYPE (GtkFileFilter, gtk_file_filter, GTK_TYPE_OBJECT)
80
81 static void
82 gtk_file_filter_init (GtkFileFilter *object)
83 {
84 }
85
86 static void
87 gtk_file_filter_class_init (GtkFileFilterClass *class)
88 {
89   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
90
91   gobject_class->finalize = gtk_file_filter_finalize;
92 }
93
94 static void
95 filter_rule_free (FilterRule *rule)
96 {
97   switch (rule->type)
98     {
99     case FILTER_RULE_MIME_TYPE:
100       g_free (rule->u.mime_type);
101       break;
102     case FILTER_RULE_PATTERN:
103       g_free (rule->u.pattern);
104       break;
105     case FILTER_RULE_CUSTOM:
106       if (rule->u.custom.notify)
107         rule->u.custom.notify (rule->u.custom.data);
108       break;
109     case FILTER_RULE_PIXBUF_FORMATS:
110       g_slist_free (rule->u.pixbuf_formats);
111       break;
112     default:
113       g_assert_not_reached ();
114     }
115
116   g_slice_free (FilterRule, rule);
117 }
118
119 static void
120 gtk_file_filter_finalize (GObject  *object)
121 {
122   GtkFileFilter *filter = GTK_FILE_FILTER (object);
123
124   g_slist_foreach (filter->rules, (GFunc)filter_rule_free, NULL);
125   g_slist_free (filter->rules);
126
127   g_free (filter->name);
128
129   G_OBJECT_CLASS (gtk_file_filter_parent_class)->finalize (object);
130 }
131
132 /**
133  * gtk_file_filter_new:
134  * 
135  * Creates a new #GtkFileFilter with no rules added to it.
136  * Such a filter doesn't accept any files, so is not
137  * particularly useful until you add rules with
138  * gtk_file_filter_add_mime_type(), gtk_file_filter_add_pattern(),
139  * or gtk_file_filter_add_custom(). To create a filter
140  * that accepts any file, use:
141  * |[
142  * GtkFileFilter *filter = gtk_file_filter_new ();
143  * gtk_file_filter_add_pattern (filter, "*");
144  * ]|
145  * 
146  * Return value: a new #GtkFileFilter
147  * 
148  * Since: 2.4
149  **/
150 GtkFileFilter *
151 gtk_file_filter_new (void)
152 {
153   return g_object_new (GTK_TYPE_FILE_FILTER, NULL);
154 }
155
156 /**
157  * gtk_file_filter_set_name:
158  * @filter: a #GtkFileFilter
159  * @name: (allow-none): the human-readable-name for the filter, or %NULL
160  *   to remove any existing name.
161  * 
162  * Sets the human-readable name of the filter; this is the string
163  * that will be displayed in the file selector user interface if
164  * there is a selectable list of filters.
165  * 
166  * Since: 2.4
167  **/
168 void
169 gtk_file_filter_set_name (GtkFileFilter *filter,
170                           const gchar   *name)
171 {
172   g_return_if_fail (GTK_IS_FILE_FILTER (filter));
173   
174   g_free (filter->name);
175
176   filter->name = g_strdup (name);
177 }
178
179 /**
180  * gtk_file_filter_get_name:
181  * @filter: a #GtkFileFilter
182  * 
183  * Gets the human-readable name for the filter. See gtk_file_filter_set_name().
184  * 
185  * Return value: The human-readable name of the filter,
186  *   or %NULL. This value is owned by GTK+ and must not
187  *   be modified or freed.
188  * 
189  * Since: 2.4
190  **/
191 G_CONST_RETURN gchar *
192 gtk_file_filter_get_name (GtkFileFilter *filter)
193 {
194   g_return_val_if_fail (GTK_IS_FILE_FILTER (filter), NULL);
195   
196   return filter->name;
197 }
198
199 static void
200 file_filter_add_rule (GtkFileFilter *filter,
201                       FilterRule    *rule)
202 {
203   filter->needed |= rule->needed;
204   filter->rules = g_slist_append (filter->rules, rule);
205 }
206
207 /**
208  * gtk_file_filter_add_mime_type:
209  * @filter: A #GtkFileFilter
210  * @mime_type: name of a MIME type
211  * 
212  * Adds a rule allowing a given mime type to @filter.
213  * 
214  * Since: 2.4
215  **/
216 void
217 gtk_file_filter_add_mime_type (GtkFileFilter *filter,
218                                const gchar   *mime_type)
219 {
220   FilterRule *rule;
221   
222   g_return_if_fail (GTK_IS_FILE_FILTER (filter));
223   g_return_if_fail (mime_type != NULL);
224
225   rule = g_slice_new (FilterRule);
226   rule->type = FILTER_RULE_MIME_TYPE;
227   rule->needed = GTK_FILE_FILTER_MIME_TYPE;
228   rule->u.mime_type = g_strdup (mime_type);
229
230   file_filter_add_rule (filter, rule);
231 }
232
233 /**
234  * gtk_file_filter_add_pattern:
235  * @filter: a #GtkFileFilter
236  * @pattern: a shell style glob
237  * 
238  * Adds a rule allowing a shell style glob to a filter.
239  * 
240  * Since: 2.4
241  **/
242 void
243 gtk_file_filter_add_pattern (GtkFileFilter *filter,
244                              const gchar   *pattern)
245 {
246   FilterRule *rule;
247   
248   g_return_if_fail (GTK_IS_FILE_FILTER (filter));
249   g_return_if_fail (pattern != NULL);
250
251   rule = g_slice_new (FilterRule);
252   rule->type = FILTER_RULE_PATTERN;
253   rule->needed = GTK_FILE_FILTER_DISPLAY_NAME;
254   rule->u.pattern = g_strdup (pattern);
255
256   file_filter_add_rule (filter, rule);
257 }
258
259 /**
260  * gtk_file_filter_add_pixbuf_formats:
261  * @filter: a #GtkFileFilter
262  * 
263  * Adds a rule allowing image files in the formats supported
264  * by GdkPixbuf.
265  * 
266  * Since: 2.6
267  **/
268 void
269 gtk_file_filter_add_pixbuf_formats (GtkFileFilter *filter)
270 {
271   FilterRule *rule;
272   
273   g_return_if_fail (GTK_IS_FILE_FILTER (filter));
274
275   rule = g_slice_new (FilterRule);
276   rule->type = FILTER_RULE_PIXBUF_FORMATS;
277   rule->needed = GTK_FILE_FILTER_MIME_TYPE;
278   rule->u.pixbuf_formats = gdk_pixbuf_get_formats ();
279   file_filter_add_rule (filter, rule);
280 }
281
282
283 /**
284  * gtk_file_filter_add_custom:
285  * @filter: a #GtkFileFilter
286  * @needed: bitfield of flags indicating the information that the custom
287  *          filter function needs.
288  * @func: callback function; if the function returns %TRUE, then
289  *   the file will be displayed.
290  * @data: data to pass to @func
291  * @notify: function to call to free @data when it is no longer needed.
292  * 
293  * Adds rule to a filter that allows files based on a custom callback
294  * function. The bitfield @needed which is passed in provides information
295  * about what sorts of information that the filter function needs;
296  * this allows GTK+ to avoid retrieving expensive information when
297  * it isn't needed by the filter.
298  * 
299  * Since: 2.4
300  **/
301 void
302 gtk_file_filter_add_custom (GtkFileFilter         *filter,
303                             GtkFileFilterFlags     needed,
304                             GtkFileFilterFunc      func,
305                             gpointer               data,
306                             GDestroyNotify         notify)
307 {
308   FilterRule *rule;
309   
310   g_return_if_fail (GTK_IS_FILE_FILTER (filter));
311   g_return_if_fail (func != NULL);
312
313   rule = g_slice_new (FilterRule);
314   rule->type = FILTER_RULE_CUSTOM;
315   rule->needed = needed;
316   rule->u.custom.func = func;
317   rule->u.custom.data = data;
318   rule->u.custom.notify = notify;
319
320   file_filter_add_rule (filter, rule);
321 }
322
323 /**
324  * gtk_file_filter_get_needed:
325  * @filter: a #GtkFileFilter
326  * 
327  * Gets the fields that need to be filled in for the structure
328  * passed to gtk_file_filter_filter()
329  * 
330  * This function will not typically be used by applications; it
331  * is intended principally for use in the implementation of
332  * #GtkFileChooser.
333  * 
334  * Return value: bitfield of flags indicating needed fields when
335  *   calling gtk_file_filter_filter()
336  * 
337  * Since: 2.4
338  **/
339 GtkFileFilterFlags
340 gtk_file_filter_get_needed (GtkFileFilter *filter)
341 {
342   return filter->needed;
343 }
344
345 /**
346  * gtk_file_filter_filter:
347  * @filter: a #GtkFileFilter
348  * @filter_info: a #GtkFileFilterInfo structure containing information
349  *  about a file.
350  * 
351  * Tests whether a file should be displayed according to @filter.
352  * The #GtkFileFilterInfo structure @filter_info should include
353  * the fields returned from gtk_file_filter_get_needed().
354  *
355  * This function will not typically be used by applications; it
356  * is intended principally for use in the implementation of
357  * #GtkFileChooser.
358  * 
359  * Return value: %TRUE if the file should be displayed
360  * 
361  * Since: 2.4
362  **/
363 gboolean
364 gtk_file_filter_filter (GtkFileFilter           *filter,
365                         const GtkFileFilterInfo *filter_info)
366 {
367   GSList *tmp_list;
368
369   for (tmp_list = filter->rules; tmp_list; tmp_list = tmp_list->next)
370     {
371       FilterRule *rule = tmp_list->data;
372
373       if ((filter_info->contains & rule->needed) != rule->needed)
374         continue;
375       
376       switch (rule->type)
377         {
378         case FILTER_RULE_MIME_TYPE:
379           if (filter_info->mime_type != NULL &&
380               g_content_type_is_a (filter_info->mime_type, rule->u.mime_type))
381             return TRUE;
382           break;
383         case FILTER_RULE_PATTERN:
384           if (filter_info->display_name != NULL &&
385               _gtk_fnmatch (rule->u.pattern, filter_info->display_name, FALSE))
386             return TRUE;
387           break;
388         case FILTER_RULE_PIXBUF_FORMATS:
389           {
390             GSList *list;
391
392             if (!filter_info->mime_type)
393               break;
394
395             for (list = rule->u.pixbuf_formats; list; list = list->next)
396               {
397                 int i;
398                 gchar **mime_types;
399
400                 mime_types = gdk_pixbuf_format_get_mime_types (list->data);
401
402                 for (i = 0; mime_types[i] != NULL; i++)
403                   {
404                     if (strcmp (mime_types[i], filter_info->mime_type) == 0)
405                       {
406                         g_strfreev (mime_types);
407                         return TRUE;
408                       }
409                   }
410
411                 g_strfreev (mime_types);
412               }
413             break;
414           }
415         case FILTER_RULE_CUSTOM:
416           if (rule->u.custom.func (filter_info, rule->u.custom.data))
417             return TRUE;
418           break;
419         }
420     }
421
422   return FALSE;
423 }
424
425 #define __GTK_FILE_FILTER_C__
426 #include "gtkaliasdef.c"