1 /* GTK - The GIMP Toolkit
2 * gtkfilesystem.c: Filesystem abstraction functions.
3 * Copyright (C) 2003, Red Hat, Inc.
4 * Copyright (C) 2007-2008 Carlos Garnacho
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20 * Authors: Carlos Garnacho <carlos@imendio.com>
27 #include <glib/gi18n-lib.h>
29 #include "gtkfilechooser.h"
30 #include "gtkfilesystem.h"
31 #include "gtkicontheme.h"
32 #include "gtkprivate.h"
34 /* #define DEBUG_MODE */
36 #define DEBUG(x) g_debug (x);
41 #define FILES_PER_QUERY 100
43 /* The pointers we return for a GtkFileSystemVolume are opaque tokens; they are
44 * really pointers to GDrive, GVolume or GMount objects. We need an extra
45 * token for the fake "File System" volume. So, we'll return a pointer to
46 * this particular string.
48 static const gchar *root_volume_token = N_("File System");
49 #define IS_ROOT_VOLUME(volume) ((gpointer) (volume) == (gpointer) root_volume_token)
73 static guint fs_signals [FS_LAST_SIGNAL] = { 0, };
75 typedef struct AsyncFuncData AsyncFuncData;
77 struct GtkFileSystemPrivate
79 GVolumeMonitor *volume_monitor;
81 /* This list contains elements that can be
82 * of type GDrive, GVolume and GMount
86 /* This list contains GtkFileSystemBookmark structs */
89 GFileMonitor *bookmarks_monitor;
94 GtkFileSystem *file_system;
96 GCancellable *cancellable;
103 struct GtkFileSystemBookmark
109 G_DEFINE_TYPE (GtkFileSystem, _gtk_file_system, G_TYPE_OBJECT)
112 /* GtkFileSystemBookmark methods */
114 _gtk_file_system_bookmark_free (GtkFileSystemBookmark *bookmark)
116 g_object_unref (bookmark->file);
117 g_free (bookmark->label);
118 g_slice_free (GtkFileSystemBookmark, bookmark);
121 /* GtkFileSystem methods */
123 volumes_changed (GVolumeMonitor *volume_monitor,
127 GtkFileSystem *file_system;
129 gdk_threads_enter ();
131 file_system = GTK_FILE_SYSTEM (user_data);
132 g_signal_emit (file_system, fs_signals[VOLUMES_CHANGED], 0, volume);
133 gdk_threads_leave ();
137 gtk_file_system_dispose (GObject *object)
139 GtkFileSystem *file_system = GTK_FILE_SYSTEM (object);
140 GtkFileSystemPrivate *priv = file_system->priv;
146 g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL);
147 g_slist_free (priv->volumes);
148 priv->volumes = NULL;
151 if (priv->volume_monitor)
153 g_signal_handlers_disconnect_by_func (priv->volume_monitor, volumes_changed, object);
154 g_object_unref (priv->volume_monitor);
155 priv->volume_monitor = NULL;
158 G_OBJECT_CLASS (_gtk_file_system_parent_class)->dispose (object);
162 gtk_file_system_finalize (GObject *object)
164 GtkFileSystem *file_system = GTK_FILE_SYSTEM (object);
165 GtkFileSystemPrivate *priv = file_system->priv;
169 if (priv->bookmarks_monitor)
170 g_object_unref (priv->bookmarks_monitor);
174 g_slist_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
175 g_slist_free (priv->bookmarks);
178 G_OBJECT_CLASS (_gtk_file_system_parent_class)->finalize (object);
182 _gtk_file_system_class_init (GtkFileSystemClass *class)
184 GObjectClass *object_class = G_OBJECT_CLASS (class);
186 object_class->dispose = gtk_file_system_dispose;
187 object_class->finalize = gtk_file_system_finalize;
189 fs_signals[BOOKMARKS_CHANGED] =
190 g_signal_new ("bookmarks-changed",
191 G_TYPE_FROM_CLASS (object_class),
193 G_STRUCT_OFFSET (GtkFileSystemClass, bookmarks_changed),
195 g_cclosure_marshal_VOID__VOID,
198 fs_signals[VOLUMES_CHANGED] =
199 g_signal_new ("volumes-changed",
200 G_TYPE_FROM_CLASS (object_class),
202 G_STRUCT_OFFSET (GtkFileSystemClass, volumes_changed),
204 g_cclosure_marshal_VOID__VOID,
207 g_type_class_add_private (object_class, sizeof (GtkFileSystemPrivate));
211 get_bookmarks_file (void)
216 filename = g_build_filename (g_get_home_dir (), ".gtk-bookmarks", NULL);
217 file = g_file_new_for_path (filename);
224 read_bookmarks (GFile *file)
227 gchar **lines, *space;
228 GSList *bookmarks = NULL;
231 if (!g_file_load_contents (file, NULL, &contents,
235 lines = g_strsplit (contents, "\n", -1);
237 for (i = 0; lines[i]; i++)
239 GtkFileSystemBookmark *bookmark;
244 if (!g_utf8_validate (lines[i], -1, NULL))
247 bookmark = g_slice_new0 (GtkFileSystemBookmark);
249 if ((space = strchr (lines[i], ' ')) != NULL)
252 bookmark->label = g_strdup (space + 1);
255 bookmark->file = g_file_new_for_uri (lines[i]);
256 bookmarks = g_slist_prepend (bookmarks, bookmark);
259 bookmarks = g_slist_reverse (bookmarks);
267 save_bookmarks (GFile *bookmarks_file,
270 GError *error = NULL;
274 contents = g_string_new ("");
276 for (l = bookmarks; l; l = l->next)
278 GtkFileSystemBookmark *bookmark = l->data;
281 uri = g_file_get_uri (bookmark->file);
285 g_string_append (contents, uri);
288 g_string_append_printf (contents, " %s", bookmark->label);
290 g_string_append_c (contents, '\n');
294 if (!g_file_replace_contents (bookmarks_file,
296 strlen (contents->str),
297 NULL, FALSE, 0, NULL,
300 g_critical ("%s", error->message);
301 g_error_free (error);
304 g_string_free (contents, TRUE);
308 bookmarks_file_changed (GFileMonitor *monitor,
311 GFileMonitorEvent event,
314 GtkFileSystem *file_system = GTK_FILE_SYSTEM (data);
315 GtkFileSystemPrivate *priv = file_system->priv;
319 case G_FILE_MONITOR_EVENT_CHANGED:
320 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
321 case G_FILE_MONITOR_EVENT_CREATED:
322 case G_FILE_MONITOR_EVENT_DELETED:
323 g_slist_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
324 g_slist_free (priv->bookmarks);
326 priv->bookmarks = read_bookmarks (file);
328 gdk_threads_enter ();
329 g_signal_emit (data, fs_signals[BOOKMARKS_CHANGED], 0);
330 gdk_threads_leave ();
333 /* ignore at the moment */
339 mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
347 mount_root = g_mount_get_root (mount);
349 for (l = volumes; l != NULL; l = l->next)
351 GVolume *volume = G_VOLUME (l->data);
352 GFile *volume_activation_root;
354 volume_activation_root = g_volume_get_activation_root (volume);
355 if (volume_activation_root != NULL)
357 if (g_file_has_prefix (volume_activation_root, mount_root))
360 g_object_unref (volume_activation_root);
363 g_object_unref (volume_activation_root);
367 g_object_unref (mount_root);
372 get_volumes_list (GtkFileSystem *file_system)
374 GtkFileSystemPrivate *priv = file_system->priv;
385 g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL);
386 g_slist_free (priv->volumes);
387 priv->volumes = NULL;
390 /* first go through all connected drives */
391 drives = g_volume_monitor_get_connected_drives (priv->volume_monitor);
393 for (l = drives; l != NULL; l = l->next)
396 volumes = g_drive_get_volumes (drive);
400 for (ll = volumes; ll != NULL; ll = ll->next)
403 mount = g_volume_get_mount (volume);
407 /* Show mounted volume */
408 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
409 g_object_unref (mount);
413 /* Do show the unmounted volumes in the sidebar;
414 * this is so the user can mount it (in case automounting
417 * Also, even if automounting is enabled, this gives a visual
418 * cue that the user should remember to yank out the media if
419 * he just unmounted it.
421 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
424 g_object_unref (volume);
427 g_list_free (volumes);
429 else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive))
431 /* If the drive has no mountable volumes and we cannot detect media change.. we
432 * display the drive in the sidebar so the user can manually poll the drive by
433 * right clicking and selecting "Rescan..."
435 * This is mainly for drives like floppies where media detection doesn't
436 * work.. but it's also for human beings who like to turn off media detection
437 * in the OS to save battery juice.
440 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (drive));
443 g_object_unref (drive);
446 g_list_free (drives);
448 /* add all volumes that is not associated with a drive */
449 volumes = g_volume_monitor_get_volumes (priv->volume_monitor);
451 for (l = volumes; l != NULL; l = l->next)
454 drive = g_volume_get_drive (volume);
458 g_object_unref (drive);
462 mount = g_volume_get_mount (volume);
466 /* show this mount */
467 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
468 g_object_unref (mount);
472 /* see comment above in why we add an icon for a volume */
473 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
476 g_object_unref (volume);
479 /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
480 mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
482 for (l = mounts; l != NULL; l = l->next)
485 volume = g_mount_get_volume (mount);
489 g_object_unref (volume);
493 /* if there's exists one or more volumes with an activation root inside the mount,
494 * don't display the mount
496 if (mount_referenced_by_volume_activation_root (volumes, mount))
498 g_object_unref (mount);
502 /* show this mount */
503 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
504 g_object_unref (mount);
507 g_list_free (volumes);
509 g_list_free (mounts);
513 _gtk_file_system_init (GtkFileSystem *file_system)
515 GtkFileSystemPrivate *priv;
516 GFile *bookmarks_file;
517 GError *error = NULL;
521 file_system->priv = G_TYPE_INSTANCE_GET_PRIVATE (file_system,
522 GTK_TYPE_FILE_SYSTEM,
523 GtkFileSystemPrivate);
524 priv = file_system->priv;
527 priv->volume_monitor = g_volume_monitor_get ();
529 g_signal_connect (priv->volume_monitor, "mount-added",
530 G_CALLBACK (volumes_changed), file_system);
531 g_signal_connect (priv->volume_monitor, "mount-removed",
532 G_CALLBACK (volumes_changed), file_system);
533 g_signal_connect (priv->volume_monitor, "mount-changed",
534 G_CALLBACK (volumes_changed), file_system);
535 g_signal_connect (priv->volume_monitor, "volume-added",
536 G_CALLBACK (volumes_changed), file_system);
537 g_signal_connect (priv->volume_monitor, "volume-removed",
538 G_CALLBACK (volumes_changed), file_system);
539 g_signal_connect (priv->volume_monitor, "volume-changed",
540 G_CALLBACK (volumes_changed), file_system);
541 g_signal_connect (priv->volume_monitor, "drive-connected",
542 G_CALLBACK (volumes_changed), file_system);
543 g_signal_connect (priv->volume_monitor, "drive-disconnected",
544 G_CALLBACK (volumes_changed), file_system);
545 g_signal_connect (priv->volume_monitor, "drive-changed",
546 G_CALLBACK (volumes_changed), file_system);
549 bookmarks_file = get_bookmarks_file ();
550 priv->bookmarks = read_bookmarks (bookmarks_file);
551 priv->bookmarks_monitor = g_file_monitor_file (bookmarks_file,
556 g_warning ("%s", error->message);
557 g_error_free (error);
560 g_signal_connect (priv->bookmarks_monitor, "changed",
561 G_CALLBACK (bookmarks_file_changed), file_system);
563 g_object_unref (bookmarks_file);
566 /* GtkFileSystem public methods */
568 _gtk_file_system_new (void)
570 return g_object_new (GTK_TYPE_FILE_SYSTEM, NULL);
574 _gtk_file_system_list_volumes (GtkFileSystem *file_system)
576 GtkFileSystemPrivate *priv = file_system->priv;
579 DEBUG ("list_volumes");
581 get_volumes_list (file_system);
583 list = g_slist_copy (priv->volumes);
586 /* Prepend root volume */
587 list = g_slist_prepend (list, (gpointer) root_volume_token);
594 _gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
596 GtkFileSystemPrivate *priv = file_system->priv;
597 GSList *bookmarks, *files = NULL;
599 DEBUG ("list_bookmarks");
601 bookmarks = priv->bookmarks;
605 GtkFileSystemBookmark *bookmark;
607 bookmark = bookmarks->data;
608 bookmarks = bookmarks->next;
610 files = g_slist_prepend (files, g_object_ref (bookmark->file));
613 return g_slist_reverse (files);
617 free_async_data (AsyncFuncData *async_data)
619 g_object_unref (async_data->file_system);
620 g_object_unref (async_data->file);
621 g_object_unref (async_data->cancellable);
623 g_free (async_data->attributes);
628 query_info_callback (GObject *source_object,
629 GAsyncResult *result,
632 AsyncFuncData *async_data;
633 GError *error = NULL;
634 GFileInfo *file_info;
637 DEBUG ("query_info_callback");
639 file = G_FILE (source_object);
640 async_data = (AsyncFuncData *) user_data;
641 file_info = g_file_query_info_finish (file, result, &error);
643 if (async_data->callback)
645 gdk_threads_enter ();
646 ((GtkFileSystemGetInfoCallback) async_data->callback) (async_data->cancellable,
647 file_info, error, async_data->data);
648 gdk_threads_leave ();
652 g_object_unref (file_info);
655 g_error_free (error);
657 free_async_data (async_data);
661 _gtk_file_system_get_info (GtkFileSystem *file_system,
663 const gchar *attributes,
664 GtkFileSystemGetInfoCallback callback,
667 GCancellable *cancellable;
668 AsyncFuncData *async_data;
670 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
671 g_return_val_if_fail (G_IS_FILE (file), NULL);
673 cancellable = g_cancellable_new ();
675 async_data = g_new0 (AsyncFuncData, 1);
676 async_data->file_system = g_object_ref (file_system);
677 async_data->file = g_object_ref (file);
678 async_data->cancellable = g_object_ref (cancellable);
680 async_data->callback = callback;
681 async_data->data = data;
683 g_file_query_info_async (file,
685 G_FILE_QUERY_INFO_NONE,
695 drive_poll_for_media_cb (GObject *source_object,
696 GAsyncResult *result,
699 AsyncFuncData *async_data;
700 GError *error = NULL;
702 g_drive_poll_for_media_finish (G_DRIVE (source_object), result, &error);
703 async_data = (AsyncFuncData *) user_data;
705 gdk_threads_enter ();
706 ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
707 (GtkFileSystemVolume *) source_object,
708 error, async_data->data);
709 gdk_threads_leave ();
712 g_error_free (error);
716 volume_mount_cb (GObject *source_object,
717 GAsyncResult *result,
720 AsyncFuncData *async_data;
721 GError *error = NULL;
723 g_volume_mount_finish (G_VOLUME (source_object), result, &error);
724 async_data = (AsyncFuncData *) user_data;
726 gdk_threads_enter ();
727 ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
728 (GtkFileSystemVolume *) source_object,
729 error, async_data->data);
730 gdk_threads_leave ();
733 g_error_free (error);
737 _gtk_file_system_mount_volume (GtkFileSystem *file_system,
738 GtkFileSystemVolume *volume,
739 GMountOperation *mount_operation,
740 GtkFileSystemVolumeMountCallback callback,
743 GCancellable *cancellable;
744 AsyncFuncData *async_data;
745 gboolean handled = FALSE;
747 DEBUG ("volume_mount");
749 cancellable = g_cancellable_new ();
751 async_data = g_new0 (AsyncFuncData, 1);
752 async_data->file_system = g_object_ref (file_system);
753 async_data->cancellable = g_object_ref (cancellable);
755 async_data->callback = callback;
756 async_data->data = data;
758 if (G_IS_DRIVE (volume))
760 /* this path happens for drives that are not polled by the OS and where the last media
761 * check indicated that no media was available. So the thing to do here is to
762 * invoke poll_for_media() on the drive
764 g_drive_poll_for_media (G_DRIVE (volume), cancellable, drive_poll_for_media_cb, async_data);
767 else if (G_IS_VOLUME (volume))
769 g_volume_mount (G_VOLUME (volume), G_MOUNT_MOUNT_NONE, mount_operation, cancellable, volume_mount_cb, async_data);
774 free_async_data (async_data);
780 enclosing_volume_mount_cb (GObject *source_object,
781 GAsyncResult *result,
784 GtkFileSystemVolume *volume;
785 AsyncFuncData *async_data;
786 GError *error = NULL;
788 async_data = (AsyncFuncData *) user_data;
789 g_file_mount_enclosing_volume_finish (G_FILE (source_object), result, &error);
790 volume = _gtk_file_system_get_volume_for_file (async_data->file_system, G_FILE (source_object));
792 /* Silently drop G_IO_ERROR_ALREADY_MOUNTED error for gvfs backends without visible mounts. */
793 /* Better than doing query_info with additional I/O every time. */
794 if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED))
795 g_clear_error (&error);
797 gdk_threads_enter ();
798 ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, volume,
799 error, async_data->data);
800 gdk_threads_leave ();
803 g_error_free (error);
805 _gtk_file_system_volume_unref (volume);
809 _gtk_file_system_mount_enclosing_volume (GtkFileSystem *file_system,
811 GMountOperation *mount_operation,
812 GtkFileSystemVolumeMountCallback callback,
815 GCancellable *cancellable;
816 AsyncFuncData *async_data;
818 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
819 g_return_val_if_fail (G_IS_FILE (file), NULL);
821 DEBUG ("mount_enclosing_volume");
823 cancellable = g_cancellable_new ();
825 async_data = g_new0 (AsyncFuncData, 1);
826 async_data->file_system = g_object_ref (file_system);
827 async_data->file = g_object_ref (file);
828 async_data->cancellable = g_object_ref (cancellable);
830 async_data->callback = callback;
831 async_data->data = data;
833 g_file_mount_enclosing_volume (file,
837 enclosing_volume_mount_cb,
843 _gtk_file_system_insert_bookmark (GtkFileSystem *file_system,
848 GtkFileSystemPrivate *priv = file_system->priv;
850 GtkFileSystemBookmark *bookmark;
851 gboolean result = TRUE;
852 GFile *bookmarks_file;
854 bookmarks = priv->bookmarks;
858 bookmark = bookmarks->data;
859 bookmarks = bookmarks->next;
861 if (g_file_equal (bookmark->file, file))
863 /* File is already in bookmarks */
871 gchar *uri = g_file_get_uri (file);
874 GTK_FILE_CHOOSER_ERROR,
875 GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
876 "%s already exists in the bookmarks list",
884 bookmark = g_slice_new0 (GtkFileSystemBookmark);
885 bookmark->file = g_object_ref (file);
887 priv->bookmarks = g_slist_insert (priv->bookmarks, bookmark, position);
889 bookmarks_file = get_bookmarks_file ();
890 save_bookmarks (bookmarks_file, priv->bookmarks);
891 g_object_unref (bookmarks_file);
893 g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0);
899 _gtk_file_system_remove_bookmark (GtkFileSystem *file_system,
903 GtkFileSystemPrivate *priv = file_system->priv;
904 GtkFileSystemBookmark *bookmark;
906 gboolean result = FALSE;
907 GFile *bookmarks_file;
909 if (!priv->bookmarks)
912 bookmarks = priv->bookmarks;
916 bookmark = bookmarks->data;
918 if (g_file_equal (bookmark->file, file))
921 priv->bookmarks = g_slist_remove_link (priv->bookmarks, bookmarks);
922 _gtk_file_system_bookmark_free (bookmark);
923 g_slist_free_1 (bookmarks);
927 bookmarks = bookmarks->next;
932 gchar *uri = g_file_get_uri (file);
935 GTK_FILE_CHOOSER_ERROR,
936 GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
937 "%s does not exist in the bookmarks list",
945 bookmarks_file = get_bookmarks_file ();
946 save_bookmarks (bookmarks_file, priv->bookmarks);
947 g_object_unref (bookmarks_file);
949 g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0);
955 _gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
958 GtkFileSystemPrivate *priv = file_system->priv;
962 DEBUG ("get_bookmark_label");
964 bookmarks = priv->bookmarks;
968 GtkFileSystemBookmark *bookmark;
970 bookmark = bookmarks->data;
971 bookmarks = bookmarks->next;
973 if (g_file_equal (file, bookmark->file))
975 label = g_strdup (bookmark->label);
984 _gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
988 GtkFileSystemPrivate *priv = file_system->priv;
989 gboolean changed = FALSE;
990 GFile *bookmarks_file;
993 DEBUG ("set_bookmark_label");
995 bookmarks = priv->bookmarks;
999 GtkFileSystemBookmark *bookmark;
1001 bookmark = bookmarks->data;
1002 bookmarks = bookmarks->next;
1004 if (g_file_equal (file, bookmark->file))
1006 g_free (bookmark->label);
1007 bookmark->label = g_strdup (label);
1013 bookmarks_file = get_bookmarks_file ();
1014 save_bookmarks (bookmarks_file, priv->bookmarks);
1015 g_object_unref (bookmarks_file);
1018 g_signal_emit_by_name (file_system, "bookmarks-changed", 0);
1021 GtkFileSystemVolume *
1022 _gtk_file_system_get_volume_for_file (GtkFileSystem *file_system,
1027 DEBUG ("get_volume_for_file");
1029 mount = g_file_find_enclosing_mount (file, NULL, NULL);
1031 if (!mount && g_file_is_native (file))
1032 return (GtkFileSystemVolume *) root_volume_token;
1034 return (GtkFileSystemVolume *) mount;
1037 /* GtkFileSystemVolume public methods */
1039 _gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume)
1041 DEBUG ("volume_get_display_name");
1043 if (IS_ROOT_VOLUME (volume))
1044 return g_strdup (_(root_volume_token));
1045 if (G_IS_DRIVE (volume))
1046 return g_drive_get_name (G_DRIVE (volume));
1047 else if (G_IS_MOUNT (volume))
1048 return g_mount_get_name (G_MOUNT (volume));
1049 else if (G_IS_VOLUME (volume))
1050 return g_volume_get_name (G_VOLUME (volume));
1056 _gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume)
1060 DEBUG ("volume_is_mounted");
1062 if (IS_ROOT_VOLUME (volume))
1067 if (G_IS_MOUNT (volume))
1069 else if (G_IS_VOLUME (volume))
1073 mount = g_volume_get_mount (G_VOLUME (volume));
1078 g_object_unref (mount);
1086 _gtk_file_system_volume_get_root (GtkFileSystemVolume *volume)
1090 DEBUG ("volume_get_base");
1092 if (IS_ROOT_VOLUME (volume))
1093 return g_file_new_for_uri ("file:///");
1095 if (G_IS_MOUNT (volume))
1096 file = g_mount_get_root (G_MOUNT (volume));
1097 else if (G_IS_VOLUME (volume))
1101 mount = g_volume_get_mount (G_VOLUME (volume));
1105 file = g_mount_get_root (mount);
1106 g_object_unref (mount);
1114 get_pixbuf_from_gicon (GIcon *icon,
1120 GtkIconTheme *icon_theme;
1121 GtkIconInfo *icon_info;
1124 screen = gtk_widget_get_screen (GTK_WIDGET (widget));
1125 icon_theme = gtk_icon_theme_get_for_screen (screen);
1127 icon_info = gtk_icon_theme_lookup_by_gicon (icon_theme,
1130 GTK_ICON_LOOKUP_USE_BUILTIN);
1135 pixbuf = gtk_icon_info_load_icon (icon_info, error);
1136 gtk_icon_info_free (icon_info);
1142 _gtk_file_system_volume_render_icon (GtkFileSystemVolume *volume,
1150 DEBUG ("volume_get_icon_name");
1152 if (IS_ROOT_VOLUME (volume))
1153 icon = g_themed_icon_new ("drive-harddisk");
1154 else if (G_IS_DRIVE (volume))
1155 icon = g_drive_get_icon (G_DRIVE (volume));
1156 else if (G_IS_VOLUME (volume))
1157 icon = g_volume_get_icon (G_VOLUME (volume));
1158 else if (G_IS_MOUNT (volume))
1159 icon = g_mount_get_icon (G_MOUNT (volume));
1164 pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, error);
1166 g_object_unref (icon);
1171 GtkFileSystemVolume *
1172 _gtk_file_system_volume_ref (GtkFileSystemVolume *volume)
1174 if (IS_ROOT_VOLUME (volume))
1177 if (G_IS_MOUNT (volume) ||
1178 G_IS_VOLUME (volume) ||
1179 G_IS_DRIVE (volume))
1180 g_object_ref (volume);
1186 _gtk_file_system_volume_unref (GtkFileSystemVolume *volume)
1188 /* Root volume doesn't need to be freed */
1189 if (IS_ROOT_VOLUME (volume))
1192 if (G_IS_MOUNT (volume) ||
1193 G_IS_VOLUME (volume) ||
1194 G_IS_DRIVE (volume))
1195 g_object_unref (volume);
1198 /* GFileInfo helper functions */
1200 _gtk_file_info_render_icon (GFileInfo *info,
1205 GdkPixbuf *pixbuf = NULL;
1206 const gchar *thumbnail_path;
1208 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
1211 pixbuf = gdk_pixbuf_new_from_file_at_size (thumbnail_path,
1212 icon_size, icon_size,
1217 icon = g_file_info_get_icon (info);
1220 pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
1224 /* Use general fallback for all files without icon */
1225 icon = g_themed_icon_new ("text-x-generic");
1226 pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
1227 g_object_unref (icon);
1235 _gtk_file_info_consider_as_directory (GFileInfo *info)
1237 GFileType type = g_file_info_get_file_type (info);
1239 return (type == G_FILE_TYPE_DIRECTORY ||
1240 type == G_FILE_TYPE_MOUNTABLE ||
1241 type == G_FILE_TYPE_SHORTCUT);