Removable Media Bar



Yo

To finish my nautilus hacking for the night here's a Removable Media
Bar. It adds the blue bar at the top of windows that contain removable
media and provides an Eject button (for CDs, Zip or Jaz discs) and an
unmount button for usb sticks and things like that.

I know there are bugs galore about doing things like this, but I can't
for the life of me find one. So, here it is.

And everyone likes screenshots, so
http://folks.o-hand.com/iain/eject-unmount.png

iain
Index: nautilus-removable-media-bar.h
===================================================================
--- nautilus-removable-media-bar.h	(revision 0)
+++ nautilus-removable-media-bar.h	(revision 0)
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Iain Holmes <iain gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Iain Holmes <iain gnome org>
+ *
+ */
+
+#ifndef __NAUTILUS_REMOVABLE_MEDIA_BAR_H
+#define __NAUTILUS_REMOVABLE_MEDIA_BAR_H
+
+#include <gtk/gtk.h>
+#include <libgnomevfs/gnome-vfs-volume.h>
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_REMOVABLE_MEDIA_BAR         (nautilus_removable_media_bar_get_type ())
+#define NAUTILUS_REMOVABLE_MEDIA_BAR(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), NAUTILUS_TYPE_REMOVABLE_MEDIA_BAR, NautilusRemovableMediaBar))
+#define NAUTILUS_REMOVABLE_MEDIA_BAR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), NAUTILUS_TYPE_REMOVABLE_MEDIA_BAR, NautilusRemovableMediaBarClass))
+#define NAUTILUS_IS_REMOVABLE_MEDIA_BAR(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), NAUTILUS_TYPE_REMOVABLE_MEDIA_BAR))
+#define NAUTILUS_IS_REMOVABLE_MEDIA_BAR_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), NAUTILUS_TYPE_REMOVABLE_MEDIA_BAR))
+#define NAUTILUS_REMOVABLE_MEDIA_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NAUTILUS_TYPE_REMOVABLE_MEDIA_BAR, NautilusRemovableMediaBarClass))
+
+typedef struct NautilusRemovableMediaBarPrivate NautilusRemovableMediaBarPrivate;
+
+typedef struct
+{
+	GtkHBox	box;
+
+	NautilusRemovableMediaBarPrivate *priv;
+} NautilusRemovableMediaBar;
+
+typedef struct
+{
+	GtkHBoxClass	    parent_class;
+} NautilusRemovableMediaBarClass;
+
+GType		 nautilus_removable_media_bar_get_type	(void) G_GNUC_CONST;
+
+GtkWidget	*nautilus_removable_media_bar_new	(GnomeVFSVolume *volume);
+
+G_END_DECLS
+
+#endif /* __GS_TRASH_BAR_H */
Index: nautilus-window-manage-views.c
===================================================================
--- nautilus-window-manage-views.c	(revision 12857)
+++ nautilus-window-manage-views.c	(working copy)
@@ -36,6 +36,7 @@
 #include "nautilus-main.h"
 #include "nautilus-window-private.h"
 #include "nautilus-trash-bar.h"
+#include "nautilus-removable-media-bar.h"
 #include "nautilus-zoom-control.h"
 #include <eel/eel-accessibility.h>
 #include <eel/eel-debug.h>
@@ -52,6 +53,7 @@
 #include <libgnomeui/gnome-dialog-util.h>
 #include <libgnomeui/gnome-icon-theme.h>
 #include <libgnomevfs/gnome-vfs-async-ops.h>
+#include <libgnomevfs/gnome-vfs-volume-monitor.h>
 #include <libgnomevfs/gnome-vfs-uri.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
 #include <libnautilus-extension/nautilus-location-widget-provider.h>
@@ -1193,6 +1195,74 @@
 	nautilus_window_add_extra_location_widget (window, bar);
 }
 
