Am Montag, den 10.10.2005, 16:23 +0200 schrieb Luca Ferretti: > Il giorno sab, 08/10/2005 alle 15.42 -0500, Travis Watkins ha scritto: > > On 10/7/05, Christian Neumair <chris gnome-de org> wrote: > > > > Not true. Better, it seems bugged. Try to middle-clic and drag an item > > > > (/f over a shortcut in Places sidebar, them select "Cancel" from > > > > popup-menu. This don't cancel the action, but will copy the item. Copy, > > > > Move and Link works fine, instead. > > > > > > Maybe you could rephrase your comment? > > > > I think he is trying to say that you can't cancel a middle-click DnD > > action. If you click cancel it will copy the file anyway. > > Doh! Yeah, this is what I meant. Sorry. OK, updated patch attached. -- 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 11 Oct 2005 11:07:06 -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 +375,242 @@ 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;
+ 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;
+
+ model = gtk_tree_view_get_model (tree_view);
+ gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, &pos);
+
+ 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;
+ }
+
+ if (path == NULL || context->action == 0) {
+ nautilus_drag_destroy_selection_list (sidebar->drag_data);
+ sidebar->drag_data_received = FALSE;
+
+ return FALSE;
+ }
+
+ 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 +673,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