Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/Makefile.am,v
retrieving revision 1.343
diff -u -p -r1.343 Makefile.am
--- Makefile.am	12 Dec 2004 11:45:25 -0000	1.343
+++ Makefile.am	18 Dec 2004 11:46:06 -0000
@@ -113,6 +113,7 @@ panel_sources =			\
 	panel-force-quit.c	\
 	panel-lockdown.c	\
 	panel-addto.c		\
+	panel-connect-server.c	\
 	$(EGG_RECENT_FILES_C)	\
 	$(NULL)
 
@@ -158,6 +159,7 @@ panel_headers =			\
 	panel-force-quit.h	\
 	panel-lockdown.h	\
 	panel-addto.h		\
+	panel-connect-server.h	\
 	$(EGG_RECENT_FILES_H)	\
 	$(NULL)
 
Index: menu.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/menu.c,v
retrieving revision 1.729
diff -u -p -r1.729 menu.c
--- menu.c	15 Dec 2004 09:30:39 -0000	1.729
+++ menu.c	18 Dec 2004 11:46:06 -0000
@@ -1088,6 +1088,35 @@ drag_data_get_string_cb (GtkWidget *widg
 }
 
 void
+setup_uri_drag (GtkWidget  *menuitem,
+		const char *uri,
+		const char *icon)
+{
+	static GtkTargetEntry menu_item_targets[] = {
+		{ "text/uri-list", 0, 0 }
+	};
+
+	if (panel_lockdown_get_locked_down ())
+		return;
+
+	gtk_drag_source_set (menuitem,
+			     GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
+			     menu_item_targets, 1,
+			     GDK_ACTION_COPY);
+
+	/* FIXME: waiting for bug #116577
+	gtk_drag_source_set_icon_name (GTK_WIDGET (button), icon); */
+	
+	g_signal_connect_data (G_OBJECT (menuitem), "drag_data_get",
+			       G_CALLBACK (drag_data_get_string_cb),
+			       g_strdup (uri),
+			       (GClosureNotify)g_free,
+			       0 /* connect_flags */);
+	g_signal_connect (G_OBJECT (menuitem), "drag_end",
+			  G_CALLBACK (drag_end_menu_cb), NULL);
+}
+
+void
 setup_internal_applet_drag (GtkWidget             *menuitem,
 			    PanelActionButtonType  type)
 {
@@ -1284,6 +1313,10 @@ handle_menu_tree_changed (MenuTree  *tre
 
 	g_object_set_data (G_OBJECT (menu),
 			   "panel-menu-needs-loading",
+			   GUINT_TO_POINTER (TRUE));
+
+	g_object_set_data (G_OBJECT (menu),
+			   "panel-menu-needs-appending",
 			   GUINT_TO_POINTER (TRUE));
 }
 
Index: menu.h
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/menu.h,v
retrieving revision 1.102
diff -u -p -r1.102 menu.h
--- menu.h	15 Dec 2004 09:30:39 -0000	1.102
+++ menu.h	18 Dec 2004 11:46:06 -0000
@@ -50,6 +50,9 @@ GtkWidget      *create_main_menu        
 
 void		setup_internal_applet_drag (GtkWidget             *menuitem,
 					    PanelActionButtonType  type);
+void            setup_uri_drag             (GtkWidget  *menuitem,
+					    const char *uri,
+					    const char *icon);
 
 GtkWidget *	panel_create_menu              (void);
 
Index: panel-action-button.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-action-button.c,v
retrieving revision 1.36
diff -u -p -r1.36 panel-action-button.c
--- panel-action-button.c	16 Dec 2004 20:24:05 -0000	1.36
+++ panel-action-button.c	18 Dec 2004 11:46:06 -0000
@@ -38,6 +38,7 @@
 #include "panel-profile.h"
 #include "panel-stock-icons.h"
 #include "panel-typebuiltins.h"
+#include "panel-connect-server.h"
 #include "panel-force-quit.h"
 #include "panel-util.h"
 #include "panel-session.h"
@@ -66,13 +67,14 @@ struct _PanelActionButtonPrivate {
 static GObjectClass *parent_class;
 
 static GConfEnumStringPair panel_action_type_map [] = {
-	{ PANEL_ACTION_NONE,         "none"         },
-	{ PANEL_ACTION_LOCK,         "lock"         },
-	{ PANEL_ACTION_LOGOUT,       "logout"       },
-	{ PANEL_ACTION_RUN,          "run"          },
-	{ PANEL_ACTION_SEARCH,       "search"       },
-	{ PANEL_ACTION_SCREENSHOT,   "screenshot"   },
-	{ PANEL_ACTION_FORCE_QUIT,   "force-quit"   },
+	{ PANEL_ACTION_NONE,           "none"           },
+	{ PANEL_ACTION_LOCK,           "lock"           },
+	{ PANEL_ACTION_LOGOUT,         "logout"         },
+	{ PANEL_ACTION_RUN,            "run"            },
+	{ PANEL_ACTION_SEARCH,         "search"         },
+	{ PANEL_ACTION_SCREENSHOT,     "screenshot"     },
+	{ PANEL_ACTION_FORCE_QUIT,     "force-quit"     },
+	{ PANEL_ACTION_CONNECT_SERVER, "connect-server" }
 };
 
 /* Lock Screen
@@ -259,6 +261,14 @@ panel_action_force_quit (GtkWidget *widg
 	panel_force_quit (gtk_widget_get_screen (widget));
 }
 
+/* Connect Server
+ */
+static void
+panel_action_connect_server (GtkWidget *widget)
+{
+	panel_connect_server_show (gtk_widget_get_screen (widget));
+}
+
 typedef struct {
 	PanelActionButtonType   type;
 	char                   *stock_icon;
@@ -347,6 +357,16 @@ static PanelAction actions [] = {
 		"ACTION:force-quit:NEW",
 		panel_action_force_quit, NULL, NULL,
 		panel_lockdown_get_disable_force_quit
+	},
+	{
+		PANEL_ACTION_CONNECT_SERVER,
+		NULL,
+		"gnome-globe", //FIXME icon
+		N_("Connect to Server..."),
+		N_("Connect to a remote server"), //FIXME
+		"gospanel-563", //FIXME
+		"ACTION:connect-server:NEW",
+		panel_action_connect_server, NULL, NULL, NULL
 	}
 };
 
Index: panel-addto.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-addto.c,v
retrieving revision 1.21
diff -u -p -r1.21 panel-addto.c
--- panel-addto.c	15 Dec 2004 12:43:06 -0000	1.21
+++ panel-addto.c	18 Dec 2004 11:46:07 -0000
@@ -59,6 +59,7 @@ typedef struct {
 
 	GSList       *applet_list;
 	GSList       *application_list;
+	GSList       *settings_list;
 
 	guint         name_notify;
 
@@ -648,6 +649,29 @@ panel_addto_make_application_model (Pane
 
 	menu_tree_unref (tree);
 
+	tree = menu_tree_lookup ("settings.menu");
+
+	if ((root = menu_tree_get_root_directory (tree))) {
+		GtkTreeIter iter;
+
+		gtk_tree_store_append (store, &iter, NULL);
+		gtk_tree_store_set (store, &iter,
+				    COLUMN_ICON, NULL,
+				    COLUMN_TEXT, NULL,
+				    COLUMN_DATA, NULL,
+				    COLUMN_SEARCH, NULL,
+				    -1);
+
+		panel_addto_make_application_list (&dialog->settings_list,
+						   root);
+		panel_addto_populate_application_model (store, NULL,
+							dialog->settings_list);
+
+		menu_tree_directory_unref (root);
+	}
+
+	menu_tree_unref (tree);
+
 	return GTK_TREE_MODEL (store);
 }
 
@@ -866,6 +890,7 @@ panel_addto_dialog_free (PanelAddtoDialo
 	g_slist_free (dialog->applet_list);
 
 	panel_addto_dialog_free_application_list (dialog->application_list);
+	panel_addto_dialog_free_application_list (dialog->settings_list);
 
 	if (dialog->menu_tree)
 		menu_tree_unref (dialog->menu_tree);
Index: panel-connect-server.c
===================================================================
RCS file: panel-connect-server.c
diff -N panel-connect-server.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panel-connect-server.c	18 Dec 2004 11:46:07 -0000
@@ -0,0 +1,768 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/*
+ * panel-connect-server.c: Connect to server... dialog
+ * Code comes from nautilus (src/nautils-connect-server-dialog.c)
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ * Copyright (C) 2004 Vincent Untz
+ *
+ * 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; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "panel-connect-server.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-volume.h>
+#include <libgnomeui/gnome-url.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtktable.h>
+#include <gtk/gtkeditable.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkcombobox.h>
+
+#include "panel-util.h"
+
+/* TODO:
+ * - dns-sd fill out servers
+ * - pre-fill user?
+ * - name entry + pre-fill
+ * - folder browse function
+ */
+
+struct _PanelConnectServerDialogDetails {
+	GtkWidget *table;
+	
+	GtkWidget *type_combo;
+	GtkWidget *uri_entry;
+	GtkWidget *server_entry;
+	GtkWidget *share_entry;
+	GtkWidget *port_entry;
+	GtkWidget *folder_entry;
+	GtkWidget *user_entry;
+
+	GtkWidget *name_entry;
+};
+
+static void  panel_connect_server_class_init (PanelConnectServerDialogClass *class);
+static void  panel_connect_server_init       (PanelConnectServerDialog      *dialog);
+
+static GObjectClass *parent_class;
+
+enum {
+	RESPONSE_BROWSE,
+	RESPONSE_CONNECT
+};	
+
+/* Keep this order in sync with strings below */
+enum {
+	TYPE_SSH,
+	TYPE_ANON_FTP,
+	TYPE_FTP,
+	TYPE_SMB,
+	TYPE_DAV,
+	TYPE_DAVS,
+	TYPE_URI
+};
+
+static void
+panel_connect_server_finalize (GObject *object)
+{
+	PanelConnectServerDialog *dialog;
+
+	dialog = PANEL_CONNECT_SERVER_DIALOG (object);
+
+	g_object_unref (dialog->details->uri_entry);
+	g_object_unref (dialog->details->server_entry);
+	g_object_unref (dialog->details->share_entry);
+	g_object_unref (dialog->details->port_entry);
+	g_object_unref (dialog->details->folder_entry);
+	g_object_unref (dialog->details->user_entry);
+	g_object_unref (dialog->details->name_entry);
+	
+	g_free (dialog->details);
+
+	parent_class->finalize (object);
+}
+
+static void
+panel_connect_server_destroy (GtkObject *object)
+{
+	PanelConnectServerDialog *dialog;
+
+	dialog = PANEL_CONNECT_SERVER_DIALOG (object);
+	
+	GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+connect_to_server (PanelConnectServerDialog *dialog)
+{
+	char *uri;
+	char *user_uri;
+	GnomeVFSURI *vfs_uri;
+	char *name;
+	char *icon;
+	int type;
+	GError *error;
+	
+	type = gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->details->type_combo));
+
+	if (type == TYPE_URI) {
+		user_uri = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->uri_entry), 0, -1);
+		uri = gnome_vfs_make_uri_from_input (user_uri);
+		g_free (user_uri);
+	
+		vfs_uri = gnome_vfs_uri_new (uri);
+		
+		if (vfs_uri == NULL) {
+			panel_error_dialog (gtk_window_get_screen (GTK_WINDOW (dialog)),
+					    "cannot_connect_server", TRUE,
+					    _("\"%s\" is not a valid location."),
+					    _("Please check the spelling and try again."),
+					    uri);
+			return;
+		} else {
+			gnome_vfs_uri_unref (vfs_uri);
+		}
+	} else {
+		char *method, *user, *port, *initial_path, *server, *folder;
+		char *t, *join;
+		gboolean free_initial_path, free_user, free_port;
+
+		server = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->server_entry), 0, -1);
+		if (strlen (server) == 0) {
+			panel_error_dialog (gtk_window_get_screen (GTK_WINDOW (dialog)),
+					    "cannot_connect_server", TRUE,
+					    _("You must enter a name for the server."),
+					    _("Please enter a name and try again."));
+			g_free (server);
+			return;
+		}
+		
+		method = "";
+		user = "";
+		port = "";
+		initial_path = "";
+		free_initial_path = FALSE;
+		free_user = FALSE;
+		free_port = FALSE;
+		switch (type) {
+		case TYPE_SSH:
+			method = "sftp";
+			break;
+		case TYPE_ANON_FTP:
+			method = "ftp";
+			user = "anonymous";
+			break;
+		case TYPE_FTP:
+			method = "ftp";
+			break;
+		case TYPE_SMB:
+			method = "smb";
+			t = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->share_entry), 0, -1);
+			initial_path = g_strconcat ("/", t, NULL);
+			free_initial_path = TRUE;
+			g_free (t);
+			break;
+		case TYPE_DAV:
+			method = "dav";
+			break;
+		case TYPE_DAVS:
+			method = "davs";
+			break;
+		}
+
+		if (dialog->details->port_entry->parent != NULL) {
+			free_port = TRUE;
+			port = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->port_entry), 0, -1);
+		}
+		folder = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->folder_entry), 0, -1);
+		if (dialog->details->user_entry->parent != NULL) {
+			free_user = TRUE;
+			
+			t = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->user_entry), 0, -1);
+
+			user = gnome_vfs_escape_string (t);
+
+			g_free (t);
+		}
+
+		if (folder[0] != 0 &&
+		    folder[0] != '/') {
+			join = "/";
+		} else {
+			join = "";
+		}
+
+		t = folder;
+		folder = g_strconcat (initial_path, join, t, NULL);
+		g_free (t);
+
+		t = folder;
+		folder = gnome_vfs_escape_path_string (t);
+		g_free (t);
+
+		uri = g_strdup_printf ("%s://%s%s%s%s%s%s",
+				       method,
+				       user, (user[0] != 0) ? "@" : "",
+				       server,
+				       (port[0] != 0) ? ":" : "", port,
+				       folder);
+
+		if (free_initial_path) {
+			g_free (initial_path);
+		}
+		g_free (server);
+		if (free_port) {
+			g_free (port);
+		}
+		g_free (folder);
+		if (free_user) {
+			g_free (user);
+		}
+	}
+	
+	name = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->name_entry), 0, -1);
+	if (strlen (name) == 0) {
+		const char *host, *path;
+		char *path_utf8, *basename;
+		
+		g_free (name);
+		
+		vfs_uri = gnome_vfs_uri_new (uri);
+	
+		if (vfs_uri == NULL) {
+			g_warning ("Illegal uri in connect to server!\n");
+			g_free (uri);
+			g_free (name);
+			return;
+		} 
+
+		host = gnome_vfs_uri_get_host_name (vfs_uri);
+		path = gnome_vfs_uri_get_path (vfs_uri);
+		if (path != NULL &&
+		    strlen (path) > 0 &&
+		    strcmp (path, "/") != 0) {
+			path_utf8 = gnome_vfs_format_uri_for_display (uri);
+			basename = g_path_get_basename (path_utf8);
+			name = g_strdup_printf (_("%s on %s"), basename, host);
+			g_free (path_utf8);
+			g_free (basename);
+		} else {
+			name = g_strdup (host);
+		}
+		gnome_vfs_uri_unref (vfs_uri);
+	}
+		
+	if (g_str_has_prefix (uri, "smb:")) {
+		icon = "gnome-fs-smb";
+	} else if (g_str_has_prefix (uri, "ssh:") ||
+		   g_str_has_prefix (uri, "sftp:")) {
+		icon = "gnome-fs-ssh";
+	} else if (g_str_has_prefix (uri, "ftp:")) {
+		icon = "gnome-fs-ftp";
+	} else {
+		icon = "gnome-fs-share";
+	}
+	
+	gnome_vfs_connect_to_server (uri, name, icon); //FIXME this should be async!!!
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+
+	error = NULL;
+	gnome_url_show_on_screen (uri,
+				  gtk_widget_get_screen (GTK_WIDGET (dialog)),
+				  &error);
+
+	if (error) {
+		char *escaped;
+		escaped = g_markup_escape_text (uri, -1);
+		panel_error_dialog (gtk_widget_get_screen (GTK_WIDGET (dialog)),
+				    "cannot_show_connected_uri", TRUE,
+				    _("Cannot display location '%s'"),
+				    "%s",
+				    escaped,
+				    error->message);
+
+		g_error_free (error);
+		g_free (escaped);
+	}
+
+	g_free (uri);
+	g_free (name);
+}
+
+static void
+response_callback (PanelConnectServerDialog *dialog,
+		   int response_id,
+		   gpointer data)
+{
+	GError *error;
+
+	switch (response_id) {
+	case RESPONSE_BROWSE:
+		error = NULL;
+		gnome_url_show_on_screen ("network:///",
+					  gtk_widget_get_screen (GTK_WIDGET (dialog)),
+					  &error);
+
+		if (error) {
+			panel_error_dialog (gtk_widget_get_screen (GTK_WIDGET (dialog)),
+					    "cannot_show_network", TRUE,
+					    _("Cannot display location 'network:///'"),
+					    "%s",
+					    error->message);
+
+			g_error_free (error);
+		}
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		break;
+	case RESPONSE_CONNECT:
+		connect_to_server (dialog);
+		break;
+	case GTK_RESPONSE_NONE:
+	case GTK_RESPONSE_DELETE_EVENT:
+	case GTK_RESPONSE_CANCEL:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		break;
+	default :
+		g_assert_not_reached ();
+	}
+}
+
+static void
+panel_connect_server_class_init (PanelConnectServerDialogClass *class)
+{
+	GObjectClass *gobject_class;
+	GtkObjectClass *object_class;
+
+	parent_class = g_type_class_peek_parent (class);
+
+	gobject_class = G_OBJECT_CLASS (class);
+	gobject_class->finalize = panel_connect_server_finalize;
+	
+	object_class = GTK_OBJECT_CLASS (class);
+	object_class->destroy = panel_connect_server_destroy;
+}
+
+GType
+panel_connect_server_get_type (void)
+{
+        static GType type;
+
+        if (!type) {
+                static GTypeInfo info = {
+                        sizeof (PanelConnectServerDialogClass),
+                        NULL, NULL,
+                        (GClassInitFunc) panel_connect_server_class_init,
+                        NULL, NULL,
+                        sizeof (PanelConnectServerDialog), 0,
+                        (GInstanceInitFunc) panel_connect_server_init,
+                        NULL
+                };
+
+		type = g_type_register_static (
+				GTK_TYPE_DIALOG, "PanelConnectServerDialog", &info, 0);
+        }
+
+        return type;
+}
+
+static void
+setup_for_type (PanelConnectServerDialog *dialog)
+{
+	int type, i;
+	gboolean show_share, show_port, show_user;
+	GtkWidget *label, *table;
+
+	type = gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->details->type_combo));
+
+	if (dialog->details->uri_entry->parent != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->table),
+				      dialog->details->uri_entry);
+	}
+	if (dialog->details->server_entry->parent != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->table),
+				      dialog->details->server_entry);
+	}
+	if (dialog->details->share_entry->parent != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->table),
+				      dialog->details->share_entry);
+	}
+	if (dialog->details->port_entry->parent != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->table),
+				      dialog->details->port_entry);
+	}
+	if (dialog->details->folder_entry->parent != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->table),
+				      dialog->details->folder_entry);
+	}
+	if (dialog->details->user_entry->parent != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->table),
+				      dialog->details->user_entry);
+	}
+	if (dialog->details->name_entry->parent != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->table),
+				      dialog->details->name_entry);
+	}
+	/* Destroy all labels */
+	gtk_container_foreach (GTK_CONTAINER (dialog->details->table),
+			       (GtkCallback) gtk_widget_destroy, NULL);
+
+	
+	i = 1;
+	table = dialog->details->table;
+	
+	if (type == TYPE_URI) {
+		label = gtk_label_new_with_mnemonic (_("_Location (URI):"));
+		gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+		gtk_widget_show (label);
+		gtk_table_attach (GTK_TABLE (table), label,
+				  0, 1,
+				  i, i+1,
+				  GTK_FILL, GTK_FILL,
+				  0, 0);
+		
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->uri_entry);
+		gtk_widget_show (dialog->details->uri_entry);
+		gtk_table_attach (GTK_TABLE (table), dialog->details->uri_entry,
+				  1, 2,
+				  i, i+1,
+				  GTK_FILL | GTK_EXPAND, GTK_FILL,
+				  0, 0);
+
+		i++;
+		
+		goto connection_name;
+	}
+	
+	switch (type) {
+	default:
+	case TYPE_SSH:
+	case TYPE_FTP:
+	case TYPE_DAV:
+	case TYPE_DAVS:
+		show_share = FALSE;
+		show_port = TRUE;
+		show_user = TRUE;
+		break;
+	case TYPE_ANON_FTP:
+		show_share = FALSE;
+		show_port = TRUE;
+		show_user = FALSE;
+		break;
+	case TYPE_SMB:
+		show_share = TRUE;
+		show_port = FALSE;
+		show_user = TRUE;
+		break;
+	}
+
+	label = gtk_label_new_with_mnemonic (_("_Server:"));
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_widget_show (label);
+	gtk_table_attach (GTK_TABLE (table), label,
+			  0, 1,
+			  i, i+1,
+			  GTK_FILL, GTK_FILL,
+			  0, 0);
+	
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->server_entry);
+	gtk_widget_show (dialog->details->server_entry);
+	gtk_table_attach (GTK_TABLE (table), dialog->details->server_entry,
+			  1, 2,
+			  i, i+1,
+			  GTK_FILL | GTK_EXPAND, GTK_FILL,
+			  0, 0);
+
+	i++;
+
+	label = gtk_label_new (_("Optional information:"));
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_widget_show (label);
+	gtk_table_attach (GTK_TABLE (table), label,
+			  0, 2,
+			  i, i+1,
+			  GTK_FILL, GTK_FILL,
+			  0, 0);
+
+	i++;
+	
+	if (show_share) {
+		label = gtk_label_new_with_mnemonic (_("_Share:"));
+		gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+		gtk_widget_show (label);
+		gtk_table_attach (GTK_TABLE (table), label,
+				  0, 1,
+				  i, i+1,
+				  GTK_FILL, GTK_FILL,
+				  0, 0);
+		
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->share_entry);
+		gtk_widget_show (dialog->details->share_entry);
+		gtk_table_attach (GTK_TABLE (table), dialog->details->share_entry,
+				  1, 2,
+				  i, i+1,
+				  GTK_FILL | GTK_EXPAND, GTK_FILL,
+				  0, 0);
+
+		i++;
+	}
+
+	if (show_port) {
+		label = gtk_label_new_with_mnemonic (_("_Port:"));
+		gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+		gtk_widget_show (label);
+		gtk_table_attach (GTK_TABLE (table), label,
+				  0, 1,
+				  i, i+1,
+				  GTK_FILL, GTK_FILL,
+				  0, 0);
+		
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->port_entry);
+		gtk_widget_show (dialog->details->port_entry);
+		gtk_table_attach (GTK_TABLE (table), dialog->details->port_entry,
+				  1, 2,
+				  i, i+1,
+				  GTK_FILL | GTK_EXPAND, GTK_FILL,
+				  0, 0);
+
+		i++;
+	}
+
+	label = gtk_label_new_with_mnemonic (_("_Folder:"));
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_widget_show (label);
+	gtk_table_attach (GTK_TABLE (table), label,
+			  0, 1,
+			  i, i+1,
+			  GTK_FILL, GTK_FILL,
+			  0, 0);
+	
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->folder_entry);
+	gtk_widget_show (dialog->details->folder_entry);
+	gtk_table_attach (GTK_TABLE (table), dialog->details->folder_entry,
+			  1, 2,
+			  i, i+1,
+			  GTK_FILL | GTK_EXPAND, GTK_FILL,
+			  0, 0);
+
+	i++;
+
+	if (show_user) {
+		label = gtk_label_new_with_mnemonic (_("_User Name:"));
+		gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+		gtk_widget_show (label);
+		gtk_table_attach (GTK_TABLE (table), label,
+				  0, 1,
+				  i, i+1,
+				  GTK_FILL, GTK_FILL,
+				  0, 0);
+		
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->user_entry);
+		gtk_widget_show (dialog->details->user_entry);
+		gtk_table_attach (GTK_TABLE (table), dialog->details->user_entry,
+				  1, 2,
+				  i, i+1,
+				  GTK_FILL | GTK_EXPAND, GTK_FILL,
+				  0, 0);
+
+		i++;
+	}
+
+
+ connection_name:
+	
+	label = gtk_label_new_with_mnemonic (_("_Name to use for connection:"));
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_widget_show (label);
+	gtk_table_attach (GTK_TABLE (table), label,
+			  0, 1,
+			  i, i+1,
+			  GTK_FILL, GTK_FILL,
+			  0, 0);
+	
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->name_entry);
+	gtk_widget_show (dialog->details->name_entry);
+	gtk_table_attach (GTK_TABLE (table), dialog->details->name_entry,
+			  1, 2,
+			  i, i+1,
+			  GTK_FILL | GTK_EXPAND, GTK_FILL,
+			  0, 0);
+	
+	i++;
+
+}
+
+static void
+combo_changed_callback (GtkComboBox *combo_box,
+			PanelConnectServerDialog *dialog)
+{
+	setup_for_type (dialog);
+}
+
+
+static void
+port_insert_text (GtkEditable *editable,
+		  const gchar *new_text,
+		  gint         new_text_length,
+		  gint        *position)
+{
+	if (new_text_length < 0) {
+		new_text_length = strlen (new_text);
+	}
+
+	if (new_text_length != 1 ||
+	    !g_ascii_isdigit (new_text[0])) {
+		gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (editable)));
+		g_signal_stop_emission_by_name (editable, "insert_text");
+	}
+}
+
+
+static void
+panel_connect_server_init (PanelConnectServerDialog *dialog)
+{
+	GtkWidget *label;
+	GtkWidget *table;
+	GtkWidget *combo;
+	GtkWidget *hbox;
+	GtkWidget *vbox;
+	
+	dialog->details = g_new0 (PanelConnectServerDialogDetails, 1);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), _("Connect to Server"));
+	gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
+	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+	vbox = gtk_vbox_new (FALSE, 6);
+	gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+			    vbox, FALSE, TRUE, 0);
+	gtk_widget_show (vbox);
+			    
+	hbox = gtk_hbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox),
+			    hbox, FALSE, TRUE, 0);
+	gtk_widget_show (hbox);
+	
+	label = gtk_label_new_with_mnemonic (_("Service _type:"));
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_widget_show (label);
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    label, FALSE, FALSE, 0);
+
+	dialog->details->type_combo = combo = gtk_combo_box_new_text ();
+	/* Keep this in sync with enum */
+	gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
+				   _("SSH"));
+	gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
+				   _("Public FTP"));
+	gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
+				   _("FTP (with login)"));
+	gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
+				   _("Windows share"));
+	gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
+				   _("WebDAV (HTTP)"));
+	gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
+				   _("Secure WebDAV (HTTPS)"));
+	gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
+				   _("Custom Location"));
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), TYPE_ANON_FTP);
+	gtk_widget_show (combo);
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    combo, TRUE, TRUE, 0);
+	g_signal_connect (combo, "changed",
+			  G_CALLBACK (combo_changed_callback),
+			  dialog);
+	
+
+	hbox = gtk_hbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox),
+			    hbox, FALSE, TRUE, 0);
+	gtk_widget_show (hbox);
+
+	label = gtk_label_new_with_mnemonic ("    ");
+	gtk_widget_show (label);
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    label, FALSE, FALSE, 0);
+	
+	
+	dialog->details->table = table = gtk_table_new (5, 2, FALSE);
+	gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+	gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+	gtk_widget_show (table);
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    table, TRUE, TRUE, 0);
+
+	dialog->details->uri_entry = gtk_entry_new ();
+	dialog->details->server_entry = gtk_entry_new ();
+	dialog->details->share_entry = gtk_entry_new ();
+	dialog->details->port_entry = gtk_entry_new ();
+	g_signal_connect (dialog->details->port_entry, "insert_text", G_CALLBACK (port_insert_text),
+			  NULL);
+	dialog->details->folder_entry = gtk_entry_new ();
+	dialog->details->user_entry = gtk_entry_new ();
+	dialog->details->name_entry = gtk_entry_new ();
+	/* We need an extra ref so we can remove them from the table */
+	g_object_ref (dialog->details->uri_entry);
+	g_object_ref (dialog->details->server_entry);
+	g_object_ref (dialog->details->share_entry);
+	g_object_ref (dialog->details->port_entry);
+	g_object_ref (dialog->details->folder_entry);
+	g_object_ref (dialog->details->user_entry);
+	g_object_ref (dialog->details->name_entry);
+	
+	setup_for_type (dialog);
+	
+	gtk_dialog_add_button (GTK_DIALOG (dialog),
+			       _("Browse _Network"),
+			       RESPONSE_BROWSE);
+	gtk_dialog_add_button (GTK_DIALOG (dialog),
+			       GTK_STOCK_CANCEL,
+			       GTK_RESPONSE_CANCEL);
+	gtk_dialog_add_button (GTK_DIALOG (dialog),
+			       _("C_onnect"),
+			       RESPONSE_CONNECT);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+					 RESPONSE_CONNECT);
+
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (response_callback),
+			  dialog);
+
+
+}
+
+void
+panel_connect_server_show (GdkScreen *screen)
+{
+	GtkWidget *dialog;
+
+	dialog = gtk_widget_new (PANEL_TYPE_CONNECT_SERVER_DIALOG, NULL);
+
+	if (screen)
+		gtk_window_set_screen (GTK_WINDOW (dialog), screen);
+
+	gtk_widget_show (dialog);
+}
Index: panel-connect-server.h
===================================================================
RCS file: panel-connect-server.h
diff -N panel-connect-server.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panel-connect-server.h	18 Dec 2004 11:46:07 -0000
@@ -0,0 +1,52 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/*
+ * panel-connect-server.h: Connect to server... dialog
+ * Code comes from nautilus (src/nautils-connect-server-dialog.h)
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ * Copyright (C) 2004 Vincent Untz
+ *
+ * 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; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PANEL_CONNECT_SERVER_H
+#define PANEL_CONNECT_SERVER_H
+
+#include <gtk/gtkdialog.h>
+
+#define PANEL_TYPE_CONNECT_SERVER_DIALOG         (panel_connect_server_get_type ())
+#define PANEL_CONNECT_SERVER_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_CONNECT_SERVER_DIALOG, PanelConnectServerDialog))
+#define PANEL_CONNECT_SERVER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_CONNECT_SERVER_DIALOG, PanelConnectServerDialogClass))
+#define PANEL_IS_CONNECT_SERVER_DIALOG(obj)      (G_TYPE_INSTANCE_CHECK_TYPE ((obj), PANEL_TYPE_CONNECT_SERVER_DIALOG)
+
+typedef struct _PanelConnectServerDialog        PanelConnectServerDialog;
+typedef struct _PanelConnectServerDialogClass   PanelConnectServerDialogClass;
+typedef struct _PanelConnectServerDialogDetails PanelConnectServerDialogDetails;
+
+struct _PanelConnectServerDialog {
+	GtkDialog dialog;
+	PanelConnectServerDialogDetails *details;
+};
+
+struct _PanelConnectServerDialogClass {
+	GtkDialogClass parent_class;
+};
+
+GType panel_connect_server_get_type (void);
+void  panel_connect_server_show     (GdkScreen *screen);
+
+#endif /* PANEL_CONNECT_SERVER_H */
Index: panel-enums.h
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-enums.h,v
retrieving revision 1.5
diff -u -p -r1.5 panel-enums.h
--- panel-enums.h	16 Jan 2004 14:30:20 -0000	1.5
+++ panel-enums.h	18 Dec 2004 11:46:07 -0000
@@ -94,6 +94,7 @@ typedef enum {
         PANEL_ACTION_SEARCH,
         PANEL_ACTION_SCREENSHOT,
 	PANEL_ACTION_FORCE_QUIT,
+	PANEL_ACTION_CONNECT_SERVER,
         PANEL_ACTION_LAST
 } PanelActionButtonType;
 
