Re: [Nautilus-list] Using drag and drop to copy files in Nautilus?



Attached is a patch to Nautilus which adds the Drag and Drop
functionality I wanted.  I based it on the stuff you did.  I gave it
minimal testing.  (It compiles, it installs, it copied a file when I did
the drag.) Let me know if you find anything wrong with it.  

On 25 Jul 2001 11:15:43 -0400, Jonathan Blandford wrote:
> Benjamin Kahn <xkahn ximian com> writes:
> 
> > I'm writing a small panel applet which allows you to browse your home
> > directory as a panel menu.  
> > 
> > <plug> it's in gnome cvs in module file_menu_applet if you want to check
> > it out.</plug>
> > 
> > Anyway, I've been hooking up drag and drop and it's working okay. Except
> > in Nautilus. I'm trying to make Nautilus copy or move the file, but it
> > isn't working. I'm using text/uri-list as my mime type and Nautilus treats
> > that as a URL link. Reading through the nautilus drag and drop source
> > code, it looks like that's all it will ever do with that mime type.  (I
> > tested it with the panel and with gmc just to be sure.)  
> > 
> > So does this mean that I have to use Nautilus's internal mime
> > type: x-special/gnome-icon-list to perform a move and copy?  Is there any
> > other way to do it?  What risks should I look out for if I use a type is
> > seems obviously internal?
> 
> Surprisingly enough, I just ran into this bug yesterday, and tried to
> fix it a bit (in the redhat-outstanding-patches branch).  It seems like
> the handling of text/uri-list is sort of poor.  I'd like this to be
> improved at some point -- maybe I'll have time today.  If you want to
> look at it, I can tell you where the code is handled.
> 
> Thanks,
> -Jonathan


Index: libnautilus-private/nautilus-icon-container.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-container.c,v
retrieving revision 1.216
diff -u -r1.216 nautilus-icon-container.c
--- libnautilus-private/nautilus-icon-container.c	2001/07/19 21:35:13	1.216
+++ libnautilus-private/nautilus-icon-container.c	2001/07/30 05:52:43
@@ -3224,9 +3224,10 @@
 				  object_class->type,
 				  GTK_SIGNAL_OFFSET (NautilusIconContainerClass, 
 						     handle_uri_list),
-				  gtk_marshal_NONE__POINTER_INT_INT,
-				  GTK_TYPE_NONE, 3,
+				  eel_gtk_marshal_NONE__POINTER_INT_INT_INT,
+				  GTK_TYPE_NONE, 4,
 				  GTK_TYPE_POINTER,
+				  GTK_TYPE_INT,
 				  GTK_TYPE_INT,
 				  GTK_TYPE_INT);
 
Index: libnautilus-private/nautilus-icon-dnd.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-dnd.c,v
retrieving revision 1.91
diff -u -r1.91 nautilus-icon-dnd.c
--- libnautilus-private/nautilus-icon-dnd.c	2001/07/20 17:36:33	1.91
+++ libnautilus-private/nautilus-icon-dnd.c	2001/07/30 05:52:43
@@ -84,6 +84,7 @@
 								  int y);
 static void     receive_dropped_uri_list                          (NautilusIconContainer *container, 
 								  char* keyword, 
+								  GdkDragAction action,
 								  int x, 
 								  int y);
 static void     nautilus_icon_container_free_drag_data           (NautilusIconContainer *container);
@@ -461,7 +462,7 @@
 		case EEL_ICON_DND_URL:
 			receive_dropped_uri_list
 				(NAUTILUS_ICON_CONTAINER (widget),
-				 (char*) data->data, x, y);
+				 (char*) data->data, context->action, x, y);
 			gtk_drag_finish (context, TRUE, FALSE, time);
 			break;
 
@@ -660,7 +661,7 @@
 
 /* handle dropped uri list */
 static void
