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 library 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 library 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 Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 * Authors: Carlos Garnacho <carlos@imendio.com>
26 #include <glib/gi18n-lib.h>
28 #include "gtkfilechooser.h"
29 #include "gtkfilesystem.h"
30 #include "gtkicontheme.h"
31 #include "gtkprivate.h"
33 /* #define DEBUG_MODE */
35 #define DEBUG(x) g_debug (x);
40 #define FILES_PER_QUERY 100
42 /* The pointers we return for a GtkFileSystemVolume are opaque tokens; they are
43 * really pointers to GDrive, GVolume or GMount objects. We need an extra
44 * token for the fake "File System" volume. So, we'll return a pointer to
45 * this particular string.
47 static const gchar *root_volume_token = N_("File System");
48 #define IS_ROOT_VOLUME(volume) ((gpointer) (volume) == (gpointer) root_volume_token)
72 static guint fs_signals [FS_LAST_SIGNAL] = { 0, };
74 typedef struct AsyncFuncData AsyncFuncData;
76 struct GtkFileSystemPrivate
78 GVolumeMonitor *volume_monitor;
80 /* This list contains elements that can be
81 * of type GDrive, GVolume and GMount
85 /* This list contains GtkFileSystemBookmark structs */
88 GFileMonitor *bookmarks_monitor;
93 GtkFileSystem *file_system;
95 GCancellable *cancellable;
102 struct GtkFileSystemBookmark
108 G_DEFINE_TYPE (GtkFileSystem, _gtk_file_system, G_TYPE_OBJECT)
111 /* GtkFileSystemBookmark methods */
113 _gtk_file_system_bookmark_free (GtkFileSystemBookmark *bookmark)
115 g_object_unref (bookmark->file);
116 g_free (bookmark->label);
117 g_slice_free (GtkFileSystemBookmark, bookmark);
120 /* GtkFileSystem methods */
122 volumes_changed (GVolumeMonitor *volume_monitor,
126 GtkFileSystem *file_system;
128 gdk_threads_enter ();
130 file_system = GTK_FILE_SYSTEM (user_data);
131 g_signal_emit (file_system, fs_signals[VOLUMES_CHANGED], 0, volume);
132 gdk_threads_leave ();
136 gtk_file_system_dispose (GObject *object)
138 GtkFileSystem *file_system = GTK_FILE_SYSTEM (object);
139 GtkFileSystemPrivate *priv = file_system->priv;
145 g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL);
146 g_slist_free (priv->volumes);
147 priv->volumes = NULL;
150 if (priv->volume_monitor)
152 g_signal_handlers_disconnect_by_func (priv->volume_monitor, volumes_changed, object);
153 g_object_unref (priv->volume_monitor);
154 priv->volume_monitor = NULL;
157 G_OBJECT_CLASS (_gtk_file_system_parent_class)->dispose (object);
161 gtk_file_system_finalize (GObject *object)
163 GtkFileSystem *file_system = GTK_FILE_SYSTEM (object);
164 GtkFileSystemPrivate *priv = file_system->priv;
168 if (priv->bookmarks_monitor)
169 g_object_unref (priv->bookmarks_monitor);
173 g_slist_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
174 g_slist_free (priv->bookmarks);
177 G_OBJECT_CLASS (_gtk_file_system_parent_class)->finalize (object);
181 _gtk_file_system_class_init (GtkFileSystemClass *class)
183 GObjectClass *object_class = G_OBJECT_CLASS (class);
185 object_class->dispose = gtk_file_system_dispose;
186 object_class->finalize = gtk_file_system_finalize;
188 fs_signals[BOOKMARKS_CHANGED] =
189 g_signal_new ("bookmarks-changed",
190 G_TYPE_FROM_CLASS (object_class),
192 G_STRUCT_OFFSET (GtkFileSystemClass, bookmarks_changed),
194 g_cclosure_marshal_VOID__VOID,
197 fs_signals[VOLUMES_CHANGED] =
198 g_signal_new ("volumes-changed",
199 G_TYPE_FROM_CLASS (object_class),
201 G_STRUCT_OFFSET (GtkFileSystemClass, volumes_changed),
203 g_cclosure_marshal_VOID__VOID,
206 g_type_class_add_private (object_class, sizeof (GtkFileSystemPrivate));
210 get_bookmarks_file (void)
215 filename = g_build_filename (g_get_home_dir (), ".gtk-bookmarks", NULL);
216 file = g_file_new_for_path (filename);
223 read_bookmarks (GFile *file)
226 gchar **lines, *space;
227 GSList *bookmarks = NULL;
230 if (!g_file_load_contents (file, NULL, &contents,
234 lines = g_strsplit (contents, "\n", -1);
236 for (i = 0; lines[i]; i++)
238 GtkFileSystemBookmark *bookmark;
243 if (!g_utf8_validate (lines[i], -1, NULL))
246 bookmark = g_slice_new0 (GtkFileSystemBookmark);
248 if ((space = strchr (lines[i], ' ')) != NULL)
251 bookmark->label = g_strdup (space + 1);
254 bookmark->file = g_file_new_for_uri (lines[i]);
255 bookmarks = g_slist_prepend (bookmarks, bookmark);
258 bookmarks = g_slist_reverse (bookmarks);
266 save_bookmarks (GFile *bookmarks_file,
269 GError *error = NULL;
273 contents = g_string_new ("");
275 for (l = bookmarks; l; l = l->next)
277 GtkFileSystemBookmark *bookmark = l->data;
280 uri = g_file_get_uri (bookmark->file);
284 g_string_append (contents, uri);
287 g_string_append_printf (contents, " %s", bookmark->label);
289 g_string_append_c (contents, '\n');
293 if (!g_file_replace_contents (bookmarks_file,
295 strlen (contents->str),
296 NULL, FALSE, 0, NULL,
299 g_critical ("%s", error->message);
300 g_error_free (error);
303 g_string_free (contents, TRUE);
307 bookmarks_file_changed (GFileMonitor *monitor,
310 GFileMonitorEvent event,
313 GtkFileSystem *file_system = GTK_FILE_SYSTEM (data);
314 GtkFileSystemPrivate *priv = file_system->priv;
318 case G_FILE_MONITOR_EVENT_CHANGED:
319 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
320 case G_FILE_MONITOR_EVENT_CREATED:
321 case G_FILE_MONITOR_EVENT_DELETED:
322 g_slist_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
323 g_slist_free (priv->bookmarks);
325 priv->bookmarks = read_bookmarks (file);
327 gdk_threads_enter ();
328 g_signal_emit (data, fs_signals[BOOKMARKS_CHANGED], 0);
329 gdk_threads_leave ();
332 /* ignore at the moment */
338 mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
346 mount_root = g_mount_get_root (mount);
348 for (l = volumes; l != NULL; l = l->next)
350 GVolume *volume = G_VOLUME (l->data);
351 GFile *volume_activation_root;
353 volume_activation_root = g_volume_get_activation_root (volume);
354 if (volume_activation_root != NULL)
356 if (g_file_has_prefix (volume_activation_root, mount_root))
359 g_object_unref (volume_activation_root);
362 g_object_unref (volume_activation_root);
366 g_object_unref (mount_root);
371 get_volumes_list (GtkFileSystem *file_system)
373 GtkFileSystemPrivate *priv = file_system->priv;
384 g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL);
385 g_slist_free (priv->volumes);
386 priv->volumes = NULL;
389 /* first go through all connected drives */
390 drives = g_volume_monitor_get_connected_drives (priv->volume_monitor);
392 for (l = drives; l != NULL; l = l->next)
395 volumes = g_drive_get_volumes (drive);
399 for (ll = volumes; ll != NULL; ll = ll->next)
402 mount = g_volume_get_mount (volume);
406 /* Show mounted volume */
407 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
408 g_object_unref (mount);
412 /* Do show the unmounted volumes in the sidebar;
413 * this is so the user can mount it (in case automounting
416 * Also, even if automounting is enabled, this gives a visual
417 * cue that the user should remember to yank out the media if
418 * he just unmounted it.
420 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
423 g_object_unref (volume);
426 g_list_free (volumes);
428 else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive))
430 /* If the drive has no mountable volumes and we cannot detect media change.. we
431 * display the drive in the sidebar so the user can manually poll the drive by
432 * right clicking and selecting "Rescan..."
434 * This is mainly for drives like floppies where media detection doesn't
435 * work.. but it's also for human beings who like to turn off media detection
436 * in the OS to save battery juice.
439 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (drive));
442 g_object_unref (drive);
445 g_list_free (drives);
447 /* add all volumes that is not associated with a drive */
448 volumes = g_volume_monitor_get_volumes (priv->volume_monitor);
450 for (l = volumes; l != NULL; l = l->next)
453 drive = g_volume_get_drive (volume);
457 g_object_unref (drive);
461 mount = g_volume_get_mount (volume);
465 /* show this mount */
466 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
467 g_object_unref (mount);
471 /* see comment above in why we add an icon for a volume */
472 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
475 g_object_unref (volume);
478 /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
479 mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
481 for (l = mounts; l != NULL; l = l->next)
484 volume = g_mount_get_volume (mount);
488 g_object_unref (volume);
492 /* if there's exists one or more volumes with an activation root inside the mount,
493 * don't display the mount
495 if (mount_referenced_by_volume_activation_root (volumes, mount))
497 g_object_unref (mount);
501 /* show this mount */
502 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
503 g_object_unref (mount);
506 g_list_free (volumes);
508 g_list_free (mounts);
512 _gtk_file_system_init (GtkFileSystem *file_system)
514 GtkFileSystemPrivate *priv;
515 GFile *bookmarks_file;
516 GError *error = NULL;
520 file_system->priv = G_TYPE_INSTANCE_GET_PRIVATE (file_system,
521 GTK_TYPE_FILE_SYSTEM,
522 GtkFileSystemPrivate);
523 priv = file_system->priv;
526 priv->volume_monitor = g_volume_monitor_get ();
528 g_signal_connect (priv->volume_monitor, "mount-added",
529 G_CALLBACK (volumes_changed), file_system);
530 g_signal_connect (priv->volume_monitor, "mount-removed",
531 G_CALLBACK (volumes_changed), file_system);
532 g_signal_connect (priv->volume_monitor, "mount-changed",
533 G_CALLBACK (volumes_changed), file_system);
534 g_signal_connect (priv->volume_monitor, "volume-added",
535 G_CALLBACK (volumes_changed), file_system);
536 g_signal_connect (priv->volume_monitor, "volume-removed",
537 G_CALLBACK (volumes_changed), file_system);
538 g_signal_connect (priv->volume_monitor, "volume-changed",
539 G_CALLBACK (volumes_changed), file_system);
540 g_signal_connect (priv->volume_monitor, "drive-connected",
541 G_CALLBACK (volumes_changed), file_system);
542 g_signal_connect (priv->volume_monitor, "drive-disconnected",
543 G_CALLBACK (volumes_changed), file_system);
544 g_signal_connect (priv->volume_monitor, "drive-changed",
545 G_CALLBACK (volumes_changed), file_system);
548 bookmarks_file = get_bookmarks_file ();
549 priv->bookmarks = read_bookmarks (bookmarks_file);
550 priv->bookmarks_monitor = g_file_monitor_file (bookmarks_file,
555 g_warning ("%s", error->message);
556 g_error_free (error);
559 g_signal_connect (priv->bookmarks_monitor, "changed",
560 G_CALLBACK (bookmarks_file_changed), file_system);
562 g_object_unref (bookmarks_file);
565 /* GtkFileSystem public methods */
567 _gtk_file_system_new (void)
569 return g_object_new (GTK_TYPE_FILE_SYSTEM, NULL);
573 _gtk_file_system_list_volumes (GtkFileSystem *file_system)
575 GtkFileSystemPrivate *priv = file_system->priv;
578 DEBUG ("list_volumes");
580 get_volumes_list (file_system);
582 list = g_slist_copy (priv->volumes);
585 /* Prepend root volume */
586 list = g_slist_prepend (list, (gpointer) root_volume_token);
593 _gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
595 GtkFileSystemPrivate *priv = file_system->priv;
596 GSList *bookmarks, *files = NULL;
598 DEBUG ("list_bookmarks");
600 bookmarks = priv->bookmarks;
604 GtkFileSystemBookmark *bookmark;
606 bookmark = bookmarks->data;
607 bookmarks = bookmarks->next;
609 files = g_slist_prepend (files, g_object_ref (bookmark->file));
612 return g_slist_reverse (files);
616 free_async_data (AsyncFuncData *async_data)
618 g_object_unref (async_data->file_system);
619 g_object_unref (async_data->file);
620 g_object_unref (async_data->cancellable);
622 g_free (async_data->attributes);
627 query_info_callback (GObject *source_object,
628 GAsyncResult *result,
631 AsyncFuncData *async_data;
632 GError *error = NULL;
633 GFileInfo *file_info;
636 DEBUG ("query_info_callback");
638 file = G_FILE (source_object);
639 async_data = (AsyncFuncData *) user_data;
640 file_info = g_file_query_info_finish (file, result, &error);
642 if (async_data->callback)
644 gdk_threads_enter ();
645 ((GtkFileSystemGetInfoCallback) async_data->callback) (async_data->cancellable,
646 file_info, error, async_data->data);
647 gdk_threads_leave ();
651 g_object_unref (file_info);
654 g_error_free (error);
656 free_async_data (async_data);
660 _gtk_file_system_get_info (GtkFileSystem *file_system,
662 const gchar *attributes,
663 GtkFileSystemGetInfoCallback callback,
666 GCancellable *cancellable;
667 AsyncFuncData *async_data;
669 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
670 g_return_val_if_fail (G_IS_FILE (file), NULL);
672 cancellable = g_cancellable_new ();
674 async_data = g_new0 (AsyncFuncData, 1);
675 async_data->file_system = g_object_ref (file_system);
676 async_data->file = g_object_ref (file);
677 async_data->cancellable = g_object_ref (cancellable);
679 async_data->callback = callback;
680 async_data->data = data;
682 g_file_query_info_async (file,
684 G_FILE_QUERY_INFO_NONE,
694 drive_poll_for_media_cb (GObject *source_object,
695 GAsyncResult *result,
698 AsyncFuncData *async_data;
699 GError *error = NULL;
701 g_drive_poll_for_media_finish (G_DRIVE (source_object), result, &error);
702 async_data = (AsyncFuncData *) user_data;
704 gdk_threads_enter ();
705 ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
706 (GtkFileSystemVolume *) source_object,
707 error, async_data->data);
708 gdk_threads_leave ();
711 g_error_free (error);
715 volume_mount_cb (GObject *source_object,
716 GAsyncResult *result,
719 AsyncFuncData *async_data;
720 GError *error = NULL;
722 g_volume_mount_finish (G_VOLUME (source_object), result, &error);
723 async_data = (AsyncFuncData *) user_data;
725 gdk_threads_enter ();
726 ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
727 (GtkFileSystemVolume *) source_object,
728 error, async_data->data);
729 gdk_threads_leave ();
732 g_error_free (error);
736 _gtk_file_system_mount_volume (GtkFileSystem *file_system,
737 GtkFileSystemVolume *volume,
738 GMountOperation *mount_operation,
739 GtkFileSystemVolumeMountCallback callback,
742 GCancellable *cancellable;
743 AsyncFuncData *async_data;
744 gboolean handled = FALSE;
746 DEBUG ("volume_mount");
748 cancellable = g_cancellable_new ();
750 async_data = g_new0 (AsyncFuncData, 1);
751 async_data->file_system = g_object_ref (file_system);
752 async_data->cancellable = g_object_ref (cancellable);
754 async_data->callback = callback;
755 async_data->data = data;
757 if (G_IS_DRIVE (volume))
759 /* this path happens for drives that are not polled by the OS and where the last media
760 * check indicated that no media was available. So the thing to do here is to
761 * invoke poll_for_media() on the drive
763 g_drive_poll_for_media (G_DRIVE (volume), cancellable, drive_poll_for_media_cb, async_data);
766 else if (G_IS_VOLUME (volume))
768 g_volume_mount (G_VOLUME (volume), G_MOUNT_MOUNT_NONE, mount_operation, cancellable, volume_mount_cb, async_data);
773 free_async_data (async_data);
779 enclosing_volume_mount_cb (GObject *source_object,
780 GAsyncResult *result,
783 GtkFileSystemVolume *volume;
784 AsyncFuncData *async_data;
785 GError *error = NULL;
787 async_data = (AsyncFuncData *) user_data;
788 g_file_mount_enclosing_volume_finish (G_FILE (source_object), result, &error);
789 volume = _gtk_file_system_get_volume_for_file (async_data->file_system, G_FILE (source_object));
791 /* Silently drop G_IO_ERROR_ALREADY_MOUNTED error for gvfs backends without visible mounts. */
792 /* Better than doing query_info with additional I/O every time. */
793 if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED))
794 g_clear_error (&error);
796 gdk_threads_enter ();
797 ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, volume,
798 error, async_data->data);
799 gdk_threads_leave ();
802 g_error_free (error);
804 _gtk_file_system_volume_unref (volume);
808 _gtk_file_system_mount_enclosing_volume (GtkFileSystem *file_system,
810 GMountOperation *mount_operation,
811 GtkFileSystemVolumeMountCallback callback,
814 GCancellable *cancellable;
815 AsyncFuncData *async_data;
817 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
818 g_return_val_if_fail (G_IS_FILE (file), NULL);
820 DEBUG ("mount_enclosing_volume");
822 cancellable = g_cancellable_new ();
824 async_data = g_new0 (AsyncFuncData, 1);
825 async_data->file_system = g_object_ref (file_system);
826 async_data->file = g_object_ref (file);
827 async_data->cancellable = g_object_ref (cancellable);
829 async_data->callback = callback;
830 async_data->data = data;
832 g_file_mount_enclosing_volume (file,
836 enclosing_volume_mount_cb,
842 _gtk_file_system_insert_bookmark (GtkFileSystem *file_system,
847 GtkFileSystemPrivate *priv = file_system->priv;
849 GtkFileSystemBookmark *bookmark;
850 gboolean result = TRUE;
851 GFile *bookmarks_file;
853 bookmarks = priv->bookmarks;
857 bookmark = bookmarks->data;
858 bookmarks = bookmarks->next;
860 if (g_file_equal (bookmark->file, file))
862 /* File is already in bookmarks */
870 gchar *uri = g_file_get_uri (file);
873 GTK_FILE_CHOOSER_ERROR,
874 GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
875 "%s already exists in the bookmarks list",
883 bookmark = g_slice_new0 (GtkFileSystemBookmark);
884 bookmark->file = g_object_ref (file);
886 priv->bookmarks = g_slist_insert (priv->bookmarks, bookmark, position);
888 bookmarks_file = get_bookmarks_file ();
889 save_bookmarks (bookmarks_file, priv->bookmarks);
890 g_object_unref (bookmarks_file);
892 g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0);
898 _gtk_file_system_remove_bookmark (GtkFileSystem *file_system,
902 GtkFileSystemPrivate *priv = file_system->priv;
903 GtkFileSystemBookmark *bookmark;
905 gboolean result = FALSE;
906 GFile *bookmarks_file;
908 if (!priv->bookmarks)
911 bookmarks = priv->bookmarks;
915 bookmark = bookmarks->data;
917 if (g_file_equal (bookmark->file, file))
920 priv->bookmarks = g_slist_remove_link (priv->bookmarks, bookmarks);
921 _gtk_file_system_bookmark_free (bookmark);
922 g_slist_free_1 (bookmarks);
926 bookmarks = bookmarks->next;
931 gchar *uri = g_file_get_uri (file);
934 GTK_FILE_CHOOSER_ERROR,
935 GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
936 "%s does not exist in the bookmarks list",
944 bookmarks_file = get_bookmarks_file ();
945 save_bookmarks (bookmarks_file, priv->bookmarks);
946 g_object_unref (bookmarks_file);
948 g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0);
954 _gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
957 GtkFileSystemPrivate *priv = file_system->priv;
961 DEBUG ("get_bookmark_label");
963 bookmarks = priv->bookmarks;
967 GtkFileSystemBookmark *bookmark;
969 bookmark = bookmarks->data;
970 bookmarks = bookmarks->next;
972 if (g_file_equal (file, bookmark->file))
974 label = g_strdup (bookmark->label);
983 _gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
987 GtkFileSystemPrivate *priv = file_system->priv;
988 gboolean changed = FALSE;
989 GFile *bookmarks_file;
992 DEBUG ("set_bookmark_label");
994 bookmarks = priv->bookmarks;
998 GtkFileSystemBookmark *bookmark;
1000 bookmark = bookmarks->data;
1001 bookmarks = bookmarks->next;
1003 if (g_file_equal (file, bookmark->file))
1005 g_free (bookmark->label);
1006 bookmark->label = g_strdup (label);
1012 bookmarks_file = get_bookmarks_file ();
1013 save_bookmarks (bookmarks_file, priv->bookmarks);
1014 g_object_unref (bookmarks_file);
1017 g_signal_emit_by_name (file_system, "bookmarks-changed", 0);
1020 GtkFileSystemVolume *
1021 _gtk_file_system_get_volume_for_file (GtkFileSystem *file_system,
1026 DEBUG ("get_volume_for_file");
1028 mount = g_file_find_enclosing_mount (file, NULL, NULL);
1030 if (!mount && g_file_is_native (file))
1031 return (GtkFileSystemVolume *) root_volume_token;
1033 return (GtkFileSystemVolume *) mount;
1036 /* GtkFileSystemVolume public methods */
1038 _gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume)
1040 DEBUG ("volume_get_display_name");
1042 if (IS_ROOT_VOLUME (volume))
1043 return g_strdup (_(root_volume_token));
1044 if (G_IS_DRIVE (volume))
1045 return g_drive_get_name (G_DRIVE (volume));
1046 else if (G_IS_MOUNT (volume))
1047 return g_mount_get_name (G_MOUNT (volume));
1048 else if (G_IS_VOLUME (volume))
1049 return g_volume_get_name (G_VOLUME (volume));
1055 _gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume)
1059 DEBUG ("volume_is_mounted");
1061 if (IS_ROOT_VOLUME (volume))
1066 if (G_IS_MOUNT (volume))
1068 else if (G_IS_VOLUME (volume))
1072 mount = g_volume_get_mount (G_VOLUME (volume));
1077 g_object_unref (mount);
1085 _gtk_file_system_volume_get_root (GtkFileSystemVolume *volume)
1089 DEBUG ("volume_get_base");
1091 if (IS_ROOT_VOLUME (volume))
1092 return g_file_new_for_uri ("file:///");
1094 if (G_IS_MOUNT (volume))
1095 file = g_mount_get_root (G_MOUNT (volume));
1096 else if (G_IS_VOLUME (volume))
1100 mount = g_volume_get_mount (G_VOLUME (volume));
1104 file = g_mount_get_root (mount);
1105 g_object_unref (mount);
1113 get_pixbuf_from_gicon (GIcon *icon,
1119 GtkIconTheme *icon_theme;
1120 GtkIconInfo *icon_info;
1123 screen = gtk_widget_get_screen (GTK_WIDGET (widget));
1124 icon_theme = gtk_icon_theme_get_for_screen (screen);
1126 icon_info = gtk_icon_theme_lookup_by_gicon (icon_theme,
1129 GTK_ICON_LOOKUP_USE_BUILTIN);
1134 pixbuf = gtk_icon_info_load_icon (icon_info, error);
1135 gtk_icon_info_free (icon_info);
1141 _gtk_file_system_volume_render_icon (GtkFileSystemVolume *volume,
1149 DEBUG ("volume_get_icon_name");
1151 if (IS_ROOT_VOLUME (volume))
1152 icon = g_themed_icon_new ("drive-harddisk");
1153 else if (G_IS_DRIVE (volume))
1154 icon = g_drive_get_icon (G_DRIVE (volume));
1155 else if (G_IS_VOLUME (volume))
1156 icon = g_volume_get_icon (G_VOLUME (volume));
1157 else if (G_IS_MOUNT (volume))
1158 icon = g_mount_get_icon (G_MOUNT (volume));
1163 pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, error);
1165 g_object_unref (icon);
1170 GtkFileSystemVolume *
1171 _gtk_file_system_volume_ref (GtkFileSystemVolume *volume)
1173 if (IS_ROOT_VOLUME (volume))
1176 if (G_IS_MOUNT (volume) ||
1177 G_IS_VOLUME (volume) ||
1178 G_IS_DRIVE (volume))
1179 g_object_ref (volume);
1185 _gtk_file_system_volume_unref (GtkFileSystemVolume *volume)
1187 /* Root volume doesn't need to be freed */
1188 if (IS_ROOT_VOLUME (volume))
1191 if (G_IS_MOUNT (volume) ||
1192 G_IS_VOLUME (volume) ||
1193 G_IS_DRIVE (volume))
1194 g_object_unref (volume);
1197 /* GFileInfo helper functions */
1199 _gtk_file_info_render_icon (GFileInfo *info,
1204 GdkPixbuf *pixbuf = NULL;
1205 const gchar *thumbnail_path;
1207 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
1210 pixbuf = gdk_pixbuf_new_from_file_at_size (thumbnail_path,
1211 icon_size, icon_size,
1216 icon = g_file_info_get_icon (info);
1219 pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
1223 /* Use general fallback for all files without icon */
1224 icon = g_themed_icon_new ("text-x-generic");
1225 pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
1226 g_object_unref (icon);
1234 _gtk_file_info_consider_as_directory (GFileInfo *info)
1236 GFileType type = g_file_info_get_file_type (info);
1238 return (type == G_FILE_TYPE_DIRECTORY ||
1239 type == G_FILE_TYPE_MOUNTABLE ||
1240 type == G_FILE_TYPE_SHORTCUT);