Index: panel-menu-bar.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-menu-bar.c,v
retrieving revision 1.42
diff -u -p -r1.42 panel-menu-bar.c
--- panel-menu-bar.c	16 Dec 2004 09:16:33 -0000	1.42
+++ panel-menu-bar.c	18 Dec 2004 11:46:07 -0000
@@ -1,5 +1,5 @@
 /*
- * panel-menu-bar.c: panel Applications/Actions menu bar
+ * panel-menu-bar.c: panel Applications/Places/System menu bar
  *
  * Copyright (C) 2003 Sun Microsystems, Inc.
  *
@@ -20,6 +20,7 @@
  *
  * Authors:
  *	Mark McLoughlin <mark@skynet.ie>
+ *	Vincent Untz <vincent@vuntz.net>
  */
 
 #include <config.h>
@@ -29,6 +30,11 @@
 #include <string.h>
 #include <glib/gi18n.h>
 
+#include <libgnome/gnome-desktop-item.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libgnomeui/gnome-url.h>
+
 #include "panel-util.h"
 #include "panel-background.h"
 #include "panel-action-button.h"
@@ -36,23 +42,207 @@
 #include "panel-recent.h"
 #include "applet.h"
 #include "menu.h"
+#include "panel-gconf.h"
 #include "panel-globals.h"
 #include "panel-profile.h"
 #include "panel-lockdown.h"
 
