[patch] Support showing drives and volumes on the desktop
- From: Federico Mena Quintero <federico ximian com>
- To: nautilus-list gnome org
- Subject: [patch] Support showing drives and volumes on the desktop
- Date: Thu, 05 Oct 2006 20:16:14 -0500
Right now, Nautilus only supports showing volume icons on the desktop.
This is fine for volumes which are not associated to a drive, and for
auto-mounted volumes which come out of drives which HAL and friends can
monitor.
However, certain drives like floppies and Zip drives (and some broken
CD-ROMs) don't support media checks. That is, the hardware won't notify
the system when the user inserts media in the drive. Thus, HAL and
g-v-m are not able to automount the drive as soon as media is inserted.
For this kind of drives, the only way for users to access them is to
open computer:/// and double-click on the drive there. This is really
cumbersome.
The right policy for showing drives and volumes is exactly what we have
right now, *plus* the addition of showing drives which do not support
media checks.
The first patch (nautilus-drives-and-volumes-on-desktop.diff) implements
this policy. It's a large patch, but it's well-documented in the
ChangeLog. It basically adds the ability for NautilusDesktopLink to
represent a drive or a volume, and for the links to be updated whenever
a drive sprouts a volume. It handles drives with multiple partitions;
in that case, one volume icon is created for each partition that gets
mounted. This patch applies cleanly to HEAD.
The second patch (nautilus-directory-view-mount-drive.diff) is from
Nautilus in GNOME 2.12, i.e. what is in SLED 10. I couldn't quite grok
Manny's changes in fm-directory-view.c to support activating multiple
files at the same time. What the patch does is to handle a race
condition in which the gnome_vfs_drive_mount() callback gets run, *but*
the drive doesn't yet know that it is mounted. This is because
GnomeVFSVolumeMonitor hasn't been notified yet by gnome-vfs-daemon. To
handle this, the patch delays the activation callback until the drive
really knows that it is mounted.
Manny, I would love your help in porting this second patch over to HEAD,
since you know the surrounding code a lot better :)
I'm really happy with the way both patches have been working in
SLED 10. Floppies and old/broken media appear on the desktop
seamlessly, and users have been quite pleased.
Federico
2006-10-05 Federico Mena Quintero <federico novell com>
Support displaying drive icons in the desktop, even if the drives
are not mounted. Do this only for drives which are supposed to be
user-visible (i.e. those that do not support media checks and so
we cannot know when the user inserts media in them).
Also, support drives with multiple partitions, which will lead to
multiple volumes for the same drive.
To do this, we add several things:
1. The ability for NautilusDesktopLink to represent a drive as
well as a volume.
2. The ability to "transform" a NautilusDesktopLink which
represented a drive, into one that represents a volume. This
happens when a drive is mounted.
3. Keep the invariant that drives are only displayed if they are
unmounted and user visible. If they are mounted, they get
replaced with volume links.
* libnautilus-private/nautilus-desktop-link-monitor.c (struct
NautilusDesktopLinkMonitorDetails): Added "connected_id" and
"disconnected_id" fields for the signal IDs of GnomeVFSDrive.
(volume_delete_dialog): Added message about not being able to move
a drive to the trash. Support drives or volumes.
(should_show_drive): New utility function. Drives are shown if
they are user-visible, they are not mounted, and the preference to
show desktop volumes is turned on.
(should_show_volume): New utility function. Volumes are shown if
they are user visible and the preference to show desktop volumes
is turned on.
(create_drive_link): New utility function; creates a
NautilusDesktopLink for a GnomeVFSDrive.
(create_volume_link): Use should_show_volume().
(link_corresponds_to_drive): New function. A NautilusDesktopLink
corresponds to a drive if it represents the drive itself, or if it
represents a volume relative to that drive.
(find_unique_link_for_drive): New function. Returns the
NautilusDesktopLink in the desktop that corresponds uniquely to a
given drive; if there is more than one volume link for a drive
(e.g. a drive with multiple partitions), returns NULL.
(drive_connected_callback): New callback. When a drive is
connected, we create a link for it if appropriate.
(drive_disconnected_callback): New callback. When a drive is
disconnected, we remove all the links that correspond to it: a
single drive link for an unmounted drive, or one or more volume
links for a mounted drive.
(volume_mounted_callback): If the volume has a drive, and there is
an existing link for that drive, update the link to represent the
volume instead. Otherwise, create volume link as usual.
(find_link_for_volume): New utility function; returns the link on
the desktop which corresponds to a particular volume.
(volume_unmounted_callback): If unmounting a volume would yield a
drive that is user visible, transform the corresponding link from
representing the volume, into one that represents the drive.
Otherwise, remove the link as usual.
(refresh_volume_links): New function; does the initial population
of the links for drives and volumes.
(desktop_volumes_visible_changed): New callback; use
refresh_volume_links().
(nautilus_desktop_link_monitor_init): Use refresh_volume_links()
instead of doing things by hand here. Also, connect to
"drive_connected" and "drive_disconnected" on the volume monitor.
* libnautilus-private/nautilus-desktop-icon-file.c
(update_info_from_link): Accept a drive or a volume, not just
volumes.
* libnautilus-private/nautilus-desktop-link.h
(nautilus_desktop_link_new_from_drive_or_volume): New prototype.
Replaces nautilus_desktop_link_new_from_volume().
(nautilus_desktop_link_get_drive_or_volume): New prototype.
Replaces nautilus_desktop_link_get_volume().
(nautilus_desktop_link_update_from_volume): New prototype.
* libnautilus-private/nautilus-desktop-link.c (struct
NautilusDesktopLinkDetails): Replaced the "volume" field with
"drive_or_volume".
(reread_drive_or_volume): Refresh the link as appropriate from a
drive or a volume.
(desktop_link_finalize): Unref the drive or volume appropriately.
(nautilus_desktop_link_new_from_drive_or_volume): Replacement for
nautilus_desktop_link_new_from_volume().
(nautilus_desktop_link_get_drive_or_volume): Replacement for
nautilus_desktop_link_get_volume().
(nautilus_desktop_link_update_from_volume): New public function;
replaces nautilus_desktop_link_new_from_volume(). Updates the
link's information from a volume. This does the actual
transformation of a link from a drive to volume when an unmounted
drive gets first mounted, and vice-versa.
Index: libnautilus-private/nautilus-desktop-icon-file.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-desktop-icon-file.c,v
retrieving revision 1.8
diff -u -p -r1.8 nautilus-desktop-icon-file.c
--- libnautilus-private/nautilus-desktop-icon-file.c 18 Mar 2006 07:13:49 -0000 1.8
+++ libnautilus-private/nautilus-desktop-icon-file.c 6 Oct 2006 00:32:43 -0000
@@ -179,7 +179,7 @@ update_info_from_link (NautilusDesktopIc
NautilusFile *file;
GnomeVFSFileInfo *file_info;
NautilusDesktopLink *link;
- GnomeVFSVolume *volume;
+ GObject *drive_or_volume;
file = NAUTILUS_FILE (icon_file);
@@ -216,9 +216,21 @@ update_info_from_link (NautilusDesktopIc
GNOME_VFS_FILE_INFO_FIELDS_ACCESS |
GNOME_VFS_FILE_INFO_FIELDS_LINK_COUNT;
- volume = nautilus_desktop_link_get_volume (link);
- nautilus_file_set_volume (file, volume);
- gnome_vfs_volume_unref (volume);
+ drive_or_volume = nautilus_desktop_link_get_drive_or_volume (link);
+
+ if (GNOME_IS_VFS_VOLUME (drive_or_volume)) {
+ GnomeVFSVolume *volume;
+
+ volume = GNOME_VFS_VOLUME (drive_or_volume);
+ nautilus_file_set_volume (file, volume);
+ gnome_vfs_volume_unref (volume);
+ } else {
+ GnomeVFSDrive *drive;
+
+ drive = GNOME_VFS_DRIVE (drive_or_volume);
+ nautilus_file_set_drive (file, drive);
+ gnome_vfs_drive_unref (drive);
+ }
file->details->file_info_is_up_to_date = TRUE;
Index: libnautilus-private/nautilus-desktop-link-monitor.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-desktop-link-monitor.c,v
retrieving revision 1.17
diff -u -p -r1.17 nautilus-desktop-link-monitor.c
--- libnautilus-private/nautilus-desktop-link-monitor.c 18 Mar 2006 07:13:49 -0000 1.17
+++ libnautilus-private/nautilus-desktop-link-monitor.c 6 Oct 2006 00:32:43 -0000
@@ -52,13 +52,14 @@ struct NautilusDesktopLinkMonitorDetails
NautilusDesktopLink *trash_link;
NautilusDesktopLink *network_link;
+ gulong connected_id;
+ gulong disconnected_id;
gulong mount_id;
gulong unmount_id;
GList *volume_links;
};
-
static void nautilus_desktop_link_monitor_init (gpointer object,
gpointer klass);
static void nautilus_desktop_link_monitor_class_init (gpointer klass);
@@ -69,6 +70,8 @@ EEL_CLASS_BOILERPLATE (NautilusDesktopLi
static NautilusDesktopLinkMonitor *the_link_monitor = NULL;
+static void refresh_volume_links (NautilusDesktopLinkMonitor *monitor);
+
static void
destroy_desktop_link_monitor (void)
{
@@ -104,41 +107,48 @@ static void
volume_delete_dialog (GtkWidget *parent_view,
NautilusDesktopLink *link)
{
- GnomeVFSVolume *volume;
+ GObject *drive_or_volume;
char *dialog_str;
+ char *detail_str;
char *display_name;
- volume = nautilus_desktop_link_get_volume (link);
+ drive_or_volume = nautilus_desktop_link_get_drive_or_volume (link);
+ if (drive_or_volume == NULL)
+ return;
- if (volume != NULL) {
- display_name = nautilus_desktop_link_get_display_name (link);
+ display_name = nautilus_desktop_link_get_display_name (link);
+
+ if (GNOME_IS_VFS_VOLUME (drive_or_volume)) {
dialog_str = g_strdup_printf (_("You cannot move the volume \"%s\" to the trash."),
display_name);
- g_free (display_name);
- if (eject_for_type (gnome_vfs_volume_get_device_type (volume))) {
- eel_run_simple_dialog
- (parent_view,
- FALSE,
- GTK_MESSAGE_ERROR,
- dialog_str,
- _("If you want to eject the volume, please use \"Eject\" in the "
- "popup menu of the volume."),
- GTK_STOCK_OK, NULL);
+ if (eject_for_type (gnome_vfs_volume_get_device_type (GNOME_VFS_VOLUME (drive_or_volume)))) {
+ detail_str = _("If you want to eject the volume, please use \"Eject\" in the "
+ "popup menu of the volume.");
} else {
- eel_run_simple_dialog
- (parent_view,
- FALSE,
- GTK_MESSAGE_ERROR,
- dialog_str,
- _("If you want to unmount the volume, please use \"Unmount Volume\" in the "
- "popup menu of the volume."),
- GTK_STOCK_OK, NULL);
+ detail_str = _("If you want to unmount the volume, please use \"Unmount Volume\" in the "
+ "popup menu of the volume.");
}
+ } else {
+ dialog_str = g_strdup_printf (_("You cannot move the drive \"%s\" to the trash."),
+ display_name);
+
+ detail_str = NULL;
+ }
+
+ eel_run_simple_dialog (parent_view, FALSE, GTK_MESSAGE_ERROR,
+ dialog_str,
+ detail_str,
+ NULL, GTK_STOCK_OK, NULL);
- gnome_vfs_volume_unref (volume);
- g_free (dialog_str);
+ if (GNOME_IS_VFS_VOLUME (drive_or_volume)) {
+ gnome_vfs_volume_unref (GNOME_VFS_VOLUME (drive_or_volume));
+ } else {
+ gnome_vfs_drive_unref (GNOME_VFS_DRIVE (drive_or_volume));
}
+
+ g_free (display_name);
+ g_free (dialog_str);
}
void
@@ -196,6 +206,34 @@ 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 (!should_show_drive (drive))
+ return;
+
+ link = nautilus_desktop_link_new_from_drive_or_volume (G_OBJECT (drive));
+ monitor->details->volume_links = g_list_prepend (monitor->details->volume_links, link);
+}
+
static void
create_volume_link (NautilusDesktopLinkMonitor *monitor,
GnomeVFSVolume *volume)
@@ -204,24 +242,198 @@ 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_volume (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_connected_callback (GnomeVFSVolumeMonitor *volume_monitor,
+ GnomeVFSDrive *drive,
+ NautilusDesktopLinkMonitor *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
volume_mounted_callback (GnomeVFSVolumeMonitor *volume_monitor,
GnomeVFSVolume *volume,
NautilusDesktopLinkMonitor *monitor)
{
- create_volume_link (monitor, volume);
+ 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;
}
@@ -230,22 +442,31 @@ volume_unmounted_callback (GnomeVFSVolum
GnomeVFSVolume *volume,
NautilusDesktopLinkMonitor *monitor)
{
- GList *l;
NautilusDesktopLink *link;
- GnomeVFSVolume *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_volume (l->data);
- if (volume == other_volume) {
- gnome_vfs_volume_unref (other_volume);
- link = l->data;
- break;
+ /* fprintf (stderr, "volume unmounted!\n"); */
+
+ 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 {
+ remove_link = TRUE;
}
- gnome_vfs_volume_unref (other_volume);
+ } 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);
}
@@ -322,32 +543,60 @@ desktop_network_visible_changed (gpointe
}
static void
-desktop_volumes_visible_changed (gpointer callback_data)
+refresh_volume_links (NautilusDesktopLinkMonitor *monitor)
{
GnomeVFSVolumeMonitor *volume_monitor;
- NautilusDesktopLinkMonitor *monitor;
- GList *l, *volumes;
volume_monitor = gnome_vfs_get_volume_monitor ();
- monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
+
+ /* Free existing links */
+
+ g_list_foreach (monitor->details->volume_links, (GFunc)g_object_unref, NULL);
+ g_list_free (monitor->details->volume_links);
+ monitor->details->volume_links = NULL;
+
+ /* Scan the links again */
if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)) {
- if (monitor->details->volume_links == NULL) {
- volumes = gnome_vfs_volume_monitor_get_mounted_volumes (volume_monitor);
- for (l = volumes; l != NULL; l = l->next) {
- create_volume_link (monitor, l->data);
- gnome_vfs_volume_unref (l->data);
- }
- g_list_free (volumes);
+ GList *l;
+ GList *volumes, *drives;
+
+ /* Unmounted drives */
+
+ drives = gnome_vfs_volume_monitor_get_connected_drives (volume_monitor);
+ for (l = drives; l != NULL; l = l->next) {
+ GnomeVFSDrive *drive;
+
+ drive = GNOME_VFS_DRIVE (l->data);
+ create_drive_link (monitor, drive);
+ gnome_vfs_drive_unref (drive);
}
- } else {
- g_list_foreach (monitor->details->volume_links, (GFunc)g_object_unref, NULL);
- g_list_free (monitor->details->volume_links);
- monitor->details->volume_links = NULL;
+ g_list_free (drives);
+
+ /* Volumes */
+
+ volumes = gnome_vfs_volume_monitor_get_mounted_volumes (volume_monitor);
+ for (l = volumes; l != NULL; l = l->next) {
+ GnomeVFSVolume *volume;
+
+ volume = GNOME_VFS_VOLUME (l->data);
+ create_volume_link (monitor, volume);
+ gnome_vfs_volume_unref (volume);
+ }
+ g_list_free (volumes);
}
}
static void
+desktop_volumes_visible_changed (gpointer callback_data)
+{
+ NautilusDesktopLinkMonitor *monitor;
+
+ monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
+ refresh_volume_links (monitor);
+}
+
+static void
create_link_and_add_preference (NautilusDesktopLink **link_ref,
NautilusDesktopLinkType link_type,
const char *preference_key,
@@ -365,8 +614,6 @@ static void
nautilus_desktop_link_monitor_init (gpointer object, gpointer klass)
{
NautilusDesktopLinkMonitor *monitor;
- GList *l, *volumes;
- GnomeVFSVolume *volume;
GnomeVFSVolumeMonitor *volume_monitor;
monitor = NAUTILUS_DESKTOP_LINK_MONITOR (object);
@@ -404,22 +651,22 @@ nautilus_desktop_link_monitor_init (gpoi
desktop_network_visible_changed,
monitor);
- /* Volume links */
+ /* Drives and volumes */
- volume_monitor = gnome_vfs_get_volume_monitor ();
-
- volumes = gnome_vfs_volume_monitor_get_mounted_volumes (volume_monitor);
- for (l = volumes; l != NULL; l = l->next) {
- volume = l->data;
- create_volume_link (monitor, volume);
- gnome_vfs_volume_unref (volume);
- }
- g_list_free (volumes);
+ refresh_volume_links (monitor);
eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE,
desktop_volumes_visible_changed,
monitor);
+ volume_monitor = gnome_vfs_get_volume_monitor ();
+
+ monitor->details->connected_id = g_signal_connect_object (volume_monitor, "drive_connected",
+ G_CALLBACK (drive_connected_callback),
+ monitor, 0);
+ 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);
monitor->details->unmount_id = g_signal_connect_object (volume_monitor, "volume_unmounted",
Index: libnautilus-private/nautilus-desktop-link.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-desktop-link.c,v
retrieving revision 1.14
diff -u -p -r1.14 nautilus-desktop-link.c
--- libnautilus-private/nautilus-desktop-link.c 18 Mar 2006 07:13:49 -0000 1.14
+++ libnautilus-private/nautilus-desktop-link.c 6 Oct 2006 00:32:43 -0000
@@ -53,8 +53,8 @@ struct NautilusDesktopLinkDetails {
/* Just for trash icons: */
gulong trash_state_handler;
- /* Just for volume icons: */
- GnomeVFSVolume *volume;
+ /* Just for drive/volume icons */
+ GObject *drive_or_volume;
};
static void nautilus_desktop_link_init (gpointer object,
@@ -192,28 +192,52 @@ nautilus_desktop_link_new (NautilusDeskt
return link;
}
-NautilusDesktopLink *
-nautilus_desktop_link_new_from_volume (GnomeVFSVolume *volume)
+static void
+reread_drive_or_volume (NautilusDesktopLink *link)
{
- NautilusDesktopLink *link;
- GnomeVFSDrive *drive;
char *name, *filename;
+ char *display_name, *activation_uri, *icon;
- link = NAUTILUS_DESKTOP_LINK (g_object_new (NAUTILUS_TYPE_DESKTOP_LINK, NULL));
-
- link->details->type = NAUTILUS_DESKTOP_LINK_VOLUME;
+ g_assert (link->details->type == NAUTILUS_DESKTOP_LINK_VOLUME);
+ g_assert (link->details->drive_or_volume != NULL);
+
+ g_free (link->details->filename);
+ g_free (link->details->display_name);
+ g_free (link->details->activation_uri);
+ g_free (link->details->icon);
- link->details->volume = gnome_vfs_volume_ref (volume);
+ if (GNOME_IS_VFS_VOLUME (link->details->drive_or_volume)) {
+ GnomeVFSVolume *volume;
+ GnomeVFSDrive *drive;
+
+ volume = GNOME_VFS_VOLUME (link->details->drive_or_volume);
+
+ /* We try to use the drive name to get somewhat stable filenames
+ for metadata */
+ drive = gnome_vfs_volume_get_drive (volume);
+ if (drive != NULL) {
+ name = gnome_vfs_drive_get_display_name (drive);
+ } else {
+ name = gnome_vfs_volume_get_display_name (volume);
+ }
+ gnome_vfs_drive_unref (drive);
- /* We try to use the drive name to get somewhat stable filenames
- for metadata */
- drive = gnome_vfs_volume_get_drive (volume);
- if (drive != NULL) {
- name = gnome_vfs_drive_get_display_name (drive);
+ display_name = gnome_vfs_volume_get_display_name (volume);
+ activation_uri = gnome_vfs_volume_get_activation_uri (volume);
+ icon = gnome_vfs_volume_get_icon (volume);
} else {
- name = gnome_vfs_volume_get_display_name (volume);
+ GnomeVFSDrive *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);
+
+ display_name = gnome_vfs_drive_get_display_name (drive);
+ activation_uri = NULL; /* We don't know the activation URI until the drive gets mounted */
+ icon = gnome_vfs_drive_get_icon (drive);
}
- gnome_vfs_drive_unref (drive);
filename = g_strconcat (name, ".volume", NULL);
link->details->filename =
@@ -221,21 +245,51 @@ nautilus_desktop_link_new_from_volume (G
filename);
g_free (filename);
g_free (name);
+
+ 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->display_name = gnome_vfs_volume_get_display_name (volume);
-
- link->details->activation_uri = gnome_vfs_volume_get_activation_uri (volume);
- link->details->icon = gnome_vfs_volume_get_icon (volume);
+ 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;
}
-GnomeVFSVolume *
-nautilus_desktop_link_get_volume (NautilusDesktopLink *link)
+GObject *
+nautilus_desktop_link_get_drive_or_volume (NautilusDesktopLink *link)
{
- return gnome_vfs_volume_ref (link->details->volume);
+ if (GNOME_IS_VFS_VOLUME (link->details->drive_or_volume))
+ return G_OBJECT (gnome_vfs_volume_ref (GNOME_VFS_VOLUME (link->details->drive_or_volume)));
+ else
+ return G_OBJECT (gnome_vfs_drive_ref (GNOME_VFS_DRIVE (link->details->drive_or_volume)));
}
@@ -389,7 +443,11 @@ desktop_link_finalize (GObject *object)
}
if (link->details->type == NAUTILUS_DESKTOP_LINK_VOLUME) {
- gnome_vfs_volume_unref (link->details->volume);
+ if (GNOME_IS_VFS_VOLUME (link->details->drive_or_volume)) {
+ gnome_vfs_volume_unref (GNOME_VFS_VOLUME (link->details->drive_or_volume));
+ } else {
+ gnome_vfs_drive_unref (GNOME_VFS_DRIVE (link->details->drive_or_volume));
+ }
}
g_free (link->details->filename);
@@ -410,4 +468,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);
+
+ 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);
}
Index: libnautilus-private/nautilus-desktop-link.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-desktop-link.h,v
retrieving revision 1.4
diff -u -p -r1.4 nautilus-desktop-link.h
--- libnautilus-private/nautilus-desktop-link.h 10 Dec 2005 02:40:35 -0000 1.4
+++ libnautilus-private/nautilus-desktop-link.h 6 Oct 2006 00:32:43 -0000
@@ -26,6 +26,7 @@
#define NAUTILUS_DESKTOP_LINK_H
#include <libnautilus-private/nautilus-file.h>
+#include <libgnomevfs/gnome-vfs-drive.h>
#include <libgnomevfs/gnome-vfs-volume.h>
#define NAUTILUS_TYPE_DESKTOP_LINK \
@@ -61,7 +62,7 @@ typedef enum {
GType nautilus_desktop_link_get_type (void);
NautilusDesktopLink * nautilus_desktop_link_new (NautilusDesktopLinkType type);
-NautilusDesktopLink * nautilus_desktop_link_new_from_volume (GnomeVFSVolume *volume);
+NautilusDesktopLink * nautilus_desktop_link_new_from_drive_or_volume (GObject *object);
NautilusDesktopLinkType nautilus_desktop_link_get_link_type (NautilusDesktopLink *link);
char * nautilus_desktop_link_get_file_name (NautilusDesktopLink *link);
char * nautilus_desktop_link_get_display_name (NautilusDesktopLink *link);
@@ -70,10 +71,12 @@ char * nautilus_desktop
gboolean nautilus_desktop_link_get_date (NautilusDesktopLink *link,
NautilusDateType date_type,
time_t *date);
-GnomeVFSVolume * nautilus_desktop_link_get_volume (NautilusDesktopLink *link);
+GObject * nautilus_desktop_link_get_drive_or_volume (NautilusDesktopLink *link);
gboolean nautilus_desktop_link_can_rename (NautilusDesktopLink *link);
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 */
Index: src/file-manager/fm-directory-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-directory-view.c,v
retrieving revision 1.750
diff -u -p -r1.750 fm-directory-view.c
--- src/file-manager/fm-directory-view.c 8 Aug 2006 14:43:25 -0000 1.750
+++ src/file-manager/fm-directory-view.c 6 Oct 2006 00:32:46 -0000
@@ -8498,7 +8498,7 @@ activation_drive_mounted_callback (gbool
parameters = callback_data;
- parameters->mount_success &= succeeded;
+ parameters->mount_success = parameters->mount_success && succeeded;
if (!succeeded && !parameters->cancelled) {
if (*error == 0 &&
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.
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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]