[gthumb] load the original image when copying to the clipboard and saving



commit 05ec784908c00b861706df2dbc6438c10a93bf06
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Thu Oct 10 17:44:28 2013 +0200

    load the original image when copying to the clipboard and saving

 extensions/image_viewer/gth-image-viewer-page.c |   90 +++++-----
 gthumb/Makefile.am                              |    2 +
 gthumb/gth-image-task-chain.c                   |  209 +++++++++++++++++++++++
 gthumb/gth-image-task-chain.h                   |   57 ++++++
 gthumb/gth-image-task.c                         |    4 -
 gthumb/gth-save-image-task.c                    |   15 +-
 gthumb/gth-save-image-task.h                    |    6 +-
 7 files changed, 325 insertions(+), 58 deletions(-)
---
diff --git a/extensions/image_viewer/gth-image-viewer-page.c b/extensions/image_viewer/gth-image-viewer-page.c
index 3b0c72c..6602bac 100644
--- a/extensions/image_viewer/gth-image-viewer-page.c
+++ b/extensions/image_viewer/gth-image-viewer-page.c
@@ -1248,7 +1248,6 @@ _gth_image_viewer_page_real_save (GthViewerPage *base,
        GthImageViewerPage *self;
        SaveData           *data;
        GthFileData        *current_file;
-       GthImage           *image;
        GthTask            *task;
 
        self = (GthImageViewerPage *) base;
@@ -1288,8 +1287,10 @@ _gth_image_viewer_page_real_save (GthViewerPage *base,
         * wants to save (see load_file_delayed_cb in gth-browser.c). */
        g_file_info_set_attribute_boolean (data->file_to_save->info, "gth::file::is-modified", FALSE);
 
-       image = gth_image_new_for_surface (gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER 
(self->priv->viewer)));
-       task = gth_save_image_task_new (image, mime_type, data->file_to_save, GTH_OVERWRITE_RESPONSE_YES);
+       task = gth_image_task_chain_new (_("Saving"),
+                                        gth_original_image_task_new (self),
+                                        gth_save_image_task_new (NULL, mime_type, data->file_to_save, 
GTH_OVERWRITE_RESPONSE_YES),
+                                        NULL);
        g_signal_connect (task,
                          "completed",
                          G_CALLBACK (save_image_task_completed_cb),
@@ -1297,7 +1298,6 @@ _gth_image_viewer_page_real_save (GthViewerPage *base,
        gth_browser_exec_task (GTH_BROWSER (self->priv->browser), task, FALSE);
 
        _g_object_unref (task);
-       _g_object_unref (image);
 }
 
 
@@ -1698,22 +1698,45 @@ gth_image_viewer_page_get_is_modified (GthImageViewerPage *self)
 }
 
 
-void
-gth_image_viewer_page_copy_image (GthImageViewerPage *self)
+/* -- gth_image_viewer_page_copy_image -- */
+
+
+static void
+copy_image_original_image_ready_cb (GthTask  *task,
+                                   GError   *error,
+                                   gpointer  user_data)
 {
-       cairo_surface_t *image;
-       GtkClipboard    *clipboard;
-       GdkPixbuf       *pixbuf;
+       GthImageViewerPage *self = user_data;
+       cairo_surface_t    *image;
 
-       image = gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (self->priv->viewer));
-       if (image == NULL)
-               return;
+       image = gth_original_image_task_get_image (task);
+       if (image != NULL) {
+               GtkClipboard *clipboard;
+               GdkPixbuf    *pixbuf;
 
-       clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (self->priv->viewer), 
GDK_SELECTION_CLIPBOARD);
-       pixbuf = _gdk_pixbuf_new_from_cairo_surface (image);
-       gtk_clipboard_set_image (clipboard, pixbuf);
+               clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (self->priv->viewer), 
GDK_SELECTION_CLIPBOARD);
+               pixbuf = _gdk_pixbuf_new_from_cairo_surface (image);
+               gtk_clipboard_set_image (clipboard, pixbuf);
 
-       g_object_unref (pixbuf);
+               g_object_unref (pixbuf);
+       }
+
+       cairo_surface_destroy (image);
+       g_object_unref (task);
+}
+
+
+void
+gth_image_viewer_page_copy_image (GthImageViewerPage *self)
+{
+       GthTask *task;
+
+       task = gth_original_image_task_new (self);
+       g_signal_connect (task,
+                         "completed",
+                         G_CALLBACK (copy_image_original_image_ready_cb),
+                         self);
+       gth_browser_exec_task (self->priv->browser, task, FALSE);
 }
 
 