+#define BOOKMARKS_FILENAME      ".gtk-bookmarks"
+#define DESKTOP_IS_HOME_DIR_DIR "/apps/nautilus/preferences"
+#define DESKTOP_IS_HOME_DIR_KEY "/apps/nautilus/preferences/desktop_is_home_dir"
+
+/*
+ * TODO:
+ *   + submenus if there are too many items in places
+ *   + should we show disks with no volume or unmounted volume?
+ *   + drag and drop loses icon for URIs
+ *   + drag and drop to items in the menu
+ *   + if a menu is open and get updated, it should not reappear and not just
+ *     disappear
+ *   + see FIXME
+ *
+ * Known bugs:
+ *   + no update when the GTK+ bookmarks are modified. It seems gamin doesn't
+ *     receive a modify event when the file is modified/deleted. It's probably
+ *     a bug in inotify or gamin.
+ *   + sometimes crash when mounting a new volume. Unreproducable right now
+ *     because gnome-vfs-daemon doesn't send a notification when a volume is
+ *     (un)mounted anymore...
+ */
+
 #define PANEL_MENU_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_MENU_BAR, PanelMenuBarPrivate))
 
 struct _PanelMenuBarPrivate {
-	AppletInfo            *info;
-	PanelWidget           *panel;
+	AppletInfo  *info;
+	PanelWidget *panel;
+
+	GtkWidget   *applications_menu;
+	GtkWidget   *places_menu;
+	GtkWidget   *system_menu;
+	GtkWidget   *applications_item;
+	GtkWidget   *places_item;
+	GtkWidget   *system_item;
 
-	GtkWidget             *applications_menu;
-	GtkWidget             *actions_menu;
-	GtkWidget             *actions_item;
+	GnomeVFSMonitorHandle *bookmarks_monitor;
+
+	gulong       volume_mounted_id;
+	gulong       volume_unmounted_id;
 };
 
