]> Pileus Git - ~andy/gtk/blob - gtk/gtkfilesystem.c
c4bbbdefb8cf6c89d93bfac9e2ca8205b84d58af
[~andy/gtk] / gtk / gtkfilesystem.c
1 /* GTK - The GIMP Toolkit
2  * gtkfilesystem.c: Abstract file system interfaces
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 <gmodule.h>
23 #include "gtkfilesystem.h"
24 #include "gtkicontheme.h"
25 #include "gtkmodules.h"
26 #include "gtkintl.h"
27 #include "gtkstock.h"
28 #include "gtkalias.h"
29
30 #include <string.h>
31
32 struct _GtkFileInfo
33 {
34   GtkFileTime modification_time;
35   gint64 size;
36   gchar *display_name;
37   gchar *display_key;
38   gchar *mime_type;
39   gchar *icon_name;
40   guint is_folder : 1;
41   guint is_hidden : 1;
42 };
43
44 static void gtk_file_system_base_init (gpointer g_class);
45 static void gtk_file_folder_base_init (gpointer g_class);
46
47 GQuark
48 gtk_file_system_error_quark (void)
49 {
50   return g_quark_from_static_string ("gtk-file-system-error-quark");
51 }
52
53 /*****************************************
54  *             GtkFileInfo               *
55  *****************************************/
56 GType
57 gtk_file_info_get_type (void)
58 {
59   static GType our_type = 0;
60   
61   if (our_type == 0)
62     our_type = g_boxed_type_register_static (I_("GtkFileInfo"),
63                                              (GBoxedCopyFunc) gtk_file_info_copy,
64                                              (GBoxedFreeFunc) gtk_file_info_free);
65
66   return our_type;
67 }
68
69 GtkFileInfo *
70 gtk_file_info_new  (void)
71 {
72   GtkFileInfo *info;
73   
74   info = g_new0 (GtkFileInfo, 1);
75
76   return info;
77 }
78
79 GtkFileInfo *
80 gtk_file_info_copy (GtkFileInfo *info)
81 {
82   GtkFileInfo *new_info;
83
84   g_return_val_if_fail (info != NULL, NULL);
85
86   new_info = g_memdup (info, sizeof (GtkFileInfo));
87   if (new_info->display_name)
88     new_info->display_name = g_strdup (new_info->display_name);
89   if (new_info->display_key)
90     new_info->display_key = g_strdup (new_info->display_key);
91   if (new_info->mime_type)
92     new_info->mime_type = g_strdup (new_info->mime_type);
93   if (new_info->icon_name)
94     new_info->icon_name = g_strdup (new_info->icon_name);
95   if (new_info->display_key)
96     new_info->display_key = g_strdup (new_info->display_key);
97
98   return new_info;
99 }
100
101 void
102 gtk_file_info_free (GtkFileInfo *info)
103 {
104   g_return_if_fail (info != NULL);
105
106   g_free (info->display_name);
107   g_free (info->mime_type);
108   g_free (info->display_key);
109   g_free (info->icon_name);
110
111   g_free (info);
112 }
113
114 G_CONST_RETURN gchar *
115 gtk_file_info_get_display_name (const GtkFileInfo *info)
116 {
117   g_return_val_if_fail (info != NULL, NULL);
118   
119   return info->display_name;
120 }
121
122 /**
123  * gtk_file_info_get_display_key:
124  * @info: a #GtkFileInfo
125  * 
126  * Returns for the collation key for the display name for @info. 
127  * This is useful when sorting a bunch of #GtkFileInfo structures 
128  * since the collate key will be only computed once.
129  * 
130  * Return value: The collate key for the display name, or %NULL
131  *   if the display name hasn't been set.
132  **/
133 G_CONST_RETURN gchar *
134 gtk_file_info_get_display_key (const GtkFileInfo *info)
135 {
136   g_return_val_if_fail (info != NULL, NULL);
137
138   if (!info->display_key && info->display_name)
139     {
140       /* Since info->display_key is only a cache, we cast off the const
141        */
142       ((GtkFileInfo *)info)->display_key = g_utf8_collate_key_for_filename (info->display_name, -1);
143     }
144         
145   return info->display_key;
146 }
147
148 void
149 gtk_file_info_set_display_name (GtkFileInfo *info,
150                                 const gchar *display_name)
151 {
152   g_return_if_fail (info != NULL);
153
154   if (display_name == info->display_name)
155     return;
156
157   g_free (info->display_name);
158   if (info->display_key)
159     {
160       g_free (info->display_key);
161       info->display_key = NULL;
162     }
163
164   info->display_name = g_strdup (display_name);
165 }
166
167 gboolean
168 gtk_file_info_get_is_folder (const GtkFileInfo *info)
169 {
170   g_return_val_if_fail (info != NULL, FALSE);
171   
172   return info->is_folder;
173 }
174
175 void
176 gtk_file_info_set_is_folder (GtkFileInfo *info,
177                              gboolean     is_folder)
178 {
179   g_return_if_fail (info != NULL);
180
181   info->is_folder = is_folder != FALSE;
182 }
183
184 gboolean
185 gtk_file_info_get_is_hidden (const GtkFileInfo *info)
186 {
187   g_return_val_if_fail (info != NULL, FALSE);
188   
189   return info->is_hidden;
190 }
191
192 void
193 gtk_file_info_set_is_hidden (GtkFileInfo *info,
194                              gboolean     is_hidden)
195 {
196   g_return_if_fail (info != NULL);
197
198   info->is_hidden = is_hidden != FALSE;
199 }
200
201 G_CONST_RETURN gchar *
202 gtk_file_info_get_mime_type (const GtkFileInfo *info)
203 {
204   g_return_val_if_fail (info != NULL, NULL);
205   
206   return info->mime_type;
207 }
208
209 void
210 gtk_file_info_set_mime_type (GtkFileInfo *info,
211                              const gchar *mime_type)
212 {
213   g_return_if_fail (info != NULL);
214   
215   g_free (info->mime_type);
216
217   info->mime_type = g_strdup (mime_type);
218 }
219
220 GtkFileTime
221 gtk_file_info_get_modification_time (const GtkFileInfo *info)
222 {
223   g_return_val_if_fail (info != NULL, 0);
224
225   return info->modification_time;
226 }
227
228 void
229 gtk_file_info_set_modification_time (GtkFileInfo *info,
230                                      GtkFileTime  modification_time)
231 {
232   g_return_if_fail (info != NULL);
233   
234   info->modification_time = modification_time;
235 }
236
237 gint64
238 gtk_file_info_get_size (const GtkFileInfo *info)
239 {
240   g_return_val_if_fail (info != NULL, 0);
241   
242   return info->size;
243 }
244
245 void
246 gtk_file_info_set_size (GtkFileInfo *info,
247                         gint64       size)
248 {
249   g_return_if_fail (info != NULL);
250   g_return_if_fail (size >= 0);
251   
252   info->size = size;
253 }
254
255 void
256 gtk_file_info_set_icon_name (GtkFileInfo *info,
257                              const gchar *icon_name)
258 {
259   g_return_if_fail (info != NULL);
260   
261   g_free (info->icon_name);
262
263   info->icon_name = g_strdup (icon_name);
264 }
265
266 G_CONST_RETURN gchar *
267 gtk_file_info_get_icon_name (const GtkFileInfo *info)
268 {
269   g_return_val_if_fail (info != NULL, NULL);
270   
271   return info->icon_name;
272 }
273
274 GdkPixbuf *
275 gtk_file_info_render_icon (const GtkFileInfo  *info,
276                            GtkWidget          *widget,
277                            gint                pixel_size,
278                            GError            **error)
279 {
280   GdkPixbuf *pixbuf = NULL;
281
282   g_return_val_if_fail (info != NULL, NULL);
283   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
284
285   if (info->icon_name)
286     {
287       if (g_path_is_absolute (info->icon_name))
288         pixbuf = gdk_pixbuf_new_from_file_at_size (info->icon_name,
289                                                    pixel_size,
290                                                    pixel_size,
291                                                    NULL);
292       else
293         {
294           GtkIconTheme *icon_theme;
295
296           icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
297           if (gtk_icon_theme_has_icon (icon_theme, info->icon_name))
298             pixbuf = gtk_icon_theme_load_icon (icon_theme, info->icon_name,
299                                                pixel_size, 0, NULL);
300         }
301     }
302
303   if (!pixbuf)
304     {
305       /* load a fallback icon */
306       pixbuf = gtk_widget_render_icon (widget,
307                                        gtk_file_info_get_is_folder (info)
308                                         ? GTK_STOCK_DIRECTORY : GTK_STOCK_FILE,
309                                        GTK_ICON_SIZE_SMALL_TOOLBAR,
310                                        NULL);
311       if (!pixbuf && error)
312         g_set_error (error,
313                      GTK_FILE_SYSTEM_ERROR,
314                      GTK_FILE_SYSTEM_ERROR_FAILED,
315                      _("Could not get a stock icon for %s\n"),
316                      info->icon_name);
317     }
318
319   return pixbuf;
320 }
321
322 /*****************************************
323  *          GtkFileSystemHandle          *
324  *****************************************/
325
326 enum
327 {
328   PROP_0,
329   PROP_CANCELLED
330 };
331
332 G_DEFINE_TYPE (GtkFileSystemHandle, gtk_file_system_handle, G_TYPE_OBJECT)
333
334 static void
335 gtk_file_system_handle_init (GtkFileSystemHandle *handle)
336 {
337   handle->file_system = NULL;
338   handle->cancelled = FALSE;
339 }
340
341 static void
342 gtk_file_system_handle_set_property (GObject      *object,
343                                      guint         prop_id,
344                                      const GValue *value,
345                                      GParamSpec   *pspec)
346 {
347   G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
348 }
349
350 static void
351 gtk_file_system_handle_get_property (GObject    *object,
352                                      guint       prop_id,
353                                      GValue     *value,
354                                      GParamSpec *pspec)
355 {
356   GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (object);
357
358   switch (prop_id)
359     {
360       case PROP_CANCELLED:
361         g_value_set_boolean (value, handle->cancelled);
362         break;
363
364       default:
365         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
366         break;
367     }
368 }
369
370 static void
371 gtk_file_system_handle_class_init (GtkFileSystemHandleClass *klass)
372 {
373   GObjectClass *o_class;
374
375   o_class = (GObjectClass *)klass;
376   o_class->set_property = gtk_file_system_handle_set_property;
377   o_class->get_property = gtk_file_system_handle_get_property;
378
379   g_object_class_install_property (o_class,
380                                    PROP_CANCELLED,
381                                    g_param_spec_boolean ("cancelled",
382                                                          P_("Cancelled"),
383                                                          P_("Whether or not the operation has been successfully cancelled"),
384                                                          FALSE,
385                                                          G_PARAM_READABLE));
386 }
387
388 /*****************************************
389  *             GtkFileSystem             *
390  *****************************************/
391 GType
392 gtk_file_system_get_type (void)
393 {
394   static GType file_system_type = 0;
395
396   if (!file_system_type)
397     {
398       const GTypeInfo file_system_info =
399       {
400         sizeof (GtkFileSystemIface),  /* class_size */
401         gtk_file_system_base_init,    /* base_init */
402         NULL,                         /* base_finalize */
403       };
404
405       file_system_type = g_type_register_static (G_TYPE_INTERFACE,
406                                                  I_("GtkFileSystem"),
407                                                  &file_system_info, 0);
408
409       g_type_interface_add_prerequisite (file_system_type, G_TYPE_OBJECT);
410     }
411
412   return file_system_type;
413 }
414
415 static void
416 gtk_file_system_base_init (gpointer g_class)
417 {
418   static gboolean initialized = FALSE;
419   
420   if (!initialized)
421     {
422       GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
423
424       g_signal_new (I_("volumes-changed"),
425                     iface_type,
426                     G_SIGNAL_RUN_LAST,
427                     G_STRUCT_OFFSET (GtkFileSystemIface, volumes_changed),
428                     NULL, NULL,
429                     g_cclosure_marshal_VOID__VOID,
430                     G_TYPE_NONE, 0);
431       g_signal_new (I_("bookmarks-changed"),
432                     iface_type,
433                     G_SIGNAL_RUN_LAST,
434                     G_STRUCT_OFFSET (GtkFileSystemIface, bookmarks_changed),
435                     NULL, NULL,
436                     g_cclosure_marshal_VOID__VOID,
437                     G_TYPE_NONE, 0);
438
439       initialized = TRUE;
440     }
441 }
442
443 GSList *
444 gtk_file_system_list_volumes (GtkFileSystem  *file_system)
445 {
446   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
447
448   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_volumes (file_system);
449 }
450
451 GtkFileSystemHandle *
452 gtk_file_system_get_folder (GtkFileSystem                  *file_system,
453                             const GtkFilePath              *path,
454                             GtkFileInfoType                 types,
455                             GtkFileSystemGetFolderCallback  callback,
456                             gpointer                        data)
457 {
458   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
459   g_return_val_if_fail (path != NULL, NULL);
460   g_return_val_if_fail (callback != NULL, NULL);
461
462   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_folder (file_system, path, types, callback, data);
463 }
464
465 GtkFileSystemHandle *
466 gtk_file_system_get_info (GtkFileSystem *file_system,
467                           const GtkFilePath *path,
468                           GtkFileInfoType types,
469                           GtkFileSystemGetInfoCallback callback,
470                           gpointer data)
471 {
472   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
473   g_return_val_if_fail (path != NULL, NULL);
474   g_return_val_if_fail (callback != NULL, NULL);
475
476   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_info (file_system, path, types, callback, data);
477 }
478
479 GtkFileSystemHandle *
480 gtk_file_system_create_folder (GtkFileSystem                     *file_system,
481                                const GtkFilePath                 *path,
482                                GtkFileSystemCreateFolderCallback  callback,
483                                gpointer                           data)
484 {
485   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
486   g_return_val_if_fail (path != NULL, NULL);
487   g_return_val_if_fail (callback != NULL, NULL);
488
489   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->create_folder (file_system, path, callback, data);
490 }
491
492 void
493 gtk_file_system_cancel_operation (GtkFileSystemHandle *handle)
494 {
495   g_return_if_fail (GTK_IS_FILE_SYSTEM_HANDLE (handle));
496
497   GTK_FILE_SYSTEM_GET_IFACE (handle->file_system)->cancel_operation (handle);
498 }
499
500 /**
501  * gtk_file_system_get_volume_for_path:
502  * @file_system: a #GtkFileSystem
503  * @path: a #GtkFilePath
504  * 
505  * Queries the file system volume that corresponds to a specific path.
506  * There might not be a volume for all paths (consinder for instance remote
507  * shared), so this can return NULL.
508  * 
509  * Return value: the #GtkFileSystemVolume that corresponds to the specified
510  * @path, or NULL if there is no such volume. You should free this value with
511  * gtk_file_system_volume_free().
512  **/
513 GtkFileSystemVolume *
514 gtk_file_system_get_volume_for_path (GtkFileSystem     *file_system,
515                                      const GtkFilePath *path)
516 {
517   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
518   g_return_val_if_fail (path != NULL, NULL);
519
520   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_volume_for_path (file_system, path);
521 }
522
523 /**
524  * gtk_file_system_volume_free:
525  * @file_system: a #GtkFileSystem
526  * @volume: a #GtkFileSystemVolume
527  * 
528  * Frees a #GtkFileSystemVolume structure as returned by
529  * gtk_file_system_list_volumes().
530  **/
531 void
532 gtk_file_system_volume_free (GtkFileSystem       *file_system,
533                              GtkFileSystemVolume *volume)
534 {
535   g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system));
536   g_return_if_fail (volume != NULL);
537
538   GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_free (file_system, volume);
539 }
540
541 /**
542  * gtk_file_system_volume_get_base_path:
543  * @file_system: a #GtkFileSystem
544  * @volume: a #GtkFileSystemVolume
545  * 
546  * Queries the base path for a volume.  For example, a CD-ROM device may yield a
547  * path of "/mnt/cdrom".
548  * 
549  * Return value: a #GtkFilePath with the base mount path of the specified
550  * @volume.
551  **/
552 GtkFilePath *
553 gtk_file_system_volume_get_base_path (GtkFileSystem       *file_system,
554                                       GtkFileSystemVolume *volume)
555 {
556   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
557   g_return_val_if_fail (volume != NULL, NULL);
558
559   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_base_path (file_system, volume);
560 }
561
562 /**
563  * gtk_file_system_volume_get_is_mounted:
564  * @file_system: a #GtkFileSystem
565  * @volume: a #GtkFileSystemVolume
566  * 
567  * Queries whether a #GtkFileSystemVolume is mounted or not.  If it is not, it
568  * can be mounted with gtk_file_system_volume_mount().
569  * 
570  * Return value: TRUE if the @volume is mounted, FALSE otherwise.
571  **/
572 gboolean
573 gtk_file_system_volume_get_is_mounted (GtkFileSystem       *file_system,
574                                        GtkFileSystemVolume *volume)
575 {
576   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
577   g_return_val_if_fail (volume != NULL, FALSE);
578
579   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_is_mounted (file_system, volume);
580 }
581
582 /**
583  * gtk_file_system_volume_mount:
584  * @file_system: a #GtkFileSystem
585  * @volume: a #GtkFileSystemVolume
586  * @error: location to store error, or %NULL
587  * 
588  * Tries to mount an unmounted volume.  This may cause the "volumes-changed"
589  * signal in the @file_system to be emitted.
590  * 
591  * Return value: TRUE if the @volume was mounted successfully, FALSE otherwise.
592  **/
593 /* FIXME XXX: update documentation above */
594 GtkFileSystemHandle *
595 gtk_file_system_volume_mount (GtkFileSystem                    *file_system,
596                               GtkFileSystemVolume              *volume,
597                               GtkFileSystemVolumeMountCallback  callback,
598                               gpointer                          data)
599 {
600   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
601   g_return_val_if_fail (volume != NULL, NULL);
602   g_return_val_if_fail (callback != NULL, NULL);
603
604   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_mount (file_system, volume, callback, data);
605 }
606
607 /**
608  * gtk_file_system_volume_get_display_name:
609  * @file_system: a #GtkFileSystem
610  * @volume: a #GtkFileSystemVolume
611  * 
612  * Queries the human-readable name for a @volume.  This string can be displayed
613  * in a list of volumes that can be accessed, for example.
614  * 
615  * Return value: A string with the human-readable name for a #GtkFileSystemVolume.
616  **/
617 char *
618 gtk_file_system_volume_get_display_name (GtkFileSystem        *file_system, 
619                                          GtkFileSystemVolume  *volume)
620 {
621   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
622   g_return_val_if_fail (volume != NULL, NULL);
623
624   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_display_name (file_system, volume);
625 }
626
627 /**
628  * gtk_file_system_volume_render_icon:
629  * @file_system: a #GtkFileSystem
630  * @volume: a #GtkFileSystemVolume
631  * @widget: Reference widget to render icons.
632  * @pixel_size: Size of the icon.
633  * @error: location to store error, or %NULL
634  * 
635  * Renders an icon suitable for a file #GtkFileSystemVolume.
636  * 
637  * Return value: A #GdkPixbuf containing an icon, or NULL if the icon could not
638  * be rendered.  In the latter case, the @error value will be set as
639  * appropriate.
640  **/
641 GdkPixbuf *
642 gtk_file_system_volume_render_icon (GtkFileSystem        *file_system,
643                                     GtkFileSystemVolume  *volume,
644                                     GtkWidget            *widget,
645                                     gint                  pixel_size,
646                                     GError              **error)
647 {
648   gchar *icon_name;
649   GdkPixbuf *pixbuf = NULL;
650
651   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
652   g_return_val_if_fail (volume != NULL, NULL);
653   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
654   g_return_val_if_fail (pixel_size > 0, NULL);
655   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
656
657   icon_name = gtk_file_system_volume_get_icon_name (file_system, volume,
658                                                     error);
659   if (icon_name)
660     {
661       GtkIconTheme *icon_theme;
662
663       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
664       if (gtk_icon_theme_has_icon (icon_theme, icon_name))
665         pixbuf = gtk_icon_theme_load_icon (icon_theme,
666                                            icon_name, pixel_size, 0, NULL);
667       g_free (icon_name);
668     }
669
670   if (!pixbuf)
671     pixbuf = gtk_widget_render_icon (widget,
672                                      GTK_STOCK_HARDDISK,
673                                      GTK_ICON_SIZE_SMALL_TOOLBAR,
674                                      NULL);
675
676   return pixbuf;
677 }
678
679 /**
680  * gtk_file_system_volume_get_icon_name:
681  * @file_system: a #GtkFileSystem
682  * @volume: a #GtkFileSystemVolume
683  * @error: location to store error, or %NULL
684  * 
685  * Gets an icon name suitable for a #GtkFileSystemVolume.
686  * 
687  * Return value: An icon name which can be used for rendering an icon for
688  * this volume, or %NULL if no icon name could be found.  In the latter
689  * case, the @error value will be set as appropriate.
690  **/
691 gchar *
692 gtk_file_system_volume_get_icon_name (GtkFileSystem        *file_system,
693                                       GtkFileSystemVolume  *volume,
694                                       GError              **error)
695 {
696   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
697   g_return_val_if_fail (volume != NULL, NULL);
698   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
699
700   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_icon_name (file_system,
701                                                                         volume,
702                                                                         error);
703 }
704
705 /**
706  * gtk_file_system_get_parent:
707  * @file_system: a #GtkFileSystem
708  * @path: base path name
709  * @parent: location to store parent path name
710  * @error: location to store error, or %NULL
711  * 
712  * Gets the name of the parent folder of a path.  If the path has no parent, as when
713  * you request the parent of a file system root, then @parent will be set to %NULL.
714  * 
715  * Return value: %TRUE if the operation was successful:  @parent will be set to
716  * the name of the @path's parent, or to %NULL if @path is already a file system
717  * root.  If the operation fails, this function returns %FALSE, sets @parent to
718  * NULL, and sets the @error value if it is specified.
719  **/
720 gboolean
721 gtk_file_system_get_parent (GtkFileSystem     *file_system,
722                             const GtkFilePath *path,
723                             GtkFilePath      **parent,
724                             GError           **error)
725 {
726   gboolean result;
727   
728   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
729   g_return_val_if_fail (path != NULL, FALSE);
730   g_return_val_if_fail (parent != NULL, FALSE);
731   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
732
733   *parent = NULL;
734
735   result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_parent (file_system, path, parent, error);
736   g_assert (result || *parent == NULL);
737
738   return result;
739 }
740
741 GtkFilePath *
742 gtk_file_system_make_path (GtkFileSystem    *file_system,
743                           const GtkFilePath *base_path,
744                           const gchar       *display_name,
745                           GError           **error)
746 {
747   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
748   g_return_val_if_fail (base_path != NULL, NULL);
749   g_return_val_if_fail (display_name != NULL, NULL);
750   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
751
752   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->make_path (file_system, base_path, display_name, error);
753 }
754
755 /**
756  * gtk_file_system_parse:
757  * @file_system: a #GtkFileSystem
758  * @base_path: reference folder with respect to which relative
759  *            paths should be interpreted.
760  * @str: the string to parse
761  * @folder: location to store folder portion of result, or %NULL
762  * @file_part: location to store file portion of result, or %NULL
763  * @error: location to store error, or %NULL
764  * 
765  * Given a string entered by a user, parse it (possibly using
766  * heuristics) into a folder path and a UTF-8 encoded
767  * filename part. (Suitable for passing to gtk_file_system_make_path())
768  *
769  * Note that the returned filename point may point to a subfolder
770  * of the returned folder. Adding a trailing path separator is needed
771  * to enforce the interpretation as a folder name.
772  *
773  * If parsing fails because the syntax of @str is not understood,
774  * and error of type GTK_FILE_SYSTEM_ERROR_BAD_FILENAME will
775  * be set in @error and %FALSE returned.
776  *
777  * If parsing fails because a path was encountered that doesn't
778  * exist on the filesystem, then an error of type
779  * %GTK_FILE_SYSTEM_ERROR_NONEXISTENT will be set in @error
780  * and %FALSE returned. (This only applies to parsing relative paths,
781  * not to interpretation of @file_part. No check is made as
782  * to whether @file_part exists.)
783  *
784  * Return value: %TRUE if the parsing succeeds, otherwise, %FALSE.
785  **/
786 gboolean
787 gtk_file_system_parse (GtkFileSystem     *file_system,
788                        const GtkFilePath *base_path,
789                        const gchar       *str,
790                        GtkFilePath      **folder,
791                        gchar            **file_part,
792                        GError           **error)
793 {
794   GtkFilePath *tmp_folder = NULL;
795   gchar *tmp_file_part = NULL;
796   gboolean result;
797
798   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
799   g_return_val_if_fail (base_path != NULL, FALSE);
800   g_return_val_if_fail (str != NULL, FALSE);
801   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
802
803   result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->parse (file_system, base_path, str,
804                                                            &tmp_folder, &tmp_file_part,
805                                                            error);
806   g_assert (result || (tmp_folder == NULL && tmp_file_part == NULL));
807
808   if (folder)
809     *folder = tmp_folder;
810   else
811     gtk_file_path_free (tmp_folder);
812
813   if (file_part)
814     *file_part = tmp_file_part;
815   else
816     g_free (tmp_file_part);
817
818   return result;
819 }
820
821
822 gchar *
823 gtk_file_system_path_to_uri (GtkFileSystem     *file_system,
824                              const GtkFilePath *path)
825 {
826   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
827   g_return_val_if_fail (path != NULL, NULL);
828   
829   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_uri (file_system, path);
830 }
831
832 gchar *
833 gtk_file_system_path_to_filename (GtkFileSystem     *file_system,
834                                   const GtkFilePath *path)
835 {
836   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
837   g_return_val_if_fail (path != NULL, NULL);
838   
839   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_filename (file_system, path);
840 }
841
842 GtkFilePath *
843 gtk_file_system_uri_to_path (GtkFileSystem *file_system,
844                              const gchar    *uri)
845 {
846   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
847   g_return_val_if_fail (uri != NULL, NULL);
848   
849   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->uri_to_path (file_system, uri);
850 }
851
852 GtkFilePath *
853 gtk_file_system_filename_to_path (GtkFileSystem *file_system,
854                                   const gchar   *filename)
855 {
856   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
857   g_return_val_if_fail (filename != NULL, NULL);
858
859   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->filename_to_path (file_system, filename);
860 }
861
862 /**
863  * gtk_file_system_path_is_local:
864  * @filesystem: a #GtkFileSystem
865  * @path: A #GtkFilePath from that filesystem
866  * 
867  * Checks whether a #GtkFilePath is local; that is whether
868  * gtk_file_system_path_to_filename would return non-%NULL.
869  * 
870  * Return value: %TRUE if the path is loca
871  **/
872 gboolean
873 gtk_file_system_path_is_local (GtkFileSystem     *file_system,
874                                const GtkFilePath *path)
875 {
876   gchar *filename;
877   gboolean result;
878     
879   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
880   g_return_val_if_fail (path != NULL, FALSE);
881
882   filename = gtk_file_system_path_to_filename (file_system, path);
883   result = filename != NULL;
884   g_free (filename);
885
886   return result;
887 }
888
889 /**
890  * gtk_file_system_insert_bookmark:
891  * @file_system: a #GtkFileSystem
892  * @path: path of the bookmark to add
893  * @position: index in the bookmarks list at which the @path should be inserted; use 0
894  * for the beginning, and -1 or the number of bookmarks itself for the end of the list.
895  * @error: location to store error, or %NULL
896  * 
897  * Adds a path for a folder to the user's bookmarks list.  If the operation
898  * succeeds, the "bookmarks_changed" signal will be emitted.  Bookmark paths are
899  * unique; if you try to insert a @path that already exists, the operation will
900  * fail and the @error will be set to #GTK_FILE_SYSTEM_ERROR_ALREADY_EXISTS.  To
901  * reorder the list of bookmarks, use gtk_file_system_remove_bookmark() to
902  * remove the path in question, and call gtk_file_system_insert_bookmark() with
903  * the new position for the path.
904  * 
905  * Return value: TRUE if the operation succeeds, FALSE otherwise.  In the latter case,
906  * the @error value will be set.
907  **/
908 gboolean
909 gtk_file_system_insert_bookmark (GtkFileSystem     *file_system,
910                                  const GtkFilePath *path,
911                                  gint               position,
912                                  GError           **error)
913 {
914   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
915   g_return_val_if_fail (path != NULL, FALSE);
916
917   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->insert_bookmark (file_system, path, position, error);
918 }
919
920 /**
921  * gtk_file_system_remove_bookmark:
922  * @file_system: a #GtkFileSystem
923  * @path: path of the bookmark to remove
924  * @error: location to store error, or %NULL
925  * 
926  * Removes a bookmark folder from the user's bookmarks list.  If the operation
927  * succeeds, the "bookmarks_changed" signal will be emitted.  If you try to remove
928  * a @path which does not exist in the bookmarks list, the operation will fail
929  * and the @error will be set to GTK_FILE_SYSTEM_ERROR_NONEXISTENT.
930  * 
931  * Return value: TRUE if the operation succeeds, FALSE otherwise.  In the latter
932  * case, the @error value will be set.
933  **/
934 gboolean
935 gtk_file_system_remove_bookmark (GtkFileSystem     *file_system,
936                                  const GtkFilePath *path,
937                                  GError           **error)
938 {
939   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
940   g_return_val_if_fail (path != NULL, FALSE);
941
942   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->remove_bookmark (file_system, path, error);
943 }
944
945 /**
946  * gtk_file_system_list_bookmarks:
947  * @file_system: a #GtkFileSystem
948  * 
949  * Queries the list of bookmarks in the file system.
950  * 
951  * Return value: A list of #GtkFilePath, or NULL if there are no configured
952  * bookmarks.  You should use gtk_file_paths_free() to free this list.
953  *
954  * See also: gtk_file_system_get_supports_bookmarks()
955  **/
956 GSList *
957 gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
958 {
959   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
960
961   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_bookmarks (file_system);
962 }
963
964 /**
965  * gtk_file_system_get_bookmark_label:
966  * @file_system: a #GtkFileSystem
967  * @path: path of the bookmark 
968  *
969  * Gets the label to display for a bookmark, or %NULL.
970  *
971  * Returns: the label for the bookmark @path
972  *
973  * Since: 2.8
974  */
975 gchar *
976 gtk_file_system_get_bookmark_label (GtkFileSystem     *file_system,
977                                     const GtkFilePath *path)
978 {
979   GtkFileSystemIface *iface;
980
981   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
982   g_return_val_if_fail (path != NULL, NULL);
983
984   iface = GTK_FILE_SYSTEM_GET_IFACE (file_system);
985   if (iface->get_bookmark_label)
986     return iface->get_bookmark_label (file_system, path);
987
988   return NULL;
989 }
990
991 /**
992  * gtk_file_system_set_bookmark_label:
993  * @file_system: a #GtkFileSystem
994  * @path: path of the bookmark 
995  * @label: the label for the bookmark, or %NULL to display
996  *   the path itself
997  *
998  * Sets the label to display for a bookmark.
999  *
1000  * Since: 2.8
1001  */
1002 void
1003 gtk_file_system_set_bookmark_label (GtkFileSystem     *file_system,
1004                                     const GtkFilePath *path,
1005                                     const gchar       *label)
1006 {
1007   GtkFileSystemIface *iface;
1008
1009   g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system));
1010   g_return_if_fail (path != NULL);
1011
1012   iface = GTK_FILE_SYSTEM_GET_IFACE (file_system);
1013   if (iface->set_bookmark_label)
1014     iface->set_bookmark_label (file_system, path, label);
1015 }
1016
1017 /*****************************************
1018  *             GtkFileFolder             *
1019  *****************************************/
1020 GType
1021 gtk_file_folder_get_type (void)
1022 {
1023   static GType file_folder_type = 0;
1024
1025   if (!file_folder_type)
1026     {
1027       const GTypeInfo file_folder_info =
1028       {
1029         sizeof (GtkFileFolderIface),  /* class_size */
1030         gtk_file_folder_base_init,    /* base_init */
1031         NULL,                         /* base_finalize */
1032       };
1033
1034       file_folder_type = g_type_register_static (G_TYPE_INTERFACE,
1035                                                  I_("GtkFileFolder"),
1036                                                  &file_folder_info, 0);
1037       
1038       g_type_interface_add_prerequisite (file_folder_type, G_TYPE_OBJECT);
1039     }
1040
1041   return file_folder_type;
1042 }
1043
1044 static void
1045 gtk_file_folder_base_init (gpointer g_class)
1046 {
1047   static gboolean initialized = FALSE;
1048   
1049   if (!initialized)
1050     {
1051       GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
1052
1053       g_signal_new (I_("deleted"),
1054                     iface_type,
1055                     G_SIGNAL_RUN_LAST,
1056                     G_STRUCT_OFFSET (GtkFileFolderIface, deleted),
1057                     NULL, NULL,
1058                     g_cclosure_marshal_VOID__VOID,
1059                     G_TYPE_NONE, 0);
1060       g_signal_new (I_("files-added"),
1061                     iface_type,
1062                     G_SIGNAL_RUN_LAST,
1063                     G_STRUCT_OFFSET (GtkFileFolderIface, files_added),
1064                     NULL, NULL,
1065                     g_cclosure_marshal_VOID__POINTER,
1066                     G_TYPE_NONE, 1,
1067                     G_TYPE_POINTER);
1068       g_signal_new (I_("files-changed"),
1069                     iface_type,
1070                     G_SIGNAL_RUN_LAST,
1071                     G_STRUCT_OFFSET (GtkFileFolderIface, files_changed),
1072                     NULL, NULL,
1073                     g_cclosure_marshal_VOID__POINTER,
1074                     G_TYPE_NONE, 1,
1075                     G_TYPE_POINTER);
1076       g_signal_new (I_("files-removed"),
1077                     iface_type,
1078                     G_SIGNAL_RUN_LAST,
1079                     G_STRUCT_OFFSET (GtkFileFolderIface, files_removed),
1080                     NULL, NULL,
1081                     g_cclosure_marshal_VOID__POINTER,
1082                     G_TYPE_NONE, 1,
1083                     G_TYPE_POINTER);
1084       g_signal_new (I_("finished-loading"),
1085                     iface_type,
1086                     G_SIGNAL_RUN_LAST,
1087                     G_STRUCT_OFFSET (GtkFileFolderIface, finished_loading),
1088                     NULL, NULL,
1089                     g_cclosure_marshal_VOID__VOID,
1090                     G_TYPE_NONE, 0);
1091
1092       initialized = TRUE;
1093     }
1094 }
1095
1096 gboolean
1097 gtk_file_folder_list_children (GtkFileFolder    *folder,
1098                                GSList          **children,
1099                                GError          **error)
1100 {
1101   gboolean result;
1102   GSList *tmp_children = NULL;
1103   
1104   g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), FALSE);
1105   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1106
1107   result = GTK_FILE_FOLDER_GET_IFACE (folder)->list_children (folder, &tmp_children, error);
1108   g_assert (result || tmp_children == NULL);
1109
1110   if (children)
1111     *children = tmp_children;
1112   else
1113     gtk_file_paths_free (tmp_children);
1114
1115   return result;
1116 }
1117
1118 GtkFileInfo *
1119 gtk_file_folder_get_info (GtkFileFolder     *folder,
1120                           const GtkFilePath *path,
1121                           GError           **error)
1122 {
1123   g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), NULL);
1124   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1125
1126   return GTK_FILE_FOLDER_GET_IFACE (folder)->get_info (folder, path, error);
1127 }
1128
1129 gboolean
1130 gtk_file_folder_is_finished_loading (GtkFileFolder *folder)
1131 {
1132   GtkFileFolderIface *iface;
1133
1134   g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), TRUE);
1135
1136   iface = GTK_FILE_FOLDER_GET_IFACE (folder);
1137   if (!iface->is_finished_loading)
1138     return TRUE;
1139   else
1140     return iface->is_finished_loading (folder);
1141 }
1142
1143
1144 /*****************************************
1145  *         GtkFilePath modules           *
1146  *****************************************/
1147
1148 /* We make these real functions in case either copy or free are implemented as macros
1149  */
1150 static gpointer
1151 gtk_file_path_real_copy (gpointer boxed)
1152 {
1153   return gtk_file_path_copy ((GtkFilePath *) boxed);
1154 }
1155
1156 static void
1157 gtk_file_path_real_free (gpointer boxed)
1158 {
1159   gtk_file_path_free (boxed);
1160 }
1161
1162 GType
1163 gtk_file_path_get_type (void)
1164 {
1165   static GType our_type = 0;
1166   
1167   if (our_type == 0)
1168     our_type = g_boxed_type_register_static (I_("GtkFilePath"),
1169                                              (GBoxedCopyFunc) gtk_file_path_real_copy,
1170                                              (GBoxedFreeFunc) gtk_file_path_real_free);
1171
1172   return our_type;
1173 }
1174
1175
1176 GSList *
1177 gtk_file_paths_sort (GSList *paths)
1178 {
1179 #ifndef G_OS_WIN32
1180   return g_slist_sort (paths, (GCompareFunc)strcmp);
1181 #else
1182   return g_slist_sort (paths, (GCompareFunc)_gtk_file_system_win32_path_compare);
1183 #endif
1184 }
1185
1186 /**
1187  * gtk_file_paths_copy:
1188  * @paths: A #GSList of #GtkFilePath structures.
1189  * 
1190  * Copies a list of #GtkFilePath structures.
1191  * 
1192  * Return value: A copy of @paths.  Since the contents of the list are copied as
1193  * well, you should use gtk_file_paths_free() to free the result.
1194  **/
1195 GSList *
1196 gtk_file_paths_copy (GSList *paths)
1197 {
1198   GSList *head, *tail, *l;
1199
1200   head = tail = NULL;
1201
1202   for (l = paths; l; l = l->next)
1203     {
1204       GtkFilePath *path;
1205       GSList *node;
1206
1207       path = l->data;
1208       node = g_slist_alloc ();
1209
1210       if (tail)
1211         tail->next = node;
1212       else
1213         head = node;
1214
1215       node->data = gtk_file_path_copy (path);
1216       tail = node;
1217     }
1218
1219   return head;
1220 }
1221
1222 void
1223 gtk_file_paths_free (GSList *paths)
1224 {
1225   GSList *tmp_list;
1226
1227   for (tmp_list = paths; tmp_list; tmp_list = tmp_list->next)
1228     gtk_file_path_free (tmp_list->data);
1229
1230   g_slist_free (paths);
1231 }
1232
1233 /*****************************************
1234  *         GtkFileSystem modules         *
1235  *****************************************/
1236
1237 typedef struct _GtkFileSystemModule GtkFileSystemModule;
1238 typedef struct _GtkFileSystemModuleClass GtkFileSystemModuleClass;
1239
1240 struct _GtkFileSystemModule
1241 {
1242   GTypeModule parent_instance;
1243   
1244   GModule *library;
1245
1246   void            (*init)     (GTypeModule    *module);
1247   void            (*exit)     (void);
1248   GtkFileSystem * (*create)   (void);
1249
1250   gchar *path;
1251 };
1252
1253 struct _GtkFileSystemModuleClass
1254 {
1255   GTypeModuleClass parent_class;
1256 };
1257
1258 G_DEFINE_TYPE (GtkFileSystemModule, _gtk_file_system_module, G_TYPE_TYPE_MODULE)
1259 #define GTK_TYPE_FILE_SYSTEM_MODULE       (_gtk_file_system_module_get_type ())
1260 #define GTK_FILE_SYSTEM_MODULE(module)    (G_TYPE_CHECK_INSTANCE_CAST ((module), GTK_TYPE_FILE_SYSTEM_MODULE, GtkFileSystemModule))
1261
1262
1263 static GSList *loaded_file_systems;
1264
1265 static gboolean
1266 gtk_file_system_module_load (GTypeModule *module)
1267 {
1268   GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module);
1269   
1270   fs_module->library = g_module_open (fs_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
1271   if (!fs_module->library)
1272     {
1273       g_warning (g_module_error());
1274       return FALSE;
1275     }
1276   
1277   /* extract symbols from the lib */
1278   if (!g_module_symbol (fs_module->library, "fs_module_init",
1279                         (gpointer *)&fs_module->init) ||
1280       !g_module_symbol (fs_module->library, "fs_module_exit", 
1281                         (gpointer *)&fs_module->exit) ||
1282       !g_module_symbol (fs_module->library, "fs_module_create", 
1283                         (gpointer *)&fs_module->create))
1284     {
1285       g_warning (g_module_error());
1286       g_module_close (fs_module->library);
1287       
1288       return FALSE;
1289     }
1290             
1291   /* call the filesystems's init function to let it */
1292   /* setup anything it needs to set up. */
1293   fs_module->init (module);
1294
1295   return TRUE;
1296 }
1297
1298 static void
1299 gtk_file_system_module_unload (GTypeModule *module)
1300 {
1301   GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module);
1302   
1303   fs_module->exit();
1304
1305   g_module_close (fs_module->library);
1306   fs_module->library = NULL;
1307
1308   fs_module->init = NULL;
1309   fs_module->exit = NULL;
1310   fs_module->create = NULL;
1311 }
1312
1313 /* This only will ever be called if an error occurs during
1314  * initialization
1315  */
1316 static void
1317 gtk_file_system_module_finalize (GObject *object)
1318 {
1319   GtkFileSystemModule *module = GTK_FILE_SYSTEM_MODULE (object);
1320
1321   g_free (module->path);
1322
1323   G_OBJECT_CLASS (_gtk_file_system_module_parent_class)->finalize (object);
1324 }
1325
1326 static void
1327 _gtk_file_system_module_class_init (GtkFileSystemModuleClass *class)
1328 {
1329   GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
1330   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
1331   
1332   module_class->load = gtk_file_system_module_load;
1333   module_class->unload = gtk_file_system_module_unload;
1334
1335   gobject_class->finalize = gtk_file_system_module_finalize;
1336 }
1337
1338 static void
1339 _gtk_file_system_module_init (GtkFileSystemModule *fs_module)
1340 {
1341 }
1342
1343
1344 static GtkFileSystem *
1345 _gtk_file_system_module_create (GtkFileSystemModule *fs_module)
1346 {
1347   GtkFileSystem *fs;
1348   
1349   if (g_type_module_use (G_TYPE_MODULE (fs_module)))
1350     {
1351       fs = fs_module->create ();
1352       g_type_module_unuse (G_TYPE_MODULE (fs_module));
1353       return fs;
1354     }
1355   return NULL;
1356 }
1357
1358
1359 GtkFileSystem *
1360 _gtk_file_system_create (const char *file_system_name)
1361 {
1362   GSList *l;
1363   char *module_path;
1364   GtkFileSystemModule *fs_module;
1365   GtkFileSystem *fs;
1366
1367   for (l = loaded_file_systems; l != NULL; l = l->next)
1368     {
1369       fs_module = l->data;
1370       
1371       if (strcmp (G_TYPE_MODULE (fs_module)->name, file_system_name) == 0)
1372         return _gtk_file_system_module_create (fs_module);
1373     }
1374
1375   fs = NULL;
1376   if (g_module_supported ())
1377     {
1378       module_path = _gtk_find_module (file_system_name, "filesystems");
1379
1380       if (module_path)
1381         {
1382           fs_module = g_object_new (GTK_TYPE_FILE_SYSTEM_MODULE, NULL);
1383
1384           g_type_module_set_name (G_TYPE_MODULE (fs_module), file_system_name);
1385           fs_module->path = g_strdup (module_path);
1386
1387           loaded_file_systems = g_slist_prepend (loaded_file_systems,
1388                                                  fs_module);
1389
1390           fs = _gtk_file_system_module_create (fs_module);
1391         }
1392       
1393       g_free (module_path);
1394     }
1395   
1396   return fs;
1397 }
1398
1399 #define __GTK_FILE_SYSTEM_C__
1400 #include "gtkaliasdef.c"