[eog] Refactored eog jobs system.



commit e5c7e101621e19e908a834ae33480c72365bd361
Author: Javier Sánchez <jsanchez deskblue com>
Date:   Fri Feb 15 20:17:28 2013 +0100

    Refactored eog jobs system.

 src/Makefile.am                              |    4 +-
 src/eog-debug.h                              |    2 +
 src/eog-image.c                              |    6 +-
 src/eog-job-queue.c                          |  234 -----
 src/eog-job-scheduler.c                      |  187 ++++
 src/{eog-job-queue.h => eog-job-scheduler.h} |   33 +-
 src/eog-jobs.c                               | 1341 ++++++++++++++++----------
 src/eog-jobs.h                               |  341 ++++---
 src/eog-list-store.c                         |    6 +-
 src/eog-thumb-view.c                         |    4 +-
 src/eog-window.c                             |   26 +-
 src/main.c                                   |    4 +-
 12 files changed, 1247 insertions(+), 941 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 3ce66c2..815c29c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -48,7 +48,7 @@ INST_H_FILES =                                \
        eog-file-chooser.h              \
        eog-image.h                     \
        eog-image-save-info.h           \
-       eog-job-queue.h                 \
+       eog-job-scheduler.h             \
        eog-jobs.h                      \
        eog-list-store.h                \
        eog-properties-dialog.h         \
@@ -74,7 +74,7 @@ libeog_c_files =                      \
        eog-image.c                     \
        eog-image-jpeg.c                \
        eog-image-save-info.c           \
-       eog-job-queue.c                 \
+       eog-job-scheduler.c             \
        eog-jobs.c                      \
        eog-list-store.c                \
        eog-metadata-sidebar.c          \
diff --git a/src/eog-debug.h b/src/eog-debug.h
index 1d06480..c9bd93e 100644
--- a/src/eog-debug.h
+++ b/src/eog-debug.h
@@ -30,6 +30,8 @@
 
 #include <glib.h>
 
