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




commit 7f2e9248bdafb03e4aec81b2e5d24b800aaeb6ea
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-files-view.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 94 insertions(+), 1 deletion(-)
---
diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c
index 95d6a01c8..b1fc6c564 100644
--- a/src/nautilus-files-view.c
+++ b/src/nautilus-files-view.c
@@ -2728,6 +2728,86 @@ handle_clipboard_data (NautilusFilesView *view,
     }
 }
 
+static void
+on_paste_dialog_response (GtkDialog *dialog,
+                          gint       response_id,
+                          gpointer   user_data)
+{
+    GdkPixbuf *pixbuf = user_data;
+    if (response_id == GTK_RESPONSE_ACCEPT)
+    {
+        gchar *dest_uri = g_object_get_data (G_OBJECT (dialog), "dest_uri");
+        g_autoptr (GFile) dest_dir = g_file_new_for_uri (dest_uri);
+        g_autoptr (GFile) location = NULL;
+        g_autofree gchar *filename = NULL;
+        g_autofree gchar *full_path = NULL;
+        const char *extension;
+        GtkWidget *entry;
+        GtkWidget *drop_down;
+        GtkWidget *content_area = gtk_dialog_get_content_area (dialog);
+
+        entry = gtk_widget_get_first_child (content_area);
+        drop_down = gtk_widget_get_last_child (content_area);
+        extension = gtk_string_list_get_string (GTK_STRING_LIST (gtk_drop_down_get_model (GTK_DROP_DOWN 
(drop_down))),
+                                                gtk_drop_down_get_selected (GTK_DROP_DOWN (drop_down)));
+        filename = g_strdup_printf ("%s.%s", gtk_editable_get_text (GTK_EDITABLE (entry)), extension);
+        location = g_file_get_child (dest_dir, filename);
+        full_path = g_file_get_path (location);
+
+        gdk_pixbuf_save (pixbuf, full_path, extension, NULL, NULL);
+    }
+
+    g_object_unref (pixbuf);
+    gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static GtkWidget *
+make_paste_filename_dialog (GtkWindow *window)
+{
+    GtkWidget *dialog;
+    GtkWidget *content_area;
+    GtkWidget *entry;
+    GtkDialogFlags flags;
+    const char * const file_types[] = {"png", "jpeg", "bmp", NULL};
+    GtkWidget *drop_down = gtk_drop_down_new_from_strings (file_types);
+
+    gtk_widget_set_margin_top (drop_down, 12);
+    gtk_widget_set_margin_bottom (drop_down, 12);
+    gtk_widget_set_margin_start (drop_down, 12);
+    gtk_widget_set_margin_end (drop_down, 12);
+
+    flags = GTK_DIALOG_USE_HEADER_BAR | GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
+
+    dialog = gtk_dialog_new_with_buttons (_("New Image from Clipboard"),
+                                          window,
+                                          flags,
+                                          _("_OK"),
+                                          GTK_RESPONSE_ACCEPT,
+                                          _("Cancel"),
+                                          GTK_RESPONSE_CANCEL,
+                                          NULL);
+
+    gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+    entry = gtk_entry_new ();
+
+    gtk_widget_set_margin_top (entry, 12);
+    gtk_widget_set_margin_bottom (entry, 12);
+    gtk_widget_set_margin_start (entry, 12);
+    gtk_widget_set_margin_end (entry, 12);
+
+    gtk_entry_set_placeholder_text (GTK_ENTRY (entry), _("Enter desired filename for pasted image"));
+
+    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+    gtk_box_append (GTK_BOX (content_area), entry);
+    gtk_box_append (GTK_BOX (content_area), drop_down);
+    gtk_orientable_set_orientation (GTK_ORIENTABLE (content_area), GTK_ORIENTATION_HORIZONTAL);
+
+    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+
+    return dialog;
+}
+
 static void
 paste_value_received_callback (GObject      *source_object,
                                GAsyncResult *result,
@@ -2752,6 +2832,14 @@ paste_value_received_callback (GObject      *source_object,
         }
         handle_clipboard_data (data->view, clip, data->dest_uri, data->action);
     }
+    else if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
+    {
+        GdkPixbuf *pixbuf = gdk_pixbuf_copy (g_value_get_object (value));
+        GtkWidget *dialog = make_paste_filename_dialog (nautilus_files_view_get_containing_window 
(data->view));
+        gtk_widget_show (dialog);
+        g_object_set_data_full (G_OBJECT (dialog), "dest_uri", g_strdup (data->dest_uri), (GDestroyNotify) 
g_free);
+        g_signal_connect (dialog, "response", G_CALLBACK (on_paste_dialog_response), pixbuf);
+    }
     else  if (G_VALUE_HOLDS (value, G_TYPE_FILE))
     {
         g_autofree char *view_uri = NULL;
@@ -2796,6 +2884,10 @@ 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))
+    {
+        gdk_clipboard_read_value_async (clipboard, GDK_TYPE_PIXBUF, 0, priv->clipboard_cancellable, 
paste_value_received_callback, data);
+    }
 }
 
 static void
@@ -7216,7 +7308,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]