From dd57435413a10b288153d1ae0062d37e58bcffd1 Mon Sep 17 00:00:00 2001 From: Eric Koegel Date: Sat, 17 Dec 2011 10:37:04 +0300 Subject: [PATCH] Adds the code required to perform a paste on the on the desktop. Fixes bug 3804. --- src/xfdesktop-clipboard-manager.c | 114 ++++++++++++++++++++++++++++++------- src/xfdesktop-file-icon-manager.c | 27 ++++++++- 2 files changed, 120 insertions(+), 21 deletions(-) diff --git a/src/xfdesktop-clipboard-manager.c b/src/xfdesktop-clipboard-manager.c index 76b4bef..ed90aa0 100644 --- a/src/xfdesktop-clipboard-manager.c +++ b/src/xfdesktop-clipboard-manager.c @@ -307,7 +307,6 @@ xfdesktop_clipboard_manager_owner_changed (GtkClipboard *clipboard, } -#if 0 static void xfdesktop_clipboard_manager_contents_received (GtkClipboard *clipboard, GtkSelectionData *selection_data, @@ -318,6 +317,8 @@ xfdesktop_clipboard_manager_contents_received (GtkClipboard *clipboard, GtkWindow *parent = GTK_WINDOW(gtk_widget_get_toplevel(request->widget)); gboolean path_copy = TRUE; GList *path_list = NULL; + GList *dest_file_list = NULL; + GList *l = NULL; gchar *data; /* check whether the retrieval worked */ @@ -340,19 +341,43 @@ xfdesktop_clipboard_manager_contents_received (GtkClipboard *clipboard, } /* determine the path list stored with the selection */ - path_list = thunar_vfs_path_list_from_string (data, NULL); + path_list = xfdesktop_file_utils_file_list_from_string (data); } /* perform the action if possible */ if (G_LIKELY (path_list != NULL)) { + for (l = path_list; l; l = l->next) { + gchar *dest_basename = g_file_get_basename(l->data); + + if(dest_basename && *dest_basename != '\0') { + /* If we copy a file, we need to use the new absolute filename + * as the destination. If we move, we need to use the destination + * directory. */ + if(path_copy) { + GFile *dest_file = g_file_get_child(request->target_file, dest_basename); + dest_file_list = g_list_prepend(dest_file_list, dest_file); + } else { + dest_file_list = g_list_prepend(dest_file_list, request->target_file); + } + } + g_free(dest_basename); + } + + dest_file_list = g_list_reverse(dest_file_list); + if (G_LIKELY (path_copy)) - xfdesktop_file_utils_copy_into(parent, path_list, request->target_path); - //thunar_application_copy_into (application, request->widget, path_list, request->target_path, request->new_files_closure); - else - xfdesktop_file_utils_move_into(parent, path_list, request->target_path); - //thunar_application_move_into (application, request->widget, path_list, request->target_path, request->new_files_closure); - thunar_vfs_path_list_free (path_list); + { + xfdesktop_file_utils_transfer_files(GDK_ACTION_COPY, + path_list, + dest_file_list, + gtk_widget_get_screen(GTK_WIDGET(parent))); + } else { + xfdesktop_file_utils_transfer_files(GDK_ACTION_MOVE, + path_list, + dest_file_list, + gtk_widget_get_screen(GTK_WIDGET(parent))); + } /* clear the clipboard if it contained "cutted data" * (gtk_clipboard_clear takes care of not clearing @@ -365,18 +390,11 @@ xfdesktop_clipboard_manager_contents_received (GtkClipboard *clipboard, * if either the Xserver or our GTK+ version * doesn't support the XFixes extension. */ -#if GTK_CHECK_VERSION(2,6,0) if (!gdk_display_supports_selection_notification (gtk_clipboard_get_display (manager->clipboard))) -#endif { xfdesktop_clipboard_manager_owner_changed (manager->clipboard, NULL, manager); } } - else - { - /* tell the user that we cannot paste */ -// thunar_dialogs_show_error (request->widget, NULL, _("There is nothing on the clipboard to paste")); - } /* free the request */ if (G_LIKELY (request->widget != NULL)) @@ -384,10 +402,11 @@ xfdesktop_clipboard_manager_contents_received (GtkClipboard *clipboard, if (G_LIKELY (request->new_files_closure != NULL)) g_closure_unref (request->new_files_closure); g_object_unref (G_OBJECT (request->manager)); - thunar_vfs_path_unref (request->target_path); - g_free (request); + + g_list_free(dest_file_list); + g_list_free(path_list); } -#endif + static void @@ -654,6 +673,61 @@ xfdesktop_clipboard_manager_cut_files (XfdesktopClipboardManager *manager, gboolean xfdesktop_clipboard_manager_get_can_paste (XfdesktopClipboardManager *manager) { - /* FIXME: implement */ - return FALSE; + g_return_val_if_fail (XFDESKTOP_IS_CLIPBOARD_MANAGER (manager), FALSE); + return manager->can_paste; +} + + +/** + * thunar_clipboard_manager_paste_files: + * @manager : a #XfdesktopClipboardManager. + * @target_file : the #GFile of the folder to which the contents on the clipboard + * should be pasted. + * @widget : a #GtkWidget, on which to perform the paste or %NULL if no widget is + * known. + * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, + * which will be emitted when the job finishes with the + * list of #GFiles created by the job, or + * %NULL if you're not interested in the signal. + * + * Pastes the contents from the clipboard associated with @manager to the directory + * referenced by @target_file. + * Code copied and adapted from thunar-clipboard-manager.c + * Copyright (c) 2005-2006 Benedikt Meurer + * Copyright (c) 2009-2011 Jannis Pohlmann + **/ +void +xfdesktop_clipboard_manager_paste_files (XfdesktopClipboardManager *manager, + GFile *target_file, + GtkWidget *widget, + GClosure *new_files_closure) +{ + XfdesktopClipboardPasteRequest *request; + + g_return_if_fail (XFDESKTOP_IS_CLIPBOARD_MANAGER (manager)); + g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget)); + + /* prepare the paste request */ + request = g_slice_new0 (XfdesktopClipboardPasteRequest); + request->manager = g_object_ref (G_OBJECT (manager)); + request->target_file = g_object_ref (target_file); + request->widget = widget; + + /* take a reference on the closure (if any) */ + if (G_LIKELY (new_files_closure != NULL)) + { + request->new_files_closure = new_files_closure; + g_closure_ref (new_files_closure); + g_closure_sink (new_files_closure); + } + + /* get notified when the widget is destroyed prior to + * completing the clipboard contents retrieval + */ + if (G_LIKELY (request->widget != NULL)) + g_object_add_weak_pointer (G_OBJECT (request->widget), (gpointer) &request->widget); + + /* schedule the request */ + gtk_clipboard_request_contents (manager->clipboard, manager->x_special_gnome_copied_files, + xfdesktop_clipboard_manager_contents_received, request); } diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c index d3ca2eb..b7fada2 100644 --- a/src/xfdesktop-file-icon-manager.c +++ b/src/xfdesktop-file-icon-manager.c @@ -858,6 +858,15 @@ xfdesktop_file_icon_menu_delete(GtkWidget *widget, } static void +xfdesktop_file_icon_menu_paste(GtkWidget *widget, + gpointer user_data) +{ + XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data); + if(widget && fmanager) + xfdesktop_clipboard_manager_paste_files(clipboard_manager, fmanager->priv->folder, widget, NULL); +} + +static void xfdesktop_file_icon_menu_properties(GtkWidget *widget, gpointer user_data) { @@ -1616,7 +1625,11 @@ xfdesktop_file_icon_manager_populate_context_menu(XfceDesktop *desktop, mi = gtk_image_menu_item_new_from_stock(GTK_STOCK_PASTE, NULL); gtk_widget_show(mi); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); - /* FIXME: implement */ + if(xfdesktop_clipboard_manager_get_can_paste(clipboard_manager)) { + g_signal_connect(G_OBJECT(mi), "activate", + G_CALLBACK(xfdesktop_file_icon_menu_paste), + fmanager); + } else gtk_widget_set_sensitive(mi, FALSE); } else { mi = gtk_image_menu_item_new_from_stock(GTK_STOCK_COPY, NULL); @@ -2098,6 +2111,18 @@ xfdesktop_file_icon_manager_key_press(GtkWidget *widget, } return TRUE; + case GDK_v: + case GDK_V: + if(!(evt->state & GDK_CONTROL_MASK) + || (evt->state & (GDK_SHIFT_MASK|GDK_MOD1_MASK|GDK_MOD4_MASK))) + { + return FALSE; + } + if(xfdesktop_clipboard_manager_get_can_paste(clipboard_manager)) { + xfdesktop_clipboard_manager_paste_files(clipboard_manager, fmanager->priv->folder, widget, NULL); + } + return TRUE; + case GDK_r: case GDK_R: if(!(evt->state & GDK_CONTROL_MASK) -- 1.7.5.4