Index: nautilus-places-sidebar.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-places-sidebar.c,v
retrieving revision 1.18
diff -u -p -r1.18 nautilus-places-sidebar.c
--- nautilus-places-sidebar.c	15 Apr 2006 16:19:44 -0000	1.18
+++ nautilus-places-sidebar.c	29 Apr 2006 21:35:47 -0000
@@ -114,9 +114,21 @@ static void  nautilus_places_sidebar_ifa
 static void  sidebar_provider_iface_init               (NautilusSidebarProviderIface *iface);
 static GType nautilus_places_sidebar_provider_get_type (void);
 
+/* Identifiers for target types */
+enum {
+  GTK_TREE_MODEL_ROW,
+  TEXT_URI_LIST
+};
+
+/* Target types for dragging from the shortcuts list */
+static const GtkTargetEntry source_targets[] = {
+	{ "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW }
+};
+
 /* Target types for dropping into the shortcuts list */
 static const GtkTargetEntry drop_targets [] = {
-	{ NAUTILUS_ICON_DND_URI_LIST_TYPE, 0, NAUTILUS_ICON_DND_URI_LIST }
+	{ "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW },
+	{ "text/uri-list", 0, TEXT_URI_LIST }
 };
 
 G_DEFINE_TYPE_WITH_CODE (NautilusPlacesSidebar, nautilus_places_sidebar, GTK_TYPE_SCROLLED_WINDOW,
@@ -604,6 +616,28 @@ can_accept_items_as_bookmarks (const GLi
 	return TRUE;
 }
 
+static void
+drag_begin_callback (GtkWidget             *widget,
+		     GdkDragContext        *context,
+		     NautilusPlacesSidebar *sidebar)
+{
+}
+
+static void
+drag_end_callback (GtkWidget             *widget,
+		   GdkDragContext        *context,
+		   NautilusPlacesSidebar *sidebar)
+{
+}
+
+static void
+drag_data_delete_callback (GtkWidget             *widget,
+			   GdkDragContext        *context,
+			   NautilusPlacesSidebar *sidebar)
+{
+  g_signal_stop_emission_by_name (widget, "drag-data-delete");
+}
+
 static gboolean
 drag_motion_callback (GtkTreeView *tree_view,
 		      GdkDragContext *context,
@@ -626,32 +660,37 @@ drag_motion_callback (GtkTreeView *tree_
 	compute_drop_position (tree_view, x, y, &path, &pos, sidebar);
 
 	if (pos == GTK_TREE_VIEW_DROP_BEFORE ||
-	    pos == GTK_TREE_VIEW_DROP_AFTER ||
-	    sidebar->drag_list == NULL) {
+	    pos == GTK_TREE_VIEW_DROP_AFTER ) {
 		if (can_accept_items_as_bookmarks (sidebar->drag_list)) {
 			action = GDK_ACTION_COPY;
 		} else {
 			action = 0;
 		}
 	} else {
-		model = gtk_tree_view_get_model (tree_view);
-		gtk_tree_model_get_iter (model, &iter, path);
-		gtk_tree_model_get (model, &iter,
-				    PLACES_SIDEBAR_COLUMN_URI, &uri,
-				    -1);
-		nautilus_drag_default_drop_action_for_icons (context, uri,
-							     sidebar->drag_list,
-							     &action);
-		g_free (uri);
+		if (sidebar->drag_list == NULL)
+			action = 0;
+		else {
+			model = gtk_tree_view_get_model (tree_view);
+			gtk_tree_model_get_iter (model, &iter, path);
+			gtk_tree_model_get (model, &iter,
+					    PLACES_SIDEBAR_COLUMN_URI, &uri,
+					    -1);
+			nautilus_drag_default_drop_action_for_icons (context, uri,
+								     sidebar->drag_list,
+								     &action);
+			g_free (uri);
+		}
 	}
 
 	gtk_tree_view_set_drag_dest_row (tree_view, path, pos);
 	gtk_tree_path_free (path);
 	g_signal_stop_emission_by_name (tree_view, "drag-motion");
 
-	gdk_drag_status (context, action, time);
-
-	return TRUE;
+	if (action != 0) {
+		gdk_drag_status (context, action, time);
+		return TRUE;
+	} else
+		return FALSE;
 }
 
 static void
@@ -751,6 +790,49 @@ build_selection_list (const char *data)
 	return g_list_reverse (result);
 }
 
+/* Reorders the selected bookmark to the specified position */
+static void
+reorder_bookmarks (NautilusPlacesSidebar *sidebar,
+		  int                    new_position)
+{
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	GtkTreeSelection *selection;
+	GtkTreePath *path;
+	NautilusBookmark *bookmark;
+	int old_position;
+	int bookmarks_index;
+
+	/* Get the selected path */
+
+	selection = gtk_tree_view_get_selection (sidebar->tree_view);
+
+	if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
+		return;
+
+	model = gtk_tree_view_get_model (sidebar->tree_view);
+	path = gtk_tree_model_get_path (model, &iter);
+	old_position = *gtk_tree_path_get_indices (path);
+	gtk_tree_path_free (path);
+
+	bookmarks_index = get_bookmark_index (sidebar->tree_view);
+	old_position -= bookmarks_index;
+	if (old_position < 0)
+		return;
+	g_assert (old_position < nautilus_bookmark_list_length (sidebar->bookmarks));
+
+	/* Remove the path from the old position and insert it in the new one */
+
+	if (old_position == new_position)
+		return;
+
+	bookmark = nautilus_bookmark_list_item_at (sidebar->bookmarks, old_position);
+	nautilus_bookmark_list_insert_item (sidebar->bookmarks, bookmark, new_position);
+	if (old_position > new_position)
+		old_position++;
+	nautilus_bookmark_list_delete_item_at (sidebar->bookmarks, old_position);
+}
+
 static void
 drag_data_received_callback (GtkWidget *widget,
 			     GdkDragContext *context,
@@ -773,9 +855,9 @@ drag_data_received_callback (GtkWidget *
 
 	tree_view = GTK_TREE_VIEW (widget);
 
-
 	if (!sidebar->drag_data_received) {
-		if (selection_data->target != GDK_NONE) {
+		if (selection_data->target != GDK_NONE &&
+		    info == TEXT_URI_LIST) {
 			sidebar->drag_list = build_selection_list (selection_data->data);
 		} else {
 			sidebar->drag_list = NULL;
@@ -806,12 +888,15 @@ drag_data_received_callback (GtkWidget *
 	
 		g_assert (position >= bookmarks_index);
 		position -= bookmarks_index;
-	
 		switch (info) {
-		case NAUTILUS_ICON_DND_URI_LIST:
+		case TEXT_URI_LIST:
 			bookmarks_drop_uris (sidebar, selection_data->data, position);
 			success = TRUE;
 			break;
+		case GTK_TREE_MODEL_ROW:
+			reorder_bookmarks (sidebar, position);
+			success = TRUE;
+			break;
 		default:
 			g_assert_not_reached ();
 			break;
@@ -833,7 +918,7 @@ drag_data_received_callback (GtkWidget *
 					    -1);
 
 			switch (info) {
-			case NAUTILUS_ICON_DND_URI_LIST:
+			case TEXT_URI_LIST:
 				selection_list = build_selection_list (selection_data->data);
 				uris = uri_list_from_selection (selection_list);
 				nautilus_file_operations_copy_move (uris, NULL, drop_uri,
@@ -843,6 +928,9 @@ drag_data_received_callback (GtkWidget *
 				g_list_free (uris);
 				success = TRUE;
 				break;
+			case GTK_TREE_MODEL_ROW:
+				success = FALSE;
+				break;
 			default:
 				g_assert_not_reached ();
 				break;
@@ -1197,12 +1285,26 @@ nautilus_places_sidebar_init (NautilusPl
 		(tree_view, "row_activated", 
 		 G_CALLBACK (row_activated_callback), sidebar, 0);
 
-	gtk_drag_dest_set (GTK_WIDGET (tree_view), 0,
+
+	gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (tree_view),
+						GDK_BUTTON1_MASK,
+						source_targets,
+						G_N_ELEMENTS (source_targets),
+						GDK_ACTION_MOVE);
+	gtk_drag_dest_set (GTK_WIDGET (tree_view),
+			   0,
 			   drop_targets, G_N_ELEMENTS (drop_targets),
 			   GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
 
 	g_signal_connect (tree_view, "key-press-event",
 			  G_CALLBACK (bookmarks_key_press_event_cb), sidebar);
+
+	g_signal_connect (tree_view, "drag-begin",
+			  G_CALLBACK (drag_begin_callback), sidebar);
+	g_signal_connect (tree_view, "drag-end",
+			  G_CALLBACK (drag_end_callback), sidebar);
+	g_signal_connect (tree_view, "drag-data-delete",
+			  G_CALLBACK (drag_data_delete_callback), sidebar);
 	g_signal_connect (tree_view, "drag-motion",
 			  G_CALLBACK (drag_motion_callback), sidebar);
 	g_signal_connect (tree_view, "drag-leave",