-receive_dropped_uri_list (NautilusIconContainer *container, char *uri_list, int x, int y)
+receive_dropped_uri_list (NautilusIconContainer *container, char *uri_list, GdkDragAction action, int x, int y)
 {	
 	if (uri_list == NULL) {
 		return;
@@ -668,6 +669,7 @@
 	
 	gtk_signal_emit_by_name (GTK_OBJECT (container), "handle_uri_list",
 				 uri_list,
+				 action,
 				 x, y);
 }
 
Index: src/file-manager/fm-desktop-icon-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-desktop-icon-view.c,v
retrieving revision 1.139
diff -u -r1.139 fm-desktop-icon-view.c
--- src/file-manager/fm-desktop-icon-view.c	2001/07/23 10:42:36	1.139
+++ src/file-manager/fm-desktop-icon-view.c	2001/07/30 05:52:43
@@ -114,6 +114,7 @@
 								   FMDesktopIconView      *icon_view);
 static void     icon_view_handle_uri_list                   	  (NautilusIconContainer  *container,
 								   const char             *item_uris,
+								   GdkDragAction           action,
 								   int                     x,
 								   int                     y,
 								   FMDirectoryView        *view);
@@ -865,7 +866,7 @@
 
 static void
 icon_view_handle_uri_list (NautilusIconContainer *container, const char *item_uris,
-			   int x, int y, FMDirectoryView *view)
+			   GdkDragAction action, int x, int y, FMDirectoryView *view)
 {
 	GList *uri_list, *node;
 	GnomeDesktopEntry *entry;
Index: src/file-manager/fm-icon-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-icon-view.c,v
retrieving revision 1.208
diff -u -r1.208 fm-icon-view.c
--- src/file-manager/fm-icon-view.c	2001/07/15 09:00:44	1.208
+++ src/file-manager/fm-icon-view.c	2001/07/30 05:52:43
@@ -34,6 +34,7 @@
 #include <eel/eel-gtk-extensions.h>
 #include <eel/eel-gtk-macros.h>
 #include <eel/eel-string.h>
+#include <eel/eel-vfs-extensions.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <gtk/gtkmain.h>
@@ -45,10 +46,12 @@
 #include <libgnome/gnome-i18n.h>
 #include <libgnome/gnome-config.h>
 #include <libgnome/gnome-metadata.h>
+#include <libgnome/gnome-mime.h>
 #include <libgnomevfs/gnome-vfs-async-ops.h>
 #include <libgnomevfs/gnome-vfs-uri.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
 #include <libgnomevfs/gnome-vfs-xfer.h>
+#include <libgnomevfs/gnome-vfs-mime.h>
 #include <libnautilus-private/nautilus-audio-player.h>
 #include <libnautilus-private/nautilus-bonobo-extensions.h>
 #include <libnautilus-private/nautilus-directory-background.h>
@@ -115,49 +118,56 @@
 } MenuItemType;
 
 /* forward declarations */
