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.
24 #include "gtkfilesystem.h"
25 #include "gtkicontheme.h"
26 #include "gtkmodules.h"
32 GtkFileTime modification_time;
41 static void gtk_file_system_base_init (gpointer g_class);
42 static void gtk_file_folder_base_init (gpointer g_class);
45 gtk_file_system_error_quark (void)
47 static GQuark quark = 0;
49 quark = g_quark_from_static_string ("gtk-file-system-error-quark");
53 /*****************************************
55 *****************************************/
57 gtk_file_info_get_type (void)
59 static GType our_type = 0;
62 our_type = g_boxed_type_register_static ("GtkFileInfo",
63 (GBoxedCopyFunc) gtk_file_info_copy,
64 (GBoxedFreeFunc) gtk_file_info_free);
70 gtk_file_info_new (void)
74 info = g_new0 (GtkFileInfo, 1);
80 gtk_file_info_copy (GtkFileInfo *info)
82 GtkFileInfo *new_info;
84 g_return_val_if_fail (info != NULL, NULL);
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->mime_type)
90 new_info->mime_type = g_strdup (new_info->mime_type);
96 gtk_file_info_free (GtkFileInfo *info)
98 g_return_if_fail (info != NULL);
100 if (info->display_name)
101 g_free (info->display_name);
103 g_free (info->mime_type);
104 if (info->display_key)
105 g_free (info->display_key);
110 G_CONST_RETURN gchar *
111 gtk_file_info_get_display_name (const GtkFileInfo *info)
113 g_return_val_if_fail (info != NULL, NULL);
115 return info->display_name;
119 * gtk_file_info_get_display_key:
120 * @info: a #GtkFileInfo
122 * Returns results of g_utf8_collate_key() on the display name
123 * for @info. This is useful when sorting a bunch of #GtkFileInfo
124 * structures since the collate key will be only computed once.
126 * Return value: The collate key for the display name, or %NULL
127 * if the display name hasn't been set.
129 G_CONST_RETURN gchar *
130 gtk_file_info_get_display_key (const GtkFileInfo *info)
132 g_return_val_if_fail (info != NULL, NULL);
134 if (!info->display_key && info->display_name)
136 /* Since info->display_key is only a cache, we cast off the const
138 ((GtkFileInfo *)info)->display_key = g_utf8_collate_key (info->display_name, -1);
141 return info->display_key;
145 gtk_file_info_set_display_name (GtkFileInfo *info,
146 const gchar *display_name)
148 g_return_if_fail (info != NULL);
150 if (display_name == info->display_name)
153 if (info->display_name)
154 g_free (info->display_name);
155 if (info->display_key)
157 g_free (info->display_key);
158 info->display_key = NULL;
161 info->display_name = g_strdup (display_name);
165 gtk_file_info_get_is_folder (const GtkFileInfo *info)
167 g_return_val_if_fail (info != NULL, FALSE);
169 return info->is_folder;
173 gtk_file_info_set_is_folder (GtkFileInfo *info,
176 g_return_if_fail (info != NULL);
178 info->is_folder = is_folder != FALSE;
182 gtk_file_info_get_is_hidden (const GtkFileInfo *info)
184 g_return_val_if_fail (info != NULL, FALSE);
186 return info->is_hidden;
190 gtk_file_info_set_is_hidden (GtkFileInfo *info,
193 g_return_if_fail (info != NULL);
195 info->is_hidden = is_hidden != FALSE;
198 G_CONST_RETURN gchar *
199 gtk_file_info_get_mime_type (const GtkFileInfo *info)
201 g_return_val_if_fail (info != NULL, NULL);
203 return info->mime_type;
207 gtk_file_info_set_mime_type (GtkFileInfo *info,
208 const gchar *mime_type)
210 g_return_if_fail (info != NULL);
213 g_free (info->mime_type);
215 info->mime_type = g_strdup (mime_type);
219 gtk_file_info_get_modification_time (const GtkFileInfo *info)
221 g_return_val_if_fail (info != NULL, 0);
223 return info->modification_time;
227 gtk_file_info_set_modification_time (GtkFileInfo *info,
228 GtkFileTime modification_time)
230 g_return_if_fail (info != NULL);
232 info->modification_time = modification_time;
236 gtk_file_info_get_size (const GtkFileInfo *info)
238 g_return_val_if_fail (info != NULL, 0);
244 gtk_file_info_set_size (GtkFileInfo *info,
247 g_return_if_fail (info != NULL);
248 g_return_if_fail (size >= 0);
254 /*****************************************
256 *****************************************/
258 gtk_file_system_get_type (void)
260 static GType file_system_type = 0;
262 if (!file_system_type)
264 static const GTypeInfo file_system_info =
266 sizeof (GtkFileSystemIface), /* class_size */
267 gtk_file_system_base_init, /* base_init */
268 NULL, /* base_finalize */
271 file_system_type = g_type_register_static (G_TYPE_INTERFACE,
273 &file_system_info, 0);
275 g_type_interface_add_prerequisite (file_system_type, G_TYPE_OBJECT);
278 return file_system_type;
282 gtk_file_system_base_init (gpointer g_class)
284 static gboolean initialized = FALSE;
288 GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
290 g_signal_new ("volumes-changed",
293 G_STRUCT_OFFSET (GtkFileSystemIface, volumes_changed),
295 g_cclosure_marshal_VOID__VOID,
297 g_signal_new ("bookmarks-changed",
300 G_STRUCT_OFFSET (GtkFileSystemIface, bookmarks_changed),
302 g_cclosure_marshal_VOID__VOID,
310 gtk_file_system_list_volumes (GtkFileSystem *file_system)
312 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
314 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_volumes (file_system);
318 gtk_file_system_get_folder (GtkFileSystem *file_system,
319 const GtkFilePath *path,
320 GtkFileInfoType types,
323 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
324 g_return_val_if_fail (path != NULL, NULL);
325 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
327 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_folder (file_system, path, types, error);
331 gtk_file_system_create_folder(GtkFileSystem *file_system,
332 const GtkFilePath *path,
335 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
336 g_return_val_if_fail (path != NULL, FALSE);
337 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
339 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->create_folder (file_system, path, error);
343 * gtk_file_system_get_volume_for_path:
344 * @file_system: a #GtkFileSystem
345 * @path: a #GtkFilePath
347 * Queries the file system volume that corresponds to a specific path.
348 * There might not be a volume for all paths (consinder for instance remote
349 * shared), so this can return NULL.
351 * Return value: the #GtkFileSystemVolume that corresponds to the specified
352 * @path, or NULL if there is no such volume. You should free this value with
353 * gtk_file_system_volume_free().
355 GtkFileSystemVolume *
356 gtk_file_system_get_volume_for_path (GtkFileSystem *file_system,
357 const GtkFilePath *path)
359 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
360 g_return_val_if_fail (path != NULL, NULL);
362 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_volume_for_path (file_system, path);
366 * gtk_file_system_volume_free:
367 * @file_system: a #GtkFileSystem
368 * @volume: a #GtkFileSystemVolume
370 * Frees a #GtkFileSystemVolume structure as returned by
371 * gtk_file_system_list_volumes().
374 gtk_file_system_volume_free (GtkFileSystem *file_system,
375 GtkFileSystemVolume *volume)
377 g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system));
378 g_return_if_fail (volume != NULL);
380 GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_free (file_system, volume);
384 * gtk_file_system_volume_get_base_path:
385 * @file_system: a #GtkFileSystem
386 * @volume: a #GtkFileSystemVolume
388 * Queries the base path for a volume. For example, a CD-ROM device may yield a
389 * path of "/mnt/cdrom".
391 * Return value: a #GtkFilePath with the base mount path of the specified
395 gtk_file_system_volume_get_base_path (GtkFileSystem *file_system,
396 GtkFileSystemVolume *volume)
398 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
399 g_return_val_if_fail (volume != NULL, NULL);
401 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_base_path (file_system, volume);
405 * gtk_file_system_volume_get_is_mounted:
406 * @file_system: a #GtkFileSystem
407 * @volume: a #GtkFileSystemVolume
409 * Queries whether a #GtkFileSystemVolume is mounted or not. If it is not, it
410 * can be mounted with gtk_file_system_volume_mount().
412 * Return value: TRUE if the @volume is mounted, FALSE otherwise.
415 gtk_file_system_volume_get_is_mounted (GtkFileSystem *file_system,
416 GtkFileSystemVolume *volume)
418 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
419 g_return_val_if_fail (volume != NULL, FALSE);
421 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_is_mounted (file_system, volume);
425 * gtk_file_system_volume_mount:
426 * @file_system: a #GtkFileSystem
427 * @volume: a #GtkFileSystemVolume
428 * @error: location to store error, or %NULL
430 * Tries to mount an unmounted volume. This may cause the "volumes-changed"
431 * signal in the @file_system to be emitted.
433 * Return value: TRUE if the @volume was mounted successfully, FALSE otherwise.
436 gtk_file_system_volume_mount (GtkFileSystem *file_system,
437 GtkFileSystemVolume *volume,
440 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
441 g_return_val_if_fail (volume != NULL, FALSE);
442 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
444 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_mount (file_system, volume, error);
448 * gtk_file_system_volume_get_display_name:
449 * @file_system: a #GtkFileSystem
450 * @volume: a #GtkFileSystemVolume
452 * Queries the human-readable name for a @volume. This string can be displayed
453 * in a list of volumes that can be accessed, for example.
455 * Return value: A string with the human-readable name for a #GtkFileSystemVolume.
458 gtk_file_system_volume_get_display_name (GtkFileSystem *file_system,
459 GtkFileSystemVolume *volume)
461 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
462 g_return_val_if_fail (volume != NULL, NULL);
464 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_display_name (file_system, volume);
468 * gtk_file_system_volume_render_icon:
469 * @file_system: a #GtkFileSystem
470 * @volume: a #GtkFileSystemVolume
471 * @widget: Reference widget to render icons.
472 * @pixel_size: Size of the icon.
473 * @error: location to store error, or %NULL
475 * Renders an icon suitable for a file #GtkFileSystemVolume.
477 * Return value: A #GdkPixbuf containing an icon, or NULL if the icon could not
478 * be rendered. In the latter case, the @error value will be set as
482 gtk_file_system_volume_render_icon (GtkFileSystem *file_system,
483 GtkFileSystemVolume *volume,
488 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
489 g_return_val_if_fail (volume != NULL, NULL);
490 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
491 g_return_val_if_fail (pixel_size > 0, NULL);
492 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
494 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_render_icon (file_system,
502 * gtk_file_system_get_parent:
503 * @file_system: a #GtkFileSystem
504 * @path: base path name
505 * @parent: location to store parent path name
506 * @error: location to store error, or %NULL
508 * Gets the name of the parent folder of a path. If the path has no parent, as when
509 * you request the parent of a file system root, then @parent will be set to %NULL.
511 * Return value: %TRUE if the operation was successful: @parent will be set to
512 * the name of the @path's parent, or to %NULL if @path is already a file system
513 * root. If the operation fails, this function returns %FALSE, sets @parent to
514 * NULL, and sets the @error value if it is specified.
517 gtk_file_system_get_parent (GtkFileSystem *file_system,
518 const GtkFilePath *path,
519 GtkFilePath **parent,
524 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
525 g_return_val_if_fail (path != NULL, FALSE);
526 g_return_val_if_fail (parent != NULL, FALSE);
527 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
531 result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_parent (file_system, path, parent, error);
532 g_assert (result || *parent == NULL);
538 gtk_file_system_make_path (GtkFileSystem *file_system,
539 const GtkFilePath *base_path,
540 const gchar *display_name,
543 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
544 g_return_val_if_fail (base_path != NULL, NULL);
545 g_return_val_if_fail (display_name != NULL, NULL);
546 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
548 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->make_path (file_system, base_path, display_name, error);
552 * gtk_file_system_parse:
553 * @file_system: a #GtkFileSystem
554 * @base_path: reference folder with respect to which relative
555 * paths should be interpreted.
556 * @str: the string to parse
557 * @folder: location to store folder portion of result, or %NULL
558 * @file_part: location to store file portion of result, or %NULL
559 * @error: location to store error, or %NULL
561 * Given a string entered by a user, parse it (possibly using
562 * heuristics) into a folder path and a UTF-8 encoded
563 * filename part. (Suitable for passing to gtk_file_system_make_path())
565 * Note that the returned filename point may point to a subfolder
566 * of the returned folder. Adding a trailing path separator is needed
567 * to enforce the interpretation as a folder name.
569 * If parsing fails because the syntax of @str is not understood,
570 * and error of type GTK_FILE_SYSTEM_ERROR_BAD_FILENAME will
571 * be set in @error and %FALSE returned.
573 * If parsing fails because a path was encountered that doesn't
574 * exist on the filesystem, then an error of type
575 * %GTK_FILE_SYSTEM_ERROR_NONEXISTENT will be set in @error
576 * and %FALSE returned. (This only applies to parsing relative paths,
577 * not to interpretation of @file_part. No check is made as
578 * to whether @file_part exists.)
580 * Return value: %TRUE if the parsing succeeds, otherwise, %FALSE.
583 gtk_file_system_parse (GtkFileSystem *file_system,
584 const GtkFilePath *base_path,
586 GtkFilePath **folder,
590 GtkFilePath *tmp_folder = NULL;
591 gchar *tmp_file_part = NULL;
594 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
595 g_return_val_if_fail (base_path != NULL, FALSE);
596 g_return_val_if_fail (str != NULL, FALSE);
597 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
599 result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->parse (file_system, base_path, str,
600 &tmp_folder, &tmp_file_part,
602 g_assert (result || (tmp_folder == NULL && tmp_file_part == NULL));
605 *folder = tmp_folder;
607 gtk_file_path_free (tmp_folder);
610 *file_part = tmp_file_part;
612 g_free (tmp_file_part);
619 gtk_file_system_path_to_uri (GtkFileSystem *file_system,
620 const GtkFilePath *path)
622 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
623 g_return_val_if_fail (path != NULL, NULL);
625 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_uri (file_system, path);
629 gtk_file_system_path_to_filename (GtkFileSystem *file_system,
630 const GtkFilePath *path)
632 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
633 g_return_val_if_fail (path != NULL, NULL);
635 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_filename (file_system, path);
639 gtk_file_system_uri_to_path (GtkFileSystem *file_system,
642 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
643 g_return_val_if_fail (uri != NULL, NULL);
645 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->uri_to_path (file_system, uri);
649 gtk_file_system_filename_to_path (GtkFileSystem *file_system,
650 const gchar *filename)
652 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
653 g_return_val_if_fail (filename != NULL, NULL);
655 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->filename_to_path (file_system, filename);
659 * gtk_file_system_path_is_local:
660 * @filesystem: a #GtkFileSystem
661 * @path: A #GtkFilePath from that filesystem
663 * Checks whether a #GtkFilePath is local; that is whether
664 * gtk_file_system_path_to_filename would return non-%NULL.
666 * Return value: %TRUE if the path is loca
669 gtk_file_system_path_is_local (GtkFileSystem *file_system,
670 const GtkFilePath *path)
675 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
676 g_return_val_if_fail (path != NULL, FALSE);
678 filename = gtk_file_system_path_to_filename (file_system, path);
679 result = filename != NULL;
686 gtk_file_system_render_icon (GtkFileSystem *file_system,
687 const GtkFilePath *path,
692 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
693 g_return_val_if_fail (path != NULL, NULL);
694 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
695 g_return_val_if_fail (pixel_size > 0, NULL);
697 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->render_icon (file_system, path, widget, pixel_size, error);
701 * gtk_file_system_insert_bookmark:
702 * @file_system: a #GtkFileSystem
703 * @path: path of the bookmark to add
704 * @position: index in the bookmarks list at which the @path should be inserted; use 0
705 * for the beginning, and -1 or the number of bookmarks itself for the end of the list.
706 * @error: location to store error, or %NULL
708 * Adds a path for a folder to the user's bookmarks list. If the operation
709 * succeeds, the "bookmarks_changed" signal will be emitted. Bookmark paths are
710 * unique; if you try to insert a @path that already exists, the operation will
711 * fail and the @error will be set to #GTK_FILE_SYSTEM_ERROR_ALREADY_EXISTS. To
712 * reorder the list of bookmarks, use gtk_file_system_remove_bookmark() to
713 * remove the path in question, and call gtk_file_system_insert_bookmark() with
714 * the new position for the path.
716 * Return value: TRUE if the operation succeeds, FALSE otherwise. In the latter case,
717 * the @error value will be set.
720 gtk_file_system_insert_bookmark (GtkFileSystem *file_system,
721 const GtkFilePath *path,
725 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
726 g_return_val_if_fail (path != NULL, FALSE);
728 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->insert_bookmark (file_system, path, position, error);
732 * gtk_file_system_remove_bookmark:
733 * @file_system: a #GtkFileSystem
734 * @path: path of the bookmark to remove
735 * @error: location to store error, or %NULL
737 * Removes a bookmark folder from the user's bookmarks list. If the operation
738 * succeeds, the "bookmarks_changed" signal will be emitted. If you try to remove
739 * a @path which does not exist in the bookmarks list, the operation will fail
740 * and the @error will be set to GTK_FILE_SYSTEM_ERROR_NONEXISTENT.
742 * Return value: TRUE if the operation succeeds, FALSE otherwise. In the latter
743 * case, the @error value will be set.
746 gtk_file_system_remove_bookmark (GtkFileSystem *file_system,
747 const GtkFilePath *path,
750 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
751 g_return_val_if_fail (path != NULL, FALSE);
753 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->remove_bookmark (file_system, path, error);
757 * gtk_file_system_list_bookmarks:
758 * @file_system: a #GtkFileSystem
760 * Queries the list of bookmarks in the file system.
762 * Return value: A list of #GtkFilePath, or NULL if there are no configured
763 * bookmarks. You should use gtk_file_paths_free() to free this list.
765 * See also: gtk_file_system_get_supports_bookmarks()
768 gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
770 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
772 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_bookmarks (file_system);
775 /*****************************************
777 *****************************************/
779 gtk_file_folder_get_type (void)
781 static GType file_folder_type = 0;
783 if (!file_folder_type)
785 static const GTypeInfo file_folder_info =
787 sizeof (GtkFileFolderIface), /* class_size */
788 gtk_file_folder_base_init, /* base_init */
789 NULL, /* base_finalize */
792 file_folder_type = g_type_register_static (G_TYPE_INTERFACE,
794 &file_folder_info, 0);
796 g_type_interface_add_prerequisite (file_folder_type, G_TYPE_OBJECT);
799 return file_folder_type;
803 gtk_file_folder_base_init (gpointer g_class)
805 static gboolean initialized = FALSE;
809 GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
811 g_signal_new ("deleted",
814 G_STRUCT_OFFSET (GtkFileFolderIface, deleted),
816 g_cclosure_marshal_VOID__VOID,
818 g_signal_new ("files-added",
821 G_STRUCT_OFFSET (GtkFileFolderIface, files_added),
823 g_cclosure_marshal_VOID__POINTER,
826 g_signal_new ("files-changed",
829 G_STRUCT_OFFSET (GtkFileFolderIface, files_changed),
831 g_cclosure_marshal_VOID__POINTER,
834 g_signal_new ("files-removed",
837 G_STRUCT_OFFSET (GtkFileFolderIface, files_removed),
839 g_cclosure_marshal_VOID__POINTER,
842 g_signal_new ("finished-loading",
845 G_STRUCT_OFFSET (GtkFileFolderIface, finished_loading),
847 g_cclosure_marshal_VOID__VOID,
855 gtk_file_folder_list_children (GtkFileFolder *folder,
860 GSList *tmp_children = NULL;
862 g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), FALSE);
863 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
865 result = GTK_FILE_FOLDER_GET_IFACE (folder)->list_children (folder, &tmp_children, error);
866 g_assert (result || tmp_children == NULL);
869 *children = tmp_children;
871 gtk_file_paths_free (tmp_children);
877 gtk_file_folder_get_info (GtkFileFolder *folder,
878 const GtkFilePath *path,
881 g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), NULL);
882 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
884 return GTK_FILE_FOLDER_GET_IFACE (folder)->get_info (folder, path, error);
888 gtk_file_folder_is_finished_loading (GtkFileFolder *folder)
890 g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), TRUE);
892 if (!GTK_FILE_FOLDER_GET_IFACE (folder)->is_finished_loading)
895 return GTK_FILE_FOLDER_GET_IFACE (folder)->is_finished_loading (folder);
899 /*****************************************
900 * GtkFilePath modules *
901 *****************************************/
903 /* We make these real functions in case either copy or free are implemented as macros
906 gtk_file_path_real_copy (gpointer boxed)
908 return gtk_file_path_copy ((GtkFilePath *) boxed);
912 gtk_file_path_real_free (gpointer boxed)
914 gtk_file_path_free (boxed);
918 gtk_file_path_get_type (void)
920 static GType our_type = 0;
923 our_type = g_boxed_type_register_static ("GtkFilePath",
924 (GBoxedCopyFunc) gtk_file_path_real_copy,
925 (GBoxedFreeFunc) gtk_file_path_real_free);
932 gtk_file_paths_sort (GSList *paths)
934 return g_slist_sort (paths, (GCompareFunc)strcmp);
938 * gtk_file_paths_copy:
939 * @paths: A #GSList of #GtkFilePath structures.
941 * Copies a list of #GtkFilePath structures.
943 * Return value: A copy of @paths. Since the contents of the list are copied as
944 * well, you should use gtk_file_paths_free() to free the result.
947 gtk_file_paths_copy (GSList *paths)
949 GSList *head, *tail, *l;
953 for (l = paths; l; l = l->next)
959 node = g_slist_alloc ();
966 node->data = gtk_file_path_copy (path);
974 gtk_file_paths_free (GSList *paths)
978 for (tmp_list = paths; tmp_list; tmp_list = tmp_list->next)
979 gtk_file_path_free (tmp_list->data);
981 g_slist_free (paths);
984 /*****************************************
985 * GtkFileSystem modules *
986 *****************************************/
988 typedef struct _GtkFileSystemModule GtkFileSystemModule;
989 typedef struct _GtkFileSystemModuleClass GtkFileSystemModuleClass;
991 struct _GtkFileSystemModule
993 GTypeModule parent_instance;
997 void (*init) (GTypeModule *module);
999 GtkFileSystem * (*create) (void);
1004 struct _GtkFileSystemModuleClass
1006 GTypeModuleClass parent_class;
1009 G_DEFINE_TYPE (GtkFileSystemModule, _gtk_file_system_module, G_TYPE_TYPE_MODULE);
1010 #define GTK_TYPE_FILE_SYSTEM_MODULE (_gtk_file_system_module_get_type ())
1011 #define GTK_FILE_SYSTEM_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), GTK_TYPE_FILE_SYSTEM_MODULE, GtkFileSystemModule))
1014 static GSList *loaded_file_systems;
1017 gtk_file_system_module_load (GTypeModule *module)
1019 GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module);
1021 fs_module->library = g_module_open (fs_module->path, 0);
1022 if (!fs_module->library)
1024 g_warning (g_module_error());
1028 /* extract symbols from the lib */
1029 if (!g_module_symbol (fs_module->library, "fs_module_init",
1030 (gpointer *)&fs_module->init) ||
1031 !g_module_symbol (fs_module->library, "fs_module_exit",
1032 (gpointer *)&fs_module->exit) ||
1033 !g_module_symbol (fs_module->library, "fs_module_create",
1034 (gpointer *)&fs_module->create))
1036 g_warning (g_module_error());
1037 g_module_close (fs_module->library);
1042 /* call the filesystems's init function to let it */
1043 /* setup anything it needs to set up. */
1044 fs_module->init (module);
1050 gtk_file_system_module_unload (GTypeModule *module)
1052 GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module);
1056 g_module_close (fs_module->library);
1057 fs_module->library = NULL;
1059 fs_module->init = NULL;
1060 fs_module->exit = NULL;
1061 fs_module->create = NULL;
1064 /* This only will ever be called if an error occurs during
1068 gtk_file_system_module_finalize (GObject *object)
1070 GtkFileSystemModule *module = GTK_FILE_SYSTEM_MODULE (object);
1072 g_free (module->path);
1074 G_OBJECT_CLASS (_gtk_file_system_module_parent_class)->finalize (object);
1078 _gtk_file_system_module_class_init (GtkFileSystemModuleClass *class)
1080 GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
1081 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
1083 module_class->load = gtk_file_system_module_load;
1084 module_class->unload = gtk_file_system_module_unload;
1086 gobject_class->finalize = gtk_file_system_module_finalize;
1090 _gtk_file_system_module_init (GtkFileSystemModule *fs_module)
1095 static GtkFileSystem *
1096 _gtk_file_system_module_create (GtkFileSystemModule *fs_module)
1100 if (g_type_module_use (G_TYPE_MODULE (fs_module)))
1102 fs = fs_module->create ();
1103 g_type_module_unuse (G_TYPE_MODULE (fs_module));
1111 _gtk_file_system_create (const char *file_system_name)
1115 GtkFileSystemModule *fs_module;
1118 for (l = loaded_file_systems; l != NULL; l = l->next)
1120 fs_module = l->data;
1122 if (strcmp (G_TYPE_MODULE (fs_module)->name, file_system_name) == 0)
1123 return _gtk_file_system_module_create (fs_module);
1127 if (g_module_supported ())
1129 module_path = _gtk_find_module (file_system_name, "filesystems");
1133 fs_module = g_object_new (GTK_TYPE_FILE_SYSTEM_MODULE, NULL);
1135 g_type_module_set_name (G_TYPE_MODULE (fs_module), file_system_name);
1136 fs_module->path = g_strdup (module_path);
1138 loaded_file_systems = g_slist_prepend (loaded_file_systems,
1141 fs = _gtk_file_system_module_create (fs_module);
1144 g_free (module_path);