File nautilus-172870-support-drives-and-volumes.diff of Package nautilus
2006-05-22 Federico Mena Quintero <federico@novell.com>
* src/file-manager/fm-directory-view.c (ActivateParameters): Added
a file_changed_id field.
(fm_directory_view_activate_file): Initialize
parameters->file_changed_id to 0.
(activation_drive_mounted_callback): If the drive thinks it is not
mounted yet, it is because gnome-vfs-volume-monitor hasn't emitted
its volume_mounted signal yet. In that case, wait for the
parameters->file to change --- that will let us know that the
drive really got mounted.
(activation_file_changed_after_drive_mounted): New function to
handle the "changed" signal on parameters->file from above.
Actually call activate_activation_uri_ready_callback() here, since
the drive now really knows that it is mounted, and
parameters->file has been updated with its activation URI.
2006-05-21 Federico Mena Quintero <federico@novell.com>
* libnautilus-private/nautilus-desktop-link.c
(reread_drive_or_volume): New helper function; moved the code to
read the data from the drive_or_volume over from
nautilus_desktop_link_new_from_drive_or_volume().
(nautilus_desktop_link_new_from_drive_or_volume): Use
reread_drive_or_volume().
(nautilus_desktop_link_update_from_volume): Call
reread_drive_or_volume(). This will actually cause the link to
update its data when the volume changes. Duh!
2006-05-19 Federico Mena Quintero <federico@novell.com>
* libnautilus-private/nautilus-desktop-link.h: New prototype for
nautilus_desktop_link_update_from_volume().
* libnautilus-private/nautilus-desktop-link.c
(nautilus_desktop_link_update_from_volume): New function.
NautilusDesktopLinks can now change between containing an
unmounted drive, and a mounted volume. This lets us have stable
desktop icons with no reloading of the volumes.
* libnautilus-private/nautilus-desktop-link-monitor.c
(find_unique_link_for_drive): New helper function.
(volume_mounted_callback): If the volume has a drive, first use
find_unique_link_for_drive() to see if there's a drive link that
can be updated for the volume. Otherwise, create a new link.
(volume_unmounted_callback): Instead of refreshing the links,
see if we can just update an existing volume link, or if we just
need to remove the link altogether.
(nautilus_desktop_link_monitor_init): Connect separate callbacks
to drive_connected and drive_disconnected.
(drive_connected_callback): Add a link for the drive if we don't
have one already.
(drive_disconnected_callback): Remove all the links that
correspond to the drive.
diff -uNrp nautilus-old/libnautilus-private/nautilus-desktop-link.c nautilus-new/libnautilus-private/nautilus-desktop-link.c
--- nautilus-old/libnautilus-private/nautilus-desktop-link.c 2006-06-01 13:18:34.000000000 -0500
+++ nautilus-new/libnautilus-private/nautilus-desktop-link.c 2006-06-01 13:26:18.000000000 -0500
@@ -192,28 +192,25 @@ nautilus_desktop_link_new (NautilusDeskt
return link;
}
-NautilusDesktopLink *
-nautilus_desktop_link_new_from_drive_or_volume (GObject *object)
+static void
+reread_drive_or_volume (NautilusDesktopLink *link)
{
- NautilusDesktopLink *link;
char *name, *filename;
char *display_name, *activation_uri, *icon;
- gboolean is_volume;
- is_volume = GNOME_IS_VFS_VOLUME (object);
-
- g_return_val_if_fail (GNOME_IS_VFS_DRIVE (object) || is_volume, NULL);
+ g_assert (link->details->type == NAUTILUS_DESKTOP_LINK_VOLUME);
+ g_assert (link->details->drive_or_volume != NULL);
- link = NAUTILUS_DESKTOP_LINK (g_object_new (NAUTILUS_TYPE_DESKTOP_LINK, NULL));
-
- link->details->type = NAUTILUS_DESKTOP_LINK_VOLUME;
+ g_free (link->details->filename);
+ g_free (link->details->display_name);
+ g_free (link->details->activation_uri);
+ g_free (link->details->icon);
- if (is_volume) {
+ if (GNOME_IS_VFS_VOLUME (link->details->drive_or_volume)) {
GnomeVFSVolume *volume;
GnomeVFSDrive *drive;
- volume = gnome_vfs_volume_ref (GNOME_VFS_VOLUME (object));
- link->details->drive_or_volume = G_OBJECT (volume);
+ volume = GNOME_VFS_VOLUME (link->details->drive_or_volume);
/* We try to use the drive name to get somewhat stable filenames
for metadata */
@@ -231,8 +228,9 @@ nautilus_desktop_link_new_from_drive_or_
} else {
GnomeVFSDrive *drive;
- drive = gnome_vfs_drive_ref (GNOME_VFS_DRIVE (object));
- link->details->drive_or_volume = G_OBJECT (drive);
+ g_assert (GNOME_IS_VFS_DRIVE (link->details->drive_or_volume));
+
+ drive = GNOME_VFS_DRIVE (link->details->drive_or_volume);
name = gnome_vfs_drive_get_display_name (drive);
@@ -251,7 +249,35 @@ nautilus_desktop_link_new_from_drive_or_
link->details->display_name = display_name;
link->details->activation_uri = activation_uri;
link->details->icon = icon;
+}
+
+NautilusDesktopLink *
+nautilus_desktop_link_new_from_drive_or_volume (GObject *object)
+{
+ NautilusDesktopLink *link;
+ gboolean is_volume;
+
+ is_volume = GNOME_IS_VFS_VOLUME (object);
+
+ g_return_val_if_fail (GNOME_IS_VFS_DRIVE (object) || is_volume, NULL);
+
+ link = NAUTILUS_DESKTOP_LINK (g_object_new (NAUTILUS_TYPE_DESKTOP_LINK, NULL));
+
+ link->details->type = NAUTILUS_DESKTOP_LINK_VOLUME;
+
+ if (is_volume) {
+ GnomeVFSVolume *volume;
+ volume = gnome_vfs_volume_ref (GNOME_VFS_VOLUME (object));
+ link->details->drive_or_volume = G_OBJECT (volume);
+ } else {
+ GnomeVFSDrive *drive;
+
+ drive = gnome_vfs_drive_ref (GNOME_VFS_DRIVE (object));
+ link->details->drive_or_volume = G_OBJECT (drive);
+ }
+
+ reread_drive_or_volume (link);
create_icon_file (link);
return link;
@@ -443,3 +469,64 @@ nautilus_desktop_link_class_init (gpoint
object_class->finalize = desktop_link_finalize;
}
+
+void
+nautilus_desktop_link_update_from_volume (NautilusDesktopLink *link,
+ GnomeVFSVolume *volume)
+{
+ g_return_if_fail (NAUTILUS_IS_DESKTOP_LINK (link));
+ g_return_if_fail (GNOME_IS_VFS_VOLUME (volume));
+
+ g_assert (link->details->type == NAUTILUS_DESKTOP_LINK_VOLUME);
+ g_assert (link->details->drive_or_volume != NULL);
+
+ if (GNOME_IS_VFS_DRIVE (link->details->drive_or_volume)) {
+ GnomeVFSDrive *drive;
+
+ drive = gnome_vfs_volume_get_drive (volume);
+
+ /* Do we need to use gnome_vfs_drive_compare()? */
+ g_assert (G_OBJECT (drive) == G_OBJECT (link->details->drive_or_volume));
+ gnome_vfs_drive_unref (drive);
+
+ /* The link is for a drive. If the new volume is mounted,
+ * replace the link's object with the volume. If the new volume
+ * is unmounted, just refresh the link (who knows why we didn't
+ * get the mount notification before).
+ */
+
+ if (gnome_vfs_volume_is_mounted (volume)) {
+ gnome_vfs_drive_unref (GNOME_VFS_DRIVE (link->details->drive_or_volume));
+
+ gnome_vfs_volume_ref (volume);
+ link->details->drive_or_volume = G_OBJECT (volume);
+ }
+
+ /* The link will get updated below */
+ } else {
+ g_assert (GNOME_IS_VFS_VOLUME (link->details->drive_or_volume));
+
+ /* Do we need to use gnome_vfs_volume_compare()? */
+ g_assert (GNOME_VFS_VOLUME (link->details->drive_or_volume) == volume);
+
+ /* If the volume got unmounted, restore the link's object to the
+ * corresponding drive. Otherwise, we shouldn't need to be
+ * called, but just update the link in that case.
+ */
+
+ if (!gnome_vfs_volume_is_mounted (volume)) {
+ GnomeVFSDrive *drive;
+
+ drive = gnome_vfs_volume_get_drive (volume);
+
+ gnome_vfs_volume_unref (GNOME_VFS_VOLUME (link->details->drive_or_volume));
+
+ link->details->drive_or_volume = G_OBJECT (drive);
+ }
+
+ /* The link will get updated below */
+ }
+
+ reread_drive_or_volume (link);
+ nautilus_desktop_link_changed (link);
+}
diff -uNrp nautilus-old/libnautilus-private/nautilus-desktop-link.h nautilus-new/libnautilus-private/nautilus-desktop-link.h
--- nautilus-old/libnautilus-private/nautilus-desktop-link.h 2006-06-01 13:18:34.000000000 -0500
+++ nautilus-new/libnautilus-private/nautilus-desktop-link.h 2006-06-01 13:26:18.000000000 -0500
@@ -77,4 +77,7 @@ gboolean nautilus_desktop
gboolean nautilus_desktop_link_rename (NautilusDesktopLink *link,
const char *name);
+void nautilus_desktop_link_update_from_volume (NautilusDesktopLink *link,
+ GnomeVFSVolume *volume);
+
#endif /* NAUTILUS_DESKTOP_LINK_H */
diff -uNrp nautilus-old/libnautilus-private/nautilus-desktop-link-monitor.c nautilus-new/libnautilus-private/nautilus-desktop-link-monitor.c
--- nautilus-old/libnautilus-private/nautilus-desktop-link-monitor.c 2006-06-01 13:18:34.000000000 -0500
+++ nautilus-new/libnautilus-private/nautilus-desktop-link-monitor.c 2006-06-01 13:26:18.000000000 -0500
@@ -206,15 +206,28 @@ nautilus_desktop_link_monitor_make_filen
return unique_name;
}
+static gboolean
+should_show_drive (GnomeVFSDrive *drive)
+{
+ return (gnome_vfs_drive_is_user_visible (drive)
+ && !gnome_vfs_drive_is_mounted (drive)
+ && eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE));
+}
+
+static gboolean
+should_show_volume (GnomeVFSVolume *volume)
+{
+ return (gnome_vfs_volume_is_user_visible (volume)
+ && eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE));
+}
+
static void
create_drive_link (NautilusDesktopLinkMonitor *monitor,
GnomeVFSDrive *drive)
{
NautilusDesktopLink *link;
- if (!(eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)
- && gnome_vfs_drive_is_user_visible (drive)
- && !gnome_vfs_drive_is_mounted (drive)))
+ if (!should_show_drive (drive))
return;
link = nautilus_desktop_link_new_from_drive_or_volume (G_OBJECT (drive));
@@ -229,22 +242,132 @@ create_volume_link (NautilusDesktopLinkM
link = NULL;
- if (!gnome_vfs_volume_is_user_visible (volume)) {
+ if (!should_show_volume (volume)) {
return;
}
- if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)) {
- link = nautilus_desktop_link_new_from_drive_or_volume (G_OBJECT (volume));
- monitor->details->volume_links = g_list_prepend (monitor->details->volume_links, link);
+ link = nautilus_desktop_link_new_from_drive_or_volume (G_OBJECT (volume));
+ monitor->details->volume_links = g_list_prepend (monitor->details->volume_links, link);
+}
+
+static gboolean
+link_corresponds_to_drive (NautilusDesktopLink *link,
+ GnomeVFSDrive *drive)
+{
+ GObject *drive_or_volume;
+ gboolean same;
+
+ drive_or_volume = nautilus_desktop_link_get_drive_or_volume (link);
+ same = FALSE;
+
+ if (GNOME_IS_VFS_DRIVE (drive_or_volume)) {
+ GnomeVFSDrive *link_drive;
+
+ link_drive = GNOME_VFS_DRIVE (drive_or_volume);
+
+ if (link_drive == drive) {
+ same = TRUE;
+ }
+
+ gnome_vfs_drive_unref (link_drive);
+ } else {
+ GnomeVFSVolume *link_volume;
+ GnomeVFSDrive *link_drive;
+
+ link_volume = GNOME_VFS_VOLUME (drive_or_volume);
+ link_drive = gnome_vfs_volume_get_drive (link_volume);
+
+ if (link_drive == drive) {
+ same = TRUE;
+ }
+
+ if (link_drive) {
+ gnome_vfs_drive_unref (link_drive);
+ }
+
+ gnome_vfs_volume_unref (link_volume);
+ }
+
+ return same;
+}
+
+static NautilusDesktopLink *
+find_unique_link_for_drive (NautilusDesktopLinkMonitor *monitor,
+ GnomeVFSDrive *drive)
+{
+ GList *l;
+ NautilusDesktopLink *first_volume_link_for_drive;
+
+ first_volume_link_for_drive = NULL;
+
+ for (l = monitor->details->volume_links; l; l = l->next) {
+ NautilusDesktopLink *link;
+
+ link = NAUTILUS_DESKTOP_LINK (l->data);
+
+ if (link_corresponds_to_drive (link, drive)) {
+ if (first_volume_link_for_drive == NULL) {
+ first_volume_link_for_drive = link;
+ } else {
+ return NULL; /* We know that we have more than
+ * one link for volumes that belong
+ * to the same drive, so there is
+ * no unique link for the drive.
+ */
+ }
+ }
}
+
+ return first_volume_link_for_drive;
}
static void
-drive_connect_disconnect_callback (GnomeVFSVolumeMonitor *volume_monitor,
- GnomeVFSDrive *drive,
- NautilusDesktopLinkMonitor *monitor)
+drive_connected_callback (GnomeVFSVolumeMonitor *volume_monitor,
+ GnomeVFSDrive *drive,
+ NautilusDesktopLinkMonitor *monitor)
{
- refresh_volume_links (monitor);
+ NautilusDesktopLink *link;
+
+ /* fprintf (stderr, "drive connected!\n"); */
+
+ link = find_unique_link_for_drive (monitor, drive);
+
+ if (link)
+ return; /* huh, we already have a link for that drive... */
+
+ create_drive_link (monitor, drive);
+}
+
+static void
+drive_disconnected_callback (GnomeVFSVolumeMonitor *volume_monitor,
+ GnomeVFSDrive *drive,
+ NautilusDesktopLinkMonitor *monitor)
+{
+ GList *l;
+
+ /* fprintf (stderr, "drive disconnected!\n"); */
+
+ /* Remove all the links that correspond to that drive, even if they have
+ * mounted volumes.
+ */
+
+ l = monitor->details->volume_links;
+
+ while (l) {
+ GList *next;
+ NautilusDesktopLink *link;
+
+ next = l->next;
+ link = NAUTILUS_DESKTOP_LINK (l->data);
+
+ if (link_corresponds_to_drive (link, drive)) {
+ g_object_unref (link);
+ monitor->details->volume_links = g_list_remove_link (monitor->details->volume_links, l);
+ g_list_free_1 (l);
+ }
+
+ l = next;
+ }
}
static void
@@ -252,11 +375,65 @@ volume_mounted_callback (GnomeVFSVolumeM
GnomeVFSVolume *volume,
NautilusDesktopLinkMonitor *monitor)
{
-#if 0
- create_volume_link (monitor, volume);
-#else
- refresh_volume_links (monitor);
-#endif
+ GnomeVFSDrive *drive;
+
+ /* fprintf (stderr, "volume mounted!\n"); */
+
+ drive = gnome_vfs_volume_get_drive (volume);
+
+ if (drive) {
+ NautilusDesktopLink *link;
+
+ /* We may have an existing link for the drive, which needs to be
+ * updated for the volume. Or we may have several volumes
+ * within the same drive; in this case, we need to create a
+ * completely new link.
+ */
+
+ link = find_unique_link_for_drive (monitor, drive);
+ gnome_vfs_drive_unref (drive);
+
+ if (link) {
+ /* fprintf (stderr, "updating desktop link from mounted volume\n"); */
+ nautilus_desktop_link_update_from_volume (link, volume);
+ } else {
+ /* fprintf (stderr, "creating desktop link\n"); */
+ create_volume_link (monitor, volume);
+ }
+ } else {
+ /* fprintf (stderr, "creating desktop link\n"); */
+ create_volume_link (monitor, volume);
+ }
+}
+
+static NautilusDesktopLink *
+find_link_for_volume (NautilusDesktopLinkMonitor *monitor,
+ GnomeVFSVolume *volume)
+{
+ GList *l;
+
+ for (l = monitor->details->volume_links; l != NULL; l = l->next) {
+ NautilusDesktopLink *link;
+ GObject *drive_or_volume;
+ gboolean same;
+
+ link = NAUTILUS_DESKTOP_LINK (l->data);
+ drive_or_volume = nautilus_desktop_link_get_drive_or_volume (link);
+
+ same = FALSE;
+
+ if (GNOME_IS_VFS_VOLUME (drive_or_volume)) {
+ same = (GNOME_VFS_VOLUME (drive_or_volume) == volume);
+ gnome_vfs_volume_unref (GNOME_VFS_VOLUME (drive_or_volume));
+ } else {
+ gnome_vfs_drive_unref (GNOME_VFS_DRIVE (drive_or_volume));
+ }
+
+ if (same)
+ return link;
+ }
+
+ return NULL;
}
@@ -265,34 +442,34 @@ volume_unmounted_callback (GnomeVFSVolum
GnomeVFSVolume *volume,
NautilusDesktopLinkMonitor *monitor)
{
-#if 0
- GList *l;
NautilusDesktopLink *link;
- GObject *other_volume;
+ GnomeVFSDrive *drive;
+ gboolean remove_link;
- link = NULL;
- for (l = monitor->details->volume_links; l != NULL; l = l->next) {
- other_volume = nautilus_desktop_link_get_drive_or_volume (l->data);
- if (GNOME_IS_VFS_VOLUME (other_volume) && volume == GNOME_VFS_VOLUME (other_volume)) {
- gnome_vfs_volume_unref (GNOME_VFS_VOLUME (other_volume));
- link = l->data;
- break;
- }
+ /* fprintf (stderr, "volume unmounted!\n"); */
- if (GNOME_IS_VFS_VOLUME (other_volume)) {
- gnome_vfs_volume_unref (GNOME_VFS_VOLUME (other_volume));
+ link = find_link_for_volume (monitor, volume);
+ if (!link) {
+ return;
+ }
+
+ remove_link = FALSE;
+
+ drive = gnome_vfs_volume_get_drive (volume);
+ if (drive) {
+ if (should_show_drive (drive)) {
+ nautilus_desktop_link_update_from_volume (link, volume);
} else {
- gnome_vfs_drive_unref (GNOME_VFS_DRIVE (other_volume));
+ remove_link = TRUE;
}
+ } else {
+ remove_link = TRUE;
}
- if (link) {
+ if (remove_link) {
monitor->details->volume_links = g_list_remove (monitor->details->volume_links, link);
g_object_unref (link);
}
-#else
- refresh_volume_links (monitor);
-#endif
}
static void
@@ -485,10 +662,10 @@ nautilus_desktop_link_monitor_init (gpoi
volume_monitor = gnome_vfs_get_volume_monitor ();
monitor->details->connected_id = g_signal_connect_object (volume_monitor, "drive_connected",
- G_CALLBACK (drive_connect_disconnect_callback),
+ G_CALLBACK (drive_connected_callback),
monitor, 0);
- monitor->details->disconnected_id = g_signal_connect_object (volume_monitor, "drive_connected",
- G_CALLBACK (drive_connect_disconnect_callback),
+ monitor->details->disconnected_id = g_signal_connect_object (volume_monitor, "drive_disconnected",
+ G_CALLBACK (drive_disconnected_callback),
monitor, 0);
monitor->details->mount_id = g_signal_connect_object (volume_monitor, "volume_mounted",
G_CALLBACK (volume_mounted_callback), monitor, 0);
diff -uNrp nautilus-old/src/file-manager/fm-directory-view.c nautilus-new/src/file-manager/fm-directory-view.c
--- nautilus-old/src/file-manager/fm-directory-view.c 2006-06-01 13:18:34.000000000 -0500
+++ nautilus-new/src/file-manager/fm-directory-view.c 2006-06-01 13:26:18.000000000 -0500
@@ -278,6 +278,7 @@ typedef struct {
gboolean mounted;
gboolean mounting;
gboolean cancelled;
+ gulong file_changed_id;
} ActivateParameters;
enum {
@@ -7385,6 +7386,25 @@ activate_callback (NautilusFile *file, g
}
static void
+activation_file_changed_after_drive_mounted (NautilusFile *file,
+ gpointer data)
+{
+ ActivateParameters *parameters;
+ GnomeVFSDrive *drive;
+
+ parameters = data;
+
+ drive = nautilus_file_get_drive (parameters->file); /* we don't own this reference */
+ g_assert (drive != NULL);
+ g_assert (gnome_vfs_drive_is_mounted (drive));
+
+ g_signal_handler_disconnect (parameters->file, parameters->file_changed_id);
+ parameters->file_changed_id = 0;
+
+ activate_activation_uri_ready_callback (parameters->file, parameters);
+}
+
+static void
activation_drive_mounted_callback (gboolean succeeded,
char *error,
char *detailed_error,
@@ -7398,9 +7418,35 @@ activation_drive_mounted_callback (gbool
parameters->mounting = FALSE;
if (succeeded && !parameters->cancelled) {
- activate_activation_uri_ready_callback (parameters->file,
- parameters);
+ GnomeVFSDrive *drive;
+
+ /* fprintf (stderr, "LOG: activation_drive_mounted_callback(): drive got mounted successfully\n"); */
+
+ drive = nautilus_file_get_drive (parameters->file); /* we don't own this reference */
+ g_assert (drive != NULL);
+
+ if (gnome_vfs_drive_is_mounted (drive)) {
+ /* fprintf (stderr, "LOG: activation_drive_mounted_callback(): drive is really mounted; activating...\n"); */
+ activate_activation_uri_ready_callback (parameters->file,
+ parameters);
+ } else {
+ /* Hack alert: Here, the drive is already mounted, but
+ * gnome-vfs-volume-monitor thinks that it is not. This
+ * is because gnome-vfs-daemon has not yet notified it.
+ * So we'll wait for the parameters->file to change:
+ * this will happen when gnome-vfs-volume-monitor
+ * actually picks up and emits the volume_mounted
+ * notification, and the NautilusDesktopLink modifies
+ * the NautilusFile.
+ */
+ /* fprintf (stderr, "LOG: activation_drive_mounted_callback(): delaying activation...\n"); */
+ parameters->file_changed_id =
+ g_signal_connect (parameters->file, "changed",
+ G_CALLBACK (activation_file_changed_after_drive_mounted),
+ parameters);
+ }
} else {
+ /* fprintf (stderr, "LOG: activation_drive_mounted_callback(): drive didn't get mounted\n"); */
if (!parameters->cancelled) {
stop_activate (parameters);
@@ -7448,6 +7494,7 @@ activate_activation_uri_ready_callback (
if (drive != NULL &&
!gnome_vfs_drive_is_mounted (drive)) {
parameters->mounting = TRUE;
+ /* fprintf (stderr, "LOG: activate_activation_uri_ready_callback() calling gnome_vfs_drive_mount()\n"); */
gnome_vfs_drive_mount (drive, activation_drive_mounted_callback, callback_data);
return;
}
@@ -7458,6 +7505,7 @@ activate_activation_uri_ready_callback (
*/
actual_file = NULL;
uri = nautilus_file_get_activation_uri (file);
+ /* fprintf (stderr, "LOG: activate_activation_uri_ready_callback() got activation uri %s\n", uri); */
if (!(eel_str_has_prefix (uri, NAUTILUS_DESKTOP_COMMAND_SPECIFIER) ||
eel_str_has_prefix (uri, NAUTILUS_COMMAND_SPECIFIER))) {
actual_file = nautilus_file_get (uri);
@@ -7528,6 +7576,7 @@ fm_directory_view_activate_file (FMDirec
parameters->mounted = FALSE;
parameters->mounting = FALSE;
parameters->cancelled = FALSE;
+ parameters->file_changed_id = 0;
file_name = nautilus_file_get_display_name (file);
timed_wait_prompt = g_strdup_printf (_("Opening \"%s\"."), file_name);