-static void                 create_icon_container                              (FMIconView           *icon_view);
-static void                 fm_icon_view_initialize                            (FMIconView           *icon_view);
-static void                 fm_icon_view_initialize_class                      (FMIconViewClass      *klass);
-static gboolean             fm_icon_view_is_empty                              (FMDirectoryView      *view);
-static void                 fm_icon_view_set_directory_sort_by                 (FMIconView           *icon_view,
-										NautilusFile         *file,
-										const char           *sort_by);
-static void                 fm_icon_view_set_zoom_level                        (FMIconView           *view,
-										NautilusZoomLevel     new_level,
-										gboolean              always_set_level);
-gboolean                    fm_icon_view_supports_auto_layout                  (FMIconView           *view);
-static void                 fm_icon_view_update_icon_container_fonts           (FMIconView           *icon_view);
-static void                 fm_icon_view_update_icon_container_smooth_font     (FMIconView           *icon_view);
-static void                 fm_icon_view_update_icon_container_font_size_table (FMIconView           *icon_view);
-static void                 fm_icon_view_update_click_mode                     (FMIconView           *icon_view);
-static void                 fm_icon_view_update_smooth_graphics_mode           (FMIconView           *icon_view);
-static gboolean             fm_icon_view_using_tighter_layout                  (FMIconView           *icon_view);
-static gboolean             fm_icon_view_get_directory_tighter_layout          (FMIconView           *icon_view,
-										NautilusFile         *file);
-static void                 fm_icon_view_set_directory_tighter_layout          (FMIconView           *icon_view,
-										NautilusFile         *file,
-										gboolean              tighter_layout);
-static gboolean             real_supports_auto_layout                          (FMIconView           *view);
-static const SortCriterion *get_sort_criterion_by_id                           (const char           *id);
-static const SortCriterion *get_sort_criterion_by_sort_type                    (NautilusFileSortType  sort_type);
-static void                 set_sort_criterion_by_id                           (FMIconView           *icon_view,
-										const char           *id);
-static gboolean             set_sort_reversed                                  (FMIconView           *icon_view,
-										gboolean              new_value);
-static void                 switch_to_manual_layout                            (FMIconView           *view);
-static void                 preview_audio                                      (FMIconView           *icon_view,
-										NautilusFile         *file,
-										gboolean              start_flag);
-static void                 update_layout_menus                                (FMIconView           *view);
-static void                 default_sort_in_reverse_order_changed_callback     (gpointer              callback_data);
-static void                 default_sort_order_changed_callback                (gpointer              callback_data);
-static void                 default_use_tighter_layout_changed_callback        (gpointer              callback_data);
-static void                 default_use_manual_layout_changed_callback         (gpointer              callback_data);
-static void                 default_zoom_level_changed_callback                (gpointer              callback_data);
-static void                 default_zoom_level_font_size_changed_callback      (gpointer              callback_data);
-static void                 font_changed_callback                              (gpointer              callback_data);
-static void                 smooth_font_changed_callback                       (gpointer              callback_data);
+static void                 create_icon_container                              (FMIconView            *icon_view);
+static void                 fm_icon_view_initialize                            (FMIconView            *icon_view);
+static void                 fm_icon_view_initialize_class                      (FMIconViewClass       *klass);
+static gboolean             fm_icon_view_is_empty                              (FMDirectoryView       *view);
+static void                 fm_icon_view_set_directory_sort_by                 (FMIconView            *icon_view,
+										NautilusFile          *file,
+										const char            *sort_by);
+static void                 fm_icon_view_set_zoom_level                        (FMIconView            *view,
+										NautilusZoomLevel      new_level,
+										gboolean               always_set_level);
+gboolean                    fm_icon_view_supports_auto_layout                  (FMIconView            *view);
+static void                 fm_icon_view_update_icon_container_fonts           (FMIconView            *icon_view);
+static void                 fm_icon_view_update_icon_container_smooth_font     (FMIconView            *icon_view);
+static void                 fm_icon_view_update_icon_container_font_size_table (FMIconView            *icon_view);
+static void                 fm_icon_view_update_click_mode                     (FMIconView            *icon_view);
+static void                 fm_icon_view_update_smooth_graphics_mode           (FMIconView            *icon_view);
+static gboolean             fm_icon_view_using_tighter_layout                  (FMIconView            *icon_view);
+static gboolean             fm_icon_view_get_directory_tighter_layout          (FMIconView            *icon_view,
+										NautilusFile          *file);
+static void                 fm_icon_view_set_directory_tighter_layout          (FMIconView            *icon_view,
+										NautilusFile          *file,
+										gboolean               tighter_layout);
+static gboolean             real_supports_auto_layout                          (FMIconView            *view);
+static const SortCriterion *get_sort_criterion_by_id                           (const char            *id);
+static const SortCriterion *get_sort_criterion_by_sort_type                    (NautilusFileSortType   sort_type);
+static void                 set_sort_criterion_by_id                           (FMIconView            *icon_view,
+										const char            *id);
+static gboolean             set_sort_reversed                                  (FMIconView            *icon_view,
+										gboolean               new_value);
+static void                 switch_to_manual_layout                            (FMIconView            *view);
+static void                 preview_audio                                      (FMIconView            *icon_view,
+										NautilusFile          *file,
+										gboolean               start_flag);
+static void                 update_layout_menus                                (FMIconView            *view);
+static void                 default_sort_in_reverse_order_changed_callback     (gpointer               callback_data);
+static void                 default_sort_order_changed_callback                (gpointer               callback_data);
+static void                 default_use_tighter_layout_changed_callback        (gpointer               callback_data);
+static void                 default_use_manual_layout_changed_callback         (gpointer               callback_data);
+static void                 default_zoom_level_changed_callback                (gpointer               callback_data);
+static void                 default_zoom_level_font_size_changed_callback      (gpointer               callback_data);
+static void                 font_changed_callback                              (gpointer               callback_data);
+static void                 smooth_font_changed_callback                       (gpointer               callback_data);
+static void                 icon_view_handle_uri_list                          (NautilusIconContainer *container,
+										const char            *item_uris,
+										GdkDragAction          action,
+										int                    x,
+										int                    y,
+										FMIconView            *view);
 