+#define EOG_GET_TYPE_NAME(instance) g_type_name_from_instance ((gpointer)instance)
+
 typedef enum {
        EOG_DEBUG_NO_DEBUG     = 0,
        EOG_DEBUG_WINDOW       = 1 << 0,
diff --git a/src/eog-image.c b/src/eog-image.c
index 4ce2e60..24791b5 100644
--- a/src/eog-image.c
+++ b/src/eog-image.c
@@ -1088,7 +1088,11 @@ eog_image_real_load (EogImage *img,
 
                bytes_read_total += bytes_read;
 
-               if (job != NULL) {
+               /* check that load job wasn't cancelled */
+               if (eog_job_is_cancelled (job)) {
+                       eog_image_cancel_load (img);
+                       continue;
+               } else {
                        float progress = (float) bytes_read_total / (float) priv->bytes;
                        eog_job_set_progress (job, progress);
                }
diff --git a/src/eog-job-scheduler.c b/src/eog-job-scheduler.c
new file mode 100644
index 0000000..9e6c7a9
--- /dev/null
+++ b/src/eog-job-scheduler.c
@@ -0,0 +1,187 @@
+/* Eye Of Gnome - Jobs scheduler
+ *
+ * Copyright (C) 2013 The Free Software Foundation
+ *
+ * Author: Javier Sánchez <jsanchez deskblue com>
+ *
+ * Based on code (ev-job-scheduler.h) by:
+ *      - Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "eog-job-scheduler.h"
+#include "eog-jobs.h"
+
+#include "eog-debug.h"
+
+/* sync thread tools */
+static GCond  job_queue_cond;
+static GMutex job_queue_mutex;
+
+/* priority queues */
+static GQueue queue_high   = G_QUEUE_INIT;
+static GQueue queue_medium = G_QUEUE_INIT;
+static GQueue queue_low    = G_QUEUE_INIT;
+
+static GQueue *job_queue[EOG_JOB_N_PRIORITIES] = {
+       &queue_high,
+       &queue_medium,
+       &queue_low
+};
+
+static void      eog_job_scheduler_enqueue_job (EogJob         *job,
+                                               EogJobPriority  priority);
+static EogJob   *eog_job_scheduler_dequeue_job (void);
+static gpointer  eog_job_scheduler             (gpointer        data);
+static void      eog_job_process               (EogJob         *job);
+
+
+static void
+eog_job_scheduler_enqueue_job (EogJob         *job,
+                              EogJobPriority  priority)
+{
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "ENQUEUED %s (%p) with priority %d",
+                          EOG_GET_TYPE_NAME (job),
+                          job,
+                          priority);
+
+       /* --- enter critical section --- */
+       g_mutex_lock (&job_queue_mutex);
+
+       g_queue_push_tail (job_queue[priority], job);
+       g_cond_broadcast  (&job_queue_cond);
+
+       /* --- leave critical section --- */
+       g_mutex_unlock (&job_queue_mutex);
+}
+
+static EogJob *
+eog_job_scheduler_dequeue_job (void)
+{
+       EogJob *job;
+       gint    priority;
+
+       /* initialization */
+       job = NULL;
+
+       while (!job) {
+               /* --- enter critical section --- */
+               g_mutex_lock (&job_queue_mutex);
+
+               /* try to retrieve the next job from priority queue */
+               for (priority = EOG_JOB_PRIORITY_HIGH; priority < EOG_JOB_N_PRIORITIES; priority++) {
+                       job = (EogJob *) g_queue_pop_head (job_queue[priority]);
+
+                       if (job)
+                               break;
+               }
+
+               /* show info for debugging */
+               eog_debug_message (DEBUG_JOBS,
+                                  (job ? "DEQUEUED %s (%p)" : "No jobs in queue"),
+                                  EOG_GET_TYPE_NAME (job),
+                                  job);
+
+               /* if there is no job, wait for it */
+               if (!job) {
+                       eog_debug_message (DEBUG_JOBS,
+                                          "Wating for jobs ...");
+
+                       g_cond_wait    (&job_queue_cond,
+                                       &job_queue_mutex);
+                       g_mutex_unlock (&job_queue_mutex);
+                       continue;
+               }
+
+               /* --- leave critical section --- */
+               g_mutex_unlock (&job_queue_mutex);
+       }
+
+       return job;
+}
+
+static gpointer
+eog_job_scheduler (gpointer data)
+{
+       EogJob *job;
+
+       while (TRUE) {
+               /* retrieve the next job */
+               job = eog_job_scheduler_dequeue_job ();
+
+               /* execute the job */
+               eog_job_process (job);
+
+               /* free executed job */
+               g_object_unref  (job);
+       }
+
+       return NULL;
+}
+
+static void
+eog_job_process (EogJob *job)
+{
+       g_return_if_fail (EOG_IS_JOB (job));
+
+       /* nothing to do if job was cancelled */
+       if (eog_job_is_cancelled (job))
+               return;
+
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "PROCESSING a %s (%p)",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
+
+       /* process the current job */
+       eog_job_run (job);
+}
+
+void
+eog_job_scheduler_init ()
+{
+       g_thread_new ("EogJobScheduler",
+                     eog_job_scheduler,
+                     NULL);
+}
+
+void
+eog_job_scheduler_add_job (EogJob *job)
+{
+       g_return_if_fail (EOG_IS_JOB (job));
+
+       /* make sure the job isn't destroyed */
+       g_object_ref (job);
+
+       /* enqueue the job */
+       eog_job_scheduler_enqueue_job (job, EOG_JOB_PRIORITY_LOW);
+}
+
+void
+eog_job_scheduler_add_job_with_priority (EogJob         *job,
+                                        EogJobPriority  priority)
+{
+       g_return_if_fail (EOG_IS_JOB (job));
+
+       /* make sure the job isn't destroyed */
+       g_object_ref (job);
+
+       /* enqueue the job */
+       eog_job_scheduler_enqueue_job (job, priority);
+}
diff --git a/src/eog-job-queue.h b/src/eog-job-scheduler.h
similarity index 51%
rename from src/eog-job-queue.h
rename to src/eog-job-scheduler.h
index 2bed060..872bdc6 100644
--- a/src/eog-job-queue.h
+++ b/src/eog-job-scheduler.h
@@ -1,11 +1,11 @@
-/* Eye Of Gnome - Jobs Queue
+/* Eye Of Gnome - Jobs scheduler
  *
- * Copyright (C) 2006 The Free Software Foundation
+ * Copyright (C) 2013 The Free Software Foundation
  *
- * Author: Lucas Rocha <lucasr gnome org>
+ * Author: Javier Sánchez <jsanchez deskblue com>
  *
- * Based on evince code (shell/ev-job-queue.h) by:
- *     - Martin Kretzschmar <martink gnome org>
+ * Based on code (ev-job-scheduler.h) by:
+ *      - Carlos Garcia Campos <carlosgc gnome org>
  *
  * 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
@@ -22,21 +22,28 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#ifndef __EOG_JOB_QUEUE_H__
-#define __EOG_JOB_QUEUE_H__
+#ifndef __EOG_JOB_SCHEDULER_H__
+#define __EOG_JOB_SCHEDULER_H__
 
 #include "eog-jobs.h"
 
-#include <gtk/gtk.h>
-
 G_BEGIN_DECLS
 
-void     eog_job_queue_init       (void);
+typedef enum {
+       EOG_JOB_PRIORITY_HIGH,
+       EOG_JOB_PRIORITY_MEDIUM,
+       EOG_JOB_PRIORITY_LOW,
+       EOG_JOB_N_PRIORITIES
+} EogJobPriority;
 
-void     eog_job_queue_add_job    (EogJob    *job);
+/* initialization */
+void eog_job_scheduler_init                  (void);
 
-gboolean eog_job_queue_remove_job (EogJob    *job);
+/* jobs management */
+void eog_job_scheduler_add_job               (EogJob         *job);
+void eog_job_scheduler_add_job_with_priority (EogJob         *job,
+                                             EogJobPriority  priority);
 
 G_END_DECLS
 
-#endif /* __EOG_JOB_QUEUE_H__ */
+#endif /* __EOG_JOB_SCHEDULER_H__ */
diff --git a/src/eog-jobs.c b/src/eog-jobs.c
index 7bae56a..3866b15 100644
--- a/src/eog-jobs.c
+++ b/src/eog-jobs.c
@@ -1,11 +1,11 @@
 /* Eye Of Gnome - Jobs
  *
- * Copyright (C) 2006 The Free Software Foundation
+ * Copyright (C) 2013 The Free Software Foundation
  *
- * Author: Lucas Rocha <lucasr gnome org>
+ * Author: Javier Sánchez <jsanchez deskblue com>
  *
- * Based on evince code (shell/ev-jobs.c) by:
- *     - Martin Kretzschmar <martink gnome org>
+ * Based on code (libview/ev-jobs.h) by:
+ *      - Carlos Garcia Campos <carlosgc gnome org>
  *
  * 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
@@ -22,61 +22,219 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include "eog-uri-converter.h"
+#include "eog-debug.h"
 #include "eog-jobs.h"
-#include "eog-job-queue.h"
-#include "eog-image.h"
-#include "eog-transform.h"
-#include "eog-list-store.h"
 #include "eog-thumbnail.h"
 #include "eog-pixbuf-util.h"
 
-#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gio/gio.h>
 
-#define EOG_JOB_GET_PRIVATE(object) \
-       (G_TYPE_INSTANCE_GET_PRIVATE ((object), EOG_TYPE_JOB, EogJobPrivate))
-
-G_DEFINE_TYPE (EogJob, eog_job, G_TYPE_OBJECT);
+G_DEFINE_ABSTRACT_TYPE (EogJob, eog_job, G_TYPE_OBJECT);
+G_DEFINE_TYPE (EogJobCopy,      eog_job_copy,      EOG_TYPE_JOB);
+G_DEFINE_TYPE (EogJobLoad,      eog_job_load,      EOG_TYPE_JOB);
+G_DEFINE_TYPE (EogJobModel,     eog_job_model,     EOG_TYPE_JOB);
+G_DEFINE_TYPE (EogJobSave,      eog_job_save,      EOG_TYPE_JOB);
+G_DEFINE_TYPE (EogJobSaveAs,    eog_job_save_as,   EOG_TYPE_JOB_SAVE);
 G_DEFINE_TYPE (EogJobThumbnail, eog_job_thumbnail, EOG_TYPE_JOB);
-G_DEFINE_TYPE (EogJobLoad, eog_job_load, EOG_TYPE_JOB);
-G_DEFINE_TYPE (EogJobModel, eog_job_model, EOG_TYPE_JOB);
 G_DEFINE_TYPE (EogJobTransform, eog_job_transform, EOG_TYPE_JOB);
-G_DEFINE_TYPE (EogJobSave, eog_job_save, EOG_TYPE_JOB);
-G_DEFINE_TYPE (EogJobSaveAs, eog_job_save_as, EOG_TYPE_JOB_SAVE);
-G_DEFINE_TYPE (EogJobCopy, eog_job_copy, EOG_TYPE_JOB);
 
-enum
-{
-       SIGNAL_FINISHED,
-       SIGNAL_PROGRESS,
-       SIGNAL_LAST_SIGNAL
+/* signals */
+enum {
+       PROGRESS,
+       CANCELLED,
+       FINISHED,
+       LAST_SIGNAL
 };
 
-static guint job_signals[SIGNAL_LAST_SIGNAL];
+static guint job_signals[LAST_SIGNAL];
+
+/* notify signal funcs */
+static void     notify_progress              (EogJob               *job);
+static void     notify_cancelled             (EogJob               *job);
+static void     notify_finished              (EogJob               *job);
+
+/* gobject vfuncs */
+static void     eog_job_class_init           (EogJobClass          *class);
+static void     eog_job_init                 (EogJob               *job);
+static void     eog_job_dispose              (GObject              *object);
+
+static void     eog_job_copy_class_init      (EogJobCopyClass      *class);
+static void     eog_job_copy_init            (EogJobCopy           *job);
+static void     eog_job_copy_dispose         (GObject              *object);
+
+static void     eog_job_load_class_init      (EogJobLoadClass      *class);
+static void     eog_job_load_init            (EogJobLoad           *job);
+static void     eog_job_load_dispose         (GObject              *object);
+
+static void     eog_job_model_class_init     (EogJobModelClass     *class);
+static void     eog_job_model_init           (EogJobModel          *job);
+static void     eog_job_model_dispose        (GObject              *object);
+
+static void     eog_job_save_class_init      (EogJobSaveClass      *class);
+static void     eog_job_save_init            (EogJobSave           *job);
+static void     eog_job_save_dispose         (GObject              *object);
+
+static void     eog_job_save_as_class_init   (EogJobSaveAsClass    *class);
+static void     eog_job_save_as_init         (EogJobSaveAs         *job);
+static void     eog_job_save_as_dispose      (GObject              *object);
+
+static void     eog_job_thumbnail_class_init (EogJobThumbnailClass *class);
+static void     eog_job_thumbnail_init       (EogJobThumbnail      *job);
+static void     eog_job_thumbnail_dispose    (GObject              *object);
+
+static void     eog_job_transform_class_init (EogJobTransformClass *class);
+static void     eog_job_transform_init       (EogJobTransform      *job);
+static void     eog_job_transform_dispose    (GObject              *object);
+
+/* vfuncs */
+static void     eog_job_run_unimplemented    (EogJob               *job);
+static void     eog_job_copy_run             (EogJob               *job);
+static void     eog_job_load_run             (EogJob               *job);
+static void     eog_job_model_run            (EogJob               *job);
+static void     eog_job_save_run             (EogJob               *job);
+static void     eog_job_save_as_run          (EogJob               *job);
+static void     eog_job_thumbnail_run        (EogJob               *job);
+static void     eog_job_transform_run        (EogJob               *job);
+
+/* callbacks */
+static void eog_job_copy_progress_callback (goffset  current_num_bytes,
+                                           goffset  total_num_bytes,
+                                           gpointer user_data);
+
+static void eog_job_save_progress_callback (EogImage *image,
+                                           gfloat    progress,
+                                           gpointer  data);
+
+/* --------------------------- notify signal funcs --------------------------- */
+static void
+notify_progress (EogJob *job)
+{
+       /* check if the current job was previously cancelled */
+       if (eog_job_is_cancelled (job))
+               return;
+
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "%s (%p) job update its progress to -> %1.2f",
+                          EOG_GET_TYPE_NAME (job),
+                          job,
+                          job->progress);
+
+       /* notify progress */
+       g_signal_emit (job,
+                      job_signals[PROGRESS],
+                      0,
+                      job->progress);
+}
+
+static void
+notify_cancelled (EogJob *job)
+{
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "%s (%p) job was CANCELLED",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
+
+       /* notify cancelation */
+       g_signal_emit (job,
+                      job_signals[CANCELLED],
+                      0);
+}
 
-static void eog_job_copy_run      (EogJob *ejob);
-static void eog_job_load_run     (EogJob *ejob);
-static void eog_job_model_run     (EogJob *ejob);
-static void eog_job_save_run      (EogJob *job);
-static void eog_job_save_as_run   (EogJob *job);
-static void eog_job_thumbnail_run (EogJob *ejob);
-static void eog_job_transform_run (EogJob *ejob);
+static void
+notify_finished (EogJob *job)
+{
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "%s (%p) job was FINISHED",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
+
+       /* notify job finalization */
+       g_signal_emit (job,
+                      job_signals[FINISHED],
+                      0);
+}
 
-static void eog_job_init (EogJob *job)
+/* --------------------------------- EogJob ---------------------------------- */
+static void
+eog_job_class_init (EogJobClass *class)
 {
-       /* NOTE: We need to allocate the mutex here so the ABI stays the same when it used to use g_mutex_new 
*/
+       GObjectClass *g_object_class = (GObjectClass *) class;
+
+       g_object_class->dispose = eog_job_dispose;
+       class->run              = eog_job_run_unimplemented;
+
+       /* signals */
+       job_signals [PROGRESS] =
+               g_signal_new ("progress",
+                             EOG_TYPE_JOB,
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (EogJobClass, progress),
+                             NULL,
+                             NULL,
+                             g_cclosure_marshal_VOID__FLOAT,
+                             G_TYPE_NONE,
+                             1,
+                             G_TYPE_FLOAT);
+
+       job_signals [CANCELLED] =
+               g_signal_new ("cancelled",
+                             EOG_TYPE_JOB,
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (EogJobClass, cancelled),
+                             NULL,
+                             NULL,
+                             g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE,
+                             0);
+
+       job_signals [FINISHED] =
+               g_signal_new ("finished",
+                             EOG_TYPE_JOB,
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (EogJobClass, finished),
+                             NULL,
+                             NULL,
+                             g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE,
+                             0);
+}
+
+static
+void eog_job_init (EogJob *job)
+{
+       /* initialize all public and private members to reasonable
+          default values. */
+       job->cancellable = g_cancellable_new ();
+       job->error       = NULL;
+
+       job->progress    = 0.0;
+       job->cancelled   = FALSE;
+       job->finished    = FALSE;
+
+       /* NOTE: we need to allocate the mutex here so the ABI stays
+          the same when it used to use g_mutex_new */
        job->mutex = g_malloc (sizeof (GMutex));
        g_mutex_init (job->mutex);
-       job->progress = 0.0;
 }
 
-static void
-eog_job_dispose (GObject *object)
+static
+void eog_job_dispose (GObject *object)
 {
        EogJob *job;
 
+       g_return_if_fail (EOG_IS_JOB (object));
+
        job = EOG_JOB (object);
 
+       /* free all public and private members */
+       if (job->cancellable) {
+               g_object_unref (job->cancellable);
+               job->cancellable = NULL;
+       }
+
        if (job->error) {
                g_error_free (job->error);
                job->error = NULL;
@@ -84,283 +242,382 @@ eog_job_dispose (GObject *object)
 
        if (job->mutex) {
                g_mutex_clear (job->mutex);
-               g_free (job->mutex);
+               g_free        (job->mutex);
        }
 
-       (* G_OBJECT_CLASS (eog_job_parent_class)->dispose) (object);
+       /* call parent dispose */
+       G_OBJECT_CLASS (eog_job_parent_class)->dispose (object);
 }
 
 static void
-eog_job_run_default (EogJob *job)
+eog_job_run_unimplemented (EogJob *job)
 {
        g_critical ("Class \"%s\" does not implement the required run action",
                    G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (job)));
 }
 
-static void
-eog_job_class_init (EogJobClass *class)
+void
+eog_job_run (EogJob *job)
 {
-       GObjectClass *oclass;
-
-       oclass = G_OBJECT_CLASS (class);
-
-       oclass->dispose = eog_job_dispose;
-
-       class->run = eog_job_run_default;
+       EogJobClass *class;
 
-       job_signals [SIGNAL_FINISHED] =
-               g_signal_new ("finished",
-                             EOG_TYPE_JOB,
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (EogJobClass, finished),
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__VOID,
-                             G_TYPE_NONE, 0);
+       g_return_if_fail (EOG_IS_JOB (job));
 
-       job_signals [SIGNAL_PROGRESS] =
-               g_signal_new ("progress",
-                             EOG_TYPE_JOB,
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (EogJobClass, progress),
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__FLOAT,
-                             G_TYPE_NONE, 1,
-                             G_TYPE_FLOAT);
+       class = EOG_JOB_GET_CLASS (job);
+       class->run (job);
 }
 
 void
-eog_job_finished (EogJob *job)
+eog_job_cancel (EogJob *job)
 {
        g_return_if_fail (EOG_IS_JOB (job));
 
-       g_signal_emit (job, job_signals[SIGNAL_FINISHED], 0);
-}
+       g_object_ref (job);
 
-/**
- * eog_job_run:
- * @job: the job to execute.
- *
- * Executes the job passed as @job. Usually there is no need to call this
- * on your own. Jobs should be executed by using the EogJobQueue.
- **/
-void
-eog_job_run (EogJob *job)
-{
-       EogJobClass *class;
+       /* check if job was cancelled previously */
+       if (job->cancelled)
+               return;
 
-       g_return_if_fail (EOG_IS_JOB (job));
+       /* check if job finished previously */
+        if (job->finished)
+               return;
 
-       class = EOG_JOB_GET_CLASS (job);
-       if (class->run)
-               class->run (job);
-       else
-               eog_job_run_default (job);
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "CANCELLING a %s (%p)",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
+
+       /* --- enter critical section --- */
+       g_mutex_lock (job->mutex);
+
+       /* cancel job */
+       job->cancelled = TRUE;
+       g_cancellable_cancel (job->cancellable);
+
+       /* --- leave critical section --- */
+       g_mutex_unlock (job->mutex);
+
+       /* notify job cancellation */
+       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+                        (GSourceFunc) notify_cancelled,
+                        job,
+                        g_object_unref);
 }
