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.
23 #include "gtkfilesystem.h"
24 #include "gtkicontheme.h"
25 #include "gtkmodules.h"
34 GtkFileTime modification_time;
44 static void gtk_file_system_base_init (gpointer g_class);
45 static void gtk_file_folder_base_init (gpointer g_class);
48 gtk_file_system_error_quark (void)
50 return 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 (I_("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->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);
102 gtk_file_info_free (GtkFileInfo *info)
104 g_return_if_fail (info != NULL);
106 g_free (info->display_name);
107 g_free (info->mime_type);
108 g_free (info->display_key);
109 g_free (info->icon_name);
114 G_CONST_RETURN gchar *
115 gtk_file_info_get_display_name (const GtkFileInfo *info)
117 g_return_val_if_fail (info != NULL, NULL);
119 return info->display_name;
123 * gtk_file_info_get_display_key:
124 * @info: a #GtkFileInfo
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.
130 * Return value: The collate key for the display name, or %NULL
131 * if the display name hasn't been set.
133 G_CONST_RETURN gchar *
134 gtk_file_info_get_display_key (const GtkFileInfo *info)
136 g_return_val_if_fail (info != NULL, NULL);
138 if (!info->display_key && info->display_name)
140 /* Since info->display_key is only a cache, we cast off the const
142 ((GtkFileInfo *)info)->display_key = g_utf8_collate_key_for_filename (info->display_name, -1);
145 return info->display_key;
149 gtk_file_info_set_display_name (GtkFileInfo *info,
150 const gchar *display_name)
152 g_return_if_fail (info != NULL);
154 if (display_name == info->display_name)
157 g_free (info->display_name);
158 if (info->display_key)
160 g_free (info->display_key);
161 info->display_key = NULL;
164 info->display_name = g_strdup (display_name);
168 gtk_file_info_get_is_folder (const GtkFileInfo *info)
170 g_return_val_if_fail (info != NULL, FALSE);
172 return info->is_folder;
176 gtk_file_info_set_is_folder (GtkFileInfo *info,
179 g_return_if_fail (info != NULL);
181 info->is_folder = is_folder != FALSE;
185 gtk_file_info_get_is_hidden (const GtkFileInfo *info)
187 g_return_val_if_fail (info != NULL, FALSE);
189 return info->is_hidden;
193 gtk_file_info_set_is_hidden (GtkFileInfo *info,
196 g_return_if_fail (info != NULL);
198 info->is_hidden = is_hidden != FALSE;
201 G_CONST_RETURN gchar *
202 gtk_file_info_get_mime_type (const GtkFileInfo *info)
204 g_return_val_if_fail (info != NULL, NULL);
206 return info->mime_type;
210 gtk_file_info_set_mime_type (GtkFileInfo *info,
211 const gchar *mime_type)
213 g_return_if_fail (info != NULL);
215 g_free (info->mime_type);
217 info->mime_type = g_strdup (mime_type);
221 gtk_file_info_get_modification_time (const GtkFileInfo *info)
223 g_return_val_if_fail (info != NULL, 0);
225 return info->modification_time;
229 gtk_file_info_set_modification_time (GtkFileInfo *info,
230 GtkFileTime modification_time)
232 g_return_if_fail (info != NULL);
234 info->modification_time = modification_time;
238 gtk_file_info_get_size (const GtkFileInfo *info)
240 g_return_val_if_fail (info != NULL, 0);
246 gtk_file_info_set_size (GtkFileInfo *info,
249 g_return_if_fail (info != NULL);
250 g_return_if_fail (size >= 0);
256 gtk_file_info_set_icon_name (GtkFileInfo *info,
257 const gchar *icon_name)
259 g_return_if_fail (info != NULL);
261 g_free (info->icon_name);
263 info->icon_name = g_strdup (icon_name);
266 G_CONST_RETURN gchar *
267 gtk_file_info_get_icon_name (const GtkFileInfo *info)
269 g_return_val_if_fail (info != NULL, NULL);
271 return info->icon_name;
275 gtk_file_info_render_icon (const GtkFileInfo *info,
280 GdkPixbuf *pixbuf = NULL;
282 g_return_val_if_fail (info != NULL, NULL);
283 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
287 if (g_path_is_absolute (info->icon_name))
288 pixbuf = gdk_pixbuf_new_from_file_at_size (info->icon_name,
294 GtkIconTheme *icon_theme;
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);
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,
311 if (!pixbuf && error)
313 GTK_FILE_SYSTEM_ERROR,
314 GTK_FILE_SYSTEM_ERROR_FAILED,
315 _("Could not get a stock icon for %s\n"),
322 /*****************************************
323 * GtkFileSystemHandle *
324 *****************************************/
332 G_DEFINE_TYPE (GtkFileSystemHandle, gtk_file_system_handle, G_TYPE_OBJECT)
335 gtk_file_system_handle_init (GtkFileSystemHandle *handle)
337 handle->file_system = NULL;
338 handle->cancelled = FALSE;
342 gtk_file_system_handle_set_property (GObject *object,
347 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
351 gtk_file_system_handle_get_property (GObject *object,
356 GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (object);
361 g_value_set_boolean (value, handle->cancelled);
365 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
371 gtk_file_system_handle_class_init (GtkFileSystemHandleClass *klass)
373 GObjectClass *o_class;
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;
379 g_object_class_install_property (o_class,
381 g_param_spec_boolean ("cancelled",
383 P_("Whether or not the operation has been successfully cancelled"),
388 /*****************************************
390 *****************************************/
392 gtk_file_system_get_type (void)
394 static GType file_system_type = 0;
396 if (!file_system_type)
398 const GTypeInfo file_system_info =
400 sizeof (GtkFileSystemIface), /* class_size */
401 gtk_file_system_base_init, /* base_init */
402 NULL, /* base_finalize */
405 file_system_type = g_type_register_static (G_TYPE_INTERFACE,
407 &file_system_info, 0);
409 g_type_interface_add_prerequisite (file_system_type, G_TYPE_OBJECT);
412 return file_system_type;
416 gtk_file_system_base_init (gpointer g_class)
418 static gboolean initialized = FALSE;
422 GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
424 g_signal_new (I_("volumes-changed"),
427 G_STRUCT_OFFSET (GtkFileSystemIface, volumes_changed),
429 g_cclosure_marshal_VOID__VOID,
431 g_signal_new (I_("bookmarks-changed"),
434 G_STRUCT_OFFSET (GtkFileSystemIface, bookmarks_changed),
436 g_cclosure_marshal_VOID__VOID,
444 gtk_file_system_list_volumes (GtkFileSystem *file_system)
446 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
448 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_volumes (file_system);
451 GtkFileSystemHandle *
452 gtk_file_system_get_folder (GtkFileSystem *file_system,
453 const GtkFilePath *path,
454 GtkFileInfoType types,
455 GtkFileSystemGetFolderCallback callback,
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);
462 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_folder (file_system, path, types, callback, data);
465 GtkFileSystemHandle *
466 gtk_file_system_get_info (GtkFileSystem *file_system,
467 const GtkFilePath *path,
468 GtkFileInfoType types,
469 GtkFileSystemGetInfoCallback callback,
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);
476 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_info (file_system, path, types, callback, data);
479 GtkFileSystemHandle *
480 gtk_file_system_create_folder (GtkFileSystem *file_system,
481 const GtkFilePath *path,
482 GtkFileSystemCreateFolderCallback callback,
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);
489 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->create_folder (file_system, path, callback, data);
493 gtk_file_system_cancel_operation (GtkFileSystemHandle *handle)
495 g_return_if_fail (GTK_IS_FILE_SYSTEM_HANDLE (handle));
497 GTK_FILE_SYSTEM_GET_IFACE (handle->file_system)->cancel_operation (handle);
501 * gtk_file_system_get_volume_for_path:
502 * @file_system: a #GtkFileSystem
503 * @path: a #GtkFilePath
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.
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().
513 GtkFileSystemVolume *
514 gtk_file_system_get_volume_for_path (GtkFileSystem *file_system,
515 const GtkFilePath *path)
517 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
518 g_return_val_if_fail (path != NULL, NULL);
520 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_volume_for_path (file_system, path);
524 * gtk_file_system_volume_free:
525 * @file_system: a #GtkFileSystem
526 * @volume: a #GtkFileSystemVolume
528 * Frees a #GtkFileSystemVolume structure as returned by
529 * gtk_file_system_list_volumes().
532 gtk_file_system_volume_free (GtkFileSystem *file_system,
533 GtkFileSystemVolume *volume)
535 g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system));
536 g_return_if_fail (volume != NULL);
538 GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_free (file_system, volume);
542 * gtk_file_system_volume_get_base_path:
543 * @file_system: a #GtkFileSystem
544 * @volume: a #GtkFileSystemVolume
546 * Queries the base path for a volume. For example, a CD-ROM device may yield a
547 * path of "/mnt/cdrom".
549 * Return value: a #GtkFilePath with the base mount path of the specified
553 gtk_file_system_volume_get_base_path (GtkFileSystem *file_system,
554 GtkFileSystemVolume *volume)
556 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
557 g_return_val_if_fail (volume != NULL, NULL);
559 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_base_path (file_system, volume);
563 * gtk_file_system_volume_get_is_mounted:
564 * @file_system: a #GtkFileSystem
565 * @volume: a #GtkFileSystemVolume
567 * Queries whether a #GtkFileSystemVolume is mounted or not. If it is not, it
568 * can be mounted with gtk_file_system_volume_mount().
570 * Return value: TRUE if the @volume is mounted, FALSE otherwise.
573 gtk_file_system_volume_get_is_mounted (GtkFileSystem *file_system,
574 GtkFileSystemVolume *volume)
576 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
577 g_return_val_if_fail (volume != NULL, FALSE);
579 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_is_mounted (file_system, volume);
583 * gtk_file_system_volume_mount:
584 * @file_system: a #GtkFileSystem
585 * @volume: a #GtkFileSystemVolume
586 * @error: location to store error, or %NULL
588 * Tries to mount an unmounted volume. This may cause the "volumes-changed"
589 * signal in the @file_system to be emitted.
591 * Return value: TRUE if the @volume was mounted successfully, FALSE otherwise.
593 /* FIXME XXX: update documentation above */
594 GtkFileSystemHandle *
595 gtk_file_system_volume_mount (GtkFileSystem *file_system,
596 GtkFileSystemVolume *volume,
597 GtkFileSystemVolumeMountCallback callback,
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);
604 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_mount (file_system, volume, callback, data);
608 * gtk_file_system_volume_get_display_name:
609 * @file_system: a #GtkFileSystem
610 * @volume: a #GtkFileSystemVolume
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.
615 * Return value: A string with the human-readable name for a #GtkFileSystemVolume.
618 gtk_file_system_volume_get_display_name (GtkFileSystem *file_system,
619 GtkFileSystemVolume *volume)
621 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
622 g_return_val_if_fail (volume != NULL, NULL);
624 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_display_name (file_system, volume);
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
635 * Renders an icon suitable for a file #GtkFileSystemVolume.
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
642 gtk_file_system_volume_render_icon (GtkFileSystem *file_system,
643 GtkFileSystemVolume *volume,
649 GdkPixbuf *pixbuf = NULL;
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);
657 icon_name = gtk_file_system_volume_get_icon_name (file_system, volume,
661 GtkIconTheme *icon_theme;
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);
671 pixbuf = gtk_widget_render_icon (widget,
673 GTK_ICON_SIZE_SMALL_TOOLBAR,
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
685 * Gets an icon name suitable for a #GtkFileSystemVolume.
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.
692 gtk_file_system_volume_get_icon_name (GtkFileSystem *file_system,
693 GtkFileSystemVolume *volume,
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);
700 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_icon_name (file_system,
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
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.
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.
721 gtk_file_system_get_parent (GtkFileSystem *file_system,
722 const GtkFilePath *path,
723 GtkFilePath **parent,
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);
735 result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_parent (file_system, path, parent, error);
736 g_assert (result || *parent == NULL);
742 gtk_file_system_make_path (GtkFileSystem *file_system,
743 const GtkFilePath *base_path,
744 const gchar *display_name,
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);
752 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->make_path (file_system, base_path, display_name, error);
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
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())
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.
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.
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.)
784 * Return value: %TRUE if the parsing succeeds, otherwise, %FALSE.
787 gtk_file_system_parse (GtkFileSystem *file_system,
788 const GtkFilePath *base_path,
790 GtkFilePath **folder,
794 GtkFilePath *tmp_folder = NULL;
795 gchar *tmp_file_part = NULL;
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);
803 result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->parse (file_system, base_path, str,
804 &tmp_folder, &tmp_file_part,
806 g_assert (result || (tmp_folder == NULL && tmp_file_part == NULL));
809 *folder = tmp_folder;
811 gtk_file_path_free (tmp_folder);
814 *file_part = tmp_file_part;
816 g_free (tmp_file_part);
823 gtk_file_system_path_to_uri (GtkFileSystem *file_system,
824 const GtkFilePath *path)
826 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
827 g_return_val_if_fail (path != NULL, NULL);
829 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_uri (file_system, path);
833 gtk_file_system_path_to_filename (GtkFileSystem *file_system,
834 const GtkFilePath *path)
836 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
837 g_return_val_if_fail (path != NULL, NULL);
839 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_filename (file_system, path);
843 gtk_file_system_uri_to_path (GtkFileSystem *file_system,
846 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
847 g_return_val_if_fail (uri != NULL, NULL);
849 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->uri_to_path (file_system, uri);
853 gtk_file_system_filename_to_path (GtkFileSystem *file_system,
854 const gchar *filename)
856 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
857 g_return_val_if_fail (filename != NULL, NULL);
859 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->filename_to_path (file_system, filename);
863 * gtk_file_system_path_is_local:
864 * @filesystem: a #GtkFileSystem
865 * @path: A #GtkFilePath from that filesystem
867 * Checks whether a #GtkFilePath is local; that is whether
868 * gtk_file_system_path_to_filename would return non-%NULL.
870 * Return value: %TRUE if the path is loca
873 gtk_file_system_path_is_local (GtkFileSystem *file_system,
874 const GtkFilePath *path)
879 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
880 g_return_val_if_fail (path != NULL, FALSE);
882 filename = gtk_file_system_path_to_filename (file_system, path);
883 result = filename != NULL;
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
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.
905 * Return value: TRUE if the operation succeeds, FALSE otherwise. In the latter case,
906 * the @error value will be set.
909 gtk_file_system_insert_bookmark (GtkFileSystem *file_system,
910 const GtkFilePath *path,
914 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
915 g_return_val_if_fail (path != NULL, FALSE);
917 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->insert_bookmark (file_system, path, position, error);
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
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.
931 * Return value: TRUE if the operation succeeds, FALSE otherwise. In the latter
932 * case, the @error value will be set.
935 gtk_file_system_remove_bookmark (GtkFileSystem *file_system,
936 const GtkFilePath *path,
939 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
940 g_return_val_if_fail (path != NULL, FALSE);
942 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->remove_bookmark (file_system, path, error);
946 * gtk_file_system_list_bookmarks:
947 * @file_system: a #GtkFileSystem
949 * Queries the list of bookmarks in the file system.
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.
954 * See also: gtk_file_system_get_supports_bookmarks()
957 gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
959 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
961 return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_bookmarks (file_system);
965 * gtk_file_system_get_bookmark_label:
966 * @file_system: a #GtkFileSystem
967 * @path: path of the bookmark
969 * Gets the label to display for a bookmark, or %NULL.
971 * Returns: the label for the bookmark @path
976 gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
977 const GtkFilePath *path)
979 GtkFileSystemIface *iface;
981 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
982 g_return_val_if_fail (path != NULL, NULL);
984 iface = GTK_FILE_SYSTEM_GET_IFACE (file_system);
985 if (iface->get_bookmark_label)
986 return iface->get_bookmark_label (file_system, path);
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
998 * Sets the label to display for a bookmark.
1003 gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
1004 const GtkFilePath *path,
1007 GtkFileSystemIface *iface;
1009 g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system));
1010 g_return_if_fail (path != NULL);
1012 iface = GTK_FILE_SYSTEM_GET_IFACE (file_system);
1013 if (iface->set_bookmark_label)
1014 iface->set_bookmark_label (file_system, path, label);
1017 /*****************************************
1019 *****************************************/
1021 gtk_file_folder_get_type (void)
1023 static GType file_folder_type = 0;
1025 if (!file_folder_type)
1027 const GTypeInfo file_folder_info =
1029 sizeof (GtkFileFolderIface), /* class_size */
1030 gtk_file_folder_base_init, /* base_init */
1031 NULL, /* base_finalize */
1034 file_folder_type = g_type_register_static (G_TYPE_INTERFACE,
1035 I_("GtkFileFolder"),
1036 &file_folder_info, 0);
1038 g_type_interface_add_prerequisite (file_folder_type, G_TYPE_OBJECT);
1041 return file_folder_type;
1045 gtk_file_folder_base_init (gpointer g_class)
1047 static gboolean initialized = FALSE;
1051 GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
1053 g_signal_new (I_("deleted"),
1056 G_STRUCT_OFFSET (GtkFileFolderIface, deleted),
1058 g_cclosure_marshal_VOID__VOID,
1060 g_signal_new (I_("files-added"),
1063 G_STRUCT_OFFSET (GtkFileFolderIface, files_added),
1065 g_cclosure_marshal_VOID__POINTER,
1068 g_signal_new (I_("files-changed"),
1071 G_STRUCT_OFFSET (GtkFileFolderIface, files_changed),
1073 g_cclosure_marshal_VOID__POINTER,
1076 g_signal_new (I_("files-removed"),
1079 G_STRUCT_OFFSET (GtkFileFolderIface, files_removed),
1081 g_cclosure_marshal_VOID__POINTER,
1084 g_signal_new (I_("finished-loading"),
1087 G_STRUCT_OFFSET (GtkFileFolderIface, finished_loading),
1089 g_cclosure_marshal_VOID__VOID,
1097 gtk_file_folder_list_children (GtkFileFolder *folder,
1102 GSList *tmp_children = NULL;
1104 g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), FALSE);
1105 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1107 result = GTK_FILE_FOLDER_GET_IFACE (folder)->list_children (folder, &tmp_children, error);
1108 g_assert (result || tmp_children == NULL);
1111 *children = tmp_children;
1113 gtk_file_paths_free (tmp_children);
1119 gtk_file_folder_get_info (GtkFileFolder *folder,
1120 const GtkFilePath *path,
1123 g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), NULL);
1124 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1126 return GTK_FILE_FOLDER_GET_IFACE (folder)->get_info (folder, path, error);
1130 gtk_file_folder_is_finished_loading (GtkFileFolder *folder)
1132 GtkFileFolderIface *iface;
1134 g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), TRUE);
1136 iface = GTK_FILE_FOLDER_GET_IFACE (folder);
1137 if (!iface->is_finished_loading)
1140 return iface->is_finished_loading (folder);
1144 /*****************************************
1145 * GtkFilePath modules *
1146 *****************************************/
1148 /* We make these real functions in case either copy or free are implemented as macros
1151 gtk_file_path_real_copy (gpointer boxed)
1153 return gtk_file_path_copy ((GtkFilePath *) boxed);
1157 gtk_file_path_real_free (gpointer boxed)
1159 gtk_file_path_free (boxed);
1163 gtk_file_path_get_type (void)
1165 static GType 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);
1177 gtk_file_paths_sort (GSList *paths)
1180 return g_slist_sort (paths, (GCompareFunc)strcmp);
1182 return g_slist_sort (paths, (GCompareFunc)_gtk_file_system_win32_path_compare);
1187 * gtk_file_paths_copy:
1188 * @paths: A #GSList of #GtkFilePath structures.
1190 * Copies a list of #GtkFilePath structures.
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.
1196 gtk_file_paths_copy (GSList *paths)
1198 GSList *head, *tail, *l;
1202 for (l = paths; l; l = l->next)
1208 node = g_slist_alloc ();
1215 node->data = gtk_file_path_copy (path);
1223 gtk_file_paths_free (GSList *paths)
1227 for (tmp_list = paths; tmp_list; tmp_list = tmp_list->next)
1228 gtk_file_path_free (tmp_list->data);
1230 g_slist_free (paths);
1233 /*****************************************
1234 * GtkFileSystem modules *
1235 *****************************************/
1237 typedef struct _GtkFileSystemModule GtkFileSystemModule;
1238 typedef struct _GtkFileSystemModuleClass GtkFileSystemModuleClass;
1240 struct _GtkFileSystemModule
1242 GTypeModule parent_instance;
1246 void (*init) (GTypeModule *module);
1247 void (*exit) (void);
1248 GtkFileSystem * (*create) (void);
1253 struct _GtkFileSystemModuleClass
1255 GTypeModuleClass parent_class;
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))
1263 static GSList *loaded_file_systems;
1266 gtk_file_system_module_load (GTypeModule *module)
1268 GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module);
1270 fs_module->library = g_module_open (fs_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
1271 if (!fs_module->library)
1273 g_warning (g_module_error());
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))
1285 g_warning (g_module_error());
1286 g_module_close (fs_module->library);
1291 /* call the filesystems's init function to let it */
1292 /* setup anything it needs to set up. */
1293 fs_module->init (module);
1299 gtk_file_system_module_unload (GTypeModule *module)
1301 GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module);
1305 g_module_close (fs_module->library);
1306 fs_module->library = NULL;
1308 fs_module->init = NULL;
1309 fs_module->exit = NULL;
1310 fs_module->create = NULL;
1313 /* This only will ever be called if an error occurs during
1317 gtk_file_system_module_finalize (GObject *object)
1319 GtkFileSystemModule *module = GTK_FILE_SYSTEM_MODULE (object);
1321 g_free (module->path);
1323 G_OBJECT_CLASS (_gtk_file_system_module_parent_class)->finalize (object);
1327 _gtk_file_system_module_class_init (GtkFileSystemModuleClass *class)
1329 GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
1330 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
1332 module_class->load = gtk_file_system_module_load;
1333 module_class->unload = gtk_file_system_module_unload;
1335 gobject_class->finalize = gtk_file_system_module_finalize;
1339 _gtk_file_system_module_init (GtkFileSystemModule *fs_module)
1344 static GtkFileSystem *
1345 _gtk_file_system_module_create (GtkFileSystemModule *fs_module)
1349 if (g_type_module_use (G_TYPE_MODULE (fs_module)))
1351 fs = fs_module->create ();
1352 g_type_module_unuse (G_TYPE_MODULE (fs_module));
1360 _gtk_file_system_create (const char *file_system_name)
1364 GtkFileSystemModule *fs_module;
1367 for (l = loaded_file_systems; l != NULL; l = l->next)
1369 fs_module = l->data;
1371 if (strcmp (G_TYPE_MODULE (fs_module)->name, file_system_name) == 0)
1372 return _gtk_file_system_module_create (fs_module);
1376 if (g_module_supported ())
1378 module_path = _gtk_find_module (file_system_name, "filesystems");
1382 fs_module = g_object_new (GTK_TYPE_FILE_SYSTEM_MODULE, NULL);
1384 g_type_module_set_name (G_TYPE_MODULE (fs_module), file_system_name);
1385 fs_module->path = g_strdup (module_path);
1387 loaded_file_systems = g_slist_prepend (loaded_file_systems,
1390 fs = _gtk_file_system_module_create (fs_module);
1393 g_free (module_path);
1399 #define __GTK_FILE_SYSTEM_C__
1400 #include "gtkaliasdef.c"