diff options
-rw-r--r-- | src/nautilus-file-operations.c | 155 | ||||
-rw-r--r-- | src/nautilus-file-operations.h | 7 | ||||
-rw-r--r-- | src/nautilus-files-view.c | 20 |
3 files changed, 178 insertions, 4 deletions
diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c index 7d364ab6c..bc215ca9d 100644 --- a/src/nautilus-file-operations.c +++ b/src/nautilus-file-operations.c @@ -236,6 +236,17 @@ typedef struct gpointer done_callback_data; } CompressJob; +typedef struct +{ + CommonJob common; + GFile *location; + GFile *dest_dir; + gboolean success; + GBytes *bytes; + NautilusCopyCallback done_callback; + gpointer done_callback_data; +} PasteImageJob; + static void source_info_clear (SourceInfo *source_info) { @@ -8017,6 +8028,150 @@ nautilus_file_operations_new_folder (GtkWidget *parent_view g_task_run_in_thread (task, create_task_thread_func); } +static void +paste_image_thread_func (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + PasteImageJob *job = task_data; + g_autoptr (GError) output_error = NULL; + g_autoptr (GFileOutputStream) stream = NULL; + int i = 0; + + while (stream == NULL) + { + g_autoptr (GError) stream_error = NULL; + g_autofree gchar *filename = NULL; + g_autofree gchar *suffix = NULL; + /* Translators: This is used to auto-generate a file name for pasted images from + * the clipboard i.e. "Pasted image.png", "Pasted image 1.png", ... */ + const gchar *base_name = _("Pasted image"); + + suffix = i == 0 ? g_strdup (".png") : g_strdup_printf (" %d.png", i); + filename = g_strdup_printf ("%s%s", base_name, suffix); + job->location = g_file_get_child (job->dest_dir, filename); + stream = g_file_create (job->location, 0, job->common.cancellable, &stream_error); + if (stream_error == NULL) + { + break; + } + else if (IS_IO_ERROR (stream_error, EXISTS)) + { + g_clear_object (&job->location); + i++; + } + else + { + return; + } + } + + nautilus_progress_info_set_progress (job->common.progress, .75, 1); + nautilus_progress_info_set_status (job->common.progress, _("Saving clipboard image to file")); + nautilus_progress_info_set_details (job->common.progress, ""); + g_output_stream_write_bytes (G_OUTPUT_STREAM (stream), job->bytes, job->common.cancellable, &output_error); + if (output_error == NULL) + { + job->success = TRUE; + nautilus_progress_info_set_progress (job->common.progress, 1, 1); + nautilus_progress_info_set_status (job->common.progress, _("Successfully pasted clipboard image to file")); + } +} + +static void +paste_image_task_done (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + PasteImageJob *job = user_data; + g_autoptr (GHashTable) debuting_files = NULL; + + debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL); + + if (job->location != NULL) + { + g_hash_table_insert (debuting_files, g_object_ref (job->location), job->location); + } + + job->done_callback (debuting_files, job->success, job->done_callback_data); + + if (!job->success) + { + if (job->location != NULL) + { + g_file_delete (job->location, NULL, NULL); + } + nautilus_progress_info_set_status (job->common.progress, _("Failed to paste image")); + } + + g_clear_object (&job->location); + g_clear_object (&job->dest_dir); + g_clear_pointer (&job->bytes, g_bytes_unref); + + finalize_common ((CommonJob *) job); +} + +static void +paste_image_received_callback (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GdkClipboard *clipboard = GDK_CLIPBOARD (source_object); + PasteImageJob *job = user_data; + g_autoptr (GTask) task = NULL; + g_autoptr (GdkTexture) texture = NULL; + g_autoptr (GError) clipboard_error = NULL; + + if (job_aborted ((CommonJob *) job)) + { + paste_image_task_done (NULL, NULL, job); + return; + } + + texture = gdk_clipboard_read_texture_finish (clipboard, res, &clipboard_error); + if (clipboard_error != NULL) + { + paste_image_task_done (NULL, NULL, job); + return; + } + + job->bytes = gdk_texture_save_to_png_bytes (texture); + nautilus_progress_info_set_progress (job->common.progress, .5, 1); + + task = g_task_new (NULL, NULL, paste_image_task_done, job); + g_task_set_task_data (task, job, NULL); + g_task_run_in_thread (task, paste_image_thread_func); +} + +void +nautilus_file_operations_paste_image_from_clipboard (GtkWidget *parent_view, + NautilusFileOperationsDBusData *dbus_data, + const char *parent_dir_uri, + NautilusCopyCallback done_callback, + gpointer done_callback_data) +{ + PasteImageJob *job; + GtkWindow *parent_window = NULL; + GdkClipboard *clipboard = gtk_widget_get_clipboard (parent_view); + + if (parent_view) + { + parent_window = (GtkWindow *) gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW); + } + + job = op_job_new (PasteImageJob, parent_window, dbus_data); + job->dest_dir = g_file_new_for_uri (parent_dir_uri); + job->location = NULL; + job->bytes = NULL; + job->done_callback = done_callback; + job->done_callback_data = done_callback_data; + + nautilus_progress_info_start (job->common.progress); + nautilus_progress_info_set_status (job->common.progress, _("Retrieving clipboard data")); + gdk_clipboard_read_texture_async (clipboard, job->common.cancellable, paste_image_received_callback, job); +} + void nautilus_file_operations_new_file_from_template (GtkWidget *parent_view, const char *parent_dir, diff --git a/src/nautilus-file-operations.h b/src/nautilus-file-operations.h index 14d664f80..99afad600 100644 --- a/src/nautilus-file-operations.h +++ b/src/nautilus-file-operations.h @@ -164,3 +164,10 @@ void nautilus_file_operations_compress (GList *files, NautilusFileOperationsDBusData *dbus_data, NautilusCreateCallback done_callback, gpointer done_callback_data); + +void +nautilus_file_operations_paste_image_from_clipboard (GtkWidget *parent_view, + NautilusFileOperationsDBusData *dbus_data, + const char *parent_dir_uri, + NautilusCopyCallback done_callback, + gpointer done_callback_data); diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index 68aa37593..1cbde20a7 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -2777,15 +2777,26 @@ paste_files (NautilusFilesView *view, PasteCallbackData *data; GdkClipboard *clipboard; GdkContentFormats *formats; - char *uri; + gchar *real_dest_uri; NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view)); formats = gdk_clipboard_get_formats (clipboard); - uri = dest_uri != NULL ? dest_uri : nautilus_files_view_get_backing_uri (view); + real_dest_uri = dest_uri != NULL ? dest_uri : nautilus_files_view_get_backing_uri (view); + + if (gdk_content_formats_contain_gtype (formats, GDK_TYPE_TEXTURE)) + { + nautilus_file_operations_paste_image_from_clipboard (GTK_WIDGET (view), + NULL, + real_dest_uri, + copy_move_done_callback, + pre_copy_move (view)); + return; + } + data = g_new0 (PasteCallbackData, 1); - data->dest_uri = uri; + data->dest_uri = real_dest_uri; data->as_link = as_link; data->view = view; @@ -7222,7 +7233,8 @@ update_actions_state_for_clipboard_targets (NautilusFilesView *view) formats = gdk_clipboard_get_formats (clipboard); is_data_copied = gdk_content_formats_contain_gtype (formats, NAUTILUS_TYPE_CLIPBOARD) || gdk_content_formats_contain_gtype (formats, GDK_TYPE_FILE_LIST) || - gdk_content_formats_contain_gtype (formats, G_TYPE_FILE); + gdk_content_formats_contain_gtype (formats, G_TYPE_FILE) || + gdk_content_formats_contain_gtype (formats, GDK_TYPE_TEXTURE); action = g_action_map_lookup_action (G_ACTION_MAP (priv->view_action_group), "paste"); |