-static gboolean
-notify_progress (gpointer data)
-{
-       EogJob *job = EOG_JOB (data);
 
-       g_signal_emit (job, job_signals[SIGNAL_PROGRESS], 0, job->progress);
+gfloat
+eog_job_get_progress (EogJob *job)
+{
+       g_return_val_if_fail (EOG_IS_JOB (job), 0.0);
 
-       return FALSE;
+       return job->progress;
 }
 
 void
-eog_job_set_progress (EogJob *job, float progress)
+eog_job_set_progress (EogJob *job,
+                     gfloat  progress)
 {
        g_return_if_fail (EOG_IS_JOB (job));
        g_return_if_fail (progress >= 0.0 && progress <= 1.0);
 
+       /* --- enter critical section --- */
        g_mutex_lock (job->mutex);
+
        job->progress = progress;
+
+       /* --- leave critical section --- */
        g_mutex_unlock (job->mutex);
 
-       g_idle_add (notify_progress, job);
+       /* notify progress */
+       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+                        (GSourceFunc) notify_progress,
+                        job,
+                        NULL);
 }
 
-static void eog_job_thumbnail_init (EogJobThumbnail *job) { /* Do Nothing */ }
-
-static void
-eog_job_thumbnail_dispose (GObject *object)
+gboolean
+eog_job_is_cancelled (EogJob *job)
 {
-       EogJobThumbnail *job;
+       g_return_val_if_fail (EOG_IS_JOB (job), TRUE);
 
-       job = EOG_JOB_THUMBNAIL (object);
-
-       if (job->image) {
-               g_object_unref (job->image);
-               job->image = NULL;
-       }
+       return job->cancelled;
+}
 
-       if (job->thumbnail) {
-               g_object_unref (job->thumbnail);
-               job->thumbnail = NULL;
-       }
+gboolean
+eog_job_is_finished (EogJob *job)
+{
+       g_return_val_if_fail (EOG_IS_JOB (job), TRUE);
 
-       (* G_OBJECT_CLASS (eog_job_thumbnail_parent_class)->dispose) (object);
+       return job->finished;
 }
 
+/* ------------------------------- EogJobCopy -------------------------------- */
 static void
-eog_job_thumbnail_class_init (EogJobThumbnailClass *class)
+eog_job_copy_class_init (EogJobCopyClass *class)
 {
-       GObjectClass *oclass;
+       GObjectClass *g_object_class = (GObjectClass *) class;
+       EogJobClass  *eog_job_class  = (EogJobClass *)  class;
 
-       oclass = G_OBJECT_CLASS (class);
-
-       oclass->dispose = eog_job_thumbnail_dispose;
+       g_object_class->dispose = eog_job_copy_dispose;
+       eog_job_class->run      = eog_job_copy_run;
+}
 
-       EOG_JOB_CLASS (class)->run = eog_job_thumbnail_run;
+static
+void eog_job_copy_init (EogJobCopy *job)
+{
+       /* initialize all public and private members to reasonable
+          default values. */
+       job->images           = NULL;
+       job->destination      = NULL;
+       job->current_position = 0;
 }
 
-EogJob *
-eog_job_thumbnail_new (EogImage *image)
+static
+void eog_job_copy_dispose (GObject *object)
 {
-       EogJobThumbnail *job;
+       EogJobCopy *job;
 
-       job = g_object_new (EOG_TYPE_JOB_THUMBNAIL, NULL);
+       g_return_if_fail (EOG_IS_JOB_COPY (object));
 
-       if (image) {
-               job->image = g_object_ref (image);
+       job = EOG_JOB_COPY (object);
+
+       /* free all public and private members */
+       if (job->images) {
+               g_list_foreach (job->images, (GFunc) g_object_unref, NULL);
+               g_list_free    (job->images);
+               job->images = NULL;
        }
 
-       return EOG_JOB (job);
+       if (job->destination) {
+               g_free (job->destination);
+               job->destination = NULL;
+       }
+
+       /* call parent dispose */
+       G_OBJECT_CLASS (eog_job_copy_parent_class)->dispose (object);
 }
 
 static void
-eog_job_thumbnail_run (EogJob *ejob)
+eog_job_copy_progress_callback (goffset  current_num_bytes,
+                               goffset  total_num_bytes,
+                               gpointer user_data)
 {
-       gchar *orig_width, *orig_height;
-       gint width, height;
-       GdkPixbuf *pixbuf;
-       EogJobThumbnail *job;
+       gfloat      progress;
+       guint       n_images;
+       EogJobCopy *job;
+
+       job = EOG_JOB_COPY (user_data);
 
-       g_return_if_fail (EOG_IS_JOB_THUMBNAIL (ejob));
+       n_images = g_list_length (job->images);
 
-       job = EOG_JOB_THUMBNAIL (ejob);
+       progress = ((current_num_bytes / (gfloat) total_num_bytes) + job->current_position) / n_images;
 
-       if (ejob->error) {
-               g_error_free (ejob->error);
-               ejob->error = NULL;
-       }
+       eog_job_set_progress (EOG_JOB (job), progress);
+}
 
-       job->thumbnail = eog_thumbnail_load (job->image,
-                                            &ejob->error);
+static void
+eog_job_copy_run (EogJob *job)
+{
+       /* initialization */
+       g_return_if_fail (EOG_IS_JOB_COPY (job));
 
-       if (!job->thumbnail) {
-               ejob->finished = TRUE;
-               return;
+       g_object_ref (job);
+
+       /* clean previous errors */
+       if (job->error) {
+               g_error_free (job->error);
+               job->error = NULL;
        }
 
-       orig_width = g_strdup (gdk_pixbuf_get_option (job->thumbnail, "tEXt::Thumb::Image::Width"));
-       orig_height = g_strdup (gdk_pixbuf_get_option (job->thumbnail, "tEXt::Thumb::Image::Height"));
+       /* check if the current job was previously cancelled */
+       if (eog_job_is_cancelled (job))
+               return;
 
-       pixbuf = eog_thumbnail_fit_to_size (job->thumbnail, EOG_LIST_STORE_THUMB_SIZE);
-       g_object_unref (job->thumbnail);
-       job->thumbnail = eog_thumbnail_add_frame (pixbuf);
-       g_object_unref (pixbuf);
+       /* --- enter critical section --- */
+       g_mutex_lock (job->mutex);
 
-       if (orig_width) {
-               sscanf (orig_width, "%i", &width);
-               g_object_set_data (G_OBJECT (job->thumbnail),
-                                  EOG_THUMBNAIL_ORIGINAL_WIDTH,
-                                  GINT_TO_POINTER (width));
-               g_free (orig_width);
-       }
-       if (orig_height) {
-               sscanf (orig_height, "%i", &height);
-               g_object_set_data (G_OBJECT (job->thumbnail),
-                                  EOG_THUMBNAIL_ORIGINAL_HEIGHT,
-                                  GINT_TO_POINTER (height));
-               g_free (orig_height);
-       }
+       /* job finished */
+       job->finished = TRUE;
 
-       if (ejob->error) {
-               g_warning ("%s", ejob->error->message);
-       }
+       /* --- leave critical section --- */
+       g_mutex_unlock (job->mutex);
 
-       ejob->finished = TRUE;
+       /* notify job finalization */
+       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+                        (GSourceFunc) notify_finished,
+                        job,
+                        g_object_unref);
 }
 
-static void eog_job_load_init (EogJobLoad *job) { /* Do Nothing */ }
-
-static void
-eog_job_load_dispose (GObject *object)
+EogJob *
+eog_job_copy_new (GList       *images,
+                 const gchar *destination)
 {
-       EogJobLoad *job;
+       EogJobCopy *job;
 
-       job = EOG_JOB_LOAD (object);
+       job = g_object_new (EOG_TYPE_JOB_COPY, NULL);
 
-       if (job->image) {
-               g_object_unref (job->image);
-               job->image = NULL;
-       }
+       if (images)
+               job->images = images;
+
+       if (destination)
+               job->destination = g_strdup (destination);
 
-       (* G_OBJECT_CLASS (eog_job_load_parent_class)->dispose) (object);
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "%s (%p) job was CREATED",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
+
+       return EOG_JOB (job);
 }
 
+/* ------------------------------- EogJobLoad -------------------------------- */
 static void
 eog_job_load_class_init (EogJobLoadClass *class)
 {
-       GObjectClass *oclass;
+       GObjectClass *g_object_class = (GObjectClass *) class;
+       EogJobClass  *eog_job_class  = (EogJobClass *)  class;
 
-       oclass = G_OBJECT_CLASS (class);
+       g_object_class->dispose = eog_job_load_dispose;
+       eog_job_class->run      = eog_job_load_run;
+}
 
-       oclass->dispose = eog_job_load_dispose;
-       EOG_JOB_CLASS (class)->run = eog_job_load_run;
+static
+void eog_job_load_init (EogJobLoad *job)
+{
+       /* initialize all public and private members to reasonable
+          default values. */
+       job->image = NULL;
+       job->data  = EOG_IMAGE_DATA_ALL;
 }
 
-EogJob *
-eog_job_load_new (EogImage *image, EogImageData data)
+static
+void eog_job_load_dispose (GObject *object)
 {
        EogJobLoad *job;
 
-       job = g_object_new (EOG_TYPE_JOB_LOAD, NULL);
+       g_return_if_fail (EOG_IS_JOB_LOAD (object));
 
-       if (image) {
-               job->image = g_object_ref (image);
+       job = EOG_JOB_LOAD (object);
+
+       /* free all public and private members */
+       if (job->image) {
+               g_object_unref (job->image);
+               job->image = NULL;
        }
-       job->data = data;
 
-       return EOG_JOB (job);
+       /* call parent dispose */
+       G_OBJECT_CLASS (eog_job_load_parent_class)->dispose (object);
 }
 
 static void
 eog_job_load_run (EogJob *job)
 {
+       EogJobLoad *job_load;
+
+       /* initialization */
        g_return_if_fail (EOG_IS_JOB_LOAD (job));
 
+       job_load = EOG_JOB_LOAD (g_object_ref (job));
+
+       /* clean previous errors */
        if (job->error) {
                g_error_free (job->error);
                job->error = NULL;
        }
 
-       eog_image_load (EOG_IMAGE (EOG_JOB_LOAD (job)->image),
-                       EOG_JOB_LOAD (job)->data,
+       /* load image from file */
+       eog_image_load (job_load->image,
+                       job_load->data,
                        job,
                        &job->error);
 
+       /* check if the current job was previously cancelled */
+       if (eog_job_is_cancelled (job))
+               return;
+
+       /* --- enter critical section --- */
+       g_mutex_lock (job->mutex);
+
+       /* job finished */
        job->finished = TRUE;
+
+       /* --- leave critical section --- */
+       g_mutex_unlock (job->mutex);
+
+       /* notify job finalization */
+       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+                        (GSourceFunc) notify_finished,
+                        job,
+                        g_object_unref);
 }
 
-static void eog_job_model_init (EogJobModel *job) { /* Do Nothing */ }
+EogJob *
+eog_job_load_new (EogImage     *image,
+                 EogImageData  data)
+{
+       EogJobLoad *job;
+
+       job = g_object_new (EOG_TYPE_JOB_LOAD, NULL);
+
+       if (image)
+               job->image = g_object_ref (image);
+
+       job->data = data;
+
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "%s (%p) job was CREATED",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
 
+       return EOG_JOB (job);
+}
+
+/* ------------------------------- EogJobModel -------------------------------- */
 static void
 eog_job_model_class_init (EogJobModelClass *class)
 {
-       EOG_JOB_CLASS (class)->run = eog_job_model_run;
+       GObjectClass *g_object_class = (GObjectClass *) class;
+       EogJobClass  *eog_job_class  = (EogJobClass *)  class;
+
+       g_object_class->dispose = eog_job_model_dispose;
+       eog_job_class->run      = eog_job_model_run;
 }
 
-EogJob *
-eog_job_model_new (GSList *file_list)
+static
+void eog_job_model_init (EogJobModel *job)
+{
+       /* initialize all public and private members to reasonable
+          default values. */
+       job->store     = NULL;
+       job->file_list = NULL;
+}
+
+static
+void eog_job_model_dispose (GObject *object)
 {
        EogJobModel *job;
 
-       job = g_object_new (EOG_TYPE_JOB_MODEL, NULL);
+       g_return_if_fail (EOG_IS_JOB_MODEL (object));
 
-       job->file_list = file_list;
+       job = EOG_JOB_MODEL (object);
 
-       return EOG_JOB (job);
+       /* free all public and private members */
+       if (job->store) {
+               g_object_unref (job->store);
+               job->store = NULL;
+       }
+
+       if (job->file_list) {
+               // g_slist_foreach (job->file_list, (GFunc) g_object_unref, NULL);
+               // g_slist_free (job->file_list);
+               job->file_list = NULL;
+       }
+
+       /* call parent dispose */
+       G_OBJECT_CLASS (eog_job_model_parent_class)->dispose (object);
 }
 
 static void
@@ -418,252 +675,221 @@ filter_files (GSList *files, GList **file_list, GList **error_list)
 }
 
 static void
-eog_job_model_run (EogJob *ejob)
+eog_job_model_run (EogJob *job)
 {
-       GList *filtered_list = NULL;
-       GList *error_list = NULL;
-       EogJobModel *job;
+       EogJobModel *job_model;
+       GList       *filtered_list;
+       GList       *error_list;
 
-       g_return_if_fail (EOG_IS_JOB_MODEL (ejob));
+       /* initialization */
+       g_return_if_fail (EOG_IS_JOB_MODEL (job));
 
-       job = EOG_JOB_MODEL (ejob);
+       job_model     = EOG_JOB_MODEL (g_object_ref (job));
+       filtered_list = NULL;
+       error_list    = NULL;
 
-       filter_files (job->file_list, &filtered_list, &error_list);
+       filter_files (job_model->file_list,
+                     &filtered_list,
+                     &error_list);
 
-       job->store = EOG_LIST_STORE (eog_list_store_new ());
+       /* --- enter critical section --- */
+       g_mutex_lock (job->mutex);
 
-       eog_list_store_add_files (job->store, filtered_list);
+       /* create a list store */
+       job_model->store = EOG_LIST_STORE (eog_list_store_new ());
+       eog_list_store_add_files (job_model->store, filtered_list);
 
+       /* --- leave critical section --- */
+       g_mutex_unlock (job->mutex);
+
+       /* free lists*/
        g_list_foreach (filtered_list, (GFunc) g_object_unref, NULL);
        g_list_free (filtered_list);
 
        g_list_foreach (error_list, (GFunc) g_free, NULL);
        g_list_free (error_list);
 
-       ejob->finished = TRUE;
-}
-
-static void eog_job_transform_init (EogJobTransform *job) { /* Do Nothing */ }
-
-static void
-eog_job_transform_dispose (GObject *object)
-{
-       EogJobTransform *job;
-
-       job = EOG_JOB_TRANSFORM (object);
-
-       if (job->trans) {
-               g_object_unref (job->trans);
-               job->trans = NULL;
-       }
-
-       g_list_foreach (job->images, (GFunc) g_object_unref, NULL);
-       g_list_free (job->images);
-
-       (* G_OBJECT_CLASS (eog_job_transform_parent_class)->dispose) (object);
-}
-
-static void
-eog_job_transform_class_init (EogJobTransformClass *class)
-{
-       GObjectClass *oclass;
+       /* --- enter critical section --- */
+       g_mutex_lock (job->mutex);
 
-       oclass = G_OBJECT_CLASS (class);
+       /* job finished */
+       job->finished = TRUE;
 
-       oclass->dispose = eog_job_transform_dispose;
+       /* --- leave critical section --- */
+       g_mutex_unlock (job->mutex);
 
-       EOG_JOB_CLASS (class)->run = eog_job_transform_run;
+       /* notify job finalization */
+       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+                        (GSourceFunc) notify_finished,
+                        job,
+                        g_object_unref);
 }
 
 EogJob *