+
 static int preview_sound_auto_value;
 
 EEL_DEFINE_CLASS_BOILERPLATE (FMIconView,
@@ -2001,7 +2011,7 @@
 			char **additional_text,
 			FMIconView *icon_view)
 {
-	char *actual_uri, *path;
+	char *actual_uri;
 	char *attribute_names;
 	char **text_array;
 	int i , slot_index;
@@ -2025,15 +2035,13 @@
 	if (nautilus_file_is_nautilus_link (file)) {
 		/* FIXME bugzilla.eazel.com 2531: Does sync. I/O and works only locally. */
 		actual_uri = nautilus_file_get_uri (file);
-		path = gnome_vfs_get_local_path_from_uri (actual_uri);
-		g_free (actual_uri);
-		if (path != NULL) {
-			*additional_text = nautilus_link_local_get_additional_text (path);
-			g_free (path);
-			return;
-		}
+		*additional_text = NULL;
+		/* This looks pretty bad.  It would be nice to get the additional text to only appear if
+		 * you zoom in a lot */
+		/* *additional_text = nautilus_link_local_get_additional_text (actual_uri); */
+		return;
 	}
-	
+
 	/* Find out what attributes go below each icon. */
 	attribute_names = fm_icon_view_get_icon_text_attribute_names (icon_view);
 	text_array = g_strsplit (attribute_names, "|", 0);
@@ -2318,6 +2326,8 @@
 static void
 fm_icon_view_initialize (FMIconView *icon_view)
 {
+	NautilusIconContainer *icon_container;
+
         g_return_if_fail (GTK_BIN (icon_view)->child == NULL);
 
 	icon_view->details = g_new0 (FMIconViewDetails, 1);
@@ -2326,6 +2336,7 @@
 	icon_view->details->timeout = -1;
 	icon_view->details->audio_preview_file = NULL;
 	create_icon_container (icon_view);
+	icon_container = get_icon_container (icon_view);
 
 	eel_preferences_add_callback_while_alive (NAUTILUS_PREFERENCES_ICON_VIEW_FONT,
 						       font_changed_callback, 
@@ -2359,6 +2370,12 @@
 						       default_zoom_level_changed_callback,
 						       icon_view,
 						       GTK_OBJECT (icon_view));
+
+	gtk_signal_connect (GTK_OBJECT (icon_container),
+			    "handle_uri_list",
+			    GTK_SIGNAL_FUNC (icon_view_handle_uri_list),
+			    icon_view);
+
 }
 
 static gboolean
@@ -2647,4 +2664,135 @@
 	fm_icon_view_update_smooth_graphics_mode (icon_view);
 
 	gtk_widget_show (GTK_WIDGET (icon_container));
+}
+
+static void
+icon_view_handle_uri_list (NautilusIconContainer *container, const char *item_uris,
+			   GdkDragAction action, int x, int y, FMIconView *view)
+{
+
+	GList *uri_list, *node, *real_uri_list = NULL;
+	GnomeDesktopEntry *entry;
+	GdkPoint point;
+	char *uri, *local_path;
+	char *stripped_uri;
+	const char *last_slash, *link_name;
+	char *container_uri;
+	char *container_path;
+	
+	if (item_uris == NULL) {
+		return;
+	}
+	
+	container_uri = fm_directory_view_get_uri (FM_DIRECTORY_VIEW (view));
+	container_path = gnome_vfs_get_local_path_from_uri (container_uri);
+
+	/* If the container_path is bad at this point, 
+	 * we need to pop up an annoying warning.  
+	 * FIXME: What we should do
+	 * is not accept drags on this icon view.  To fix this, look in:
+	 * nautilus-icon-dnd.c:1218 the call to be blocked
+	 * nautilus-icon-container.c:3363 the call to that function
+	 */
+
+	if (container_path == NULL) {
+
+		eel_show_warning_dialog (_("This view does not accept this type of Drag."),
+					 _("Drag and Drop error"),
+					 fm_directory_view_get_containing_window (view));
+					 
+		g_free (container_path);
+		g_free (container_uri);
+
+		return;
+	}
+
+	if (action == GDK_ACTION_ASK) {
+		action = eel_drag_drop_action_ask 
+			(GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
+	}
+	
+	/* We don't support GDK_ACTION_ASK or GDK_ACTION_PRIVATE
+	 * and we don't support combinations either. */
+	if ((action != GDK_ACTION_DEFAULT) &&
+	    (action != GDK_ACTION_COPY) &&
+	    (action != GDK_ACTION_MOVE) &&
+	    (action != GDK_ACTION_LINK)) {
+		eel_show_warning_dialog (_("Unknown Drag Action."),
+					 _("Drag and Drop error"),
+					 fm_directory_view_get_containing_window (view));
+		g_free (container_path);
+		g_free (container_uri);
+		
+		return;
+	}
+
+	point.x = x;
+	point.y = y;
+		
+	uri_list = gnome_uri_list_extract_uris (item_uris);
+
+	/* Most of what comes in here is not really URIs, but
+	 * rather paths that have a file: prefix in them.
+	 */
+	for (node = uri_list; node != NULL; node = node->next) {
+		real_uri_list = g_list_append (real_uri_list,
+					       eel_make_uri_from_half_baked_uri (node->data));
+	}
+
+	switch (action) {
+	case GDK_ACTION_DEFAULT:  /* We'll say that the default is copy. */
+	case GDK_ACTION_COPY:
+	case GDK_ACTION_MOVE:
+		fm_directory_view_move_copy_items (real_uri_list, NULL, fm_directory_view_get_uri (view),
+						   action, 0, 0, view);
+		break;
+	case GDK_ACTION_LINK:
+		for (node = real_uri_list; node != NULL; node = node->next) {
+
+			/* Make a link using the desktop file contents? */
+			local_path = gnome_vfs_get_local_path_from_uri (uri);
+			if (local_path != NULL) {
+				entry = gnome_desktop_entry_load (local_path);		
+				if (entry != NULL) {
+					
+					/* FIXME: Handle name conflicts? */
+					nautilus_link_local_create_from_gnome_entry (entry, container_path, &point);
+					gnome_desktop_entry_free (entry);
+				}
+				g_free (local_path);
+				if (entry != NULL) {
+					continue;
+				}
+			}
+			
+			/* Make a link from the URI alone. Generate the file
+			 * name by extracting the basename of the URI.
+			 */
+			/* FIXME: This should be using eel_uri_get_basename
+			 * instead of a "roll our own" solution.
+			 */
+			stripped_uri = eel_str_strip_trailing_chr (uri, '/');
+			last_slash = strrchr (stripped_uri, '/');
+			link_name = last_slash == NULL ? NULL : last_slash + 1;
+			
+			if (!eel_str_is_empty (link_name)) {
+				/* FIXME: Handle name conflicts? */
+				nautilus_link_local_create (container_path, link_name,
+							    "gnome-http-url", uri,
+							    &point, NAUTILUS_LINK_GENERIC);
+			}
+			
+			g_free (stripped_uri);
+
+			break;
+		}
+
+	}
+	
+	gnome_uri_list_free_strings (real_uri_list);
+	
+	g_free (container_path);
+	g_free (container_uri);
+	gnome_uri_list_free_strings (uri_list);
 }


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