+static GnomeVFSVolumeMonitor *volume_monitor = NULL;
+
 static GObjectClass *parent_class;
-static GtkWidget *panel_menu_bar_create_actions_menu (PanelMenuBar *menubar);
+static GtkWidget *panel_menu_bar_create_applications_menu (PanelMenuBar *menubar);
+static GtkWidget *panel_menu_bar_create_places_menu (PanelMenuBar *menubar);
+static GtkWidget *panel_menu_bar_create_system_menu (PanelMenuBar *menubar);
+
+static void
+activate_uri (GtkWidget *menuitem,
+	      char      *path)
+{
+	GError    *error = NULL;
+	GdkScreen *screen;
+	char      *url;
+	char      *escaped;
+
+	screen = menuitem_to_screen (menuitem);
+
+	url = gnome_vfs_make_uri_from_input_with_dirs (path,
+						       GNOME_VFS_MAKE_URI_DIR_HOMEDIR);
+	gnome_url_show_on_screen (url, screen, &error);
+
+	if (error) {
+		escaped = g_markup_escape_text (url, -1);
+		panel_error_dialog (screen, "cannot_show_url", TRUE,
+				    _("Cannot display location '%s'"),
+				    "%s",
+				    escaped,
+				    error->message);
+
+		g_error_free (error);
+		g_free (escaped);
+	}
+	g_free (url);
+}
+
+static void
+activate_app_def (GtkWidget *menuitem,
+		  char      *path)
+{
+	GnomeDesktopItem *item;
+	GError           *error;
+
+	error = NULL;
+	item = gnome_desktop_item_new_from_file (path, 0, &error);
+	if (item) {
+		g_assert (error == NULL);
+
+		panel_ditem_launch (item, NULL, 0,
+				    menuitem_to_screen (menuitem), &error);
+		if (error) {
+			panel_error_dialog (menuitem_to_screen (menuitem),
+					    "cannot_launch_entry", TRUE,
+					    _("Cannot launch entry"),
+					    "%s",
+					    error->message);
+
+			g_error_free (error);
+		}
+		gnome_desktop_item_unref (item);
+	} else {
+		g_assert (error != NULL);
+
+		panel_error_dialog (menuitem_to_screen (menuitem),
+				    "cannot_load_entry", TRUE,
+				    _("Cannot load entry"),
+				    "%s",
+				    error->message);
+		g_error_free (error);
+	}
+}
+
+static void
+panel_menu_bar_append_from_desktop (GtkWidget *menu,
+				    char      *path)
+{
+	GnomeDesktopItem *desktop;
+	GtkWidget        *item;
+	const char * const *data_dirs;
+	char *desktop_path;
+	char *path_freeme;
+	char *real_path;
+	int i;
+
+	path_freeme = NULL;
+
+	if (!g_str_has_suffix (path, ".desktop")) {
+		desktop_path = g_strconcat (path, ".deskstop", NULL);
+	} else {
+		desktop_path = path;
+	}
+
+	if (!g_path_is_absolute (path)) {
+		data_dirs = g_get_system_data_dirs ();
+
+		for (i = 0; data_dirs[i] != NULL; i++) {
+			path_freeme = g_build_filename (data_dirs[i],
+							"applications",
+							desktop_path, NULL);
+			if (g_file_test (path_freeme, G_FILE_TEST_IS_REGULAR))
+				break;
+			g_free (path_freeme);
+			path_freeme = NULL;
+		}
+
+		if (desktop_path != path)
+			g_free (desktop_path);
+
+		if (!path_freeme)
+			return;
+
+		real_path = path_freeme;
+	} else {
+		if (desktop_path != path)
+			path_freeme = desktop_path;
+
+		real_path = desktop_path;
+	}
+
+
+	desktop = gnome_desktop_item_new_from_file (real_path, 0, NULL);
+	if (!desktop) {
+		if (path_freeme)
+			g_free (path_freeme);
+		return;
+	}
+
+	item = gtk_image_menu_item_new ();
+        setup_menu_item_with_icon (item,
+				   panel_menu_icon_get_size (),
+				   gnome_desktop_item_get_localestring (desktop, GNOME_DESKTOP_ITEM_ICON),
+				   NULL,
+				   gnome_desktop_item_get_localestring (desktop, GNOME_DESKTOP_ITEM_NAME),
+				   TRUE);
+
+	if (gnome_desktop_item_get_string (desktop, GNOME_DESKTOP_ITEM_COMMENT) != NULL)
+		gtk_tooltips_set_tip (panel_tooltips,
+				      item,
+				      gnome_desktop_item_get_localestring (desktop, GNOME_DESKTOP_ITEM_COMMENT),
+				      NULL);
+
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+	g_signal_connect_data (item, "activate",
+			       G_CALLBACK (activate_app_def),
+			       g_strdup (real_path),
+			       (GClosureNotify) g_free, 0);
+	g_signal_connect (G_OBJECT (item), "button_press_event",
+			  G_CALLBACK (menu_dummy_button_press_event), NULL);
+	setup_uri_drag (item, real_path, gnome_desktop_item_get_localestring (desktop, GNOME_DESKTOP_ITEM_ICON));
+
+	gnome_desktop_item_unref (desktop);
+	if (path_freeme)
+		g_free (path_freeme);
+}
 
 static void
 panel_menu_bar_show_menu (PanelMenuBar *menubar,
@@ -84,65 +274,338 @@ panel_menu_bar_connect_menu_signals (Pan
 }
 
 static void
-panel_menu_bar_recreate_actions_menu (PanelMenuBar *menubar)
+panel_menu_bar_append_place_item (PanelMenuBar *menubar,
+				  const char   *icon_name,
+				  const char   *title,
+				  const char   *tooltip,
+				  GtkWidget    *menu,
+				  gboolean      free_uri,
+				  GCallback     callback,
+				  char         *uri)
+{
+	GtkWidget *item;
+
+	item = gtk_image_menu_item_new ();
+        setup_menu_item_with_icon (item,
+				   panel_menu_icon_get_size (),
+				   icon_name,
+				   NULL,
+				   title,
+				   TRUE);
+
+	gtk_tooltips_set_tip (panel_tooltips,
+			      item,
+			      tooltip,
+			      NULL);
+
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+	if (!free_uri)
+		g_signal_connect (item, "activate", callback, uri);
+	else
+		g_signal_connect_data (item, "activate", callback, uri,
+				       (GClosureNotify) g_free, 0);
+	g_signal_connect (G_OBJECT (item), "button_press_event",
+			  G_CALLBACK (menu_dummy_button_press_event), NULL);
+	setup_uri_drag (item, uri, icon_name);
+}
+
+static void
+panel_menu_bar_recreate_places_menu (PanelMenuBar *menubar)
 {
-	if (menubar->priv->actions_menu) {
-		gtk_widget_destroy (menubar->priv->actions_menu);
-		menubar->priv->actions_menu = panel_menu_bar_create_actions_menu (menubar);
+	if (menubar->priv->places_menu) {
+		gtk_widget_destroy (menubar->priv->places_menu);
+		menubar->priv->places_menu = panel_menu_bar_create_places_menu (menubar);
 		panel_menu_bar_connect_menu_signals (menubar,
-						     &menubar->priv->actions_menu);
-		gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar->priv->actions_item),
-					   menubar->priv->actions_menu);
+						     &menubar->priv->places_menu);
+		panel_applet_menu_set_recurse (GTK_MENU (menubar->priv->places_menu),
+					       "menu_panel",
+					       menubar->priv->panel);
+		gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar->priv->places_item),
+					   menubar->priv->places_menu);
 	}
 }
 