-eog_job_transform_new (GList *images, EogTransform *trans)
+eog_job_model_new (GSList *file_list)
 {
-       EogJobTransform *job;
+       EogJobModel *job;
 
-       job = g_object_new (EOG_TYPE_JOB_TRANSFORM, NULL);
+       job = g_object_new (EOG_TYPE_JOB_MODEL, NULL);
 
-       if (trans) {
-               job->trans = g_object_ref (trans);
-       } else {
-               job->trans = NULL;
-       }
+       if (file_list != NULL)
+               job->file_list = file_list;
 
-       job->images = images;
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "%s (%p) job was CREATED",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
 
        return EOG_JOB (job);
 }
 
-static gboolean
-eog_job_transform_image_modified (gpointer data)
+/* ------------------------------- EogJobSave -------------------------------- */
+static void
+eog_job_save_class_init (EogJobSaveClass *class)
 {
-       g_return_val_if_fail (EOG_IS_IMAGE (data), FALSE);
+       GObjectClass *g_object_class = (GObjectClass *) class;
+       EogJobClass  *eog_job_class  = (EogJobClass *)  class;
 
-       eog_image_modified (EOG_IMAGE (data));
-       g_object_unref (G_OBJECT (data));
-
-       return FALSE;
+       g_object_class->dispose = eog_job_save_dispose;
+       eog_job_class->run      = eog_job_save_run;
 }
 
-void
-eog_job_transform_run (EogJob *ejob)
+static
+void eog_job_save_init (EogJobSave *job)
 {
-       EogJobTransform *job;
-       GList *it;
-
-       g_return_if_fail (EOG_IS_JOB_TRANSFORM (ejob));
-
-       job = EOG_JOB_TRANSFORM (ejob);
-
-       if (ejob->error) {
-               g_error_free (ejob->error);
-               ejob->error = NULL;
-       }
-
-       for (it = job->images; it != NULL; it = it->next) {
-               EogImage *image = EOG_IMAGE (it->data);
-
-               if (job->trans == NULL) {
-                       eog_image_undo (image);
-               } else {
-                       eog_image_transform (image, job->trans, ejob);
-               }
-
-               if (eog_image_is_modified (image) || job->trans == NULL) {
-                       g_object_ref (image);
-                       g_idle_add (eog_job_transform_image_modified, image);
-               }
-       }
-
-       ejob->finished = TRUE;
+       /* initialize all public and private members to reasonable
+          default values. */
+       job->images           = NULL;
+       job->current_position = 0;
+       job->current_image    = NULL;
 }
 
-static void eog_job_save_init (EogJobSave *job) { /* do nothing */ }
-
-static void
-eog_job_save_dispose (GObject *object)
+static
+void eog_job_save_dispose (GObject *object)
 {
        EogJobSave *job;
 
+       g_return_if_fail (EOG_IS_JOB_SAVE (object));
+
        job = EOG_JOB_SAVE (object);
 
+       /* free all public and private members */
        if (job->images) {
                g_list_foreach (job->images, (GFunc) g_object_unref, NULL);
                g_list_free (job->images);
                job->images = NULL;
        }
 
-       (* G_OBJECT_CLASS (eog_job_save_parent_class)->dispose) (object);
-}
+       if (job->current_image) {
+               g_object_unref (job->current_image);
+               job->current_image = NULL;
+       }
 
-static void
-eog_job_save_class_init (EogJobSaveClass *class)
-{
-       G_OBJECT_CLASS (class)->dispose = eog_job_save_dispose;
-       EOG_JOB_CLASS (class)->run = eog_job_save_run;
+       /* call parent dispose */
+       G_OBJECT_CLASS (eog_job_save_parent_class)->dispose (object);
 }
 
-EogJob *
-eog_job_save_new (GList *images)
+static void
+eog_job_save_progress_callback (EogImage *image,
+                               gfloat    progress,
+                               gpointer  data)
 {
        EogJobSave *job;
+       guint       n_images;
+       gfloat      job_progress;
 
-       job = g_object_new (EOG_TYPE_JOB_SAVE, NULL);
-
-       job->images = images;
-       job->current_image = NULL;
+       job = EOG_JOB_SAVE (data);
 
-       return EOG_JOB (job);
-}
-
-static void
-save_progress_handler (EogImage *image, gfloat progress, gpointer data)
-{
-       EogJobSave *job = EOG_JOB_SAVE (data);
-       guint n_images = g_list_length (job->images);
-       gfloat job_progress;
-
-       job_progress = (job->current_pos / (gfloat) n_images) + (progress / n_images);
+       n_images     = g_list_length (job->images);
+       job_progress = (job->current_position / (gfloat) n_images) + (progress / n_images);
 
        eog_job_set_progress (EOG_JOB (job), job_progress);
 }
 
 static void
-eog_job_save_run (EogJob *ejob)
+eog_job_save_run (EogJob *job)
 {
-       EogJobSave *job;
-       GList *it;
-
-       g_return_if_fail (EOG_IS_JOB_SAVE (ejob));
-
-       job = EOG_JOB_SAVE (ejob);
+       /* initialization */
+       g_return_if_fail (EOG_IS_JOB_SAVE (job));
 
-       job->current_pos = 0;
+       g_object_ref (job);
 
-       for (it = job->images; it != NULL; it = it->next, job->current_pos++) {
-               EogImage *image = EOG_IMAGE (it->data);
-               EogImageSaveInfo *save_info = NULL;
-               gulong handler_id = 0;
-               gboolean success = FALSE;
-
-               job->current_image = image;
+       /* clean previous errors */
+       if (job->error) {
+               g_error_free (job->error);
+               job->error = NULL;
+       }
 
-               /* Make sure the image doesn't go away while saving */
-               eog_image_data_ref (image);
+       /* check if the current job was previously cancelled */
+       if (eog_job_is_cancelled (job))
+               return;
 
-               if (!eog_image_has_data (image, EOG_IMAGE_DATA_ALL)) {
-                       EogImageMetadataStatus m_status;
-                       gint data2load = 0;
+       /* --- enter critical section --- */
+       g_mutex_lock (job->mutex);
 
-                       m_status = eog_image_get_metadata_status (image);
-                       if (!eog_image_has_data (image, EOG_IMAGE_DATA_IMAGE)) {
-                               // Queue full read in this case
-                               data2load = EOG_IMAGE_DATA_ALL;
-                       } else if (m_status == EOG_IMAGE_METADATA_NOT_READ)
-                       {
-                               // Load only if we haven't read it yet
-                               data2load = EOG_IMAGE_DATA_EXIF
-                                               | EOG_IMAGE_DATA_XMP;
-                       }
+       /* job finished */
+       job->finished = TRUE;
 
-                       if (data2load != 0) {
-                               eog_image_load (image,
-                                               data2load,
-                                               NULL,
-                                               &ejob->error);
-                       }
-               }
+       /* --- leave critical section --- */
+       g_mutex_unlock (job->mutex);
 
-               handler_id = g_signal_connect (G_OBJECT (image),
-                                              "save-progress",
-                                              G_CALLBACK (save_progress_handler),
-                                              job);
+       /* notify job finalization */
+       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+                        (GSourceFunc) notify_finished,
+                        job,
+                        g_object_unref);
+}
 
