Remote VFS linking patch



Hi,

I've been working on a patch to allow the creation of links to remote
VFS URI's using desktop files (example use case: putting a link to your
favourite samba share on the desktop). I'm pretty new to Nautilus
hacking, so I've attached a diff (against Nautilus 2.4.0) of what I've
got so far for consideration/peer-review, before I go any further. 

There's a few things I know I need to work on:
1- There's no user-visible error handling-- I guess I could make it pop
up one of those nice eel dialogs if my gnome-vfs calls don't succeed?
2- My code allows you to make stupid links-- e.g.: to the "Start Here"
namespace (which just gives you a desktop file pointing to another
desktop file). We should probably just hide the link option in this
case. Is there a function I can query to get a list of file-system like
vfs prefixes (smb, nfs, ..) somewhere? If not, should I write one?
3- We should probably add some type of emblem to the created link to
indicate it's remote. I just haven't gotten around to this yet.

I hope the patch is o.k. otherwise.

Any and all feedback is appreciated,
-- 
William Lachance <wlach nit ca>

--- /home/wlach/nautilus-file-operations.c	2003-10-22 18:46:04.000000000 -0400
+++ nautilus-file-operations.c	2003-10-22 18:49:53.000000000 -0400
@@ -27,6 +27,7 @@
 #include <config.h>
 #include <string.h>
 #include "nautilus-file-operations.h"
+#include "nautilus-file.h"
 
 #include "nautilus-file-operations-progress.h"
 #include "nautilus-lib-self-check-functions.h"
@@ -1685,6 +1686,93 @@
 	return gnome_vfs_uri_dup (target_directory);
 }
 
+const char *desktop_link = "[Desktop Entry]\nVersion=1.0\nEncoding=UTF-8\nName=%s\nType=Link\nURL=%s\nX-Nautilus-Icon=%s\n";
+
+static char *
+get_unescaped_link_name(char *name, int count)
+{
+	char *escaped_link_name = get_link_name(name, count); 
+	char *unescaped_link_name = gnome_vfs_unescape_string (escaped_link_name, NULL);
+
+	g_free(escaped_link_name);
+
+	return unescaped_link_name;
+}
+
+void add_remote_desktop_shortcut(GnomeVFSURI *source_uri, GnomeVFSURI *target_uri)
+{
+	GnomeVFSResult result;
+	GnomeVFSHandle *handle = NULL;
+	GString *buf = g_string_new(NULL);
+	GnomeVFSFileSize bytes_written;
+	char *short_path_name = gnome_vfs_uri_extract_short_name (target_uri);
+	char *desktop_link_name;
+	char *source_file_name = gnome_vfs_uri_to_string (source_uri, GNOME_VFS_URI_HIDE_NONE);
+	NautilusFile *source_file;	
+	char *link_icon; 
+
+	int duplicate_count = 0;
+	GnomeVFSURI * parent_target_uri;
+	GnomeVFSURI * putative_target_uri;		
+	gchar *target_file_putative_name;
+
+	
+	result = gnome_vfs_create_uri (&handle, target_uri,
+				       GNOME_VFS_OPEN_WRITE, TRUE,
+				       0644);
+	if (result == GNOME_VFS_OK) {
+		desktop_link_name = get_unescaped_link_name (g_strdup(short_path_name), 1);
+	}
+	else if (result == GNOME_VFS_ERROR_FILE_EXISTS) {
+		duplicate_count = 1;
+		parent_target_uri = gnome_vfs_uri_get_parent (target_uri);
+		
+		while (result == GNOME_VFS_ERROR_FILE_EXISTS) {
+			duplicate_count++;
+			target_file_putative_name = get_unescaped_link_name (g_strdup(short_path_name), duplicate_count);
+			putative_target_uri = gnome_vfs_uri_append_file_name (parent_target_uri, target_file_putative_name);
+
+			result = gnome_vfs_create_uri (&handle, putative_target_uri,
+						       GNOME_VFS_OPEN_WRITE, TRUE,
+						       0644);
+			if (result == GNOME_VFS_OK) {
+				desktop_link_name = g_strdup(target_file_putative_name);
+			}
+
+ 			gnome_vfs_uri_unref (putative_target_uri); 
+ 			g_free (target_file_putative_name);
+		}
+
+		gnome_vfs_uri_unref (parent_target_uri);					
+	}
+
+
+	if (result == GNOME_VFS_OK) {
+		source_file = nautilus_file_get (source_file_name);
+ 		link_icon = nautilus_icon_factory_get_icon_for_file (source_file, FALSE);
+
+		g_string_printf (buf, desktop_link, desktop_link_name, source_file_name, link_icon);
+
+		result = gnome_vfs_write (handle,
+					  buf->str,
+					  buf->len,
+					  &bytes_written);
+		gnome_vfs_close (handle);
+
+		nautilus_file_unref (source_file);
+		g_free (link_icon);	
+	}
+
+	if (result != GNOME_VFS_OK) {
+		printf("Didn't succeed in writing/creating a unique file handle\n");
+	}
+	
+	g_string_free (buf, TRUE);
+	g_free (source_file_name);
+	g_free (short_path_name);
+}
+
+
 void
 nautilus_file_operations_copy_move (const GList *item_uris,
 				    GArray *relative_item_points,
@@ -1982,24 +2070,31 @@
 			}
 		}
 	}
-
-	transfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY;
-	transfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_QUERY;
-	transfer_info->done_callback = done_callback;
-	transfer_info->done_callback_data = done_callback_data;
-	transfer_info->debuting_uris = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
-	sync_transfer_info = g_new (SyncTransferInfo, 1);
-	sync_transfer_info->iterator = icon_position_iterator;
-	sync_transfer_info->debuting_uris = transfer_info->debuting_uris;
-
-	if (result == GNOME_VFS_OK) {
+	if (have_nonlocal_source && copy_action == GDK_ACTION_LINK) {
+		GList *p1=source_uri_list, *p2=target_uri_list;
+		for (p1; p1 != NULL; p1 = p1->next) {
+			add_remote_desktop_shortcut(p1->data, p2->data);
+			
+			p2 = p2->next;
+		}
+	}
+	else if (result == GNOME_VFS_OK) {
+		transfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY;
+		transfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_QUERY;
+		transfer_info->done_callback = done_callback;
+		transfer_info->done_callback_data = done_callback_data;
+		transfer_info->debuting_uris = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+		
+		sync_transfer_info = g_new (SyncTransferInfo, 1);
+		sync_transfer_info->iterator = icon_position_iterator;
+		sync_transfer_info->debuting_uris = transfer_info->debuting_uris;
+		
 		gnome_vfs_async_xfer (&transfer_info->handle, source_uri_list, target_uri_list,
-		      		      move_options, GNOME_VFS_XFER_ERROR_MODE_QUERY, 
-		      		      GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+				      move_options, GNOME_VFS_XFER_ERROR_MODE_QUERY, 
+				      GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
 				      GNOME_VFS_PRIORITY_DEFAULT,
-		      		      update_transfer_callback, transfer_info,
-		      		      sync_transfer_callback, sync_transfer_info);
+				      update_transfer_callback, transfer_info,
+				      sync_transfer_callback, sync_transfer_info);
 	}
 
 	gnome_vfs_uri_list_free (source_uri_list);


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