-static GtkWidget *
-panel_menu_bar_create_actions_menu (PanelMenuBar *menubar)
+static void
+panel_menu_bar_recreate_system_menu (PanelMenuBar *menubar)
+{
+	if (menubar->priv->system_menu) {
+		gtk_widget_destroy (menubar->priv->system_menu);
+		menubar->priv->system_menu = panel_menu_bar_create_system_menu (menubar);
+		panel_menu_bar_connect_menu_signals (menubar,
+						     &menubar->priv->system_menu);
+		panel_applet_menu_set_recurse (GTK_MENU (menubar->priv->system_menu),
+					       "menu_panel",
+					       menubar->priv->panel);
+		gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar->priv->system_item),
+					   menubar->priv->system_menu);
+	}
+}
+
+static void
+panel_menu_bar_append_applications_menu (GtkWidget    *menu,
+					 PanelMenuBar *menubar)
 {
-	GtkWidget *actions_menu;
 	GtkWidget *item;
-	gboolean   separator_inserted;
-	gboolean   last_is_separator;
 
-	actions_menu = panel_create_menu ();
+	if (!g_object_get_data (G_OBJECT (menu), "panel-menu-needs-appending"))
+		return;
 
-	last_is_separator = FALSE;
+	g_object_set_data (G_OBJECT (menu), "panel-menu-needs-appending", NULL);
 
 	item = menu_create_action_item (PANEL_ACTION_RUN);
-	if (item != NULL) {
-		gtk_menu_shell_append (GTK_MENU_SHELL (actions_menu), item);
-		add_menu_separator (actions_menu);
-		last_is_separator = TRUE;
+
+	if (item != NULL &&
+	    GTK_MENU_SHELL (menubar->priv->applications_menu)->children != NULL) {
+		add_menu_separator (menubar->priv->applications_menu);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menubar->priv->applications_menu),
+				       item);
 	}
