[nautilus/wip/corey/rework-clipboard] files-view: Allow pasting GDK_TYPE_PIXBUF




commit 8d854cd7096af97deccebccf8be1eaca4df37e7c
Author: Corey Berla <corey berla me>
Date:   Tue Sep 20 15:18:13 2022 -0700

    files-view: Allow pasting GDK_TYPE_PIXBUF
    
    In my testing, copying images was captured as GDK_TYPE_PIXBUF.
    Allow pasting those files into Nautilus.  Since we don't have
    any information regarding filename, popup a dialog that asks for a
    filename and allows choosing a supported filetype.

 src/nautilus-file-operations.c | 108 +++++++++++++++++++++++++++++++++++++++++
 src/nautilus-file-operations.h |   7 +++
 src/nautilus-files-view.c      |  12 ++++-
 3 files changed, 126 insertions(+), 1 deletion(-)
---
diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c
index aa8bd29f3..4a29bff7c 100644
--- a/src/nautilus-file-operations.c
+++ b/src/nautilus-file-operations.c
@@ -8026,6 +8026,114 @@ nautilus_file_operations_new_folder (GtkWidget                      *parent_view
     g_task_run_in_thread (task, create_task_thread_func);
 }
 
+static void
+paste_image_save_callback (GObject      *source_object,
+                           GAsyncResult *res,
+                           gpointer      user_data)
+{
+    CreateJob *job = user_data;
+
+    gdk_pixbuf_save_to_stream_finish (res, NULL);
+    nautilus_progress_info_set_progress (job->common.progress, 1, 1);
+    finalize_common ((CommonJob *) job);
+    g_object_unref (source_object);
+}
+
+static void
+paste_image_stream_ready (GObject      *source_object,
+                          GAsyncResult *res,
+                          gpointer      user_data)
+{
+    CreateJob *job = user_data;
+    g_autoptr (GError) error = NULL;
+
+    g_autoptr (GFileOutputStream) stream = g_file_create_finish (G_FILE (source_object), res, &error);
+
+    if (error != NULL && IS_IO_ERROR (error, EXISTS))
+    {
+        /* Translators: This is an auto-generated name when there's a duplicate. i.e. "Pasted image 1.png" */
+        g_autofree gchar *filename = g_strdup_printf (_("Pasted image %d.png"), ++job->length);
+        g_autoptr (GFile) location = g_file_get_child (job->dest_dir, filename);
+        g_file_create_async (location, 0, 0, job->common.cancellable, paste_image_stream_ready, job);
+    }
+    else
+    {
+        gdk_pixbuf_save_to_stream_async (job->done_callback_data,
+                                         G_OUTPUT_STREAM (stream),
+                                         "png",
+                                         job->common.cancellable,
+                                         paste_image_save_callback, job, NULL);
+    }
+}
+
+static void
+paste_image_received_callback (GObject      *source_object,
+                               GAsyncResult *res,
+                               gpointer      user_data)
+{
+    GdkClipboard *clipboard;
+    const GValue *value;
+    CreateJob *job = user_data;
+
+    clipboard = GDK_CLIPBOARD (source_object);
+
+    if (job_aborted ((CommonJob *) job))
+    {
+        return;
+    }
+
+    value = gdk_clipboard_read_value_finish (clipboard, res, NULL);
+
+    if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
+    {
+        GdkPixbuf *pixbuf = g_value_get_object (value);
+        g_autoptr (GFile) location = g_file_get_child (job->dest_dir, _("Pasted image.png"));
+
+        job->done_callback_data = gdk_pixbuf_copy (pixbuf);
+        g_file_create_async (location, 0, 0, job->common.cancellable, paste_image_stream_ready, job);
+    }
+    else
+    {
+        finalize_common ((CommonJob *) job);
+    }
+}
+
+void
+nautilus_file_operations_paste_image_from_clipboard (GtkWidget                      *parent_view,
+                                                     NautilusFileOperationsDBusData *dbus_data,
+                                                     const char                     *parent_dir_uri,
+                                                     NautilusCreateCallback          done_callback,
+                                                     gpointer                        done_callback_data)
+{
+    g_autoptr (GTask) task = NULL;
+    CreateJob *job;
+    GtkWindow *parent_window;
+    GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (parent_view));
+
+
+    if (parent_view)
+    {
+        parent_window = (GtkWindow *) gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW);
+    }
+
+    job = op_job_new (CreateJob, parent_window, dbus_data);
+    job->dest_dir = g_file_new_for_uri (parent_dir_uri);
+
+    nautilus_progress_info_start (job->common.progress);
+    nautilus_progress_info_set_details (job->common.progress,
+                                        _("Retrieving clipboard data"));
+    gdk_clipboard_read_value_async (clipboard, GDK_TYPE_PIXBUF, 0, job->common.cancellable, 
paste_image_received_callback, job);
+
+    if (!nautilus_file_undo_manager_is_operating ())
+    {
+        g_autoptr (GFile) target_dir = g_file_new_for_uri (parent_dir_uri);
+
+        /* job->common.undo_info = nautilus_file_undo_info_ext_new (NAUTILUS_FILE_UNDO_OP_COPY, */
+        /*                                                          1, */
+        /*                                                          NULL, target_dir); */
+    }
+}
+
 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..37f6ab4ac 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,
+                                                     NautilusCreateCallback          done_callback,
+                                                     gpointer                        done_callback_data);
diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c
index c78523f3a..89841ff6f 100644
--- a/src/nautilus-files-view.c
+++ b/src/nautilus-files-view.c
@@ -2795,6 +2795,15 @@ paste_files (NautilusFilesView *view,
     {
         gdk_clipboard_read_value_async (clipboard, G_TYPE_FILE, 0, priv->clipboard_cancellable, 
paste_value_received_callback, data);
     }
+    else if (gdk_content_formats_contain_gtype (formats, GDK_TYPE_PIXBUF))
+    {
+        nautilus_file_operations_paste_image_from_clipboard (GTK_WIDGET (view),
+                                                             NULL,
+                                                             data->dest_uri,
+                                                             NULL,
+                                                             NULL);
+        paste_callback_data_free (data);
+    }
 }
 
 static void
@@ -7211,7 +7220,8 @@ update_actions_state_for_clipboard_targets (NautilusFilesView *view)
     clipboard = gtk_widget_get_clipboard (GTK_WIDGET (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, G_TYPE_FILE);
+                     gdk_content_formats_contain_gtype (formats, G_TYPE_FILE) ||
+                     gdk_content_formats_contain_gtype (formats, GDK_TYPE_PIXBUF);
 
     action = g_action_map_lookup_action (G_ACTION_MAP (priv->view_action_group),
                                          "paste");


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