-               save_info = eog_image_save_info_new_from_image (image);
+EogJob *
+eog_job_save_new (GList *images)
+{
+       EogJobSave *job;
 
-               success = eog_image_save_by_info (image,
-                                                 save_info,
-                                                 &ejob->error);
+       job = g_object_new (EOG_TYPE_JOB_SAVE, NULL);
 
-               if (save_info)
-                       g_object_unref (save_info);
+       if (images)
+               job->images = images;
 
-               if (handler_id != 0)
-                       g_signal_handler_disconnect (G_OBJECT (image), handler_id);
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "%s (%p) job was CREATED",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
 
-               eog_image_data_unref (image);
+       return EOG_JOB (job);
+}
 
-               if (!success) break;
-       }
+/* ------------------------------- EogJobSaveAs -------------------------------- */
+static void
+eog_job_save_as_class_init (EogJobSaveAsClass *class)
+{
+       GObjectClass *g_object_class = (GObjectClass *) class;
+       EogJobClass  *eog_job_class  = (EogJobClass *)  class;
 
-       ejob->finished = TRUE;
+       g_object_class->dispose = eog_job_save_as_dispose;
+       eog_job_class->run      = eog_job_save_as_run;
 }
 
-static void eog_job_save_as_init (EogJobSaveAs *job) { /* do nothing */ }
+static
+void eog_job_save_as_init (EogJobSaveAs *job)
+{
+       /* initialize all public and private members to reasonable
+          default values. */
+       job->converter = NULL;
+       job->file      = NULL;
+}
 
-static void eog_job_save_as_dispose (GObject *object)
+static
+void eog_job_save_as_dispose (GObject *object)
 {
-       EogJobSaveAs *job = EOG_JOB_SAVE_AS (object);
+       EogJobSaveAs *job;
 
+       g_return_if_fail (EOG_IS_JOB_SAVE_AS (object));
+
+       job = EOG_JOB_SAVE_AS (object);
+
+       /* free all public and private members */
        if (job->converter != NULL) {
                g_object_unref (job->converter);
                job->converter = NULL;
@@ -674,226 +900,319 @@ static void eog_job_save_as_dispose (GObject *object)
                job->file = NULL;
        }
 
-       (* G_OBJECT_CLASS (eog_job_save_as_parent_class)->dispose) (object);
+       /* call parent dispose */
+       G_OBJECT_CLASS (eog_job_save_as_parent_class)->dispose (object);
 }
 
 static void
-eog_job_save_as_class_init (EogJobSaveAsClass *class)
+eog_job_save_as_run (EogJob *job)
 {
-       G_OBJECT_CLASS (class)->dispose = eog_job_save_as_dispose;
-       EOG_JOB_CLASS (class)->run = eog_job_save_as_run;
+       /* initialization */
+       g_return_if_fail (EOG_IS_JOB_SAVE_AS (job));
+
+       g_object_ref (job);
+
+       /* clean previous errors */
+       if (job->error) {
+               g_error_free (job->error);
+               job->error = NULL;
+       }
+
+       /* check if the current job was previously cancelled */
+       if (eog_job_is_cancelled (job))
+               return;
+
+       /* --- enter critical section --- */
+       g_mutex_lock (job->mutex);
+
+       /* job finished */
+       job->finished = TRUE;
+
+       /* --- leave critical section --- */
+       g_mutex_unlock (job->mutex);
+
+       /* notify job finalization */
+       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+                        (GSourceFunc) notify_finished,
+                        job,
+                        g_object_unref);
 }
 
 EogJob *
-eog_job_save_as_new (GList *images, EogURIConverter *converter, GFile *file)
+eog_job_save_as_new (GList           *images,
+                    EogURIConverter *converter,
+                    GFile           *file)
 {
        EogJobSaveAs *job;
 
-       g_assert (converter != NULL || g_list_length (images) == 1);
-
        job = g_object_new (EOG_TYPE_JOB_SAVE_AS, NULL);
 
-       EOG_JOB_SAVE(job)->images = images;
+       if (images)
+               EOG_JOB_SAVE(job)->images = images;
+
+       if (converter)
+               job->converter = g_object_ref (converter);
 
-       job->converter = converter ? g_object_ref (converter) : NULL;
-       job->file = file ? g_object_ref (file) : NULL;
+       if (file)
+               job->file = g_object_ref (file);
+
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "%s (%p) job was CREATED",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
 
        return EOG_JOB (job);
 }
 
+/* ------------------------------- EogJobThumbnail -------------------------------- */
 static void
-eog_job_save_as_run (EogJob *ejob)
+eog_job_thumbnail_class_init (EogJobThumbnailClass *class)
 {
-       EogJobSave *job;
-       EogJobSaveAs *saveas_job;
-       GList *it;
-       guint n_images;
+       GObjectClass *g_object_class = (GObjectClass *) class;
+       EogJobClass  *eog_job_class  = (EogJobClass *)  class;
 
-       g_return_if_fail (EOG_IS_JOB_SAVE_AS (ejob));
+       g_object_class->dispose = eog_job_thumbnail_dispose;
+       eog_job_class->run      = eog_job_thumbnail_run;
+}
 
-       job = EOG_JOB_SAVE (ejob);
+static
+void eog_job_thumbnail_init (EogJobThumbnail *job)
+{
+       /* initialize all public and private members to reasonable
+          default values. */
+       job->image     = NULL;
+       job->thumbnail = NULL;
+}
 
-       n_images = g_list_length (job->images);
+static
+void eog_job_thumbnail_dispose (GObject *object)
+{
+       EogJobThumbnail *job;
 
-       saveas_job = EOG_JOB_SAVE_AS (job);
+       g_return_if_fail (EOG_IS_JOB_THUMBNAIL (object));
 
-       job->current_pos = 0;
+       job = EOG_JOB_THUMBNAIL (object);
 
-       for (it = job->images; it != NULL; it = it->next, job->current_pos++) {
-               GdkPixbufFormat *format;
-               EogImageSaveInfo *src_info, *dest_info;
-               EogImage *image = EOG_IMAGE (it->data);
-               gboolean success = FALSE;
-               gulong handler_id = 0;
+       /* free all public and private members */
+       if (job->image) {
+               g_object_unref (job->image);
+               job->image = NULL;
+       }
 
-               job->current_image = image;
+       if (job->thumbnail) {
+               g_object_unref (job->thumbnail);
+               job->thumbnail = NULL;
+       }
 
-               eog_image_data_ref (image);
+       /* call parent dispose */
+       G_OBJECT_CLASS (eog_job_thumbnail_parent_class)->dispose (object);
+}
 
-               if (!eog_image_has_data (image, EOG_IMAGE_DATA_ALL)) {
-                       EogImageMetadataStatus m_status;
-                       gint data2load = 0;
+static void
+eog_job_thumbnail_run (EogJob *job)
+{
+       EogJobThumbnail *job_thumbnail;
+       gchar           *original_width;
+       gchar           *original_height;
+       gint             width;
+       gint             height;
+       GdkPixbuf       *pixbuf;
 
-                       m_status = eog_image_get_metadata_status (image);
-                       if (!eog_image_has_data (image, EOG_IMAGE_DATA_IMAGE)) {
-                               // Queue full read in this case
-                               data2load = EOG_IMAGE_DATA_ALL;
-                       } else if (m_status == EOG_IMAGE_METADATA_NOT_READ)
-                       {
-                               // Load only if we haven't read it yet
-                               data2load = EOG_IMAGE_DATA_EXIF
-                                               | EOG_IMAGE_DATA_XMP;
-                       }
+       /* initialization */
+       g_return_if_fail (EOG_IS_JOB_THUMBNAIL (job));
 
-                       if (data2load != 0) {
-                               eog_image_load (image,
-                                               data2load,
-                                               NULL,
-                                               &ejob->error);
-                       }
-               }
+       job_thumbnail = EOG_JOB_THUMBNAIL (g_object_ref (job));
 
+       /* clean previous errors */
+       if (job->error) {
+               g_error_free (job->error);
+               job->error = NULL;
+       }
 
-               g_assert (ejob->error == NULL);
+       /* try to load the image thumbnail from cache */
+       job_thumbnail->thumbnail = eog_thumbnail_load (job_thumbnail->image,
+                                                      &job->error);
 
-               handler_id = g_signal_connect (G_OBJECT (image),
-                                              "save-progress",
-                                              G_CALLBACK (save_progress_handler),
-                                              job);
+       if (!job_thumbnail->thumbnail) {
+               job->finished = TRUE;
+               return;
+       }
 
-               src_info = eog_image_save_info_new_from_image (image);
+       /* create the image thumbnail */
+       original_width  = g_strdup (gdk_pixbuf_get_option (job_thumbnail->thumbnail, 
"tEXt::Thumb::Image::Width"));
+       original_height = g_strdup (gdk_pixbuf_get_option (job_thumbnail->thumbnail, 
"tEXt::Thumb::Image::Height"));
 
-               if (n_images == 1) {
-                       g_assert (saveas_job->file != NULL);
+       pixbuf = eog_thumbnail_fit_to_size (job_thumbnail->thumbnail,
+                                           EOG_LIST_STORE_THUMB_SIZE);
 
-                       format = eog_pixbuf_get_format (saveas_job->file);
+       g_object_unref (job_thumbnail->thumbnail);
+       job_thumbnail->thumbnail = eog_thumbnail_add_frame (pixbuf);
+       g_object_unref (pixbuf);
 
-                       dest_info = eog_image_save_info_new_from_file (saveas_job->file,
-                                                                      format);
+       if (original_width) {
+               sscanf (original_width, "%i", &width);
+               g_object_set_data (G_OBJECT (job_thumbnail->thumbnail),
+                                  EOG_THUMBNAIL_ORIGINAL_WIDTH,
+                                  GINT_TO_POINTER (width));
+               g_free (original_width);
+       }
 
-               /* SaveAsDialog has already secured permission to overwrite */
-                       if (dest_info->exists) {
-                               dest_info->overwrite = TRUE;
-                       }
-               } else {
-                       GFile *dest_file;
-                       gboolean result;
+       if (original_height) {
+               sscanf (original_height, "%i", &height);
+               g_object_set_data (G_OBJECT (job_thumbnail->thumbnail),
+                                  EOG_THUMBNAIL_ORIGINAL_HEIGHT,
+                                  GINT_TO_POINTER (height));
+               g_free (original_height);
+       }
 
-                       result = eog_uri_converter_do (saveas_job->converter,
-                                                      image,
-                                                      &dest_file,
-                                                      &format,
-                                                      NULL);
+       /* show info for debugging */
+       if (job->error)
+               g_warning ("%s", job->error->message);
 
-                       g_assert (result);
+       /* --- enter critical section --- */
+       g_mutex_lock (job->mutex);
 
-                       dest_info = eog_image_save_info_new_from_file (dest_file,
-                                                                      format);
-               }
+       /* job finished */
+       job->finished = TRUE;
 
-               success = eog_image_save_as_by_info (image,
-                                                    src_info,
-                                                    dest_info,
-                                                    &ejob->error);
+       /* --- leave critical section --- */
+       g_mutex_unlock (job->mutex);
 
-               if (src_info)
-                       g_object_unref (src_info);
+       /* notify job finalization */
+       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+                        (GSourceFunc) notify_finished,
+                        job,
+                        g_object_unref);
+}
 
-               if (dest_info)
-                       g_object_unref (dest_info);
+EogJob *
+eog_job_thumbnail_new (EogImage *image)
+{
+       EogJobThumbnail *job;
 
-               if (handler_id != 0)
-                       g_signal_handler_disconnect (G_OBJECT (image), handler_id);
+       job = g_object_new (EOG_TYPE_JOB_THUMBNAIL, NULL);
 
-               eog_image_data_unref (image);
+       if (image)
+               job->image = g_object_ref (image);
 
-               if (!success)
-                       break;
-       }
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "%s (%p) job was CREATED",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
 
