"empty trash" bar



This patch adds an extra bar (similar to the ones os search and of
burn://) to the Trash directory.

screenshot: http://www.gnome.org/~pborelli/nautilus-trash-bar.png

I think it looks cool and is way more useful than having the "empty
trash" button in the Info side pane, since I rarely have the sidepane
open. Beside it's consistent with other contextual actions like "Burn
CD".


About the implementation: it was a bit tricky to figure out the right
layer of abstraction where to plug this in... I decided to make a new
"nautilus-trash-bar" object that simply knows how to empty the trash
(it's just a matter of calling nautilus_file_operations_empty_trash)
instead of making it emit a signal, given that the "empty trash" menu
item is implemented at the directory-view level and not at the
nautilus-window level. It is also the same thing that the "empty trash"
in the side pane does, so I am not making thing worse ;-)

Speaking of the sidepane: the attached patch also removes the "empty
trash" button from the sidepane since IMHO it is redundant (and the code
there it's also unnecessarily complicated, given it tries to handle
confirmation, but that is already taken care of). This part of the patch
is orthogonal to the bar, so if you want to keep the button in the pane,
this part can simply be dropped.
If you agree with removing the button, maybe we should do the same for
"Burn".


/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2006 Paolo Borelli <pborelli katamail com>
 *
 * 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: Paolo Borelli <pborelli katamail com>
 *
 */

#include "config.h"

#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>

#include "nautilus-trash-bar.h"
#include <libnautilus-private/nautilus-file-operations.h>
#include <libnautilus-private/nautilus-trash-monitor.h>

#define NAUTILUS_TRASH_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NAUTILUS_TYPE_TRASH_BAR, NautilusTrashBarPrivate))

struct NautilusTrashBarPrivate
{
	GtkTooltips *tooltips;
	GtkWidget   *button;
};

G_DEFINE_TYPE (NautilusTrashBar, nautilus_trash_bar, GTK_TYPE_HBOX)

GtkWidget *
nautilus_trash_bar_get_button (NautilusTrashBar *bar)
{
	GtkWidget *button;

	g_return_val_if_fail (bar != NULL, NULL);

	button = bar->priv->button;

	return button;
}

