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_legacy_bookmarks_file (void)
215 filename = g_build_filename (g_get_home_dir (), ".gtk-bookmarks", NULL);
216 file = g_file_new_for_path (filename);
223 get_bookmarks_file (void)
228 filename = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "bookmarks", NULL);
229 file = g_file_new_for_path (filename);
236 read_bookmarks (GFile *file)
239 gchar **lines, *space;
240 GSList *bookmarks = NULL;
243 if (!g_file_load_contents (file, NULL, &contents,
247 lines = g_strsplit (contents, "\n", -1);
249 for (i = 0; lines[i]; i++)
251 GtkFileSystemBookmark *bookmark;
256 if (!g_utf8_validate (lines[i], -1, NULL))
259 bookmark = g_slice_new0 (GtkFileSystemBookmark);
261 if ((space = strchr (lines[i], ' ')) != NULL)
264 bookmark->label = g_strdup (space + 1);
267 bookmark->file = g_file_new_for_uri (lines[i]);
268 bookmarks = g_slist_prepend (bookmarks, bookmark);
271 bookmarks = g_slist_reverse (bookmarks);
279 save_bookmarks (GFile *bookmarks_file,
282 GError *error = NULL;
288 contents = g_string_new ("");
290 for (l = bookmarks; l; l = l->next)
292 GtkFileSystemBookmark *bookmark = l->data;
295 uri = g_file_get_uri (bookmark->file);
299 g_string_append (contents, uri);
302 g_string_append_printf (contents, " %s", bookmark->label);
304 g_string_append_c (contents, '\n');
308 parent_file = g_file_get_parent (bookmarks_file);
309 path = g_file_get_path (parent_file);
310 if (g_mkdir_with_parents (path, 0700) == 0)
312 if (!g_file_replace_contents (bookmarks_file,
314 strlen (contents->str),
315 NULL, FALSE, 0, NULL,
318 g_critical ("%s", error->message);
319 g_error_free (error);
323 g_object_unref (parent_file);
324 g_string_free (contents, TRUE);
328 bookmarks_file_changed (GFileMonitor *monitor,
331 GFileMonitorEvent event,
334 GtkFileSystem *file_system = GTK_FILE_SYSTEM (data);
335 GtkFileSystemPrivate *priv = file_system->priv;
339 case G_FILE_MONITOR_EVENT_CHANGED:
340 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
341 case G_FILE_MONITOR_EVENT_CREATED:
342 case G_FILE_MONITOR_EVENT_DELETED:
343 g_slist_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
344 g_slist_free (priv->bookmarks);
346 priv->bookmarks = read_bookmarks (file);
348 gdk_threads_enter ();
349 g_signal_emit (data, fs_signals[BOOKMARKS_CHANGED], 0);
350 gdk_threads_leave ();
353 /* ignore at the moment */
359 mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
367 mount_root = g_mount_get_root (mount);
369 for (l = volumes; l != NULL; l = l->next)
371 GVolume *volume = G_VOLUME (l->data);
372 GFile *volume_activation_root;
374 volume_activation_root = g_volume_get_activation_root (volume);
375 if (volume_activation_root != NULL)
377 if (g_file_has_prefix (volume_activation_root, mount_root))
380 g_object_unref (volume_activation_root);
383 g_object_unref (volume_activation_root);
387 g_object_unref (mount_root);
392 get_volumes_list (GtkFileSystem *file_system)
394 GtkFileSystemPrivate *priv = file_system->priv;
405 g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL);
406 g_slist_free (priv->volumes);
407 priv->volumes = NULL;
410 /* first go through all connected drives */
411 drives = g_volume_monitor_get_connected_drives (priv->volume_monitor);
413 for (l = drives; l != NULL; l = l->next)
416 volumes = g_drive_get_volumes (drive);
420 for (ll = volumes; ll != NULL; ll = ll->next)
423 mount = g_volume_get_mount (volume);
427 /* Show mounted volume */
428 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
429 g_object_unref (mount);
433 /* Do show the unmounted volumes in the sidebar;
434 * this is so the user can mount it (in case automounting
437 * Also, even if automounting is enabled, this gives a visual
438 * cue that the user should remember to yank out the media if
439 * he just unmounted it.
441 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
444 g_object_unref (volume);
447 g_list_free (volumes);
449 else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive))
451 /* If the drive has no mountable volumes and we cannot detect media change.. we
452 * display the drive in the sidebar so the user can manually poll the drive by
453 * right clicking and selecting "Rescan..."
455 * This is mainly for drives like floppies where media detection doesn't
456 * work.. but it's also for human beings who like to turn off media detection
457 * in the OS to save battery juice.
460 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (drive));
463 g_object_unref (drive);
466 g_list_free (drives);
468 /* add all volumes that is not associated with a drive */
469 volumes = g_volume_monitor_get_volumes (priv->volume_monitor);
471 for (l = volumes; l != NULL; l = l->next)
474 drive = g_volume_get_drive (volume);
478 g_object_unref (drive);
482 mount = g_volume_get_mount (volume);
486 /* show this mount */
487 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
488 g_object_unref (mount);
492 /* see comment above in why we add an icon for a volume */
493 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
496 g_object_unref (volume);
499 /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
500 mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
502 for (l = mounts; l != NULL; l = l->next)
505 volume = g_mount_get_volume (mount);
509 g_object_unref (volume);
513 /* if there's exists one or more volumes with an activation root inside the mount,
514 * don't display the mount
516 if (mount_referenced_by_volume_activation_root (volumes, mount))
518 g_object_unref (mount);
522 /* show this mount */
523 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
524 g_object_unref (mount);
527 g_list_free (volumes);
529 g_list_free (mounts);
533 _gtk_file_system_init (GtkFileSystem *file_system)
535 GtkFileSystemPrivate *priv;
536 GFile *bookmarks_file;
537 GError *error = NULL;
541 file_system->priv = G_TYPE_INSTANCE_GET_PRIVATE (file_system,
542 GTK_TYPE_FILE_SYSTEM,
543 GtkFileSystemPrivate);
544 priv = file_system->priv;
547 priv->volume_monitor = g_volume_monitor_get ();
549 g_signal_connect (priv->volume_monitor, "mount-added",
550 G_CALLBACK (volumes_changed), file_system);
551 g_signal_connect (priv->volume_monitor, "mount-removed",
552 G_CALLBACK (volumes_changed), file_system);
553 g_signal_connect (priv->volume_monitor, "mount-changed",
554 G_CALLBACK (volumes_changed), file_system);
555 g_signal_connect (priv->volume_monitor, "volume-added",
556 G_CALLBACK (volumes_changed), file_system);
557 g_signal_connect (priv->volume_monitor, "volume-removed",
558 G_CALLBACK (volumes_changed), file_system);
559 g_signal_connect (priv->volume_monitor, "volume-changed",
560 G_CALLBACK (volumes_changed), file_system);
561 g_signal_connect (priv->volume_monitor, "drive-connected",
562 G_CALLBACK (volumes_changed), file_system);
563 g_signal_connect (priv->volume_monitor, "drive-disconnected",
564 G_CALLBACK (volumes_changed), file_system);
565 g_signal_connect (priv->volume_monitor, "drive-changed",
566 G_CALLBACK (volumes_changed), file_system);
569 bookmarks_file = get_bookmarks_file ();
570 priv->bookmarks = read_bookmarks (bookmarks_file);
571 if (!priv->bookmarks)
573 GFile *legacy_bookmarks_file;
575 /* Read the legacy one and write it to the new one */
576 legacy_bookmarks_file = get_legacy_bookmarks_file ();
577 priv->bookmarks = read_bookmarks (legacy_bookmarks_file);
578 save_bookmarks (bookmarks_file, priv->bookmarks);
580 g_object_unref (legacy_bookmarks_file);
583 priv->bookmarks_monitor = g_file_monitor_file (bookmarks_file,
588 g_warning ("%s", error->message);
589 g_error_free (error);
592 g_signal_connect (priv->bookmarks_monitor, "changed",
593 G_CALLBACK (bookmarks_file_changed), file_system);
595 g_object_unref (bookmarks_file);
598 /* GtkFileSystem public methods */
600 _gtk_file_system_new (void)
602 return g_object_new (GTK_TYPE_FILE_SYSTEM, NULL);
606 _gtk_file_system_list_volumes (GtkFileSystem *file_system)
608 GtkFileSystemPrivate *priv = file_system->priv;
611 DEBUG ("list_volumes");
613 get_volumes_list (file_system);
615 list = g_slist_copy (priv->volumes);
618 /* Prepend root volume */
619 list = g_slist_prepend (list, (gpointer) root_volume_token);
626 _gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
628 GtkFileSystemPrivate *priv = file_system->priv;
629 GSList *bookmarks, *files = NULL;
631 DEBUG ("list_bookmarks");
633 bookmarks = priv->bookmarks;
637 GtkFileSystemBookmark *bookmark;
639 bookmark = bookmarks->data;
640 bookmarks = bookmarks->next;
642 files = g_slist_prepend (files, g_object_ref (bookmark->file));
645 return g_slist_reverse (files);
649 free_async_data (AsyncFuncData *async_data)
651 g_object_unref (async_data->file_system);
652 g_object_unref (async_data->file);
653 g_object_unref (async_data->cancellable);
655 g_free (async_data->attributes);
660 query_info_callback (GObject *source_object,
661 GAsyncResult *result,
664 AsyncFuncData *async_data;
665 GError *error = NULL;
666 GFileInfo *file_info;
669 DEBUG ("query_info_callback");
671 file = G_FILE (source_object);
672 async_data = (AsyncFuncData *) user_data;
673 file_info = g_file_query_info_finish (file, result, &error);
675 if (async_data->callback)
677 gdk_threads_enter ();
678 ((GtkFileSystemGetInfoCallback) async_data->callback) (async_data->cancellable,
679 file_info, error, async_data->data);
680 gdk_threads_leave ();
684 g_object_unref (file_info);
687 g_error_free (error);
689 free_async_data (async_data);
693 _gtk_file_system_get_info (GtkFileSystem *file_system,
695 const gchar *attributes,
696 GtkFileSystemGetInfoCallback callback,
699 GCancellable *cancellable;
700 AsyncFuncData *async_data;
702 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
703 g_return_val_if_fail (G_IS_FILE (file), NULL);
705 cancellable = g_cancellable_new ();
707 async_data = g_new0 (AsyncFuncData, 1);
708 async_data->file_system = g_object_ref (file_system);
709 async_data->file = g_object_ref (file);
710 async_data->cancellable = g_object_ref (cancellable);
712 async_data->callback = callback;
713 async_data->data = data;
715 g_file_query_info_async (file,
717 G_FILE_QUERY_INFO_NONE,
727 drive_poll_for_media_cb (GObject *source_object,
728 GAsyncResult *result,
731 AsyncFuncData *async_data;
732 GError *error = NULL;
734 g_drive_poll_for_media_finish (G_DRIVE (source_object), result, &error);
735 async_data = (AsyncFuncData *) user_data;
737 gdk_threads_enter ();
738 ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
739 (GtkFileSystemVolume *) source_object,
740 error, async_data->data);
741 gdk_threads_leave ();
744 g_error_free (error);
748 volume_mount_cb (GObject *source_object,
749 GAsyncResult *result,
752 AsyncFuncData *async_data;
753 GError *error = NULL;
755 g_volume_mount_finish (G_VOLUME (source_object), result, &error);
756 async_data = (AsyncFuncData *) user_data;
758 gdk_threads_enter ();
759 ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
760 (GtkFileSystemVolume *) source_object,
761 error, async_data->data);
762 gdk_threads_leave ();
765 g_error_free (error);
769 _gtk_file_system_mount_volume (GtkFileSystem *file_system,
770 GtkFileSystemVolume *volume,
771 GMountOperation *mount_operation,
772 GtkFileSystemVolumeMountCallback callback,
775 GCancellable *cancellable;
776 AsyncFuncData *async_data;
777 gboolean handled = FALSE;
779 DEBUG ("volume_mount");
781 cancellable = g_cancellable_new ();
783 async_data = g_new0 (AsyncFuncData, 1);
784 async_data->file_system = g_object_ref (file_system);
785 async_data->cancellable = g_object_ref (cancellable);
787 async_data->callback = callback;
788 async_data->data = data;
790 if (G_IS_DRIVE (volume))
792 /* this path happens for drives that are not polled by the OS and where the last media
793 * check indicated that no media was available. So the thing to do here is to
794 * invoke poll_for_media() on the drive
796 g_drive_poll_for_media (G_DRIVE (volume), cancellable, drive_poll_for_media_cb, async_data);
799 else if (G_IS_VOLUME (volume))
801 g_volume_mount (G_VOLUME (volume), G_MOUNT_MOUNT_NONE, mount_operation, cancellable, volume_mount_cb, async_data);
806 free_async_data (async_data);
812 enclosing_volume_mount_cb (GObject *source_object,
813 GAsyncResult *result,
816 GtkFileSystemVolume *volume;
817 AsyncFuncData *async_data;
818 GError *error = NULL;
820 async_data = (AsyncFuncData *) user_data;
821 g_file_mount_enclosing_volume_finish (G_FILE (source_object), result, &error);
822 volume = _gtk_file_system_get_volume_for_file (async_data->file_system, G_FILE (source_object));
824 /* Silently drop G_IO_ERROR_ALREADY_MOUNTED error for gvfs backends without visible mounts. */
825 /* Better than doing query_info with additional I/O every time. */
826 if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED))
827 g_clear_error (&error);
829 gdk_threads_enter ();
830 ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, volume,
831 error, async_data->data);
832 gdk_threads_leave ();
835 g_error_free (error);
837 _gtk_file_system_volume_unref (volume);
841 _gtk_file_system_mount_enclosing_volume (GtkFileSystem *file_system,
843 GMountOperation *mount_operation,
844 GtkFileSystemVolumeMountCallback callback,
847 GCancellable *cancellable;
848 AsyncFuncData *async_data;
850 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
851 g_return_val_if_fail (G_IS_FILE (file), NULL);
853 DEBUG ("mount_enclosing_volume");
855 cancellable = g_cancellable_new ();
857 async_data = g_new0 (AsyncFuncData, 1);
858 async_data->file_system = g_object_ref (file_system);
859 async_data->file = g_object_ref (file);
860 async_data->cancellable = g_object_ref (cancellable);
862 async_data->callback = callback;
863 async_data->data = data;
865 g_file_mount_enclosing_volume (file,
869 enclosing_volume_mount_cb,
875 _gtk_file_system_insert_bookmark (GtkFileSystem *file_system,
880 GtkFileSystemPrivate *priv = file_system->priv;
882 GtkFileSystemBookmark *bookmark;
883 gboolean result = TRUE;
884 GFile *bookmarks_file;
886 bookmarks = priv->bookmarks;
890 bookmark = bookmarks->data;
891 bookmarks = bookmarks->next;
893 if (g_file_equal (bookmark->file, file))
895 /* File is already in bookmarks */
903 gchar *uri = g_file_get_uri (file);
906 GTK_FILE_CHOOSER_ERROR,
907 GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
908 "%s already exists in the bookmarks list",
916 bookmark = g_slice_new0 (GtkFileSystemBookmark);
917 bookmark->file = g_object_ref (file);
919 priv->bookmarks = g_slist_insert (priv->bookmarks, bookmark, position);
921 bookmarks_file = get_bookmarks_file ();
922 save_bookmarks (bookmarks_file, priv->bookmarks);
923 g_object_unref (bookmarks_file);
925 g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0);
931 _gtk_file_system_remove_bookmark (GtkFileSystem *file_system,
935 GtkFileSystemPrivate *priv = file_system->priv;
936 GtkFileSystemBookmark *bookmark;
938 gboolean result = FALSE;
939 GFile *bookmarks_file;
941 if (!priv->bookmarks)
944 bookmarks = priv->bookmarks;
948 bookmark = bookmarks->data;
950 if (g_file_equal (bookmark->file, file))
953 priv->bookmarks = g_slist_remove_link (priv->bookmarks, bookmarks);
954 _gtk_file_system_bookmark_free (bookmark);
955 g_slist_free_1 (bookmarks);
959 bookmarks = bookmarks->next;
964 gchar *uri = g_file_get_uri (file);
967 GTK_FILE_CHOOSER_ERROR,
968 GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
969 "%s does not exist in the bookmarks list",
977 bookmarks_file = get_bookmarks_file ();
978 save_bookmarks (bookmarks_file, priv->bookmarks);
979 g_object_unref (bookmarks_file);
981 g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0);
987 _gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
990 GtkFileSystemPrivate *priv = file_system->priv;
994 DEBUG ("get_bookmark_label");
996 bookmarks = priv->bookmarks;
1000 GtkFileSystemBookmark *bookmark;
1002 bookmark = bookmarks->data;
1003 bookmarks = bookmarks->next;
1005 if (g_file_equal (file, bookmark->file))
1007 label = g_strdup (bookmark->label);
1016 _gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
1020 GtkFileSystemPrivate *priv = file_system->priv;
1021 gboolean changed = FALSE;
1022 GFile *bookmarks_file;
1025 DEBUG ("set_bookmark_label");
1027 bookmarks = priv->bookmarks;
1031 GtkFileSystemBookmark *bookmark;
1033 bookmark = bookmarks->data;
1034 bookmarks = bookmarks->next;
1036 if (g_file_equal (file, bookmark->file))
1038 g_free (bookmark->label);
1039 bookmark->label = g_strdup (label);
1045 bookmarks_file = get_bookmarks_file ();
1046 save_bookmarks (bookmarks_file, priv->bookmarks);
1047 g_object_unref (bookmarks_file);
1050 g_signal_emit_by_name (file_system, "bookmarks-changed", 0);
1053 GtkFileSystemVolume *
1054 _gtk_file_system_get_volume_for_file (GtkFileSystem *file_system,
1059 DEBUG ("get_volume_for_file");
1061 mount = g_file_find_enclosing_mount (file, NULL, NULL);
1063 if (!mount && g_file_is_native (file))
1064 return (GtkFileSystemVolume *) root_volume_token;
1066 return (GtkFileSystemVolume *) mount;
1069 /* GtkFileSystemVolume public methods */
1071 _gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume)
1073 DEBUG ("volume_get_display_name");
1075 if (IS_ROOT_VOLUME (volume))
1076 return g_strdup (_(root_volume_token));
1077 if (G_IS_DRIVE (volume))
1078 return g_drive_get_name (G_DRIVE (volume));
1079 else if (G_IS_MOUNT (volume))
1080 return g_mount_get_name (G_MOUNT (volume));
1081 else if (G_IS_VOLUME (volume))
1082 return g_volume_get_name (G_VOLUME (volume));
1088 _gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume)
1092 DEBUG ("volume_is_mounted");
1094 if (IS_ROOT_VOLUME (volume))
1099 if (G_IS_MOUNT (volume))
1101 else if (G_IS_VOLUME (volume))
1105 mount = g_volume_get_mount (G_VOLUME (volume));
1110 g_object_unref (mount);
1118 _gtk_file_system_volume_get_root (GtkFileSystemVolume *volume)
1122 DEBUG ("volume_get_base");
1124 if (IS_ROOT_VOLUME (volume))
1125 return g_file_new_for_uri ("file:///");
1127 if (G_IS_MOUNT (volume))
1128 file = g_mount_get_root (G_MOUNT (volume));
1129 else if (G_IS_VOLUME (volume))
1133 mount = g_volume_get_mount (G_VOLUME (volume));
1137 file = g_mount_get_root (mount);
1138 g_object_unref (mount);
1146 get_pixbuf_from_gicon (GIcon *icon,
1152 GtkIconTheme *icon_theme;
1153 GtkIconInfo *icon_info;
1156 screen = gtk_widget_get_screen (GTK_WIDGET (widget));
1157 icon_theme = gtk_icon_theme_get_for_screen (screen);
1159 icon_info = gtk_icon_theme_lookup_by_gicon (icon_theme,
1162 GTK_ICON_LOOKUP_USE_BUILTIN);
1167 pixbuf = gtk_icon_info_load_icon (icon_info, error);
1168 g_object_unref (icon_info);
1174 _gtk_file_system_volume_render_icon (GtkFileSystemVolume *volume,
1182 DEBUG ("volume_get_icon_name");
1184 if (IS_ROOT_VOLUME (volume))
1185 icon = g_themed_icon_new ("drive-harddisk");
1186 else if (G_IS_DRIVE (volume))
1187 icon = g_drive_get_icon (G_DRIVE (volume));
1188 else if (G_IS_VOLUME (volume))
1189 icon = g_volume_get_icon (G_VOLUME (volume));
1190 else if (G_IS_MOUNT (volume))
1191 icon = g_mount_get_icon (G_MOUNT (volume));
1196 pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, error);
1198 g_object_unref (icon);
1203 GtkFileSystemVolume *
1204 _gtk_file_system_volume_ref (GtkFileSystemVolume *volume)
1206 if (IS_ROOT_VOLUME (volume))
1209 if (G_IS_MOUNT (volume) ||
1210 G_IS_VOLUME (volume) ||
1211 G_IS_DRIVE (volume))
1212 g_object_ref (volume);
1218 _gtk_file_system_volume_unref (GtkFileSystemVolume *volume)
1220 /* Root volume doesn't need to be freed */
1221 if (IS_ROOT_VOLUME (volume))
1224 if (G_IS_MOUNT (volume) ||
1225 G_IS_VOLUME (volume) ||
1226 G_IS_DRIVE (volume))
1227 g_object_unref (volume);
1230 /* GFileInfo helper functions */
1232 _gtk_file_info_render_icon (GFileInfo *info,
1237 GdkPixbuf *pixbuf = NULL;
1238 const gchar *thumbnail_path;
1240 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
1243 pixbuf = gdk_pixbuf_new_from_file_at_size (thumbnail_path,
1244 icon_size, icon_size,
1249 icon = g_file_info_get_icon (info);
1252 pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
1256 /* Use general fallback for all files without icon */
1257 icon = g_themed_icon_new ("text-x-generic");
1258 pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
1259 g_object_unref (icon);
1267 _gtk_file_info_consider_as_directory (GFileInfo *info)
1269 GFileType type = g_file_info_get_file_type (info);
1271 return (type == G_FILE_TYPE_DIRECTORY ||
1272 type == G_FILE_TYPE_MOUNTABLE ||
1273 type == G_FILE_TYPE_SHORTCUT);
1277 _gtk_file_has_native_path (GFile *file)
1279 char *local_file_path;
1280 gboolean has_native_path;
1282 /* Don't use g_file_is_native(), as we want to support FUSE paths if available */
1283 local_file_path = g_file_get_path (file);
1284 has_native_path = (local_file_path != NULL);
1285 g_free (local_file_path);
1287 return has_native_path;