@@ -1869,19 +1892,17 @@ typedef struct _GthOriginalImageTaskClass   GthOriginalImageTaskClass;
 
 
 struct _GthOriginalImageTask {
-       GthTask __parent;
-
-       GthImageViewerPage      *viewer_page;
-       cairo_surface_t         *image;
+       GthImageTask __parent;
+       GthImageViewerPage *viewer_page;
 };
 
 
 struct _GthOriginalImageTaskClass {
-       GthTaskClass __parent;
+       GthImageTaskClass __parent;
 };
 
 
-G_DEFINE_TYPE (GthOriginalImageTask, gth_original_image_task, GTH_TYPE_TASK)
+G_DEFINE_TYPE (GthOriginalImageTask, gth_original_image_task, GTH_TYPE_IMAGE_TASK)
 
 
 static void
@@ -1890,14 +1911,17 @@ get_original_image_ready_cb (GObject            *source_object,
                            gpointer             user_data)
 {
        GthOriginalImageTask *self = user_data;
+       cairo_surface_t      *image = NULL;
        GError               *error = NULL;
 
        gth_image_viewer_page_get_original_finish (self->viewer_page,
                                                   result,
-                                                  &self->image,
+                                                  &image,
                                                   &error);
+       gth_image_task_set_destination_surface (GTH_IMAGE_TASK (self), image);
        gth_task_completed (GTH_TASK (self), error);
 
+       cairo_surface_destroy (image);
        _g_error_free (error);
 }
 
@@ -1916,26 +1940,10 @@ gth_original_image_task_exec (GthTask *base)
 
 
 static void
-gth_original_image_task_finalize (GObject *object)
-{
-       GthOriginalImageTask *self;
-
-       self = GTH_ORIGINAL_IMAGE_TASK (object);
-       cairo_surface_destroy (self->image);
-
-       G_OBJECT_CLASS (gth_original_image_task_parent_class)->finalize (object);
-}
-
-
-static void
 gth_original_image_task_class_init (GthOriginalImageTaskClass *class)
 {
-       GObjectClass *object_class;
        GthTaskClass *task_class;
 
-       object_class = G_OBJECT_CLASS (class);
-       object_class->finalize = gth_original_image_task_finalize;
-
        task_class = GTH_TASK_CLASS (class);
        task_class->exec = gth_original_image_task_exec;
 }
@@ -1945,7 +1953,6 @@ static void
 gth_original_image_task_init (GthOriginalImageTask *self)
 {
        self->viewer_page = NULL;
-       self->image = NULL;
 }
 
 
@@ -1964,6 +1971,5 @@ gth_original_image_task_new (GthImageViewerPage *self)
 cairo_surface_t *
 gth_original_image_task_get_image (GthTask *task)
 {
-       GthOriginalImageTask *image_task = GTH_ORIGINAL_IMAGE_TASK (task);
-       return (image_task->image != NULL) ? cairo_surface_reference (image_task->image) : NULL;
+       return gth_image_task_get_destination_surface (GTH_IMAGE_TASK (task));
 }
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index 172514b..7c810e7 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -74,6 +74,7 @@ PUBLIC_HEADER_FILES =                                         \
        gth-image-saver.h                               \
        gth-image-selector.h                            \
        gth-image-task.h                                \
+       gth-image-task-chain.h                          \
        gth-image-utils.h                               \
        gth-image-viewer.h                              \
        gth-image-viewer-tool.h                         \
@@ -210,6 +211,7 @@ gthumb_SOURCES =                                    \
        gth-image-saver.c                               \
        gth-image-selector.c                            \
        gth-image-task.c                                \
+       gth-image-task-chain.c                          \
        gth-image-utils.c                               \
        gth-image-viewer.c                              \
        gth-image-viewer-tool.c                         \