+}
 
-	if (panel_is_program_in_path  ("gnome-search-tool")) {
-		item = menu_create_action_item (PANEL_ACTION_SEARCH);
-		if (item != NULL) {
-			gtk_menu_shell_append (GTK_MENU_SHELL (actions_menu),
-					       item);
-			last_is_separator = FALSE;
+static GtkWidget *
+panel_menu_bar_create_applications_menu (PanelMenuBar *menubar)
+{
+	GtkWidget *applications_menu;
+
+	applications_menu = create_applications_menu ("applications.menu", NULL);
+
+	g_object_set_data (G_OBJECT (applications_menu),
+			   "panel-menu-needs-appending",
+			   GUINT_TO_POINTER (TRUE));
+
+	g_signal_connect (applications_menu, "show",
+			  G_CALLBACK (panel_menu_bar_append_applications_menu),
+			  menubar);
+
+	return applications_menu;
+}
+
+static void
+panel_menu_bar_desktop_is_home_dir_changed (GConfClient  *client,
+					    guint         cnxn_id,
+					    GConfEntry   *entry,
+					    PanelMenuBar *menubar)
+{
+	panel_menu_bar_recreate_places_menu (menubar);
+}
+
+static void
+panel_menu_bar_gtk_bookmarks_changed (GnomeVFSMonitorHandle *handle,
+				      const gchar *monitor_uri,
+				      const gchar *info_uri,
+				      GnomeVFSMonitorEventType event_type,
+				      gpointer user_data)
+{
+	g_assert (PANEL_IS_MENU_BAR (user_data));
+
+	panel_menu_bar_recreate_places_menu (PANEL_MENU_BAR (user_data));
+}
+
+static void
+panel_menu_bar_volume_changed (GnomeVFSVolumeMonitor *monitor,
+			       GnomeVFSVolume        *volume,
+			       PanelMenuBar          *menubar)
+{
+	panel_menu_bar_recreate_places_menu (menubar);
+}
+
+static void
+panel_menu_bar_append_gtk_bookmarks (PanelMenuBar *menubar,
+				     GtkWidget    *menu)
+{
+	char *filename;
+	char *contents;
+
+	filename = g_build_filename (g_get_home_dir (),
+				     BOOKMARKS_FILENAME, NULL);
+
+	if (g_file_get_contents (filename, &contents, NULL, NULL)) {
+		gchar      **lines;
+		GHashTable  *table;
+		int          i;
+		GnomeVFSURI *uri;
+		char        *basename;
+		char        *display_uri;
+		char        *tooltip;
+
+		lines = g_strsplit (contents, "\n", -1);
+		table = g_hash_table_new (g_str_hash, g_str_equal);
+
+		//FIXME gnome_vfs_uri_exists: could there be an authentication
+		//dialog if there's a bookmarks to sftp://something?
+		for (i = 0; lines[i]; i++) {
+			if (lines[i][0] &&
+			    !g_hash_table_lookup (table, lines[i])) {
+				uri = gnome_vfs_uri_new (lines[i]);
+				if (!gnome_vfs_uri_exists (uri)) {
+					gnome_vfs_uri_unref (uri);
+					continue;
+				}
+
+				display_uri = gnome_vfs_format_uri_for_display (lines[i]);
+				/* Translators: %s is a URI */
+				tooltip = g_strdup_printf (_("Open '%s'"),
+							   display_uri);
+				g_free (display_uri);
+
+				basename = gnome_vfs_uri_extract_short_name (uri);
+				panel_menu_bar_append_place_item (
+						menubar, "gnome-fs-directory",
+						basename, tooltip,
+						menu, TRUE,
+						G_CALLBACK (activate_uri),
+						g_strdup (lines[i]));
+
+				g_hash_table_insert (table, lines[i], lines[i]);
+
+				g_free (basename);
+				g_free (tooltip);
+				gnome_vfs_uri_unref (uri);
+			}
 		}
+
+		g_free (contents);
+		g_hash_table_destroy (table);
+		g_strfreev (lines);
 	}
 
-	panel_recent_append_documents_menu (actions_menu);
+	g_free (filename);
+}
+
+static void
+panel_menu_bar_append_volumes (PanelMenuBar *menubar,
+			       GtkWidget    *menu,
+			       gboolean      connected_volumes)
+{
+	GList *mounted_volumes, *tmp;
+
+	mounted_volumes = gnome_vfs_volume_monitor_get_mounted_volumes (volume_monitor);
+
+	for (tmp = mounted_volumes; tmp != NULL; tmp = tmp->next) {
+		char *icon;
+		char *display_name;
+		char *activation_uri;
+		GnomeVFSVolume *volume = tmp->data;
+
+		if (gnome_vfs_volume_is_user_visible (volume) &&
+		    gnome_vfs_volume_is_mounted (volume) &&
+		    (gnome_vfs_volume_get_volume_type (volume) == GNOME_VFS_VOLUME_TYPE_CONNECTED_SERVER) == connected_volumes) {
+			icon = gnome_vfs_volume_get_icon (volume);
+			display_name = gnome_vfs_volume_get_display_name (volume);
+			activation_uri = gnome_vfs_volume_get_activation_uri (volume);
+			panel_menu_bar_append_place_item (menubar,
+							  icon,
+							  display_name,
+							  display_name, //FIXME tooltip
+							  menu, TRUE,
+							  G_CALLBACK (activate_uri),
+							  activation_uri);
+
+			g_free (icon);
+			g_free (display_name);
+			/* don't free activation_uri because it will be freed
+			 * automatically */
+		}
+		gnome_vfs_volume_unref (volume);
+	}
+	g_list_free (mounted_volumes);
+}
+
+static GtkWidget *
+panel_menu_bar_create_places_menu (PanelMenuBar *menubar)
+{
+	GtkWidget *places_menu;
+	GtkWidget *item;
+	char      *path;
+
+	places_menu = panel_create_menu ();
+
+	panel_menu_bar_append_from_desktop (places_menu,
+					    "nautilus-home.desktop");
+
+	if (!gconf_client_get_bool (panel_gconf_get_client (),
+				    DESKTOP_IS_HOME_DIR_KEY,
+				    NULL))
+		panel_menu_bar_append_place_item (menubar, "gnome-fs-desktop",
+						  _("Desktop"),
+						  _("Desktop directory"),
+						  places_menu, FALSE,
+						  G_CALLBACK (activate_uri),
+						  "Desktop");
+
+	path = g_build_filename (g_get_home_dir (), "Documents", NULL);
+	if (g_file_test (path, G_FILE_TEST_IS_DIR))
+		panel_menu_bar_append_place_item (menubar, "gnome-fs-directory",
+						  _("Documents"),
+						  _("Documents directory"),
+						  places_menu, FALSE,
+						  G_CALLBACK (activate_uri),
+						  "Documents");
+	g_free (path);
+
+	panel_menu_bar_append_gtk_bookmarks (menubar, places_menu);
+	add_menu_separator (places_menu);
+
+	panel_menu_bar_append_from_desktop (places_menu,
+					    "nautilus-computer.desktop");
+	panel_menu_bar_append_volumes (menubar, places_menu, FALSE);
+	add_menu_separator (places_menu);
+
+	panel_menu_bar_append_from_desktop (places_menu,
+					    "network-scheme.desktop");
+	panel_menu_bar_append_volumes (menubar, places_menu, TRUE);
+	item = menu_create_action_item (PANEL_ACTION_CONNECT_SERVER);
+	if (item != NULL)
+		gtk_menu_shell_append (GTK_MENU_SHELL (places_menu), item);
+
+	add_menu_separator (places_menu);
+
+	panel_menu_bar_append_from_desktop (places_menu,
+					    "gnome-search-tool.desktop");
+
+	panel_recent_append_documents_menu (places_menu);
+
+	return places_menu;
+}
+
+static void
+panel_menu_bar_append_system_menu (GtkWidget    *menu,
+				   PanelMenuBar *menubar)
+{
+	GtkWidget *system_menu;
+	GtkWidget *item;
+	gboolean   separator_inserted;
+
+	if (!g_object_get_data (G_OBJECT (menu), "panel-menu-needs-appending"))
+		return;
+
+	g_object_set_data (G_OBJECT (menu), "panel-menu-needs-appending", NULL);
+
+	system_menu = menubar->priv->system_menu;
+
+	if (GTK_MENU_SHELL (system_menu)->children != NULL)
+		add_menu_separator (system_menu);
 
 	if (panel_is_program_in_path ("gnome-screenshot")) {
 		item = menu_create_action_item (PANEL_ACTION_SCREENSHOT);
-		if (item != NULL) {
-			if (!last_is_separator)
-				add_menu_separator (actions_menu);
-			gtk_menu_shell_append (GTK_MENU_SHELL (actions_menu),
+		if (item != NULL)
+			gtk_menu_shell_append (GTK_MENU_SHELL (system_menu),
 					       item);
-			last_is_separator = FALSE;
-		}
 	}
 
+	panel_menu_bar_append_from_desktop (system_menu,
+					    "yelp.desktop");
+
+
+	panel_menu_bar_append_from_desktop (system_menu,
+					    "gnome-about.desktop");
+
 	separator_inserted = FALSE;
 
 	item = menu_create_action_item (PANEL_ACTION_LOCK);
 	if (item != NULL) {
-		add_menu_separator (actions_menu);
-		gtk_menu_shell_append (GTK_MENU_SHELL (actions_menu), item);
+		add_menu_separator (system_menu);
+		gtk_menu_shell_append (GTK_MENU_SHELL (system_menu), item);
 		separator_inserted = TRUE;
 	}
 
@@ -151,50 +614,123 @@ panel_menu_bar_create_actions_menu (Pane
 
 		if (item != NULL) {
 			if (!separator_inserted)
-				add_menu_separator (actions_menu);
-			gtk_menu_shell_append (GTK_MENU_SHELL (actions_menu),
+				add_menu_separator (system_menu);
+			gtk_menu_shell_append (GTK_MENU_SHELL (system_menu),
 					       item);
 		}
 	}
+}
+
+static GtkWidget *
+panel_menu_bar_create_system_menu (PanelMenuBar *menubar)
+{
+	GtkWidget *system_menu;
+
+	system_menu = create_applications_menu ("settings.menu", NULL);
+
+	g_object_set_data (G_OBJECT (system_menu),
+			   "panel-menu-needs-appending",
+			   GUINT_TO_POINTER (TRUE));
+
+	g_signal_connect (system_menu, "show",
+			  G_CALLBACK (panel_menu_bar_append_system_menu),
+			  menubar);
 
-	return actions_menu;
+	return system_menu;
 }
 
 static void
 panel_menu_bar_instance_init (PanelMenuBar      *menubar,
 			      PanelMenuBarClass *klass)
 {
-	GtkWidget *item;
 	GtkWidget *image;
+	char      *bookmarks_filename;
+	char      *bookmarks_uri;
 
 	menubar->priv = PANEL_MENU_BAR_GET_PRIVATE (menubar);
 
 	menubar->priv->info = NULL;
 
-	menubar->priv->applications_menu = create_applications_menu ("applications.menu", NULL);
+	gconf_client_add_dir (panel_gconf_get_client (),
+			      DESKTOP_IS_HOME_DIR_DIR,
+			      GCONF_CLIENT_PRELOAD_NONE,
+			      NULL);
+
+	panel_gconf_notify_add_while_alive (DESKTOP_IS_HOME_DIR_KEY,
+					    (GConfClientNotifyFunc) panel_menu_bar_desktop_is_home_dir_changed,
+					    G_OBJECT (menubar));
+
+	bookmarks_filename = g_build_filename (g_get_home_dir (),
+					       BOOKMARKS_FILENAME, NULL);
+	bookmarks_uri = gnome_vfs_get_uri_from_local_path (bookmarks_filename);
+
+	if (bookmarks_uri) {
+		GnomeVFSResult result;
+		result = gnome_vfs_monitor_add (&menubar->priv->bookmarks_monitor,
+						bookmarks_uri,
+						GNOME_VFS_MONITOR_FILE,
+						panel_menu_bar_gtk_bookmarks_changed,
+						menubar);
+		if (result != GNOME_VFS_OK)
+			g_warning ("Failed to add file monitor for %s: %s\n",
+				   bookmarks_uri,
+				   gnome_vfs_result_to_string (result));
+
+		g_free (bookmarks_uri);
+	} else {
+		g_warning ("Could not make URI of ~/"BOOKMARKS_FILENAME);
+	}
+
+	g_free (bookmarks_filename);
+
+	if (!volume_monitor)
+		volume_monitor = gnome_vfs_get_volume_monitor ();
+
+	menubar->priv->volume_mounted_id = g_signal_connect (volume_monitor,
+							     "volume_mounted",
+							     G_CALLBACK (panel_menu_bar_volume_changed),
+							     menubar);
+	menubar->priv->volume_unmounted_id = g_signal_connect (volume_monitor,
+							       "volume_unmounted",
+							       G_CALLBACK (panel_menu_bar_volume_changed),
+							       menubar);
+
+	menubar->priv->applications_menu = panel_menu_bar_create_applications_menu (menubar);
 	panel_menu_bar_connect_menu_signals (menubar,
 					     &menubar->priv->applications_menu);
 
-	menubar->priv->actions_menu = panel_menu_bar_create_actions_menu (menubar);
+	menubar->priv->places_menu = panel_menu_bar_create_places_menu (menubar);
+	panel_menu_bar_connect_menu_signals (menubar,
+					     &menubar->priv->places_menu);
+
+	menubar->priv->system_menu = panel_menu_bar_create_system_menu (menubar);
 	panel_menu_bar_connect_menu_signals (menubar,
-					     &menubar->priv->actions_menu);
+					     &menubar->priv->system_menu);
 
-	item = gtk_image_menu_item_new_with_label (_("Applications"));
+	menubar->priv->applications_item = gtk_image_menu_item_new_with_label (_("Applications"));
 	image = gtk_image_new_from_stock (PANEL_STOCK_GNOME_LOGO,
 					  panel_menu_bar_icon_get_size ());
-	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menubar->priv->applications_item),
+				       image);
 
-	gtk_menu_item_set_submenu (GTK_MENU_ITEM (item),
+	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar->priv->applications_item),
 				   menubar->priv->applications_menu);
-	gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menubar),
+			       menubar->priv->applications_item);
 