+static void
+nautilus_window_show_removable_media_bar (NautilusWindow *window)
+{
+	GnomeVFSVolumeMonitor *monitor;
+	GnomeVFSVolume *volume;
+	GnomeVFSDrive *drive, *parent_drive;
+	GList *drives, *d, *volumes, *v;
+	GtkWidget *bar;
+	char *mount_uri, *path;
+
+	g_assert (NAUTILUS_IS_WINDOW (window));
+
+	monitor = gnome_vfs_get_volume_monitor ();
+	path = g_strstr_len (window->details->location, -1, "://");
+	volume = gnome_vfs_volume_monitor_get_volume_for_path (monitor, path + 3);
+	if (volume) {
+		parent_drive = gnome_vfs_volume_get_drive (volume);
+
+		if (parent_drive) {
+			bar = nautilus_removable_media_bar_new (volume);
+			gtk_widget_show (bar);
+		
+			nautilus_window_add_extra_location_widget (window, bar);
+			gnome_vfs_drive_unref (parent_drive);
+		}
+
+		return;
+	}
+
+	drives = gnome_vfs_volume_monitor_get_connected_drives (monitor);
+	for (d = drives; d; d = d->next) {
+		drive = d->data;
+
+		if (!gnome_vfs_drive_is_user_visible (drive)) {
+			gnome_vfs_drive_unref (drive);
+			continue;
+		}
+
+		if (gnome_vfs_drive_is_mounted (drive)) {
+			/* Find which volume this window refers to */
+			volumes = gnome_vfs_drive_get_mounted_volumes (drive);
+
+			for (v = volumes; v; v = v->next) {
+				volume = v->data;
+				if (!gnome_vfs_volume_is_user_visible (volume)) {
+					gnome_vfs_volume_unref (volume);
+					continue;
+				}
+
+				mount_uri = gnome_vfs_volume_get_activation_uri (volume);
+				if (strcmp (mount_uri, window->details->location) == 0) {
+					bar = nautilus_removable_media_bar_new (volume);
+					gtk_widget_show (bar);
+					nautilus_window_add_extra_location_widget (window, bar);
+				}
+
+				g_free (mount_uri);
+				gnome_vfs_volume_unref (volume);
+			}
+			g_list_free (volumes);
+		}
+
+		gnome_vfs_drive_unref (drive);
+	}
+
+	g_list_free (drives);
+}
+
 /* Handle the changes for the NautilusWindow itself. */
 static void
 update_for_new_location (NautilusWindow *window)
@@ -1255,6 +1325,8 @@
 			nautilus_window_show_trash_bar (window);
 		}
 
+		nautilus_window_show_removable_media_bar (window);
+
 		nautilus_directory_unref (directory);
 
 		add_extension_extra_widgets (window, window->details->location);
Index: Makefile.am
===================================================================
--- Makefile.am	(revision 12857)
+++ Makefile.am	(working copy)
@@ -105,6 +105,8 @@
 	nautilus-property-browser.h		\
 	nautilus-query-editor.c			\
 	nautilus-query-editor.h			\
+	nautilus-removable-media-bar.c		\
+	nautilus-removable-media-bar.h		\
 	nautilus-search-bar.c			\
 	nautilus-search-bar.h			\
 	nautilus-self-check-functions.c 	\