-       ejob->finished = TRUE;
+       return EOG_JOB (job);
 }
 
-static void eog_job_copy_init (EogJobCopy *job) { /* do nothing */};
-
+/* ------------------------------- EogJobTransform -------------------------------- */
 static void
-eog_job_copy_dispose (GObject *object)
+eog_job_transform_class_init (EogJobTransformClass *class)
 {
-       EogJobCopy *job = EOG_JOB_COPY (object);
+       GObjectClass *g_object_class = (GObjectClass *) class;
+       EogJobClass  *eog_job_class  = (EogJobClass *)  class;
 
-       if (job->dest) {
-               g_free (job->dest);
-               job->dest = NULL;
-       }
-
-       (* G_OBJECT_CLASS (eog_job_copy_parent_class)->dispose) (object);
+       g_object_class->dispose = eog_job_transform_dispose;
+       eog_job_class->run      = eog_job_transform_run;
 }
 
-static void
-eog_job_copy_class_init (EogJobCopyClass *class)
+static
+void eog_job_transform_init (EogJobTransform *job)
 {
-       G_OBJECT_CLASS (class)->dispose = eog_job_copy_dispose;
-       EOG_JOB_CLASS (class)->run = eog_job_copy_run;
+       /* initialize all public and private members to reasonable
+          default values. */
+       job->images    = NULL;
+       job->transform = NULL;
 }
 
-EogJob *
-eog_job_copy_new (GList *images, const gchar *dest)
+static
+void eog_job_transform_dispose (GObject *object)
 {
-       EogJobCopy *job;
+       EogJobTransform *job;
 
-       g_assert (images != NULL && dest != NULL);
+       g_return_if_fail (EOG_IS_JOB_TRANSFORM (object));
 
-       job = g_object_new (EOG_TYPE_JOB_COPY, NULL);
+       job = EOG_JOB_TRANSFORM (object);
 
-       job->images = images;
-       job->dest = g_strdup (dest);
+       /* free all public and private members */
+       if (job->transform) {
+               g_object_unref (job->transform);
+               job->transform = NULL;
+       }
 
-       return EOG_JOB (job);
+       if (job->images) {
+               g_list_foreach (job->images, (GFunc) g_object_unref, NULL);
+               g_list_free (job->images);
+       }
+
+       /* call parent dispose */
+       G_OBJECT_CLASS (eog_job_transform_parent_class)->dispose (object);
+}
+
+static gboolean
+eog_job_transform_image_modified (gpointer data)
+{
+       g_return_val_if_fail (EOG_IS_IMAGE (data), FALSE);
+
+       eog_image_modified (EOG_IMAGE (data));
+       g_object_unref (G_OBJECT (data));
+
+       return FALSE;
 }
 
 static void
-eog_job_copy_progress_callback (goffset current_num_bytes,
-                               goffset total_num_bytes,
-                               gpointer user_data)
+eog_job_transform_run (EogJob *job)
 {
-       gfloat job_progress;
-       guint n_images;
-       EogJobCopy *job;
+       /* initialization */
+       g_return_if_fail (EOG_IS_JOB_TRANSFORM (job));
 
-       job = EOG_JOB_COPY (user_data);
-       n_images = g_list_length (job->images);
+       g_object_ref (job);
+
+       /* clean previous errors */
+       if (job->error) {
+               g_error_free (job->error);
+               job->error = NULL;
+       }
 
-       job_progress =  ((current_num_bytes / (gfloat) total_num_bytes) + job->current_pos)/n_images;
+       /* check if the current job was previously cancelled */
+       if (eog_job_is_cancelled (job))
+               return;
 
-       eog_job_set_progress (EOG_JOB (job), job_progress);
+       /* --- enter critical section --- */
+       g_mutex_lock (job->mutex);
+
+       /* job finished */
+       job->finished = TRUE;
+
+       /* --- leave critical section --- */
+       g_mutex_unlock (job->mutex);
+
+       /* notify job finalization */
+       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+                        (GSourceFunc) notify_finished,
+                        job,
+                        g_object_unref);
 }
 
-void
-eog_job_copy_run (EogJob *ejob)
+EogJob *
+eog_job_transform_new (GList        *images,
+                      EogTransform *transform)
 {
-       EogJobCopy *job;
-       GList *it;
-       GFile *src, *dest;
-       gchar *filename, *dest_filename;
-
-       g_return_if_fail (EOG_IS_JOB_COPY (ejob));
-
-       job = EOG_JOB_COPY (ejob);
-       job->current_pos = 0;
-
-       for (it = job->images; it != NULL; it = g_list_next (it), job->current_pos++) {
-               src = (GFile *) it->data;
-               filename = g_file_get_basename (src);
-               dest_filename = g_build_filename (job->dest, filename, NULL);
-               dest = g_file_new_for_path (dest_filename);
-
-               g_file_copy (src, dest,
-                            G_FILE_COPY_OVERWRITE, NULL,
-                            eog_job_copy_progress_callback, job,
-                            &ejob->error);
-               g_free (filename);
-               g_free (dest_filename);
-       }
+       EogJobTransform *job;
 
-       ejob->finished = TRUE;
+       job = g_object_new (EOG_TYPE_JOB_TRANSFORM, NULL);
+
+       if (images)
+               job->images = images;
+
+       if (transform)
+               job->transform = g_object_ref (transform);
+
+       /* show info for debugging */
+       eog_debug_message (DEBUG_JOBS,
+                          "%s (%p) job was CREATED",
+                          EOG_GET_TYPE_NAME (job),
+                          job);
+
+       return EOG_JOB (job);
 }