-	menubar->priv->actions_item = gtk_menu_item_new_with_label (_("Actions"));
-	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar->priv->actions_item),
-				   menubar->priv->actions_menu);
+	menubar->priv->places_item = gtk_menu_item_new_with_label (_("Places"));
+	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar->priv->places_item),
+				   menubar->priv->places_menu);
 	gtk_menu_shell_append (GTK_MENU_SHELL (menubar),
-			       menubar->priv->actions_item);
+			       menubar->priv->places_item);
 
-	panel_lockdown_notify_add (G_CALLBACK (panel_menu_bar_recreate_actions_menu),
+	menubar->priv->system_item = gtk_menu_item_new_with_label (_("System"));
+	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar->priv->system_item),
+				   menubar->priv->system_menu);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menubar),
+			       menubar->priv->system_item);
+
+	panel_lockdown_notify_add (G_CALLBACK (panel_menu_bar_recreate_system_menu),
 				   menubar);
 }
 
@@ -208,12 +744,18 @@ panel_menu_bar_parent_set (GtkWidget *wi
 
 	menubar->priv->panel = (PanelWidget *) widget->parent;
 
-	panel_applet_menu_set_recurse (GTK_MENU (menubar->priv->applications_menu),
-				       "menu_panel",
-				       menubar->priv->panel);
-	panel_applet_menu_set_recurse (GTK_MENU (menubar->priv->actions_menu),
-				       "menu_panel",
-				       menubar->priv->panel);
+	if (menubar->priv->applications_menu)
+		panel_applet_menu_set_recurse (GTK_MENU (menubar->priv->applications_menu),
+					       "menu_panel",
+					       menubar->priv->panel);
+	if (menubar->priv->places_menu)
+		panel_applet_menu_set_recurse (GTK_MENU (menubar->priv->places_menu),
+					       "menu_panel",
+					       menubar->priv->panel);
+	if (menubar->priv->system_menu)
+		panel_applet_menu_set_recurse (GTK_MENU (menubar->priv->system_menu),
+					       "menu_panel",
+					       menubar->priv->panel);
 }
 
 static void