diff --git a/gthumb/gth-image-task-chain.c b/gthumb/gth-image-task-chain.c
new file mode 100644
index 0000000..3c08565
--- /dev/null
+++ b/gthumb/gth-image-task-chain.c
@@ -0,0 +1,209 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include "glib-utils.h"
+#include "gth-image-task.h"
+#include "gth-image-task-chain.h"
+
+
+struct _GthImageTaskChainPrivate {
+       GList   *tasks;
+       GList   *current;
+       gulong   task_completed;
+       gulong   task_progress;
+       gulong   task_dialog;
+
+};
+
+
+G_DEFINE_TYPE (GthImageTaskChain, gth_image_task_chain, GTH_TYPE_TASK)
+
+
+static void
+gth_image_task_chain_finalize (GObject *object)
+{
+       GthImageTaskChain *self;
+
+       g_return_if_fail (GTH_IS_IMAGE_TASK_CHAIN (object));
+
+       self = GTH_IMAGE_TASK_CHAIN (object);
+       _g_object_list_unref (self->priv->tasks);
+
+       G_OBJECT_CLASS (gth_image_task_chain_parent_class)->finalize (object);
+}
+
+
+static void _gth_image_task_chain_exec_current_task (GthImageTaskChain *self);
+
+
+static void
+image_task_completed_cb (GthTask  *task,
+                        GError   *error,
+                        gpointer  user_data)
+{
+       GthImageTaskChain *self = user_data;
+
+       g_signal_handler_disconnect (task, self->priv->task_completed);
+       g_signal_handler_disconnect (task, self->priv->task_progress);
+       g_signal_handler_disconnect (task, self->priv->task_dialog);
+
+       if (error != NULL) {
+               gth_task_completed (GTH_TASK (self), error);
+               return;
+       }
+
+       self->priv->current = self->priv->current->next;
+       _gth_image_task_chain_exec_current_task (self);
+}
+
+
+static void
+image_task_progress_cb (GthTask    *task,
+                       const char *description,
+                       const char *details,
+                       gboolean    pulse,
+                       double      fraction,
+                       gpointer    user_data)
+{
+       GthImageTaskChain *self = user_data;
+
+       gth_task_progress (GTH_TASK (self),
+                          NULL,
+                          description,
+                          pulse,
+                          fraction);
+}
+
+
+static void
+image_task_dialog_cb (GthTask   *task,
+                     gboolean   opened,
+                     GtkWidget *dialog,
+                     gpointer   user_data)
+{
+       gth_task_dialog (GTH_TASK (user_data), opened, dialog);
+}
+
+
+static void
+_gth_image_task_chain_exec_current_task (GthImageTaskChain *self)
+{
+       GthTask *task;
+
+       if (self->priv->current == NULL) {
+               gth_task_completed (GTH_TASK (self), NULL);
+               return;
+       }
+
+       task = (GthTask *) self->priv->current->data;
+       self->priv->task_completed =
+                       g_signal_connect (task,
+                                         "completed",
+                                         G_CALLBACK (image_task_completed_cb),
+                                         self);
+       self->priv->task_progress =
+                       g_signal_connect (task,
+                                         "progress",
+                                         G_CALLBACK (image_task_progress_cb),
+                                         self);
+       self->priv->task_dialog =
+                       g_signal_connect (task,
+                                         "dialog",
+                                         G_CALLBACK (image_task_dialog_cb),
+                                         self);
+
+       if (self->priv->current != self->priv->tasks) {
+               GthTask  *previous_task;
+               GthImage *image;
+
+               previous_task = (GthTask *) self->priv->current->prev->data;
+               image = gth_image_task_get_destination (GTH_IMAGE_TASK (previous_task));
+               gth_image_task_set_source (GTH_IMAGE_TASK (task), image);
+       }
+
+       gth_task_exec (task, gth_task_get_cancellable (GTH_TASK (self)));
+}
+
+
+static void
+gth_image_task_chain_exec (GthTask *task)
+{
+       GthImageTaskChain *self;
+
+       g_return_if_fail (GTH_IS_IMAGE_TASK_CHAIN (task));
+
+       self = GTH_IMAGE_TASK_CHAIN (task);
+
+       self->priv->current = self->priv->tasks;
+       _gth_image_task_chain_exec_current_task (self);
+}
+
+
+static void
+gth_image_task_chain_class_init (GthImageTaskChainClass *klass)
+{
+       GObjectClass *object_class;
+       GthTaskClass *task_class;
+
+       g_type_class_add_private (klass, sizeof (GthImageTaskChainPrivate));
+
+       object_class = G_OBJECT_CLASS (klass);
+       object_class->finalize = gth_image_task_chain_finalize;
+
+       task_class = GTH_TASK_CLASS (klass);
+       task_class->exec = gth_image_task_chain_exec;
+}
+
+
+static void
+gth_image_task_chain_init (GthImageTaskChain *self)
+{
+       self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_IMAGE_TASK_CHAIN, GthImageTaskChainPrivate);
+       self->priv->tasks = NULL;
+       self->priv->task_completed = 0;
+       self->priv->task_dialog = 0;
+       self->priv->task_progress = 0;
+}
+
+
+GthTask *
+gth_image_task_chain_new (const char *description,
+                         GthTask    *task,
+                         ...)
+{
+       GthImageTaskChain *self;
+       va_list            args;
+
+       self = (GthImageTaskChain *) g_object_new (GTH_TYPE_IMAGE_TASK_CHAIN,
+                                                  "description", description,
+                                                  NULL);
+
+       va_start (args, task);
+       while (task != NULL) {
+               self->priv->tasks = g_list_prepend (self->priv->tasks, task);
+               task = va_arg (args, GthTask *);
+       }
+       va_end (args);
+       self->priv->tasks = g_list_reverse (self->priv->tasks);
+
+       return (GthTask *) self;
+}
diff --git a/gthumb/gth-image-task-chain.h b/gthumb/gth-image-task-chain.h
new file mode 100644
index 0000000..d789141
--- /dev/null
+++ b/gthumb/gth-image-task-chain.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2013 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_IMAGE_TASK_CHAIN_H
+#define GTH_IMAGE_TASK_CHAIN_H
+
+#include <glib.h>
+#include "gth-task.h"
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_IMAGE_TASK_CHAIN            (gth_image_task_chain_get_type ())
+#define GTH_IMAGE_TASK_CHAIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_IMAGE_TASK_CHAIN, 
GthImageTaskChain))
+#define GTH_IMAGE_TASK_CHAIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_IMAGE_TASK_CHAIN, 
GthImageTaskChainClass))
+#define GTH_IS_IMAGE_TASK_CHAIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_IMAGE_TASK_CHAIN))
+#define GTH_IS_IMAGE_TASK_CHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_IMAGE_TASK_CHAIN))
+#define GTH_IMAGE_TASK_CHAIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_IMAGE_TASK_CHAIN, 
GthImageTaskChainClass))
+
+typedef struct _GthImageTaskChain        GthImageTaskChain;
+typedef struct _GthImageTaskChainClass   GthImageTaskChainClass;
+typedef struct _GthImageTaskChainPrivate GthImageTaskChainPrivate;
+
+struct _GthImageTaskChain {
+       GthTask __parent;
+       GthImageTaskChainPrivate *priv;
+};
+
+struct _GthImageTaskChainClass {
+       GthTaskClass __parent;
+};
+
+GType          gth_image_task_chain_get_type   (void);
+GthTask *      gth_image_task_chain_new        (const char     *description,
+                                                GthTask        *task,
+                                                ...) G_GNUC_NULL_TERMINATED;
+
+G_END_DECLS
+
+#endif /* GTH_IMAGE_TASK_CHAIN_H */
diff --git a/gthumb/gth-image-task.c b/gthumb/gth-image-task.c
index 922d347..880c009 100644
--- a/gthumb/gth-image-task.c
+++ b/gthumb/gth-image-task.c
@@ -96,8 +96,6 @@ void
 gth_image_task_set_source (GthImageTask *self,
                           GthImage     *source)
 {
-       g_return_if_fail (GTH_IS_IMAGE (source));
-
        _g_object_ref (source);
        _g_object_unref (self->priv->source);
        self->priv->source = source;
@@ -135,8 +133,6 @@ void
 gth_image_task_set_destination (GthImageTask *self,
                                GthImage     *destination)
 {
-       g_return_if_fail (GTH_IS_IMAGE (destination));
-
        _g_object_ref (destination);
        _g_object_unref (self->priv->destination);
        self->priv->destination = destination;
diff --git a/gthumb/gth-save-image-task.c b/gthumb/gth-save-image-task.c
index 6edffc7..4e5c54c 100644
--- a/gthumb/gth-save-image-task.c
+++ b/gthumb/gth-save-image-task.c
@@ -3,7 +3,7 @@
 /*
  *  GThumb
  *
- *  Copyright (C) 2012 Free Software Foundation, Inc.
+ *  Copyright (C) 2012, 2013 Free Software Foundation, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -27,14 +27,13 @@
 
 
 struct _GthSaveImageTaskPrivate {
-       GthImage             *image;
        char                 *mime_type;
        GthFileData          *file_data;
        GthOverwriteResponse  overwrite_mode;
 };
 
 
-G_DEFINE_TYPE (GthSaveImageTask, gth_save_image_task, GTH_TYPE_TASK)
+G_DEFINE_TYPE (GthSaveImageTask, gth_save_image_task, GTH_TYPE_IMAGE_TASK)
 
 
 static void
@@ -44,7 +43,6 @@ gth_save_image_task_finalize (GObject *object)
 
        self = GTH_SAVE_IMAGE_TASK (object);
 
-       _g_object_unref (self->priv->image);
        g_free (self->priv->mime_type);
        _g_object_unref (self->priv->file_data);
 
@@ -127,7 +125,7 @@ save_to_file_ready_cb (GthFileData *file_data,
                        GtkWidget *d;
 
                        d = gth_overwrite_dialog_new (NULL,
-                                                     self->priv->image,
+                                                     gth_image_task_get_source (GTH_IMAGE_TASK (self)),
                                                      self->priv->file_data->file,
                                                      self->priv->overwrite_mode,
                                                      TRUE);
@@ -160,7 +158,7 @@ save_image (GthSaveImageTask *self)
        description = g_strdup_printf (_("Saving '%s'"), filename);
        gth_task_progress (GTH_TASK (self), description, NULL, TRUE, 0.0);
 
-       gth_image_save_to_file (self->priv->image,
+       gth_image_save_to_file (gth_image_task_get_source (GTH_IMAGE_TASK (self)),
                                self->priv->mime_type,
                                self->priv->file_data,
                                ((self->priv->overwrite_mode == GTH_OVERWRITE_RESPONSE_YES)
@@ -177,6 +175,7 @@ save_image (GthSaveImageTask *self)
 static void
 gth_save_image_task_exec (GthTask *task)
 {
+       gth_image_task_set_destination (GTH_IMAGE_TASK (task), gth_image_task_get_source (GTH_IMAGE_TASK 
(task)));
        save_image (GTH_SAVE_IMAGE_TASK (task));
 }
 
@@ -201,7 +200,6 @@ static void
 gth_save_image_task_init (GthSaveImageTask *self)
 {
        self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_SAVE_IMAGE_TASK, GthSaveImageTaskPrivate);
-       self->priv->image = NULL;
        self->priv->mime_type = NULL;
        self->priv->file_data = NULL;
 }
@@ -215,14 +213,13 @@ gth_save_image_task_new (GthImage             *image,
 {
        GthSaveImageTask *self;
 
-       g_return_val_if_fail (image != NULL, NULL);
        g_return_val_if_fail (file_data != NULL, NULL);
 
        self = (GthSaveImageTask *) g_object_new (GTH_TYPE_SAVE_IMAGE_TASK, NULL);
-       self->priv->image = g_object_ref (image);
        self->priv->mime_type = g_strdup (mime_type);
        self->priv->file_data = gth_file_data_dup (file_data);
        self->priv->overwrite_mode = overwrite_mode;
+       gth_image_task_set_source (GTH_IMAGE_TASK (self), image);
 
        return (GthTask *) self;
 }
diff --git a/gthumb/gth-save-image-task.h b/gthumb/gth-save-image-task.h
index ca3caa2..02a6f57 100644
--- a/gthumb/gth-save-image-task.h
+++ b/gthumb/gth-save-image-task.h
@@ -24,8 +24,8 @@
 
 #include <glib.h>
 #include "gth-image.h"
+#include "gth-image-task.h"
 #include "gth-overwrite-dialog.h"
-#include "gth-task.h"
 
 G_BEGIN_DECLS
 
@@ -41,12 +41,12 @@ typedef struct _GthSaveImageTaskClass   GthSaveImageTaskClass;
 typedef struct _GthSaveImageTaskPrivate GthSaveImageTaskPrivate;
 
 struct _GthSaveImageTask {
-       GthTask __parent;
+       GthImageTask __parent;
        GthSaveImageTaskPrivate *priv;
 };
 
 struct _GthSaveImageTaskClass {
-       GthTaskClass __parent;
+       GthImageTaskClass __parent;
 };
 
 GType       gth_save_image_task_get_type   (void);


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