[nautilus/wip/corey/rework-clipboard] files-view: Allow pasting GDK_TYPE_TEXTURE
- From: Corey Berla <coreyberla src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus/wip/corey/rework-clipboard] files-view: Allow pasting GDK_TYPE_TEXTURE
- Date: Wed, 28 Sep 2022 23:58:20 +0000 (UTC)
commit cb4a78421c3bd78c77338a11e6a67b7cc8a03a9e
Author: Corey Berla <corey berla me>
Date: Tue Sep 20 15:18:13 2022 -0700
files-view: Allow pasting GDK_TYPE_TEXTURE
Allow pasting raw images from the clipboard to a file within
Nautilus. We just get the raw data, so generate a filename
automatically. Just as with other copy operations, the select
the file after creation.
src/nautilus-file-operations.c | 155 +++++++++++++++++++++++++++++++++++++++++
src/nautilus-file-operations.h | 7 ++
src/nautilus-files-view.c | 14 +++-
3 files changed, 174 insertions(+), 2 deletions(-)
---
diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c
index aa8bd29f3..53224c03e 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;
+ GdkTexture *texture;
+ NautilusCopyCallback done_callback;
+ gpointer done_callback_data;
+} PasteImageJob;
+
static void
source_info_clear (SourceInfo *source_info)
{
@@ -8026,6 +8037,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;
+ g_autoptr (GBytes) bytes = 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;
+ }
+ }
+
+ bytes = gdk_texture_save_to_png_bytes (job->texture);
+ 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), 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_object (&job->texture);
+
+ 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 (GError) clipboard_error = NULL;
+
+ if (job_aborted ((CommonJob *) job))
+ {
+ paste_image_task_done (NULL, NULL, job);
+ return;
+ }
+
+ job->texture = gdk_clipboard_read_texture_finish (clipboard, res, &clipboard_error);
+ if (clipboard_error != NULL)
+ {
+ paste_image_task_done (NULL, NULL, job);
+ return;
+ }
+
+ 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->texture = 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 e110534e3..cc3a1f4a8 100644
--- a/src/nautilus-files-view.c
+++ b/src/nautilus-files-view.c
@@ -353,7 +353,7 @@ static void set_search_query_internal (NautilusFilesView *files_view,
static gboolean nautilus_files_view_is_read_only (NautilusFilesView *view);
static void nautilus_files_view_set_selection (NautilusView *nautilus_files_view,
- GList *selection);
+ GList *selection);
static void copy_move_done_callback (GHashTable *debuting_files,
gboolean success,
gpointer data);
@@ -2807,6 +2807,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_TEXTURE))
+ {
+ nautilus_file_operations_paste_image_from_clipboard (GTK_WIDGET (view),
+ NULL,
+ data->dest_uri,
+ copy_move_done_callback,
+ pre_copy_move (view));
+ paste_callback_data_free (data);
+ }
}
static void
@@ -7217,7 +7226,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_TEXTURE);
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]