@@ -229,12 +771,43 @@ panel_menu_bar_realized (GtkWidget     *
 }
 
 static void
+panel_menu_bar_finalize (GObject *object)
+{
+	PanelMenuBar *menubar = (PanelMenuBar *) object;
+
+	panel_lockdown_notify_remove (G_CALLBACK (panel_menu_bar_recreate_system_menu),
+				      menubar);
+
+	gconf_client_remove_dir (panel_gconf_get_client (),
+				 DESKTOP_IS_HOME_DIR_DIR,
+				 NULL);
+
+	if (menubar->priv->bookmarks_monitor != NULL)
+		gnome_vfs_monitor_cancel (menubar->priv->bookmarks_monitor);
+	menubar->priv->bookmarks_monitor = NULL;
+
+	if (menubar->priv->volume_mounted_id)
+		g_signal_handler_disconnect (volume_monitor,
+					     menubar->priv->volume_mounted_id);
+	menubar->priv->volume_mounted_id = 0;
+
+	if (menubar->priv->volume_unmounted_id)
+		g_signal_handler_disconnect (volume_monitor,
+					     menubar->priv->volume_unmounted_id);
+	menubar->priv->volume_unmounted_id = 0;
+
+	parent_class->finalize (object);
+}
+
+static void
 panel_menu_bar_class_init (PanelMenuBarClass *klass)
 {
+	GObjectClass   *gobject_class   = (GObjectClass   *) klass;
 	GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
 
 	parent_class = g_type_class_peek_parent (klass);
 
+	gobject_class->finalize  = panel_menu_bar_finalize;
 	widget_class->parent_set = panel_menu_bar_parent_set;
 
 	g_type_class_add_private (klass, sizeof (PanelMenuBarPrivate));
