The attached patch was in bugzilla [1] but unfortunetely not reviewed for some time: "The attached patch allows users to drop files to the sidebar, either for copying/moving them to the folders in the sidebar, or for adding them to it. If you hover builtin bookmarks and volumes (above sep.), only copying/moving is allowed. This patch also implements middle-click dragging." [1] http://bugzilla.gnome.org/show_bug.cgi?id=43311 -- Christian Neumair <chris gnome-de org>
Index: src/nautilus-places-sidebar.c =================================================================== RCS file: /cvs/gnome/nautilus/src/nautilus-places-sidebar.c,v retrieving revision 1.5 diff -u -p -r1.5 nautilus-places-sidebar.c --- src/nautilus-places-sidebar.c 11 Jul 2005 10:12:46 -0000 1.5 +++ src/nautilus-places-sidebar.c 3 Sep 2005 09:54:28 -0000 @@ -34,17 +34,20 @@ #include <gtk/gtkcellrendererpixbuf.h> #include <gtk/gtkcellrenderertext.h> #include <gtk/gtkliststore.h> +#include <gtk/gtkmain.h> #include <gtk/gtksizegroup.h> #include <gtk/gtkstock.h> #include <gtk/gtktreemodel.h> #include <gtk/gtktreeselection.h> #include <libgnome/gnome-macros.h> #include <libgnome/gnome-i18n.h> +#include <libnautilus-private/nautilus-dnd.h> #include <libnautilus-private/nautilus-bookmark.h> #include <libnautilus-private/nautilus-global-preferences.h> #include <libnautilus-private/nautilus-sidebar-provider.h> #include <libnautilus-private/nautilus-module.h> #include <libnautilus-private/nautilus-file-utilities.h> +#include <libnautilus-private/nautilus-file-operations.h> #include <libgnomevfs/gnome-vfs-utils.h> #include <libgnomevfs/gnome-vfs-volume-monitor.h> @@ -62,6 +65,10 @@ typedef struct { GtkListStore *store; NautilusWindowInfo *window; NautilusBookmarkList *bookmarks; + + /* DnD */ + GList *drag_data; + gboolean drag_data_received; } NautilusPlacesSidebar; typedef struct { @@ -96,6 +103,10 @@ static void nautilus_places_sidebar_ifa static void sidebar_provider_iface_init (NautilusSidebarProviderIface *iface); static GType nautilus_places_sidebar_provider_get_type (void); +static const GtkTargetEntry drop_targets [] = { + { NAUTILUS_ICON_DND_GNOME_ICON_LIST_TYPE, 0, NAUTILUS_ICON_DND_GNOME_ICON_LIST } +}; + G_DEFINE_TYPE_WITH_CODE (NautilusPlacesSidebar, nautilus_places_sidebar, GTK_TYPE_SCROLLED_WINDOW, G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SIDEBAR, nautilus_places_sidebar_iface_init)); @@ -360,6 +371,248 @@ loading_uri_callback (NautilusWindowInfo } } +static void +drag_motion_callback (GtkTreeView *tree_view, + GdkDragContext *context, + int x, + int y, + unsigned int time, + NautilusPlacesSidebar *sidebar) +{ + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + GtkTreeViewDropPosition pos; + GdkAtom target; + PlaceType place_type; + char *uri; + unsigned int action; + + if (!sidebar->drag_data_received) { + target = gtk_drag_dest_find_target (GTK_WIDGET (tree_view), context, NULL); + gtk_drag_get_data (GTK_WIDGET (tree_view), context, target, time); + } + + model = gtk_tree_view_get_model (tree_view); + + gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, &pos); + if (path != NULL) { + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type, + PLACES_SIDEBAR_COLUMN_URI, &uri, + -1); + + if (place_type == PLACES_SEPARATOR) { + gtk_tree_path_free (path); + path = NULL; + action = 0; + } else { + nautilus_drag_default_drop_action_for_icons (context, uri, + sidebar->drag_data, + &action); + + if (action == GDK_ACTION_ASK + || place_type != PLACES_BOOKMARK) { + pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE; + } + } + + g_free (uri); + } + + gtk_tree_view_set_drag_dest_row (tree_view, path, pos); + gdk_drag_status (context, action, time); +} + +static void +drag_leave_callback (GtkTreeView *tree_view, + GdkDragContext *context, + unsigned int time, + NautilusPlacesSidebar *sidebar) +{ + GdkEvent *current_event; + gtk_tree_view_set_drag_dest_row (tree_view, NULL, GTK_TREE_VIEW_DROP_BEFORE); + + current_event = gtk_get_current_event (); + if (current_event == NULL || current_event->type != GDK_DROP_START) { + /* this is not reached if the drop succeds. In that case, the + * drag data is cleared in the "drag-drop" handler */ + nautilus_drag_destroy_selection_list (sidebar->drag_data); + sidebar->drag_data_received = FALSE; + } +} + +static void +drag_data_received_callback (GtkWidget *widget, + GdkDragContext *context, + int x, + int y, + GtkSelectionData *data, + unsigned int info, + unsigned int time, + NautilusPlacesSidebar *sidebar) +{ + if (data->target != GDK_NONE) { + sidebar->drag_data = nautilus_drag_build_selection_list (data); + } else { + sidebar->drag_data = NULL; + } + + sidebar->drag_data_received = TRUE; +} + +static unsigned int +get_bookmark_index_at_path (GtkTreeView *tree_view, + GtkTreePath *bookmark_path) +{ + GtkTreeModel *model; + GtkTreePath *p; + GtkTreeIter iter; + PlaceType place_type; + int separator_index, bookmark_index; + + model = gtk_tree_view_get_model (tree_view); + + bookmark_index = *gtk_tree_path_get_indices (bookmark_path); + separator_index = -1; + + /* find separator */ + p = gtk_tree_path_new_first (); + while (p != NULL) { + gtk_tree_model_get_iter (model, &iter, p); + gtk_tree_model_get (model, &iter, + PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type, + -1); + + if (place_type == PLACES_SEPARATOR) { + separator_index = *gtk_tree_path_get_indices (p); + break; + } + + gtk_tree_path_next (p); + } + gtk_tree_path_free (p); + + g_assert (separator_index >= 0); + + return bookmark_index - separator_index - 1; +} + +static GList * +uri_list_from_selection (GList *selection) +{ + NautilusDragSelectionItem *item; + GList *ret; + GList *l; + + ret = NULL; + for (l = selection; l != NULL; l = l->next) { + item = l->data; + ret = g_list_prepend (ret, item->uri); + } + + return g_list_reverse (ret); +} + +static gboolean +drag_drop_callback (GtkTreeView *tree_view, + GdkDragContext *context, + int x, + int y, + unsigned int time, + NautilusPlacesSidebar *sidebar) +{ + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + NautilusDragSelectionItem *item; + PlaceType place_type; + GtkTreeViewDropPosition pos; + NautilusBookmark *bookmark; + GnomeVFSURI *uri; + char *drop_uri; + char *bookmark_name; + unsigned int bookmark_index; + GList *uris; + GList *l; + + if (context->action == 0) { + nautilus_drag_destroy_selection_list (sidebar->drag_data); + sidebar->drag_data_received = FALSE; + + return FALSE; + } + + model = gtk_tree_view_get_model (tree_view); + + gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, &pos); + if (path == NULL) { + nautilus_drag_destroy_selection_list (sidebar->drag_data); + sidebar->drag_data_received = FALSE; + + return FALSE; + } + + if (context->action == GDK_ACTION_ASK) { + context->action = + nautilus_drag_drop_action_ask (GTK_WIDGET (tree_view), + context->actions); + pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE; + } + + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type, + PLACES_SIDEBAR_COLUMN_URI, &drop_uri, + -1); + + if (place_type != PLACES_BOOKMARK) { + pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE; + } + + if (pos == GTK_TREE_VIEW_DROP_BEFORE + || pos == GTK_TREE_VIEW_DROP_AFTER) { + /* bookmark addition requested */ + + bookmark_index = get_bookmark_index_at_path (tree_view, path); + if (pos == GTK_TREE_VIEW_DROP_AFTER) { + bookmark_index++; + } + + for (l = sidebar->drag_data; l != NULL; l = l->next) { + item = l->data; + + uri = gnome_vfs_uri_new (item->uri); + bookmark_name = gnome_vfs_uri_extract_short_name (uri); + + bookmark = nautilus_bookmark_new (item->uri, bookmark_name); + + g_free (bookmark_name); + gnome_vfs_uri_unref (uri); + + if (!nautilus_bookmark_list_contains (sidebar->bookmarks, bookmark)) { + nautilus_bookmark_list_insert_item (sidebar->bookmarks, bookmark, bookmark_index); + } + } + } else { + /* file transfer requested */ + uris = uri_list_from_selection (sidebar->drag_data); + nautilus_file_operations_copy_move (uris, NULL, drop_uri, + context->action, GTK_WIDGET (tree_view), + NULL, NULL); + g_list_free (uris); + } + + nautilus_drag_destroy_selection_list (sidebar->drag_data); + sidebar->drag_data_received = FALSE; + + gtk_drag_finish (context, TRUE, FALSE, time); + + g_free (drop_uri); + gtk_tree_path_free (path); + return TRUE; +} static void nautilus_places_sidebar_init (NautilusPlacesSidebar *sidebar) @@ -422,6 +675,19 @@ nautilus_places_sidebar_init (NautilusPl g_signal_connect_object (tree_view, "row_activated", G_CALLBACK (row_activated_callback), sidebar, 0); + + /* DnD */ + gtk_drag_dest_set (GTK_WIDGET (tree_view), 0, + drop_targets, G_N_ELEMENTS (drop_targets), + GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); + g_signal_connect (tree_view, "drag-motion", + G_CALLBACK (drag_motion_callback), sidebar); + g_signal_connect (tree_view, "drag-leave", + G_CALLBACK (drag_leave_callback), sidebar); + g_signal_connect (tree_view, "drag-data-received", + G_CALLBACK (drag_data_received_callback), sidebar); + g_signal_connect (tree_view, "drag-drop", + G_CALLBACK (drag_drop_callback), sidebar); eel_preferences_add_callback (NAUTILUS_PREFERENCES_CLICK_POLICY, click_policy_changed_callback,
Attachment:
signature.asc
Description: This is a digitally signed message part