static void
nautilus_trash_bar_set_property (GObject      *object,
				 guint         prop_id,
				 const GValue *value,
				 GParamSpec   *pspec)
{
	NautilusTrashBar *bar;

	bar = NAUTILUS_TRASH_BAR (object);

	switch (prop_id) {
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

static void
nautilus_trash_bar_get_property (GObject    *object,
				 guint       prop_id,
				 GValue     *value,
				 GParamSpec *pspec)
{
	NautilusTrashBar *bar;

	bar = NAUTILUS_TRASH_BAR (object);

	switch (prop_id) {
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

static void
nautilus_trash_bar_finalize (GObject *object)
{
	NautilusTrashBar *bar;

	bar = NAUTILUS_TRASH_BAR (object);

	if (bar->priv->tooltips != NULL) {
		g_object_unref (bar->priv->tooltips);
	}

	G_OBJECT_CLASS (nautilus_trash_bar_parent_class)->finalize (object);
}

static void
nautilus_trash_bar_trash_state_changed (NautilusTrashMonitor *trash_monitor,
					gboolean              state,
					gpointer              data)
{
	NautilusTrashBar *bar;

	bar = NAUTILUS_TRASH_BAR (data);

	gtk_widget_set_sensitive (bar->priv->button,
				  !nautilus_trash_monitor_is_empty ());
}

static void
nautilus_trash_bar_class_init (NautilusTrashBarClass *klass)
{
	GObjectClass *object_class;

	object_class = G_OBJECT_CLASS (klass);

	object_class->finalize     = nautilus_trash_bar_finalize;
	object_class->get_property = nautilus_trash_bar_get_property;
	object_class->set_property = nautilus_trash_bar_set_property;

	g_type_class_add_private (klass, sizeof (NautilusTrashBarPrivate));
}

static void
empty_trash_callback (GtkWidget *button, gpointer data)
{
	GtkWidget *window;
	
	window = gtk_widget_get_toplevel (button);

	nautilus_file_operations_empty_trash (window);
}

static void
nautilus_trash_bar_init (NautilusTrashBar *bar)
{
	GtkWidget *label;
	GtkWidget *hbox;

	bar->priv = NAUTILUS_TRASH_BAR_GET_PRIVATE (bar);

	hbox = GTK_WIDGET (bar);

	label = gtk_label_new (_("Trash"));
	gtk_widget_show (label);
	gtk_box_pack_start (GTK_BOX (bar), label, FALSE, FALSE, 0);

	bar->priv->button = gtk_button_new_with_mnemonic (_("Empty _Trash"));
	gtk_widget_show (bar->priv->button);
	gtk_box_pack_end (GTK_BOX (hbox), bar->priv->button, FALSE, FALSE, 0);

	gtk_widget_set_sensitive (bar->priv->button,
				  !nautilus_trash_monitor_is_empty ());

	bar->priv->tooltips = gtk_tooltips_new ();
	g_object_ref_sink (bar->priv->tooltips);

	gtk_tooltips_set_tip (GTK_TOOLTIPS (bar->priv->tooltips),
			      bar->priv->button,
			      _("Delete all items in the Trash"),
			      NULL);

	g_signal_connect (bar->priv->button,
			  "clicked",
			  G_CALLBACK (empty_trash_callback),
			  bar);

	g_signal_connect_object (nautilus_trash_monitor_get (),
				 "trash_state_changed",
				 G_CALLBACK (nautilus_trash_bar_trash_state_changed),
				 bar,
				 0);
}

GtkWidget *
nautilus_trash_bar_new (void)
{
	GObject *bar;

	bar = g_object_new (NAUTILUS_TYPE_TRASH_BAR, NULL);

	return GTK_WIDGET (bar);
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2006 Paolo Borelli <pborelli katamail com>
 *
 * 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: Paolo Borelli <pborelli katamail com>
 *
 */

#ifndef __NAUTILUS_TRASH_BAR_H
#define __NAUTILUS_TRASH_BAR_H

#include <gtk/gtk.h>

G_BEGIN_DECLS

#define NAUTILUS_TYPE_TRASH_BAR	 (nautilus_trash_bar_get_type ())
#define NAUTILUS_TRASH_BAR(o)	   (G_TYPE_CHECK_INSTANCE_CAST ((o), NAUTILUS_TYPE_TRASH_BAR, NautilusTrashBar))
#define NAUTILUS_TRASH_BAR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), NAUTILUS_TYPE_TRASH_BAR, NautilusTrashBarClass))
#define NAUTILUS_IS_TRASH_BAR(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), NAUTILUS_TYPE_TRASH_BAR))
#define NAUTILUS_IS_TRASH_BAR_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), NAUTILUS_TYPE_TRASH_BAR))
#define NAUTILUS_TRASH_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NAUTILUS_TYPE_TRASH_BAR, NautilusTrashBarClass))

typedef struct NautilusTrashBarPrivate NautilusTrashBarPrivate;

typedef struct
{
	GtkHBox	box;

	NautilusTrashBarPrivate *priv;
} NautilusTrashBar;

typedef struct
{
	GtkHBoxClass	    parent_class;
} NautilusTrashBarClass;

GType		 nautilus_trash_bar_get_type	(void) G_GNUC_CONST;

GtkWidget	*nautilus_trash_bar_new		(void);

GtkWidget	*nautilus_trash_bar_get_button	(NautilusTrashBar *bar);

G_END_DECLS

#endif /* __GS_TRASH_BAR_H */
Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/nautilus/src/Makefile.am,v
retrieving revision 1.165
diff -u -p -u -p -r1.165 Makefile.am
--- src/Makefile.am	18 Oct 2006 12:37:48 -0000	1.165
+++ src/Makefile.am	14 Dec 2006 22:01:42 -0000
@@ -117,6 +117,8 @@ nautilus_SOURCES = \
 	nautilus-spatial-window.h               \
 	nautilus-throbber.c			\
 	nautilus-throbber.h			\
+	nautilus-trash-bar.c			\
+	nautilus-trash-bar.h			\
 	nautilus-window-bookmarks.c		\
 	nautilus-window-bookmarks.h		\
 	nautilus-window-manage-views.c		\
Index: src/nautilus-information-panel.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-information-panel.c,v
retrieving revision 1.235
diff -u -p -u -p -r1.235 nautilus-information-panel.c
--- src/nautilus-information-panel.c	24 May 2006 13:36:46 -0000	1.235
+++ src/nautilus-information-panel.c	14 Dec 2006 22:01:46 -0000
@@ -36,13 +36,8 @@
 #include <eel/eel-string.h>
 #include <eel/eel-vfs-extensions.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
-#include <libxml/parser.h>
-#include <gtk/gtkcheckmenuitem.h>
 #include <gtk/gtkdnd.h>
 #include <gtk/gtkhbox.h>
-#include <gtk/gtkpaned.h>
-#include <gtk/gtknotebook.h>
-#include <gtk/gtksignal.h>
 #include <glib/gi18n.h>
 #include <libgnomeui/gnome-uidefs.h>
 #include <libgnomevfs/gnome-vfs-mime-handlers.h>
@@ -52,17 +47,14 @@
 #include <libnautilus-private/nautilus-dnd.h>
 #include <libnautilus-private/nautilus-directory.h>
 #include <libnautilus-private/nautilus-file-dnd.h>
-#include <libnautilus-private/nautilus-file-operations.h>
 #include <libnautilus-private/nautilus-file.h>
 #include <libnautilus-private/nautilus-global-preferences.h>
 #include <libnautilus-private/nautilus-keep-last-vertical-box.h>
 #include <libnautilus-private/nautilus-metadata.h>
 #include <libnautilus-private/nautilus-mime-actions.h>
 #include <libnautilus-private/nautilus-program-choosing.h>
-#include <libnautilus-private/nautilus-trash-monitor.h>
 #include <libnautilus-private/nautilus-sidebar-provider.h>
 #include <libnautilus-private/nautilus-module.h>
-#include <math.h>
 
 struct NautilusInformationPanelDetails {
 	GtkVBox *container;
@@ -87,7 +79,6 @@ struct NautilusInformationPanelDetails {
 
 static gboolean nautilus_information_panel_press_event           (GtkWidget                    *widget,
 								  GdkEventButton               *event);
-static void     nautilus_information_panel_destroy               (GtkObject                    *object);
 static void     nautilus_information_panel_finalize              (GObject                      *object);
 static void     nautilus_information_panel_drag_data_received    (GtkWidget                    *widget,
 								  GdkDragContext               *context,
@@ -100,7 +91,6 @@ static void     nautilus_information_pan
 static void     nautilus_information_panel_style_set             (GtkWidget                    *widget,
 								  GtkStyle                     *previous_style);
 static void     nautilus_information_panel_theme_changed         (gpointer                      user_data);
-static void     nautilus_information_panel_confirm_trash_changed (gpointer                      user_data);
 static void     nautilus_information_panel_update_appearance     (NautilusInformationPanel     *information_panel);
 static void     nautilus_information_panel_update_buttons        (NautilusInformationPanel     *information_panel);
 static void     add_command_buttons                              (NautilusInformationPanel     *information_panel,
@@ -111,8 +101,6 @@ static void     nautilus_information_pan
 static void     sidebar_provider_iface_init                      (NautilusSidebarProviderIface *iface);
 static GType    nautilus_information_panel_provider_get_type     (void);
 
-static gboolean confirm_trash_auto_value = TRUE;
-
 enum {
 	LOCATION_CHANGED,
 	LAST_SIGNAL
@@ -213,16 +201,12 @@ nautilus_information_panel_class_init (N
 {
 	GtkWidgetClass *widget_class;
 	GObjectClass *gobject_class;
-	GtkObjectClass *object_class;
 	
 	gobject_class = G_OBJECT_CLASS (klass);
-	object_class = GTK_OBJECT_CLASS (klass);
 	widget_class = GTK_WIDGET_CLASS (klass);
 	
 	gobject_class->finalize = nautilus_information_panel_finalize;
 
-	object_class->destroy = nautilus_information_panel_destroy;
-	
 	widget_class->drag_data_received  = nautilus_information_panel_drag_data_received;
 	widget_class->button_press_event  = nautilus_information_panel_press_event;
 	widget_class->style_set = nautilus_information_panel_style_set;
@@ -262,18 +246,10 @@ static void
 nautilus_information_panel_init (NautilusInformationPanel *information_panel)
 {
 	GtkWidget *widget;
-	static gboolean setup_autos = FALSE;
 
 	widget = GTK_WIDGET (information_panel);
 
 	information_panel->details = g_new0 (NautilusInformationPanelDetails, 1);
-
-	if (!setup_autos) {
-		setup_autos = TRUE;
-		eel_preferences_add_auto_boolean (
-			NAUTILUS_PREFERENCES_CONFIRM_TRASH,
-			&confirm_trash_auto_value);
-	}	
 	
 	/* load the default background */
 	nautilus_information_panel_read_defaults (information_panel);
@@ -303,9 +279,6 @@ nautilus_information_panel_init (Nautilu
 	eel_preferences_add_callback (NAUTILUS_PREFERENCES_SIDE_PANE_BACKGROUND_COLOR, nautilus_information_panel_theme_changed, information_panel);
 	eel_preferences_add_callback (NAUTILUS_PREFERENCES_SIDE_PANE_BACKGROUND_FILENAME, nautilus_information_panel_theme_changed, information_panel);
 
-	/* add a callback for when the preference whether to confirm trashing/deleting file changes */
-	eel_preferences_add_callback (NAUTILUS_PREFERENCES_CONFIRM_TRASH, nautilus_information_panel_confirm_trash_changed, information_panel);
-
 	/* prepare ourselves to receive dropped objects */
 	gtk_drag_dest_set (GTK_WIDGET (information_panel),
 			   GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, 
@@ -314,16 +287,6 @@ nautilus_information_panel_init (Nautilu
 }
 
 static void
-nautilus_information_panel_destroy (GtkObject *object)
-{
-	NautilusInformationPanel *information_panel;
-
-	information_panel = NAUTILUS_INFORMATION_PANEL (object);
-
-	EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
-}
-
-static void
 nautilus_information_panel_finalize (GObject *object)
 {
 	NautilusInformationPanel *information_panel;
@@ -352,11 +315,6 @@ nautilus_information_panel_finalize (GOb
 					 nautilus_information_panel_theme_changed,
 					 information_panel);
 
-	eel_preferences_remove_callback (NAUTILUS_PREFERENCES_CONFIRM_TRASH,
-					 nautilus_information_panel_confirm_trash_changed,
-					 information_panel);
-
-
 	EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
 }
 
@@ -459,17 +417,6 @@ nautilus_information_panel_theme_changed
 	gtk_widget_queue_draw (GTK_WIDGET (information_panel)) ;	
 }
 
-/* handler for handling confirming trash preferences changes */
-
-static void
-nautilus_information_panel_confirm_trash_changed (gpointer user_data)
-{
-	NautilusInformationPanel *information_panel;
-	
-	information_panel = NAUTILUS_INFORMATION_PANEL (user_data);
-	nautilus_information_panel_update_buttons (information_panel);
-}
-
 /* hit testing */
 
 static InformationPanelPart
@@ -518,8 +465,8 @@ receive_dropped_uri_list (NautilusInform
 	char **uris;
 	gboolean exactly_one;
 	GtkWindow *window;
-	
-	uris = g_strsplit (selection_data->data, "\r\n", 0);
+
+	uris = g_uri_list_extract_uris ((gchar *) selection_data->data);
 	exactly_one = uris[0] != NULL && (uris[1] == NULL || uris[1][0] == '\0');
 	window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (information_panel)));
 	
@@ -974,17 +921,6 @@ add_buttons_from_metadata (NautilusInfor
 	g_strfreev (terms);
 }
 
-/* handle the hacked-in empty trash command */
-static void
-empty_trash_callback (GtkWidget *button, gpointer data)
-{
-	GtkWidget *window;
-	
-	window = gtk_widget_get_toplevel (button);
-	nautilus_file_operations_empty_trash (window);
-}
-
-
 static void
 burn_cd_callback (GtkWidget *button, gpointer data)
 {
@@ -1004,13 +940,6 @@ burn_cd_callback (GtkWidget *button, gpo
 	}
 }
 
-static void
-nautilus_information_panel_trash_state_changed_callback (NautilusTrashMonitor *trash_monitor,
-						gboolean state, gpointer callback_data)
-{
-		gtk_widget_set_sensitive (GTK_WIDGET (callback_data), !nautilus_trash_monitor_is_empty ());
-}
-
 /*
  * nautilus_information_panel_update_buttons:
  * 
@@ -1039,24 +968,6 @@ nautilus_information_panel_update_button
 		g_free(button_data);
 	}
 
-	/* here is a hack to provide an "empty trash" button when displaying the trash.  Eventually, we
-	 * need a framework to allow protocols to add commands buttons */
-	if (eel_istr_has_prefix (information_panel->details->uri, "trash:")) {
-		/* FIXME: We don't use spaces to pad labels! */
-		temp_button = gtk_button_new_with_mnemonic (_("Empty _Trash"));
-
-		gtk_box_pack_start (GTK_BOX (information_panel->details->button_box), 
-					temp_button, FALSE, FALSE, 0);
-		gtk_widget_set_sensitive (temp_button, !nautilus_trash_monitor_is_empty ());
-		gtk_widget_show (temp_button);
-		information_panel->details->has_buttons = TRUE;
-					
-		g_signal_connect (temp_button, "clicked",
-				  G_CALLBACK (empty_trash_callback), NULL);
-		
-		g_signal_connect_object (nautilus_trash_monitor_get (), "trash_state_changed",
-					 G_CALLBACK (nautilus_information_panel_trash_state_changed_callback), temp_button, 0);
-	}
 	if (eel_istr_has_prefix (information_panel->details->uri, "burn:")) {
 		/* FIXME: We don't use spaces to pad labels! */
 		temp_button = gtk_button_new_with_mnemonic (_("_Write contents to CD"));
Index: src/nautilus-window-manage-views.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-window-manage-views.c,v
retrieving revision 1.370
diff -u -p -u -p -r1.370 nautilus-window-manage-views.c
--- src/nautilus-window-manage-views.c	8 Dec 2006 09:49:40 -0000	1.370
+++ src/nautilus-window-manage-views.c	14 Dec 2006 22:01:55 -0000
@@ -35,6 +35,7 @@
 #include "nautilus-pathbar.h"
 #include "nautilus-main.h"
 #include "nautilus-window-private.h"
+#include "nautilus-trash-bar.h"
 #include "nautilus-zoom-control.h"
 #include <eel/eel-accessibility.h>
 #include <eel/eel-debug.h>
@@ -64,6 +65,7 @@
 #include <libnautilus-private/nautilus-module.h>
 #include <libnautilus-private/nautilus-monitor.h>
 #include <libnautilus-private/nautilus-search-directory.h>
+#include <libnautilus-private/nautilus-trash-directory.h>
 #include <libnautilus-private/nautilus-view-factory.h>
 #include <libnautilus-private/nautilus-window-info.h>
 
@@ -1173,7 +1175,36 @@ add_extension_extra_widgets (NautilusWin
 	}
 
 	nautilus_module_extension_list_free (providers);
-	
+}
+
+static void
+nautilus_window_show_trash_bar (NautilusWindow *window)
+{
+	g_assert (NAUTILUS_IS_WINDOW (window));
+
+	if (window->details->trash_bar == NULL) {
+		window->details->trash_bar = nautilus_trash_bar_new ();
+
+		g_signal_connect (window->details->trash_bar,
+				  "destroy",
+				  G_CALLBACK (gtk_widget_destroyed),
+				  &window->details->trash_bar);
+
+		gtk_widget_show (window->details->trash_bar);
+
+		nautilus_window_add_extra_location_widget (window,
+							   window->details->trash_bar);
+	}
+}
+
+static void
+nautilus_window_hide_trash_bar (NautilusWindow *window)
+{
+	g_assert (NAUTILUS_IS_WINDOW (window));
+
+	if (window->details->trash_bar != NULL) {
+		gtk_widget_destroy (window->details->trash_bar);
+	}
 }
 
 /* Handle the changes for the NautilusWindow itself. */
@@ -1233,6 +1264,13 @@ update_for_new_location (NautilusWindow 
 		} else {
 			nautilus_window_set_search_mode (window, FALSE, NULL);
 		}
+
+		if (NAUTILUS_IS_TRASH_DIRECTORY (directory)) {
+			nautilus_window_show_trash_bar (window);
+		} else {
+			nautilus_window_hide_trash_bar (window);
+		}
+
 		nautilus_directory_unref (directory);
 
 		add_extension_extra_widgets (window, window->details->location);
Index: src/nautilus-window-private.h
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-window-private.h,v
retrieving revision 1.115
diff -u -p -u -p -r1.115 nautilus-window-private.h
--- src/nautilus-window-private.h	24 Jul 2006 23:57:24 -0000	1.115
+++ src/nautilus-window-private.h	14 Dec 2006 22:01:55 -0000
@@ -98,6 +98,8 @@ struct NautilusWindowDetails
 
         NautilusWindowShowHiddenFilesMode show_hidden_files_mode;
         gboolean search_mode;
+
+        GtkWidget *trash_bar;
 };
 
 struct _NautilusNavigationWindowDetails {


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