Index: nautilus-removable-media-bar.c
===================================================================
--- nautilus-removable-media-bar.c	(revision 0)
+++ nautilus-removable-media-bar.c	(revision 0)
@@ -0,0 +1,253 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Iain Holmes <iain gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Iain Holmes <iain gnome org>
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <eel/eel-stock-dialogs.h>
+#include <libgnomevfs/gnome-vfs-volume-monitor.h>
+
+#include "nautilus-removable-media-bar.h"
+#include <libnautilus-private/nautilus-file-operations.h>
+#include <libnautilus-private/nautilus-icon-factory.h>
+#include <libnautilus-private/nautilus-trash-monitor.h>
+
+#define NAUTILUS_REMOVABLE_MEDIA_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NAUTILUS_TYPE_REMOVABLE_MEDIA_BAR, NautilusRemovableMediaBarPrivate))
+
+struct NautilusRemovableMediaBarPrivate
+{
+	GtkTooltips    *tooltips;
+	GtkWidget      *eject;
+	GtkWidget      *umount;
+	GtkWidget      *title;
+	GtkWidget      *image;
+	
+	GnomeVFSVolume *volume;
+};
+
+G_DEFINE_TYPE (NautilusRemovableMediaBar, nautilus_removable_media_bar, GTK_TYPE_HBOX)
+
+static void
+nautilus_removable_media_bar_set_property (GObject      *object,
+					   guint         prop_id,
+					   const GValue *value,
+					   GParamSpec   *pspec)
+{
+	NautilusRemovableMediaBar *bar;
+
+	bar = NAUTILUS_REMOVABLE_MEDIA_BAR (object);
+
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nautilus_removable_media_bar_get_property (GObject    *object,
+					   guint       prop_id,
+					   GValue     *value,
+					   GParamSpec *pspec)
+{
+	NautilusRemovableMediaBar *bar;
+
+	bar = NAUTILUS_REMOVABLE_MEDIA_BAR (object);
+
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nautilus_removable_media_bar_finalize (GObject *object)
+{
+	NautilusRemovableMediaBar *bar;
+
+	bar = NAUTILUS_REMOVABLE_MEDIA_BAR (object);
+
+	if (bar->priv->tooltips != NULL) {
+		g_object_unref (bar->priv->tooltips);
+	}
+
+	G_OBJECT_CLASS (nautilus_removable_media_bar_parent_class)->finalize (object);
+}
+
+static void
+nautilus_removable_media_bar_class_init (NautilusRemovableMediaBarClass *klass)
+{
+	GObjectClass *object_class;
+
+	object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize     = nautilus_removable_media_bar_finalize;
+	object_class->get_property = nautilus_removable_media_bar_get_property;
+	object_class->set_property = nautilus_removable_media_bar_set_property;
+
+	g_type_class_add_private (klass, sizeof (NautilusRemovableMediaBarPrivate));
+}
+
+static void
+volume_op_callback (gboolean succeeded,
+		    char    *error,
+		    char    *detailed_error,
+		    gpointer user_data)
+{
+	if (!succeeded) {
+		if (*error == 0 &&
+		    detailed_error != NULL && *detailed_error == 0) {
+			/* This means the command displays its own errors */
+			return;
+		}
+		eel_show_error_dialog_with_details (error, NULL,
+						    detailed_error, NULL);
+	}
+}
+
+static void
+eject_callback (GtkWidget *button, gpointer data)
+{
+	NautilusRemovableMediaBar *bar;
+	NautilusRemovableMediaBarPrivate *priv;
+	
+	bar = NAUTILUS_REMOVABLE_MEDIA_BAR (data);
+	priv = bar->priv;
+
+	gnome_vfs_volume_eject (priv->volume, volume_op_callback, data);
+}
+
+static void
+unmount_callback (GtkWidget *button, gpointer data)
+{
+	NautilusRemovableMediaBar *bar;
+	NautilusRemovableMediaBarPrivate *priv;
+	GnomeVFSDrive *drive;
+
+	bar = NAUTILUS_REMOVABLE_MEDIA_BAR (data);
+	priv = bar->priv;
+
+	drive = gnome_vfs_volume_get_drive (priv->volume);
+	nautilus_file_operations_unmount_drive (GTK_WIDGET (bar),
+						drive, volume_op_callback, data);
+	gnome_vfs_drive_unref (drive);
+}
+
+static void
+nautilus_removable_media_bar_init (NautilusRemovableMediaBar *bar)
+{
+	GtkWidget *hbox;
+
+	bar->priv = NAUTILUS_REMOVABLE_MEDIA_BAR_GET_PRIVATE (bar);
+
+	hbox = GTK_WIDGET (bar);
+
+	bar->priv->image = gtk_image_new ();
+	gtk_widget_show (bar->priv->image);
+	gtk_box_pack_start (GTK_BOX (bar), bar->priv->image, FALSE, FALSE, 0);
+
+	bar->priv->title = gtk_label_new (_("Removable Media"));
+	gtk_widget_show (bar->priv->title);
+	gtk_box_pack_start (GTK_BOX (bar), bar->priv->title, FALSE, FALSE, 6);
+
+	bar->priv->umount = gtk_button_new_with_mnemonic (_("_Unmount"));
+	gtk_box_pack_end (GTK_BOX (hbox), bar->priv->umount, FALSE, FALSE, 0);
+
+	bar->priv->tooltips = gtk_tooltips_new ();
+	g_object_ref_sink (bar->priv->tooltips);
+
+	gtk_tooltips_set_tip (GTK_TOOLTIPS (bar->priv->tooltips),
+			      bar->priv->umount,
+			      _("Unmount the volume"),
+			      NULL);
+
+	bar->priv->eject = gtk_button_new_with_mnemonic (_("_Eject"));
+	gtk_box_pack_end (GTK_BOX (hbox), bar->priv->eject, FALSE, FALSE, 0);
+
+	gtk_tooltips_set_tip (GTK_TOOLTIPS (bar->priv->tooltips),
+			      bar->priv->eject,
+			      _("Eject the volume"),
+			      NULL);
+
+	g_signal_connect (bar->priv->umount,
+			  "clicked",
+			  G_CALLBACK (unmount_callback),
+			  bar);
+
+	g_signal_connect (bar->priv->eject,
+			  "clicked",
+			  G_CALLBACK (eject_callback),
+			  bar);
+}
+
+static gboolean
+eject_for_type (GnomeVFSDeviceType type)
+{
+	switch (type) {
+	case GNOME_VFS_DEVICE_TYPE_CDROM:
+	case GNOME_VFS_DEVICE_TYPE_ZIP:
+	case GNOME_VFS_DEVICE_TYPE_JAZ:
+		return TRUE;
+
+	default:
+		return FALSE;
+	}
+}
+
+GtkWidget *
+nautilus_removable_media_bar_new (GnomeVFSVolume *volume)
+{
+	NautilusRemovableMediaBarPrivate *priv;
+	GnomeVFSDrive *drive;
+	GObject *bar;
+	GdkPixbuf *pixbuf;
+	char *display_name, *icon_name;
+
+	bar = g_object_new (NAUTILUS_TYPE_REMOVABLE_MEDIA_BAR, NULL);
+	priv = NAUTILUS_REMOVABLE_MEDIA_BAR_GET_PRIVATE (bar);
+
+	display_name = gnome_vfs_volume_get_display_name (volume);
+	gtk_label_set_text (GTK_LABEL (priv->title), display_name);
+	g_free (display_name);
+
+	icon_name = gnome_vfs_volume_get_icon (volume);
+	pixbuf = nautilus_icon_factory_get_pixbuf_from_name_with_stock_size (icon_name, NULL, GTK_ICON_SIZE_DND, NULL);
+	gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
+	g_free (icon_name);
+
+	priv->volume = gnome_vfs_volume_ref (volume);
+	drive = gnome_vfs_volume_get_drive (volume);
+
+	if (eject_for_type (gnome_vfs_volume_get_device_type (volume))) {
+		gtk_widget_show (priv->eject);
+	} else if (drive != NULL) {
+		if (gnome_vfs_drive_is_mounted (drive)) {
+			gtk_widget_show (priv->umount);
+		} 
+
+		gnome_vfs_drive_unref (drive);
+	}
+
+	return GTK_WIDGET (bar);
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]