diff --git a/src/eog-jobs.h b/src/eog-jobs.h
index c26e089..9139ab0 100644
--- a/src/eog-jobs.h
+++ b/src/eog-jobs.h
@@ -1,11 +1,11 @@
 /* Eye Of Gnome - Jobs
  *
- * Copyright (C) 2006 The Free Software Foundation
+ * Copyright (C) 2013 The Free Software Foundation
  *
- * Author: Lucas Rocha <lucasr gnome org>
+ * Author: Javier Sánchez <jsanchez deskblue com>
  *
- * Based on evince code (shell/ev-jobs.h) by:
- *     - Martin Kretzschmar <martink gnome org>
+ * Based on code (libview/ev-jobs.h) by:
+ *      - Carlos Garcia Campos <carlosgc gnome org>
  *
  * 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
@@ -25,250 +25,271 @@
 #ifndef __EOG_JOBS_H__
 #define __EOG_JOBS_H__
 
+#include "eog-enums.h"
+#include "eog-image.h"
 #include "eog-list-store.h"
 #include "eog-transform.h"
-#include "eog-enums.h"
+#include "eog-uri-converter.h"
 
-#include <glib.h>
-#include <gio/gio.h>
-#include <gtk/gtk.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
-#ifndef __EOG_IMAGE_DECLR__
-#define __EOG_IMAGE_DECLR__
-  typedef struct _EogImage EogImage;
-#endif
+#define EOG_TYPE_JOB                      (eog_job_get_type ())
+#define EOG_JOB(obj)                      (G_TYPE_CHECK_INSTANCE_CAST ((obj), EOG_TYPE_JOB, EogJob))
+#define EOG_JOB_CLASS(klass)              (G_TYPE_CHECK_CLASS_CAST ((klass),  EOG_TYPE_JOB, EogJobClass))
+#define EOG_IS_JOB(obj)                   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EOG_TYPE_JOB))
+#define EOG_IS_JOB_CLASS(klass)           (G_TYPE_CHECK_CLASS_TYPE ((klass),  EOG_TYPE_JOB))
+#define EOG_JOB_GET_CLASS(obj)            (G_TYPE_INSTANCE_GET_CLASS ((obj),  EOG_TYPE_JOB, EogJobClass))
+
+#define EOG_TYPE_JOB_COPY                 (eog_job_copy_get_type ())
+#define EOG_JOB_COPY(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), EOG_TYPE_JOB_COPY, EogJobCopy))
+#define EOG_JOB_COPY_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass),  EOG_TYPE_JOB_COPY, 
EogJobCopyClass))
+#define EOG_IS_JOB_COPY(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EOG_TYPE_JOB_COPY))
+#define EOG_IS_JOB_COPY_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass),  EOG_TYPE_JOB_COPY))
+#define EOG_JOB_COPY_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj),  EOG_TYPE_JOB_COPY, 
EogJobCopyClass))
+
+#define EOG_TYPE_JOB_LOAD                 (eog_job_load_get_type ())
+#define EOG_JOB_LOAD(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), EOG_TYPE_JOB_LOAD, EogJobLoad))
+#define EOG_JOB_LOAD_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass),  EOG_TYPE_JOB_LOAD, 
EogJobLoadClass))
+#define EOG_IS_JOB_LOAD(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EOG_TYPE_JOB_LOAD))
+#define EOG_IS_JOB_LOAD_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass),  EOG_TYPE_JOB_LOAD))
+#define EOG_JOB_LOAD_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj),  EOG_TYPE_JOB_LOAD, 
EogJobLoadClass))
+
+#define EOG_TYPE_JOB_MODEL                (eog_job_model_get_type ())
+#define EOG_JOB_MODEL(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), EOG_TYPE_JOB_MODEL, 
EogJobModel))
+#define EOG_JOB_MODEL_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass),  EOG_TYPE_JOB_MODEL, 
EogJobModelClass))
+#define EOG_IS_JOB_MODEL(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EOG_TYPE_JOB_MODEL))
+#define EOG_IS_JOB_MODEL_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass),  EOG_TYPE_JOB_MODEL))
+#define EOG_JOB_MODEL_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj),  EOG_TYPE_JOB_MODEL, 
EogJobModelClass))
+
+#define EOG_TYPE_JOB_SAVE                 (eog_job_save_get_type ())
+#define EOG_JOB_SAVE(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), EOG_TYPE_JOB_SAVE, EogJobSave))
+#define EOG_JOB_SAVE_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass),  EOG_TYPE_JOB_SAVE, 
EogJobSaveClass))
+#define EOG_IS_JOB_SAVE(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EOG_TYPE_JOB_SAVE))
+#define EOG_IS_JOB_SAVE_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass),  EOG_TYPE_JOB_SAVE))
+#define EOG_JOB_SAVE_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj),  EOG_TYPE_JOB_SAVE, 
EogJobSaveClass))
+
+#define EOG_TYPE_JOB_SAVE_AS              (eog_job_save_as_get_type ())
+#define EOG_JOB_SAVE_AS(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), EOG_TYPE_JOB_SAVE_AS, 
EogJobSaveAs))
+#define EOG_JOB_SAVE_AS_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass),  EOG_TYPE_JOB_SAVE_AS, 
EogJobSaveAsClass))
+#define EOG_IS_JOB_SAVE_AS(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EOG_TYPE_JOB_SAVE_AS))
+#define EOG_IS_JOB_SAVE_AS_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass),  EOG_TYPE_JOB_SAVE_AS))
+#define EOG_JOB_SAVE_AS_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj),  EOG_TYPE_JOB_SAVE_AS, 
EogJobSaveAsClass))
+
+#define EOG_TYPE_JOB_THUMBNAIL            (eog_job_thumbnail_get_type ())
+#define EOG_JOB_THUMBNAIL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EOG_TYPE_JOB_THUMBNAIL, 
EogJobThumbnail))
+#define EOG_JOB_THUMBNAIL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  EOG_TYPE_JOB_THUMBNAIL, 
EogJobThumbnailClass))
+#define EOG_IS_JOB_THUMBNAIL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EOG_TYPE_JOB_THUMBNAIL))
+#define EOG_IS_JOB_THUMBNAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  EOG_TYPE_JOB_THUMBNAIL))
+#define EOG_JOB_THUMBNAIL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  EOG_TYPE_JOB_THUMBNAIL, 
EogJobThumbnailClass))
+
+#define EOG_TYPE_JOB_TRANSFORM            (eog_job_transform_get_type ())
+#define EOG_JOB_TRANSFORM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EOG_TYPE_JOB_TRANSFORM, 
EogJobTransform))
+#define EOG_JOB_TRANSFORM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  EOG_TYPE_JOB_TRANSFORM, 
EogJobTransformClass))
+#define EOG_IS_JOB_TRANSFORM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EOG_TYPE_JOB_TRANSFORM))
+#define EOG_IS_JOB_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  EOG_TYPE_JOB_TRANSFORM))
+#define EOG_JOB_TRANSFORM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  EOG_TYPE_JOB_TRANSFORM, 
EogJobTransformClass))
+
 
 #ifndef __EOG_URI_CONVERTER_DECLR__
 #define __EOG_URI_CONVERTER_DECLR__
 typedef struct _EogURIConverter EogURIConverter;
 #endif
 
-#ifndef __EOG_JOB_DECLR__
-#define __EOG_JOB_DECLR__
-typedef struct _EogJob EogJob;
-#endif
-typedef struct _EogJobClass EogJobClass;
-
-typedef struct _EogJobThumbnail EogJobThumbnail;
-typedef struct _EogJobThumbnailClass EogJobThumbnailClass;
-
-typedef struct _EogJobLoad EogJobLoad;
-typedef struct _EogJobLoadClass EogJobLoadClass;
-
-typedef struct _EogJobModel EogJobModel;
-typedef struct _EogJobModelClass EogJobModelClass;
-
-typedef struct _EogJobTransform EogJobTransform;
-typedef struct _EogJobTransformClass EogJobTransformClass;
-
-typedef struct _EogJobSave EogJobSave;
-typedef struct _EogJobSaveClass EogJobSaveClass;
-
-typedef struct _EogJobSaveAs EogJobSaveAs;
-typedef struct _EogJobSaveAsClass EogJobSaveAsClass;
+typedef struct _EogJob               EogJob;
+typedef struct _EogJobClass          EogJobClass;
 
-typedef struct _EogJobCopy EogJobCopy;
-typedef struct _EogJobCopyClass EogJobCopyClass;
+typedef struct _EogJobCopy           EogJobCopy;
+typedef struct _EogJobCopyClass      EogJobCopyClass;
 
-#define EOG_TYPE_JOB                  (eog_job_get_type())
-#define EOG_JOB(obj)                  (G_TYPE_CHECK_INSTANCE_CAST((obj), EOG_TYPE_JOB, EogJob))
-#define EOG_JOB_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST((klass),  EOG_TYPE_JOB, EogJobClass))
-#define EOG_IS_JOB(obj)                       (G_TYPE_CHECK_INSTANCE_TYPE((obj), EOG_TYPE_JOB))
-#define EOG_JOB_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), EOG_TYPE_JOB, EogJobClass))
+typedef struct _EogJobLoad           EogJobLoad;
+typedef struct _EogJobLoadClass      EogJobLoadClass;
 
-#define EOG_TYPE_JOB_THUMBNAIL        (eog_job_thumbnail_get_type())
-#define EOG_JOB_THUMBNAIL(obj)        (G_TYPE_CHECK_INSTANCE_CAST((obj), EOG_TYPE_JOB_THUMBNAIL, 
EogJobThumbnail))
-#define EOG_JOB_THUMBNAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),  EOG_TYPE_JOB_THUMBNAIL, 
EogJobThumbnailClass))
-#define EOG_IS_JOB_THUMBNAIL(obj)      (G_TYPE_CHECK_INSTANCE_TYPE((obj), EOG_TYPE_JOB_THUMBNAIL))
+typedef struct _EogJobModel          EogJobModel;
+typedef struct _EogJobModelClass     EogJobModelClass;
 
-#define EOG_TYPE_JOB_LOAD             (eog_job_load_get_type())
-#define EOG_JOB_LOAD(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), EOG_TYPE_JOB_LOAD, EogJobLoad))
-#define EOG_JOB_LOAD_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass),  EOG_TYPE_JOB_LOAD, 
EogJobLoadClass))
-#define EOG_IS_JOB_LOAD(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), EOG_TYPE_JOB_LOAD))
+typedef struct _EogJobSave           EogJobSave;
+typedef struct _EogJobSaveClass      EogJobSaveClass;
 
-#define EOG_TYPE_JOB_MODEL            (eog_job_model_get_type())
-#define EOG_JOB_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), EOG_TYPE_JOB_MODEL, EogJobModel))
-#define EOG_JOB_MODEL_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),  EOG_TYPE_JOB_MODEL, 
EogJobModelClass))
-#define EOG_IS_JOB_MODEL(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), EOG_TYPE_JOB_MODEL))
+typedef struct _EogJobSaveAs         EogJobSaveAs;
+typedef struct _EogJobSaveAsClass    EogJobSaveAsClass;
 
-#define EOG_TYPE_JOB_TRANSFORM        (eog_job_transform_get_type())
-#define EOG_JOB_TRANSFORM(obj)        (G_TYPE_CHECK_INSTANCE_CAST((obj), EOG_TYPE_JOB_TRANSFORM, 
EogJobTransform))
-#define EOG_JOB_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),  EOG_TYPE_JOB_TRANSFORM, 
EogJobTransformClass))
-#define EOG_IS_JOB_TRANSFORM(obj)      (G_TYPE_CHECK_INSTANCE_TYPE((obj), EOG_TYPE_JOB_TRANSFORM))
-
-#define EOG_TYPE_JOB_SAVE              (eog_job_save_get_type())
-#define EOG_JOB_SAVE(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), EOG_TYPE_JOB_SAVE, EogJobSave))
-#define EOG_JOB_SAVE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), EOG_TYPE_JOB_SAVE, EogJobSaveClass))
-#define EOG_IS_JOB_SAVE(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), EOG_TYPE_JOB_SAVE))
-#define EOG_JOB_SAVE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), EOG_TYPE_JOB_SAVE, 
EogJobSaveClass))
-
-#define EOG_TYPE_JOB_SAVE_AS           (eog_job_save_as_get_type())
-#define EOG_JOB_SAVE_AS(obj)           (G_TYPE_CHECK_INSTANCE_CAST((obj), EOG_TYPE_JOB_SAVE_AS, 
EogJobSaveAs))
-#define EOG_JOB_SAVE_AS_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST((klass), EOG_TYPE_JOB_SAVE_AS, 
EogJobSaveAsClass))
-#define EOG_IS_JOB_SAVE_AS(obj)        (G_TYPE_CHECK_INSTANCE_TYPE((obj), EOG_TYPE_JOB_SAVE_AS))
-
-#define EOG_TYPE_JOB_COPY             (eog_job_copy_get_type())
-#define EOG_JOB_COPY(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), EOG_TYPE_JOB_COPY, EogJobCopy))
-#define EOG_JOB_COPY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),  EOG_TYPE_JOB_COPY, EogJobCopyClass))
-#define EOG_IS_JOB_COPY(obj)      (G_TYPE_CHECK_INSTANCE_TYPE((obj), EOG_TYPE_JOB_COPY))
+typedef struct _EogJobThumbnail      EogJobThumbnail;
+typedef struct _EogJobThumbnailClass EogJobThumbnailClass;
 
+typedef struct _EogJobTransform      EogJobTransform;
+typedef struct _EogJobTransformClass EogJobTransformClass;
 
 struct _EogJob
 {
-       GObject  parent;
+       GObject       parent;
 
-       GError   *error;
-       GMutex   *mutex;
-       float     progress;
-       gboolean  finished;
+       GCancellable *cancellable;
+       GError       *error;
+       GMutex       *mutex;
+
+       gfloat        progress;
+       gboolean      cancelled;
+       gboolean      finished;
 };
 
 struct _EogJobClass
 {
        GObjectClass parent_class;
 
-       void    (* finished) (EogJob *job);
-       void    (* progress) (EogJob *job, float progress);
-       void    (*run)       (EogJob *job);
+       /* vfuncs */
+       void    (* run)       (EogJob *job);
+
+       /* signals */
+       void    (* progress)  (EogJob *job,
+                              gfloat  progress);
+       void    (* cancelled) (EogJob *job);
+       void    (* finished)  (EogJob *job);
 };
 
-struct _EogJobThumbnail
+struct _EogJobCopy
 {
-       EogJob       parent;
-       EogImage    *image;
-       GdkPixbuf   *thumbnail;
+       EogJob           parent;
+
+       GList           *images;
+       gchar           *destination;
+       guint            current_position;
 };
 
-struct _EogJobThumbnailClass
+struct _EogJobCopyClass
 {
-       EogJobClass parent_class;
+       EogJobClass      parent_class;
 };
 
 struct _EogJobLoad
 {
-       EogJob        parent;
-       EogImage     *image;
-       EogImageData  data;
+       EogJob           parent;
+
+       EogImage        *image;
+       EogImageData     data;
 };
 
 struct _EogJobLoadClass
 {
-       EogJobClass parent_class;
+       EogJobClass      parent_class;
 };
 
 struct _EogJobModel
 {
-       EogJob        parent;
-       EogListStore *store;
-       GSList       *file_list;
-};
+       EogJob           parent;
 
-struct _EogJobModelClass
-{
-        EogJobClass parent_class;
+       EogListStore    *store;
+       GSList          *file_list;
 };
 
-struct _EogJobTransform
-{
-       EogJob        parent;
-       GList        *images;
-       EogTransform *trans;
-};
-
-struct _EogJobTransformClass
+struct _EogJobModelClass
 {
-        EogJobClass parent_class;
+        EogJobClass      parent_class;
 };
 
-typedef enum {
-       EOG_SAVE_RESPONSE_NONE,
-       EOG_SAVE_RESPONSE_RETRY,
-       EOG_SAVE_RESPONSE_SKIP,
-       EOG_SAVE_RESPONSE_OVERWRITE,
-       EOG_SAVE_RESPONSE_CANCEL,
-       EOG_SAVE_RESPONSE_LAST
-} EogJobSaveResponse;
-
 struct _EogJobSave
 {
-       EogJob    parent;
-       GList    *images;
-       guint      current_pos;
-       EogImage *current_image;
+       EogJob           parent;
+
+       GList           *images;
+       EogImage        *current_image;
+       guint            current_position;
 };
 
 struct _EogJobSaveClass
 {
-       EogJobClass parent_class;
+       EogJobClass      parent_class;
 };
 
 struct _EogJobSaveAs
 {
        EogJobSave       parent;
+
        EogURIConverter *converter;
        GFile           *file;
 };
 
 struct _EogJobSaveAsClass
 {
-       EogJobSaveClass parent;
+       EogJobSaveClass  parent;
 };
 
-struct _EogJobCopy
+struct _EogJobThumbnail
 {
-       EogJob parent;
-       GList *images;
-       guint current_pos;
-       gchar *dest;
+       EogJob           parent;
+
+       EogImage        *image;
+       GdkPixbuf       *thumbnail;
 };
 
-struct _EogJobCopyClass
+struct _EogJobThumbnailClass
 {
-       EogJobClass parent_class;
+       EogJobClass      parent_class;
 };
 
