summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nautilus-file-operations.c155
-rw-r--r--src/nautilus-file-operations.h7
-rw-r--r--src/nautilus-files-view.c20
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");