1 /* GTK - The GIMP Toolkit
2 * gtkfilesystem.c: Abstract file system interfaces
3 * Copyright (C) 2003, Red Hat, Inc.
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.
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.
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.
22 #include "gtkfilesystem.h"
23 #include "gtkicontheme.h"
30 GtkFileTime modification_time;
39 static void gtk_file_system_base_init (gpointer g_class);
40 static void gtk_file_folder_base_init (gpointer g_class);
43 gtk_file_system_error_quark (void)
45 static GQuark quark = 0;
47 quark = g_quark_from_static_string ("gtk-file-system-error-quark");
51 /*****************************************
53 *****************************************/
55 gtk_file_info_get_type (void)
57 static GType our_type = 0;
60 our_type = g_boxed_type_register_static ("GtkFileInfo",
61 (GBoxedCopyFunc) gtk_file_info_copy,
62 (GBoxedFreeFunc) gtk_file_info_free);
68 gtk_file_info_new (void)
72 info = g_new0 (GtkFileInfo, 1);
78 gtk_file_info_copy (GtkFileInfo *info)
80 GtkFileInfo *new_info;
82 g_return_val_if_fail (info != NULL, NULL);
84 new_info = g_memdup (info, sizeof (GtkFileInfo));
85 if (new_info->display_name)
86 new_info->display_name = g_strdup (new_info->display_name);
87 if (new_info->mime_type)
88 new_info->mime_type = g_strdup (new_info->mime_type);
94 gtk_file_info_free (GtkFileInfo *info)
96 g_return_if_fail (info != NULL);
98 if (info->display_name)
99 g_free (info->display_name);
101 g_free (info->mime_type);
102 if (info->display_key)
103 g_free (info->display_key);
108 G_CONST_RETURN gchar *
109 gtk_file_info_get_display_name (const GtkFileInfo *info)
111 g_return_val_if_fail (info != NULL, NULL);
113 return info->display_name;
117 * gtk_file_info_get_display_key:
118 * @info: a #GtkFileInfo
120 * Returns results of g_utf8_collate_key() on the display name
121 * for @info. This is useful when sorting a bunch of #GtkFileInfo
122 * structures since the collate key will be only computed once.
124 * Return value: The collate key for the display name, or %NULL
125 * if the display name hasn't been set.
127 G_CONST_RETURN gchar *
128 gtk_file_info_get_display_key (const GtkFileInfo *info)
130 g_return_val_if_fail (info != NULL, NULL);
132 if (!info->display_key && info->display_name)
134 /* Since info->display_key is only a cache, we cast off the const
136 ((GtkFileInfo *)info)->display_key = g_utf8_collate_key (info->display_name, -1);
139 return info->display_key;
143 gtk_file_info_set_display_name (GtkFileInfo *info,
144 const gchar *display_name)
146 g_return_if_fail (info != NULL);
148 if (info->display_name)
149 g_free (info->display_name);
150 if (info->display_key)
152 g_free (info->display_key);
153 info->display_key = NULL;
156 info->display_name = g_strdup (display_name);
160 gtk_file_info_get_is_folder (const GtkFileInfo *info)
162 g_return_val_if_fail (info != NULL, FALSE);
164 return info->is_folder;
168 gtk_file_info_set_is_folder (GtkFileInfo *info,
171 g_return_if_fail (info != NULL);
173 info->is_folder = is_folder != FALSE;
177 gtk_file_info_get_is_hidden (const GtkFileInfo *info)
179 g_return_val_if_fail (info != NULL, FALSE);
181 return info->is_hidden;
185 gtk_file_info_set_is_hidden (GtkFileInfo *info,
188 g_return_if_fail (info != NULL);
190 info->is_hidden = is_hidden != FALSE;
193 G_CONST_RETURN gchar *
194 gtk_file_info_get_mime_type (const GtkFileInfo *info)
196 g_return_val_if_fail (info != NULL, NULL);
198 return info->mime_type;
202 gtk_file_info_set_mime_type (GtkFileInfo *info,
203 const gchar *mime_type)
205 g_return_if_fail (info != NULL);
208 g_free (info->mime_type);
210 info->mime_type = g_strdup (mime_type);
214 gtk_file_info_get_modification_time (const GtkFileInfo *info)
216 g_return_val_if_fail (info != NULL, 0);
218 return info->modification_time;
222 gtk_file_info_set_modification_time (GtkFileInfo *info,
223 GtkFileTime modification_time)
225 g_return_if_fail (info != NULL);
227 info->modification_time = modification_time;
231 gtk_file_info_get_size (const GtkFileInfo *info)
233 g_return_val_if_fail (info != NULL, 0);
239 gtk_file_info_set_size (GtkFileInfo *info,
242 g_return_if_fail (info != NULL);
243 g_return_if_fail (size >= 0);
249 /*****************************************
251 *****************************************/
253 gtk_file_system_get_type (void)
255 static GType file_system_type = 0;
257 if (!file_system_type)
259 static const GTypeInfo file_system_info =
261 sizeof (GtkFileSystemIface), /* class_size */
262 gtk_file_system_base_init, /* base_init */
263 NULL, /* base_finalize */
266 file_system_type = g_type_register_static (G_TYPE_INTERFACE,
268 &file_system_info, 0);
270 g_type_interface_add_prerequisite (file_system_type, G_TYPE_OBJECT);
273 return file_system_type;
277 gtk_file_system_base_init (gpointer g_class)
279 static gboolean initialized = FALSE;
283 GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
285 g_signal_new ("volumes-changed",
288 G_STRUCT_OFFSET (GtkFileSystemIface, volumes_changed),
290 g_cclosure_marshal_VOID__VOID,
292 g_signal_new ("bookmarks-changed",
295 G_STRUCT_OFFSET (GtkFileSystemIface, bookmarks_changed),
297 g_cclosure_marshal_VOID__VOID,
305 gtk_file_system_list_volumes (GtkFileSystem *file_system)
307 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
309 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_volumes (file_system);
313 gtk_file_system_get_folder (GtkFileSystem *file_system,
314 const GtkFilePath *path,
315 GtkFileInfoType types,
318 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
319 g_return_val_if_fail (path != NULL, NULL);
320 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
322 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_folder (file_system, path, types, error);
326 gtk_file_system_create_folder(GtkFileSystem *file_system,
327 const GtkFilePath *path,
330 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
331 g_return_val_if_fail (path != NULL, FALSE);
332 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
334 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->create_folder (file_system, path, error);
338 * gtk_file_system_get_volume_for_path:
339 * @file_system: a #GtkFileSystem
340 * @path: a #GtkFilePath
342 * Queries the file system volume that corresponds to a specific path.
344 * Return value: the #GtkFileSystemVolume that corresponds to the specified
345 * @path. You should free this value with gtk_file_system_volume_free().
347 GtkFileSystemVolume *
348 gtk_file_system_get_volume_for_path (GtkFileSystem *file_system,
349 const GtkFilePath *path)
351 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
352 g_return_val_if_fail (path != NULL, NULL);
354 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_volume_for_path (file_system, path);
358 * gtk_file_system_volume_free:
359 * @file_system: a #GtkFileSystem
360 * @volume: a #GtkFileSystemVolume
362 * Frees a #GtkFileSystemVolume structure as returned by
363 * gtk_file_system_list_volumes().
366 gtk_file_system_volume_free (GtkFileSystem *file_system,
367 GtkFileSystemVolume *volume)
369 g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system));
370 g_return_if_fail (volume != NULL);
372 GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_free (file_system, volume);
376 * gtk_file_system_volume_get_base_path:
377 * @file_system: a #GtkFileSystem
378 * @volume: a #GtkFileSystemVolume
380 * Queries the base path for a volume. For example, a CD-ROM device may yield a
381 * path of "/mnt/cdrom".
383 * Return value: a #GtkFilePath with the base mount path of the specified
387 gtk_file_system_volume_get_base_path (GtkFileSystem *file_system,
388 GtkFileSystemVolume *volume)
390 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
391 g_return_val_if_fail (volume != NULL, NULL);
393 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_base_path (file_system, volume);
397 * gtk_file_system_volume_get_is_mounted:
398 * @file_system: a #GtkFileSystem
399 * @volume: a #GtkFileSystemVolume
401 * Queries whether a #GtkFileSystemVolume is mounted or not. If it is not, it
402 * can be mounted with gtk_file_system_volume_mount().
404 * Return value: TRUE if the @volume is mounted, FALSE otherwise.
407 gtk_file_system_volume_get_is_mounted (GtkFileSystem *file_system,
408 GtkFileSystemVolume *volume)
410 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
411 g_return_val_if_fail (volume != NULL, FALSE);
413 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_is_mounted (file_system, volume);
417 * gtk_file_system_volume_mount:
418 * @file_system: a #GtkFileSystem
419 * @volume: a #GtkFileSystemVolume
420 * @error: location to store error, or %NULL
422 * Tries to mount an unmounted volume. This may cause the "volumes-changed"
423 * signal in the @file_system to be emitted.
425 * Return value: TRUE if the @volume was mounted successfully, FALSE otherwise.
428 gtk_file_system_volume_mount (GtkFileSystem *file_system,
429 GtkFileSystemVolume *volume,
432 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
433 g_return_val_if_fail (volume != NULL, FALSE);
434 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
436 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_mount (file_system, volume, error);
440 * gtk_file_system_volume_get_display_name:
441 * @file_system: a #GtkFileSystem
442 * @volume: a #GtkFileSystemVolume
444 * Queries the human-readable name for a @volume. This string can be displayed
445 * in a list of volumes that can be accessed, for example.
447 * Return value: A string with the human-readable name for a #GtkFileSystemVolume.
450 gtk_file_system_volume_get_display_name (GtkFileSystem *file_system,
451 GtkFileSystemVolume *volume)
453 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
454 g_return_val_if_fail (volume != NULL, NULL);
456 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_display_name (file_system, volume);
460 * gtk_file_system_volume_render_icon:
461 * @file_system: a #GtkFileSystem
462 * @volume: a #GtkFileSystemVolume
463 * @widget: Reference widget to render icons.
464 * @pixel_size: Size of the icon.
465 * @error: location to store error, or %NULL
467 * Renders an icon suitable for a file #GtkFileSystemVolume.
469 * Return value: A #GdkPixbuf containing an icon, or NULL if the icon could not
470 * be rendered. In the latter case, the @error value will be set as
474 gtk_file_system_volume_render_icon (GtkFileSystem *file_system,
475 GtkFileSystemVolume *volume,
480 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
481 g_return_val_if_fail (volume != NULL, NULL);
482 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
483 g_return_val_if_fail (pixel_size > 0, NULL);
484 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
486 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_render_icon (file_system,
494 * gtk_file_system_get_parent:
495 * @file_system: a #GtkFileSystem
496 * @path: base path name
497 * @parent: location to store parent path name
498 * @error: location to store error, or %NULL
500 * Gets the name of the parent folder of a file.
502 * Return value: TRUE if the operation was successful; note that in this case @parent
503 * can be returned as %NULL if the base @path has no parent folder (i.e. if it is
504 * already a file system root). If the operation fails, this function returns FALSE
505 * and sets the @error value if it is specified.
508 gtk_file_system_get_parent (GtkFileSystem *file_system,
509 const GtkFilePath *path,
510 GtkFilePath **parent,
513 GtkFilePath *tmp_parent = NULL;
516 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
517 g_return_val_if_fail (path != NULL, FALSE);
518 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
520 result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_parent (file_system, path, &tmp_parent, error);
521 g_assert (result || tmp_parent == NULL);
524 *parent = tmp_parent;
526 gtk_file_path_free (tmp_parent);
532 gtk_file_system_make_path (GtkFileSystem *file_system,
533 const GtkFilePath *base_path,
534 const gchar *display_name,
537 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
538 g_return_val_if_fail (base_path != NULL, NULL);
539 g_return_val_if_fail (display_name != NULL, NULL);
540 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
542 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->make_path (file_system, base_path, display_name, error);
546 * gtk_file_system_parse:
547 * @file_system: a #GtkFileSystem
548 * @base_path: reference folder with respect to which relative
549 * paths should be interpreted.
550 * @str: the string to parse
551 * @folder: location to store folder portion of result, or %NULL
552 * @file_part: location to store file portion of result, or %NULL
553 * @error: location to store error, or %NULL
555 * Given a string entered by a user, parse it (possibly using
556 * heuristics) into a folder path and a UTF-8 encoded
557 * filename part. (Suitable for passing to gtk_file_system_make_path())
559 * Note that the returned filename point may point to a subfolder
560 * of the returned folder. Adding a trailing path separator is needed
561 * to enforce the interpretation as a folder name.
563 * If parsing fails because the syntax of @str is not understood,
564 * and error of type GTK_FILE_SYSTEM_ERROR_BAD_FILENAME will
565 * be set in @error and %FALSE returned.
567 * If parsing fails because a path was encountered that doesn't
568 * exist on the filesystem, then an error of type
569 * %GTK_FILE_SYSTEM_ERROR_NONEXISTENT will be set in @error
570 * and %FALSE returned. (This only applies to parsing relative paths,
571 * not to interpretation of @file_part. No check is made as
572 * to whether @file_part exists.)
574 * Return value: %TRUE if the parsing succeeds, otherwise, %FALSE.
577 gtk_file_system_parse (GtkFileSystem *file_system,
578 const GtkFilePath *base_path,
580 GtkFilePath **folder,
584 GtkFilePath *tmp_folder = NULL;
585 gchar *tmp_file_part = NULL;
588 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
589 g_return_val_if_fail (base_path != NULL, FALSE);
590 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
593 result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->parse (file_system, base_path, str,
594 &tmp_folder, &tmp_file_part,
596 g_assert (result || (tmp_folder == NULL && tmp_file_part == NULL));
599 *folder = tmp_folder;
601 gtk_file_path_free (tmp_folder);
604 *file_part = tmp_file_part;
606 g_free (tmp_file_part);
613 gtk_file_system_path_to_uri (GtkFileSystem *file_system,
614 const GtkFilePath *path)
616 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
617 g_return_val_if_fail (path != NULL, NULL);
619 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_uri (file_system, path);
623 gtk_file_system_path_to_filename (GtkFileSystem *file_system,
624 const GtkFilePath *path)
626 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
627 g_return_val_if_fail (path != NULL, NULL);
629 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_filename (file_system, path);
633 gtk_file_system_uri_to_path (GtkFileSystem *file_system,
636 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
637 g_return_val_if_fail (uri != NULL, NULL);
639 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->uri_to_path (file_system, uri);
643 gtk_file_system_filename_to_path (GtkFileSystem *file_system,
644 const gchar *filename)
646 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
647 g_return_val_if_fail (filename != NULL, NULL);
649 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->filename_to_path (file_system, filename);
653 gtk_file_system_render_icon (GtkFileSystem *file_system,
654 const GtkFilePath *path,
659 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
660 g_return_val_if_fail (path != NULL, NULL);
661 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
662 g_return_val_if_fail (pixel_size > 0, NULL);
664 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->render_icon (file_system, path, widget, pixel_size, error);
668 * gtk_file_system_add_bookmark:
669 * @file_system: a #GtkFileSystem
670 * @bookmark: path of the bookmark to add
671 * @error: location to store error, or %NULL
673 * Adds a bookmark folder to the user's bookmarks list. If the operation succeeds,
674 * the "bookmarks_changed" signal will be emitted.
676 * Return value: TRUE if the operation succeeds, FALSE otherwise. In the latter case,
677 * the @error value will be set.
680 gtk_file_system_add_bookmark (GtkFileSystem *file_system,
681 const GtkFilePath *path,
684 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
685 g_return_val_if_fail (path != NULL, FALSE);
687 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->add_bookmark (file_system, path, error);
691 * gtk_file_system_remove_bookmark:
692 * @file_system: a #GtkFileSystem
693 * @bookmark: path of the bookmark to remove
694 * @error: location to store error, or %NULL
696 * Removes a bookmark folder from the user's bookmarks list. If the operation
697 * succeeds, the "bookmarks_changed" signal will be emitted.
699 * Return value: TRUE if the operation succeeds, FALSE otherwise. In the latter
700 * case, the @error value will be set.
703 gtk_file_system_remove_bookmark (GtkFileSystem *file_system,
704 const GtkFilePath *path,
707 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
708 g_return_val_if_fail (path != NULL, FALSE);
710 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->remove_bookmark (file_system, path, error);
714 * gtk_file_system_list_bookmarks:
715 * @file_system: a #GtkFileSystem
717 * Queries the list of bookmarks in the file system.
719 * Return value: A list of #GtkFilePath, or NULL if there are no configured
720 * bookmarks. You should use gtk_file_paths_free() to free this list.
722 * See also: gtk_file_system_get_supports_bookmarks()
725 gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
727 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
729 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_bookmarks (file_system);
732 /*****************************************
734 *****************************************/
736 gtk_file_folder_get_type (void)
738 static GType file_folder_type = 0;
740 if (!file_folder_type)
742 static const GTypeInfo file_folder_info =
744 sizeof (GtkFileFolderIface), /* class_size */
745 gtk_file_folder_base_init, /* base_init */
746 NULL, /* base_finalize */
749 file_folder_type = g_type_register_static (G_TYPE_INTERFACE,
751 &file_folder_info, 0);
753 g_type_interface_add_prerequisite (file_folder_type, G_TYPE_OBJECT);
756 return file_folder_type;
760 gtk_file_folder_base_init (gpointer g_class)
762 static gboolean initialized = FALSE;
766 GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
768 g_signal_new ("deleted",
771 G_STRUCT_OFFSET (GtkFileFolderIface, deleted),
773 g_cclosure_marshal_VOID__VOID,
775 g_signal_new ("files-added",
778 G_STRUCT_OFFSET (GtkFileFolderIface, files_added),
780 g_cclosure_marshal_VOID__POINTER,
783 g_signal_new ("files-changed",
786 G_STRUCT_OFFSET (GtkFileFolderIface, files_changed),
788 g_cclosure_marshal_VOID__POINTER,
791 g_signal_new ("files-removed",
794 G_STRUCT_OFFSET (GtkFileFolderIface, files_removed),
796 g_cclosure_marshal_VOID__POINTER,
805 gtk_file_folder_list_children (GtkFileFolder *folder,
810 GSList *tmp_children = NULL;
812 g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), FALSE);
813 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
815 result = GTK_FILE_FOLDER_GET_IFACE (folder)->list_children (folder, &tmp_children, error);
816 g_assert (result || tmp_children == NULL);
819 *children = tmp_children;
821 gtk_file_paths_free (tmp_children);
827 gtk_file_folder_get_info (GtkFileFolder *folder,
828 const GtkFilePath *path,
831 g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), NULL);
832 g_return_val_if_fail (path != NULL, NULL);
833 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
835 return GTK_FILE_FOLDER_GET_IFACE (folder)->get_info (folder, path, error);
839 gtk_file_paths_sort (GSList *paths)
841 return g_slist_sort (paths, (GCompareFunc)strcmp);
845 * gtk_file_paths_copy:
846 * @paths: A #GSList of #GtkFilePath structures.
848 * Copies a list of #GtkFilePath structures.
850 * Return value: A copy of @paths. Since the contents of the list are copied as
851 * well, you should use gtk_file_paths_free() to free the result.
854 gtk_file_paths_copy (GSList *paths)
856 GSList *head, *tail, *l;
860 for (l = paths; l; l = l->next)
866 node = g_slist_alloc ();
873 node->data = gtk_file_path_copy (path);
881 gtk_file_paths_free (GSList *paths)
885 for (tmp_list = paths; tmp_list; tmp_list = tmp_list->next)
886 gtk_file_path_free (tmp_list->data);
888 g_slist_free (paths);
891 /*****************************************
892 * GtkFileSystem modules *
893 *****************************************/
895 typedef struct _GtkFileSystemModule GtkFileSystemModule;
896 typedef struct _GtkFileSystemModuleClass GtkFileSystemModuleClass;
898 struct _GtkFileSystemModule
900 GTypeModule parent_instance;
904 void (*init) (GTypeModule *module);
906 GtkFileSystem * (*create) (void);
911 struct _GtkFileSystemModuleClass
913 GTypeModuleClass parent_class;
916 G_DEFINE_TYPE (GtkFileSystemModule, gtk_file_system_module, G_TYPE_TYPE_MODULE);
917 #define GTK_TYPE_FILE_SYSTEM_MODULE (gtk_file_system_module_get_type ())
918 #define GTK_FILE_SYSTEM_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), GTK_TYPE_FILE_SYSTEM_MODULE, GtkFileSystemModule))
921 static GSList *loaded_file_systems;
924 gtk_file_system_module_load (GTypeModule *module)
926 GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module);
928 fs_module->library = g_module_open (fs_module->path, 0);
929 if (!fs_module->library)
931 g_warning (g_module_error());
935 /* extract symbols from the lib */
936 if (!g_module_symbol (fs_module->library, "fs_module_init",
937 (gpointer *)&fs_module->init) ||
938 !g_module_symbol (fs_module->library, "fs_module_exit",
939 (gpointer *)&fs_module->exit) ||
940 !g_module_symbol (fs_module->library, "fs_module_create",
941 (gpointer *)&fs_module->create))
943 g_warning (g_module_error());
944 g_module_close (fs_module->library);
949 /* call the filesystems's init function to let it */
950 /* setup anything it needs to set up. */
951 fs_module->init (module);
957 gtk_file_system_module_unload (GTypeModule *module)
959 GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module);
963 g_module_close (fs_module->library);
964 fs_module->library = NULL;
966 fs_module->init = NULL;
967 fs_module->exit = NULL;
968 fs_module->create = NULL;
971 /* This only will ever be called if an error occurs during
975 gtk_file_system_module_finalize (GObject *object)
977 GtkFileSystemModule *module = GTK_FILE_SYSTEM_MODULE (object);
979 g_free (module->path);
981 G_OBJECT_CLASS (gtk_file_system_module_parent_class)->finalize (object);
985 gtk_file_system_module_class_init (GtkFileSystemModuleClass *class)
987 GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
988 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
990 module_class->load = gtk_file_system_module_load;
991 module_class->unload = gtk_file_system_module_unload;
993 gobject_class->finalize = gtk_file_system_module_finalize;
997 gtk_file_system_module_init (GtkFileSystemModule *fs_module)
1002 static GtkFileSystem *
1003 _gtk_file_system_module_create (GtkFileSystemModule *fs_module)
1007 if (g_type_module_use (G_TYPE_MODULE (fs_module)))
1009 fs = fs_module->create ();
1010 g_type_module_unuse (G_TYPE_MODULE (fs_module));
1018 _gtk_file_system_create (const char *file_system_name)
1020 struct FileSystemInfo *file_system_info;
1023 GtkFileSystemModule *fs_module;
1026 for (l = loaded_file_systems; l != NULL; l = l->next)
1028 fs_module = l->data;
1030 if (strcmp (G_TYPE_MODULE (fs_module)->name, file_system_name) == 0)
1031 return _gtk_file_system_module_create (fs_module);
1035 if (g_module_supported ())
1037 module_path = _gtk_find_module (file_system_name, "filesystems");
1041 fs_module = g_object_new (GTK_TYPE_FILE_SYSTEM_MODULE, NULL);
1043 g_type_module_set_name (G_TYPE_MODULE (fs_module), file_system_name);
1044 fs_module->path = g_strdup (module_path);
1046 loaded_file_systems = g_slist_prepend (loaded_file_systems,
1049 fs = _gtk_file_system_module_create (fs_module);
1052 g_free (module_path);