-/* base job class */
-GType           eog_job_get_type           (void) G_GNUC_CONST;
-void            eog_job_finished           (EogJob          *job);
-void            eog_job_run                (EogJob          *job);
-void            eog_job_set_progress       (EogJob          *job,
-                                           float            progress);
+struct _EogJobTransform
+{
+       EogJob           parent;
 
-/* EogJobThumbnail */
-GType           eog_job_thumbnail_get_type (void) G_GNUC_CONST;
-EogJob         *eog_job_thumbnail_new      (EogImage     *image);
+       GList           *images;
+       EogTransform    *transform;
+};
+
+struct _EogJobTransformClass
+{
+        EogJobClass      parent_class;
+};
+
+
+/* EogJob */
+GType    eog_job_get_type           (void) G_GNUC_CONST;
+
+void     eog_job_run                (EogJob          *job);
+void     eog_job_cancel             (EogJob          *job);
+
+gfloat   eog_job_get_progress       (EogJob          *job);
+void     eog_job_set_progress       (EogJob          *job,
+                                    gfloat           progress);
+gboolean eog_job_is_cancelled       (EogJob          *job);
+gboolean eog_job_is_finished        (EogJob          *job);
+
+/* EogJobCopy */
+GType    eog_job_copy_get_type      (void) G_GNUC_CONST;
+EogJob  *eog_job_copy_new           (GList           *images,
+                                    const gchar     *destination);
 
 /* EogJobLoad */
-GType           eog_job_load_get_type      (void) G_GNUC_CONST;
-EogJob                *eog_job_load_new           (EogImage        *image,
-                                           EogImageData     data);
+GType    eog_job_load_get_type      (void) G_GNUC_CONST;
 
-/* EogJobModel */
-GType          eog_job_model_get_type     (void) G_GNUC_CONST;
-EogJob                *eog_job_model_new          (GSList          *file_list);
+EogJob  *eog_job_load_new           (EogImage        *image,
+                                    EogImageData     data);
 
-/* EogJobTransform */
-GType          eog_job_transform_get_type (void) G_GNUC_CONST;
-EogJob                *eog_job_transform_new      (GList           *images,
-                                           EogTransform    *trans);
+/* EogJobModel */
+GType   eog_job_model_get_type     (void) G_GNUC_CONST;
+EogJob         *eog_job_model_new          (GSList          *file_list);
 
 /* EogJobSave */
-GType          eog_job_save_get_type      (void) G_GNUC_CONST;
-EogJob         *eog_job_save_new           (GList           *images);
+GType    eog_job_save_get_type      (void) G_GNUC_CONST;
+EogJob  *eog_job_save_new           (GList           *images);
 
 /* EogJobSaveAs */
-GType          eog_job_save_as_get_type   (void) G_GNUC_CONST;
-EogJob         *eog_job_save_as_new        (GList           *images,
-                                           EogURIConverter *converter,
-                                           GFile           *file);
-
-/*EogJobCopy */
-GType          eog_job_copy_get_type      (void) G_GNUC_CONST;
-EogJob        *eog_job_copy_new           (GList            *images,
-                                          const gchar      *dest);
+GType    eog_job_save_as_get_type   (void) G_GNUC_CONST;
+EogJob  *eog_job_save_as_new        (GList           *images,
+                                    EogURIConverter *converter,
+                                    GFile           *file);
+
+/* EogJobThumbnail */
+GType    eog_job_thumbnail_get_type (void) G_GNUC_CONST;
+EogJob  *eog_job_thumbnail_new      (EogImage        *image);
+
+/* EogJobTransform */
+GType   eog_job_transform_get_type (void) G_GNUC_CONST;
+EogJob  *eog_job_transform_new      (GList           *images,
+                                    EogTransform    *transform);
 
 G_END_DECLS
 
diff --git a/src/eog-list-store.c b/src/eog-list-store.c
index b6c907b..3aa4d2f 100644
--- a/src/eog-list-store.c
+++ b/src/eog-list-store.c
@@ -24,7 +24,7 @@
 #include "eog-list-store.h"
 #include "eog-thumbnail.h"
 #include "eog-image.h"
-#include "eog-job-queue.h"
+#include "eog-job-scheduler.h"
 #include "eog-jobs.h"
 
 #include <string.h>
@@ -812,7 +812,7 @@ eog_list_store_remove_thumbnail_job (EogListStore *store,
 
        if (job != NULL) {
                g_mutex_lock (&store->priv->mutex);
-               eog_job_queue_remove_job (job);
+               eog_job_cancel (job);
                gtk_list_store_set (GTK_LIST_STORE (store), iter,
                                    EOG_LIST_STORE_EOG_JOB, NULL,
                                    -1);
@@ -849,7 +849,7 @@ eog_list_store_add_thumbnail_job (EogListStore *store, GtkTreeIter *iter)
        gtk_list_store_set (GTK_LIST_STORE (store), iter,
                            EOG_LIST_STORE_EOG_JOB, job,
                            -1);
-       eog_job_queue_add_job (job);
+       eog_job_scheduler_add_job (job);
        g_mutex_unlock (&store->priv->mutex);
        g_object_unref (job);
        g_object_unref (image);
diff --git a/src/eog-thumb-view.c b/src/eog-thumb-view.c
index 1a6cd57..c9fc638 100644
--- a/src/eog-thumb-view.c
+++ b/src/eog-thumb-view.c
@@ -26,7 +26,7 @@
 #include "eog-thumb-view.h"
 #include "eog-list-store.h"
 #include "eog-image.h"
-#include "eog-job-queue.h"
+#include "eog-job-scheduler.h"
 
 #ifdef HAVE_EXIF
 #include "eog-exif-util.h"
@@ -615,7 +615,7 @@ thumbview_on_query_tooltip_cb (GtkWidget  *widget,
                g_signal_connect (G_OBJECT (job), "finished",
                                  G_CALLBACK (on_data_loaded_cb),
                                  widget);
-               eog_job_queue_add_job (job);
+               eog_job_scheduler_add_job (job);
                g_object_unref (image);
                g_object_unref (job);
                return FALSE;
diff --git a/src/eog-window.c b/src/eog-window.c
index a830d3e..5113e03 100644
--- a/src/eog-window.c
+++ b/src/eog-window.c
@@ -47,7 +47,7 @@
 #include "eog-application-internal.h"
 #include "eog-thumb-nav.h"
 #include "eog-config-keys.h"
-#include "eog-job-queue.h"
+#include "eog-job-scheduler.h"
 #include "eog-jobs.h"
 #include "eog-util.h"
 #include "eog-save-as-dialog-helper.h"
@@ -1106,7 +1106,7 @@ eog_window_clear_load_job (EogWindow *window)
 
        if (priv->load_job != NULL) {
                if (!priv->load_job->finished)
-                       eog_job_queue_remove_job (priv->load_job);
+                       eog_job_cancel (priv->load_job);
 
                g_signal_handlers_disconnect_by_func (priv->load_job,
                                                      eog_job_progress_cb,
@@ -1172,7 +1172,7 @@ eog_job_save_progress_cb (EogJobSave *job, float progress, gpointer user_data)
                 * - the total number of images queued for saving */
                status_message = g_strdup_printf (_("Saving image \"%s\" (%u/%u)"),
                                                  str_image,
-                                                 job->current_pos + 1,
+                                                 job->current_position + 1,
                                                  n_images);
                g_free (str_image);
 
@@ -1413,7 +1413,7 @@ eog_window_clear_transform_job (EogWindow *window)
 
        if (priv->transform_job != NULL) {
                if (!priv->transform_job->finished)
-                       eog_job_queue_remove_job (priv->transform_job);
+                       eog_job_cancel (priv->transform_job);
 
                g_signal_handlers_disconnect_by_func (priv->transform_job,
                                                      eog_job_transform_cb,
@@ -1477,7 +1477,7 @@ apply_transformation (EogWindow *window, EogTransform *trans)
                          G_CALLBACK (eog_job_progress_cb),
                          window);
 
-       eog_job_queue_add_job (priv->transform_job);
+       eog_job_scheduler_add_job (priv->transform_job);
 }
 
 static void
@@ -1546,7 +1546,7 @@ handle_image_selection_changed_cb (EogThumbView *thumbview, EogWindow *window)
                          G_CALLBACK (eog_job_progress_cb),
                          window);
 
-       eog_job_queue_add_job (priv->load_job);
+       eog_job_scheduler_add_job (priv->load_job);
 
        str_image = eog_image_get_uri_for_display (image);
 
@@ -2407,7 +2407,7 @@ close_confirmation_dialog_response_handler (EogCloseConfirmationDialog *dlg,
                                          G_CALLBACK (eog_job_close_save_cb),
                                          window);
 
-                       eog_job_queue_add_job (priv->save_job);
+                       eog_job_scheduler_add_job (priv->save_job);
                }
 
                break;
@@ -2883,14 +2883,14 @@ eog_job_copy_cb (EogJobCopy *job, gpointer user_data)
 
        /* Create source GFile */
        basename = g_file_get_basename (job->images->data);
-       filepath = g_build_filename (job->dest, basename, NULL);
+       filepath = g_build_filename (job->destination, basename, NULL);
        source_file = g_file_new_for_path (filepath);
        g_free (filepath);
 
        /* Create destination GFile */
        extension = eog_util_filename_get_extension (basename);
        filename = g_strdup_printf  ("%s.%s", EOG_WALLPAPER_FILENAME, extension);
-       filepath = g_build_filename (job->dest, filename, NULL);
+       filepath = g_build_filename (job->destination, filename, NULL);
        dest_file = g_file_new_for_path (filepath);
        g_free (filename);
        g_free (extension);
@@ -2970,7 +2970,7 @@ eog_window_cmd_save (GtkAction *action, gpointer user_data)
        images = eog_thumb_view_get_selected_images (EOG_THUMB_VIEW (priv->thumbview));
 
        if (eog_window_save_images (window, images)) {
-               eog_job_queue_add_job (priv->save_job);
+               eog_job_scheduler_add_job (priv->save_job);
        }
 }
 
@@ -3095,7 +3095,7 @@ eog_window_cmd_save_as (GtkAction *action, gpointer user_data)
                          G_CALLBACK (eog_job_save_progress_cb),
                          window);
 
-       eog_job_queue_add_job (priv->save_job);
+       eog_job_scheduler_add_job (priv->save_job);
 }
 
 static void
@@ -3268,7 +3268,7 @@ eog_window_cmd_wallpaper (GtkAction *action, gpointer user_data)
                                  "progress",
                                  G_CALLBACK (eog_job_progress_cb),
                                  window);
-               eog_job_queue_add_job (priv->copy_job);
+               eog_job_scheduler_add_job (priv->copy_job);
 
                g_object_unref (file);
                g_free (filename);
@@ -5720,7 +5720,7 @@ eog_window_open_file_list (EogWindow *window, GSList *file_list)
                          G_CALLBACK (eog_job_model_cb),
                          window);
 
-       eog_job_queue_add_job (job);
+       eog_job_scheduler_add_job (job);
        g_object_unref (job);
 }
 
diff --git a/src/main.c b/src/main.c
index 5cdf002..7ae06d5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -33,7 +33,7 @@
 #include "eog-session.h"
 #include "eog-debug.h"
 #include "eog-thumbnail.h"
-#include "eog-job-queue.h"
+#include "eog-job-scheduler.h"
 #include "eog-application.h"
 #include "eog-application-internal.h"
 #include "eog-plugin-engine.h"
@@ -145,7 +145,7 @@ main (int argc, char **argv)
        xmp_init();
 #endif
        eog_debug_init ();
-       eog_job_queue_init ();
+       eog_job_scheduler_init ();
        gdk_threads_init ();
        eog_thumbnail_init ();
 


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