changeset 1012:fe82830ab8fd

converted image loader to a GObject and use signals for notification
author nadvornik
date Fri, 29 Aug 2008 20:53:53 +0000
parents 616b14da08c2
children 88ebc61e33ae
files configure.in src/Makefile.am src/cache-loader.c src/dupe.c src/gq-marshal.c src/gq-marshal.h src/gq-marshal.list src/image-load.c src/image-load.h src/image.c src/pan-view.c src/print.c src/search.c src/thumb.c src/thumb_standard.c src/typedefs.h
diffstat 16 files changed, 405 insertions(+), 184 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Fri Aug 29 12:35:13 2008 +0000
+++ b/configure.in	Fri Aug 29 20:53:53 2008 +0000
@@ -191,6 +191,7 @@
 
 AM_PATH_GTK_2_0(2.4.0,,AC_MSG_ERROR(GTK+ >= 2.4.0 not installed.))
 AC_PATH_PROGS(GDK_PIXBUF_CSOURCE, "gdk-pixbuf-csource")
+AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
 
 AC_ARG_WITH(readmedir, [  --with-readmedir=DIR    install path for readme files],
             readmedir=$withval, readmedir="$prefix/share/doc/geeqie-$VERSION")
--- a/src/Makefile.am	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/Makefile.am	Fri Aug 29 20:53:53 2008 +0000
@@ -121,6 +121,8 @@
 	filedata.h	\
 	filefilter.c	\
 	filefilter.h	\
+	gq-marshal.c	\
+	gq-marshal.h	\
 	format_canon.c	\
 	format_canon.h	\
 	format_fuji.c	\
@@ -227,3 +229,11 @@
 EXTRA_DIST = \
 	$(extra_SLIK)
 
+gq-marshal.h: gq-marshal.list
+	$(GLIB_GENMARSHAL) --prefix=gq_marshal gq-marshal.list --header >$@
+
+gq-marshal.c: gq-marshal.list
+	(echo "#include \"gq-marshal.h\"" ; $(GLIB_GENMARSHAL) --prefix=gq_marshal gq-marshal.list --body ) >$@
+
+
+
--- a/src/cache-loader.c	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/cache-loader.c	Fri Aug 29 20:53:53 2008 +0000
@@ -48,8 +48,9 @@
 		if (!cl->il && !cl->error)
 			{
 			cl->il = image_loader_new(cl->fd);
-			image_loader_set_error_func(cl->il, cache_loader_error_cb, cl);
-			if (image_loader_start(cl->il, cache_loader_done_cb, cl))
+			g_signal_connect (G_OBJECT(cl->il), "error", (GCallback)cache_loader_error_cb, cl);
+			g_signal_connect (G_OBJECT(cl->il), "done", (GCallback)cache_loader_done_cb, cl);
+			if (image_loader_start(cl->il))
 				{
 				return FALSE;
 				}
--- a/src/dupe.c	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/dupe.c	Fri Aug 29 20:53:53 2008 +0000
@@ -1534,9 +1534,10 @@
 
 					dw->img_loader = image_loader_new(di->fd);
 					image_loader_set_buffer_size(dw->img_loader, 8);
-					image_loader_set_error_func(dw->img_loader, dupe_loader_done_cb, dw);
-
-					if (!image_loader_start(dw->img_loader, dupe_loader_done_cb, dw))
+					g_signal_connect (G_OBJECT(dw->img_loader), "error", (GCallback)dupe_loader_done_cb, dw);
+					g_signal_connect (G_OBJECT(dw->img_loader), "done", (GCallback)dupe_loader_done_cb, dw);
+
+					if (!image_loader_start(dw->img_loader))
 						{
 						image_sim_free(di->simd);
 						di->simd = image_sim_new();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gq-marshal.c	Fri Aug 29 20:53:53 2008 +0000
@@ -0,0 +1,95 @@
+#include "gq-marshal.h"
+
+#include	<glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:VOID (gq-marshal.list:1) */
+
+/* VOID:INT,INT,INT,INT (gq-marshal.list:2) */
+void
+gq_marshal_VOID__INT_INT_INT_INT (GClosure     *closure,
+                                  GValue       *return_value G_GNUC_UNUSED,
+                                  guint         n_param_values,
+                                  const GValue *param_values,
+                                  gpointer      invocation_hint G_GNUC_UNUSED,
+                                  gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__INT_INT_INT_INT) (gpointer     data1,
+                                                      gint         arg_1,
+                                                      gint         arg_2,
+                                                      gint         arg_3,
+                                                      gint         arg_4,
+                                                      gpointer     data2);
+  register GMarshalFunc_VOID__INT_INT_INT_INT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 5);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__INT_INT_INT_INT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_int (param_values + 1),
+            g_marshal_value_peek_int (param_values + 2),
+            g_marshal_value_peek_int (param_values + 3),
+            g_marshal_value_peek_int (param_values + 4),
+            data2);
+}
+
+/* VOID:DOUBLE (gq-marshal.list:3) */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gq-marshal.h	Fri Aug 29 20:53:53 2008 +0000
@@ -0,0 +1,26 @@
+
+#ifndef __gq_marshal_MARSHAL_H__
+#define __gq_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:VOID (gq-marshal.list:1) */
+#define gq_marshal_VOID__VOID	g_cclosure_marshal_VOID__VOID
+
+/* VOID:INT,INT,INT,INT (gq-marshal.list:2) */
+extern void gq_marshal_VOID__INT_INT_INT_INT (GClosure     *closure,
+                                              GValue       *return_value,
+                                              guint         n_param_values,
+                                              const GValue *param_values,
+                                              gpointer      invocation_hint,
+                                              gpointer      marshal_data);
+
+/* VOID:DOUBLE (gq-marshal.list:3) */
+#define gq_marshal_VOID__DOUBLE	g_cclosure_marshal_VOID__DOUBLE
+
+G_END_DECLS
+
+#endif /* __gq_marshal_MARSHAL_H__ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gq-marshal.list	Fri Aug 29 20:53:53 2008 +0000
@@ -0,0 +1,3 @@
+VOID:VOID
+VOID:INT,INT,INT,INT
+VOID:DOUBLE
--- a/src/image-load.c	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/image-load.c	Fri Aug 29 20:53:53 2008 +0000
@@ -17,10 +17,156 @@
 #include "exif.h"
 #include "filedata.h"
 #include "ui_fileops.h"
+#include "gq-marshal.h"
 
 #include <fcntl.h>
 #include <sys/mman.h>
 
+enum {
+	SIGNAL_AREA_READY = 0,
+	SIGNAL_ERROR,
+	SIGNAL_DONE,
+	SIGNAL_PERCENT,
+	SIGNAL_COUNT
+};
+
+static guint signals[SIGNAL_COUNT] = { 0 };
+
+static void image_loader_init (GTypeInstance *instance, gpointer g_class);
+static void image_loader_class_init (ImageLoaderClass *class);
+static void image_loader_finalize(GObject *object);
+static void image_loader_stop(ImageLoader *il);
+
+GType image_loader_get_type (void)
+{
+	static GType type = 0;
+	if (type == 0) 
+		{
+		static const GTypeInfo info = {
+			sizeof (ImageLoaderClass),
+			NULL,   /* base_init */
+			NULL,   /* base_finalize */
+			(GClassInitFunc)image_loader_class_init, /* class_init */
+			NULL,   /* class_finalize */
+			NULL,   /* class_data */
+			sizeof (ImageLoader),
+			0,      /* n_preallocs */
+			(GInstanceInitFunc)image_loader_init, /* instance_init */
+			};
+		type = g_type_register_static (G_TYPE_OBJECT, "ImageLoaderType", &info, 0);
+		}
+	return type;
+}
+
+static void image_loader_init (GTypeInstance *instance, gpointer g_class)
+{
+	ImageLoader *il = (ImageLoader *)instance;
+
+	il->pixbuf = NULL;
+	il->idle_id = -1;
+	il->idle_priority = G_PRIORITY_DEFAULT_IDLE;
+	il->done = FALSE;
+	il->loader = NULL;
+
+	il->bytes_read = 0;
+	il->bytes_total = 0;
+
+	il->idle_done_id = -1;
+
+	il->idle_read_loop_count = options->image.idle_read_loop_count;
+	il->read_buffer_size = options->image.read_buffer_size;
+	il->mapped_file = NULL;
+
+	il->requested_width = 0;
+	il->requested_height = 0;
+	il->shrunk = FALSE;
+	DEBUG_1("new image loader %p, bufsize=%u idle_loop=%u", il, il->read_buffer_size, il->idle_read_loop_count);
+}
+
+static void image_loader_class_init (ImageLoaderClass *class)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+
+//	gobject_class->set_property = image_loader_set_property;
+//	gobject_class->get_property = image_loader_get_property;
+
+	gobject_class->finalize = image_loader_finalize;
+
+
+	signals[SIGNAL_AREA_READY] =
+		g_signal_new("area_ready",
+			     G_OBJECT_CLASS_TYPE(gobject_class),
+			     G_SIGNAL_RUN_LAST,
+			     G_STRUCT_OFFSET(ImageLoaderClass, area_ready),
+			     NULL, NULL,
+			     gq_marshal_VOID__INT_INT_INT_INT,
+			     G_TYPE_NONE, 4,
+			     G_TYPE_INT,
+			     G_TYPE_INT,
+			     G_TYPE_INT,
+			     G_TYPE_INT);
+
+	signals[SIGNAL_ERROR] =
+		g_signal_new("error",
+			     G_OBJECT_CLASS_TYPE(gobject_class),
+			     G_SIGNAL_RUN_LAST,
+			     G_STRUCT_OFFSET(ImageLoaderClass, error),
+			     NULL, NULL,
+			     g_cclosure_marshal_VOID__VOID,
+			     G_TYPE_NONE, 1,
+			     GDK_TYPE_EVENT);
+
+	signals[SIGNAL_DONE] =
+		g_signal_new("done",
+			     G_OBJECT_CLASS_TYPE(gobject_class),
+			     G_SIGNAL_RUN_LAST,
+			     G_STRUCT_OFFSET(ImageLoaderClass, done),
+			     NULL, NULL,
+			     g_cclosure_marshal_VOID__VOID,
+			     G_TYPE_NONE, 0);
+
+	signals[SIGNAL_PERCENT] =
+		g_signal_new("percent",
+			     G_OBJECT_CLASS_TYPE(gobject_class),
+			     G_SIGNAL_RUN_LAST,
+			     G_STRUCT_OFFSET(ImageLoaderClass, percent),
+			     NULL, NULL,
+			     g_cclosure_marshal_VOID__DOUBLE,
+			     G_TYPE_NONE, 1,
+			     G_TYPE_DOUBLE);
+
+}
+
+static void image_loader_finalize(GObject *object)
+{
+	ImageLoader *il = (ImageLoader *)object;
+
+	image_loader_stop(il);
+	if (il->idle_done_id != -1) g_source_remove(il->idle_done_id);
+	if (il->pixbuf) gdk_pixbuf_unref(il->pixbuf);
+	file_data_unref(il->fd);
+	DEBUG_1("freeing image loader %p bytes_read=%d", il, il->bytes_read);
+}
+
+void image_loader_free(ImageLoader *il)
+{
+	if (!il) return;
+	g_object_unref(G_OBJECT(il));
+}
+
+
+ImageLoader *image_loader_new(FileData *fd)
+{
+	ImageLoader *il;
+
+	if (!fd) return NULL;
+
+	il = (ImageLoader *) g_object_new(TYPE_IMAGE_LOADER, NULL);
+	
+	il->fd = file_data_ref(fd);
+	
+	return il;
+}
 
 static void image_loader_sync_pixbuf(ImageLoader *il)
 {
@@ -43,18 +189,15 @@
 {
 	ImageLoader *il = data;
 
-	if (il->func_area_ready)
+	if (!il->pixbuf)
 		{
+		image_loader_sync_pixbuf(il);
 		if (!il->pixbuf)
 			{
-			image_loader_sync_pixbuf(il);
-			if (!il->pixbuf)
-				{
-				log_printf("critical: area_ready signal with NULL pixbuf (out of mem?)\n");
-				}
+			log_printf("critical: area_ready signal with NULL pixbuf (out of mem?)\n");
 			}
-		il->func_area_ready(il, x, y, w, h, il->data_area_ready);
 		}
+	g_signal_emit(il, signals[SIGNAL_AREA_READY], 0, x, y, w, h);
 }
 
 static void image_loader_area_prepared_cb(GdkPixbufLoader *loader, gpointer data)
@@ -169,7 +312,7 @@
 {
 	image_loader_stop(il);
 
-	if (il->func_done) il->func_done(il, il->data_done);
+	g_signal_emit(il, signals[SIGNAL_DONE], 0);
 }
 
 static gint image_loader_done_delay_cb(gpointer data)
@@ -193,7 +336,7 @@
 
 	DEBUG_1("pixbuf_loader reported load error for: %s", il->fd->path);
 
-	if (il->func_error) il->func_error(il, il->data_error);
+	g_signal_emit(il, signals[SIGNAL_ERROR], 0);
 }
 
 static gint image_loader_idle_cb(gpointer data)
@@ -228,9 +371,9 @@
 		c--;
 		}
 
-	if (il->func_percent && il->bytes_total > 0)
+	if (il->bytes_total > 0)
 		{
-		il->func_percent(il, (gdouble)il->bytes_read / il->bytes_total, il->data_percent);
+		g_signal_emit(il, signals[SIGNAL_PERCENT], 0, (gdouble)il->bytes_read / il->bytes_total);
 		}
 
 	return TRUE;
@@ -362,47 +505,6 @@
 	return image_loader_begin(il);
 }
 
-ImageLoader *image_loader_new(FileData *fd)
-{
-	ImageLoader *il;
-
-	if (!fd) return NULL;
-
-	il = g_new0(ImageLoader, 1);
-	il->fd = file_data_ref(fd);
-	il->pixbuf = NULL;
-	il->idle_id = -1;
-	il->idle_priority = G_PRIORITY_DEFAULT_IDLE;
-	il->done = FALSE;
-	il->loader = NULL;
-
-	il->bytes_read = 0;
-	il->bytes_total = 0;
-
-	il->idle_done_id = -1;
-
-	il->idle_read_loop_count = options->image.idle_read_loop_count;
-	il->read_buffer_size = options->image.read_buffer_size;
-	il->mapped_file = NULL;
-
-	il->requested_width = 0;
-	il->requested_height = 0;
-	il->shrunk = FALSE;
-	DEBUG_1("new image loader %p, bufsize=%u idle_loop=%u", il, il->read_buffer_size, il->idle_read_loop_count);
-	return il;
-}
-
-void image_loader_free(ImageLoader *il)
-{
-	if (!il) return;
-
-	image_loader_stop(il);
-	if (il->idle_done_id != -1) g_source_remove(il->idle_done_id);
-	if (il->pixbuf) gdk_pixbuf_unref(il->pixbuf);
-	file_data_unref(il->fd);
-	DEBUG_1("freeing image loader %p bytes_read=%d", il, il->bytes_read);
-	g_free(il);
-}
 
 /* don't forget to gdk_pixbuf_ref() it if you want to use it after image_loader_free() */
 GdkPixbuf *image_loader_get_pixbuf(ImageLoader *il)
@@ -433,46 +535,6 @@
 	return mime;
 }
 
-void image_loader_set_area_ready_func(ImageLoader *il,
-				      void (*func_area_ready)(ImageLoader *, guint, guint, guint, guint, gpointer),
-				      gpointer data_area_ready)
-{
-	if (!il) return;
-
-	il->func_area_ready = func_area_ready;
-	il->data_area_ready = data_area_ready;
-}
-
-void image_loader_set_error_func(ImageLoader *il,
-				 void (*func_error)(ImageLoader *, gpointer),
-				 gpointer data_error)
-{
-	if (!il) return;
-
-	il->func_error = func_error;
-	il->data_error = data_error;
-}
-
-void image_loader_set_done_func(ImageLoader *il,
-				void (*func_done)(ImageLoader *, gpointer),
-				gpointer data_done)
-{
-	if (!il) return;
-
-	il->func_done = func_done;
-	il->data_done = data_done;
-}
-
-void image_loader_set_percent_func(ImageLoader *il,
-				   void (*func_percent)(ImageLoader *, gdouble, gpointer),
-				   gpointer data_percent)
-{
-	if (!il) return;
-
-	il->func_percent = func_percent;
-	il->data_percent = data_percent;
-}
-
 void image_loader_set_requested_size(ImageLoader *il, gint width, gint height)
 {
 	if (!il) return;
@@ -495,14 +557,12 @@
 	il->idle_priority = priority;
 }
 
-gint image_loader_start(ImageLoader *il, void (*func_done)(ImageLoader *, gpointer), gpointer data_done)
+gint image_loader_start(ImageLoader *il)
 {
 	if (!il) return FALSE;
 
 	if (!il->fd) return FALSE;
 
-	image_loader_set_done_func(il, func_done, data_done);
-
 	return image_loader_setup(il);
 }
 
@@ -544,7 +604,7 @@
 
 	il = image_loader_new(fd);
 
-	success = image_loader_start(il, NULL, NULL);
+	success = image_loader_start(il);
 
 	if (success && il->pixbuf)
 		{
--- a/src/image-load.h	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/image-load.h	Fri Aug 29 20:53:53 2008 +0000
@@ -14,23 +14,58 @@
 #ifndef IMAGE_LOAD_H
 #define IMAGE_LOAD_H
 
+#define TYPE_IMAGE_LOADER		(image_loader_get_type())
+
+//typedef struct _ImageLoader ImageLoader;
+typedef struct _ImageLoaderClass ImageLoaderClass;
+
+struct _ImageLoader
+{
+	GObject parent;
+	
+	/*< private >*/
+	GdkPixbuf *pixbuf;
+	FileData *fd;
+	gchar *path;
+
+	gint bytes_read;
+	gint bytes_total;
+
+	gint preview;
+
+	gint requested_width;
+	gint requested_height;
+	gint shrunk;
+
+	gint done;
+	gint idle_id;
+	gint idle_priority;
+
+	GdkPixbufLoader *loader;
+
+	gint idle_done_id;
+
+	guchar *mapped_file;
+	gint read_buffer_size;
+	gint idle_read_loop_count;
+};
+
+struct _ImageLoaderClass {
+	GObjectClass parent;
+	
+	/* class members */
+	void (*area_ready)(ImageLoader *, guint x, guint y, guint w, guint h, gpointer);
+	void (*error)(ImageLoader *, gpointer);
+	void (*done)(ImageLoader *, gpointer);
+	void (*percent)(ImageLoader *, gdouble, gpointer);
+};
+
+GType image_loader_get_type(void);
 
 ImageLoader *image_loader_new(FileData *fd);
 
 void image_loader_free(ImageLoader *il);
 
-void image_loader_set_area_ready_func(ImageLoader *il,
-				      void (*func_area_ready)(ImageLoader *, guint, guint, guint, guint, gpointer),
-				      gpointer data_area_ready);
-void image_loader_set_error_func(ImageLoader *il,
-				 void (*func_error)(ImageLoader *, gpointer),
-				 gpointer data_error);
-void image_loader_set_done_func(ImageLoader *il,
-				void (*func_done)(ImageLoader *, gpointer),
-				gpointer data_done);
-void image_loader_set_percent_func(ImageLoader *il,
-				   void (*func_percent)(ImageLoader *, gdouble, gpointer),
-				   gpointer data_percent);
 
 /* Speed up loading when you only need at most width x height size image,
  * only the jpeg GdkPixbuf loader benefits from it - so there is no
@@ -45,7 +80,7 @@
  */
 void image_loader_set_priority(ImageLoader *il, gint priority);
 
-gint image_loader_start(ImageLoader *il, void (*func_done)(ImageLoader *, gpointer), gpointer data_done);
+gint image_loader_start(ImageLoader *il);
 
 
 GdkPixbuf *image_loader_get_pixbuf(ImageLoader *il);
--- a/src/image.c	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/image.c	Fri Aug 29 20:53:53 2008 +0000
@@ -451,8 +451,10 @@
 
 	imd->read_ahead_il = image_loader_new(imd->read_ahead_fd);
 
-	image_loader_set_error_func(imd->read_ahead_il, image_read_ahead_error_cb, imd);
-	if (!image_loader_start(imd->read_ahead_il, image_read_ahead_done_cb, imd))
+	g_signal_connect (G_OBJECT(imd->read_ahead_il), "error", (GCallback)image_read_ahead_error_cb, imd);
+	g_signal_connect (G_OBJECT(imd->read_ahead_il), "error", (GCallback)image_read_ahead_done_cb, imd);
+
+	if (!image_loader_start(imd->read_ahead_il))
 		{
 		image_read_ahead_cancel(imd);
 		image_complete_util(imd, TRUE);
@@ -618,9 +620,10 @@
 		imd->read_ahead_il = NULL;
 
 		/* override the old signals */
-		image_loader_set_area_ready_func(imd->il, image_load_area_cb, imd);
-		image_loader_set_error_func(imd->il, image_load_error_cb, imd);
-		image_loader_set_done_func(imd->il, image_load_done_cb, imd);
+		g_signal_handlers_disconnect_matched(G_OBJECT(imd->il), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, imd);
+		g_signal_connect (G_OBJECT(imd->il), "area_ready", (GCallback)image_load_area_cb, imd);
+		g_signal_connect (G_OBJECT(imd->il), "error", (GCallback)image_load_error_cb, imd);
+		g_signal_connect (G_OBJECT(imd->il), "done", (GCallback)image_load_done_cb, imd);
 		image_loader_set_buffer_size(imd->il, IMAGE_LOAD_BUFFER_COUNT);
 
 #ifdef IMAGE_THROTTLE_LARGER_IMAGES
@@ -688,11 +691,12 @@
 
 	imd->il = image_loader_new(fd);
 
-	image_loader_set_area_ready_func(imd->il, image_load_area_cb, imd);
-	image_loader_set_error_func(imd->il, image_load_error_cb, imd);
+	g_signal_connect (G_OBJECT(imd->il), "area_ready", (GCallback)image_load_area_cb, imd);
+	g_signal_connect (G_OBJECT(imd->il), "error", (GCallback)image_load_error_cb, imd);
+	g_signal_connect (G_OBJECT(imd->il), "done", (GCallback)image_load_done_cb, imd);
 	image_loader_set_buffer_size(imd->il, IMAGE_LOAD_BUFFER_COUNT);
 
-	if (!image_loader_start(imd->il, image_load_done_cb, imd))
+	if (!image_loader_start(imd->il))
 		{
 		DEBUG_1("image start error");
 
@@ -1098,14 +1102,25 @@
 	return NULL;
 }
 
-static void image_loader_sync_data(ImageLoader *il, gpointer data)
+static void image_loader_sync_read_ahead_data(ImageLoader *il, gpointer old_data, gpointer data)
 {
-	/* change data for the callbacks directly */
+	if (g_signal_handlers_disconnect_by_func(G_OBJECT(il), (GCallback)image_read_ahead_error_cb, old_data))
+		g_signal_connect (G_OBJECT(il), "error", (GCallback)image_read_ahead_error_cb, data);
+
+	if (g_signal_handlers_disconnect_by_func(G_OBJECT(il), (GCallback)image_read_ahead_done_cb, old_data))
+		g_signal_connect (G_OBJECT(il), "done", (GCallback)image_read_ahead_done_cb, data);
+}
 
-	il->data_area_ready = data;
-	il->data_error = data;
-	il->data_done = data;
-	il->data_percent = data;
+static void image_loader_sync_data(ImageLoader *il, gpointer old_data, gpointer data)
+{		
+	if (g_signal_handlers_disconnect_by_func(G_OBJECT(il), (GCallback)image_load_area_cb, old_data))
+		g_signal_connect (G_OBJECT(il), "area_ready", (GCallback)image_load_area_cb, data);
+
+	if (g_signal_handlers_disconnect_by_func(G_OBJECT(il), (GCallback)image_load_error_cb, old_data))
+		g_signal_connect (G_OBJECT(il), "error", (GCallback)image_load_error_cb, data);
+
+	if (g_signal_handlers_disconnect_by_func(G_OBJECT(il), (GCallback)image_load_done_cb, old_data))
+		g_signal_connect (G_OBJECT(il), "done", (GCallback)image_load_done_cb, data);
 }
 
 /* this is more like a move function
@@ -1131,7 +1146,7 @@
 		imd->il = source->il;
 		source->il = NULL;
 
-		image_loader_sync_data(imd->il, imd);
+		image_loader_sync_data(imd->il, source, imd);
 
 		imd->delay_alter_type = source->delay_alter_type;
 		source->delay_alter_type = ALTER_NONE;
@@ -1158,7 +1173,7 @@
 	image_loader_free(imd->read_ahead_il);
 	imd->read_ahead_il = source->read_ahead_il;
 	source->read_ahead_il = NULL;
-	if (imd->read_ahead_il) image_loader_sync_data(imd->read_ahead_il, imd);
+	if (imd->read_ahead_il) image_loader_sync_read_ahead_data(imd->read_ahead_il, source, imd);
 
 	file_data_unref(imd->read_ahead_fd);
 	imd->read_ahead_fd = source->read_ahead_fd;
--- a/src/pan-view.c	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/pan-view.c	Fri Aug 29 20:53:53 2008 +0000
@@ -209,9 +209,10 @@
 #if 0
 		image_loader_set_area_ready_func(pw->il, pan_queue_image_area_cb, pw);
 #endif
-		image_loader_set_error_func(pw->il, pan_queue_image_done_cb, pw);
-
-		if (image_loader_start(pw->il, pan_queue_image_done_cb, pw)) return FALSE;
+		g_signal_connect (G_OBJECT(pw->il), "error", (GCallback)pan_queue_image_done_cb, pw);
+		g_signal_connect (G_OBJECT(pw->il), "done", (GCallback)pan_queue_image_done_cb, pw);
+
+		if (image_loader_start(pw->il)) return FALSE;
 
 		image_loader_free(pw->il);
 		pw->il = NULL;
--- a/src/print.c	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/print.c	Fri Aug 29 20:53:53 2008 +0000
@@ -2209,7 +2209,8 @@
 	if (!fd) return FALSE;
 
 	pw->job_loader = image_loader_new(fd);
-	if (!image_loader_start(pw->job_loader, print_job_render_image_loader_done, pw))
+	g_signal_connect (G_OBJECT(pw->job_loader), "done", (GCallback)print_job_render_image_loader_done, pw);
+	if (!image_loader_start(pw->job_loader))
 		{
 		image_loader_free(pw->job_loader);
 		pw->job_loader= NULL;
@@ -2355,7 +2356,8 @@
 
 	image_loader_free(pw->job_loader);
 	pw->job_loader = image_loader_new(fd);
-	if (!image_loader_start(pw->job_loader, print_job_render_proof_loader_done, pw))
+	g_signal_connect (G_OBJECT(pw->job_loader), "done", (GCallback)print_job_render_proof_loader_done, pw);
+	if (!image_loader_start(pw->job_loader))
 		{
 		image_loader_free(pw->job_loader);
 		pw->job_loader = NULL;
--- a/src/search.c	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/search.c	Fri Aug 29 20:53:53 2008 +0000
@@ -1583,8 +1583,9 @@
 		    (sd->match_similarity_enable && !sd->img_cd->similarity))
 			{
 			sd->img_loader = image_loader_new(fd);
-			image_loader_set_error_func(sd->img_loader, search_file_load_done_cb, sd);
-			if (image_loader_start(sd->img_loader, search_file_load_done_cb, sd))
+			g_signal_connect (G_OBJECT(sd->img_loader), "error", (GCallback)search_file_load_done_cb, sd);
+			g_signal_connect (G_OBJECT(sd->img_loader), "done", (GCallback)search_file_load_done_cb, sd);
+			if (image_loader_start(sd->img_loader))
 				{
 				return TRUE;
 				}
@@ -2063,8 +2064,9 @@
 				}
 
 			sd->img_loader = image_loader_new(file_data_new_simple(sd->search_similarity_path));
-			image_loader_set_error_func(sd->img_loader, search_similarity_load_done_cb, sd);
-			if (image_loader_start(sd->img_loader, search_similarity_load_done_cb, sd))
+			g_signal_connect (G_OBJECT(sd->img_loader), "error", (GCallback)search_similarity_load_done_cb, sd);
+			g_signal_connect (G_OBJECT(sd->img_loader), "done", (GCallback)search_similarity_load_done_cb, sd);
+			if (image_loader_start(sd->img_loader))
 				{
 				return;
 				}
--- a/src/thumb.c	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/thumb.c	Fri Aug 29 20:53:53 2008 +0000
@@ -168,8 +168,10 @@
 		tl->cache_hit = FALSE;
 
 		thumb_loader_setup(tl, tl->fd->path);
+	
+		g_signal_connect (G_OBJECT(tl->il), "done", (GCallback)thumb_loader_done_cb, tl);
 
-		if (!image_loader_start(tl->il, thumb_loader_done_cb, tl))
+		if (!image_loader_start(tl->il))
 			{
 			image_loader_free(tl->il);
 			tl->il = NULL;
@@ -278,8 +280,8 @@
 		image_loader_set_requested_size(tl->il, tl->max_w, tl->max_h);
 		}
 
-	image_loader_set_error_func(tl->il, thumb_loader_error_cb, tl);
-	if (tl->func_progress) image_loader_set_percent_func(tl->il, thumb_loader_percent_cb, tl);
+	g_signal_connect (G_OBJECT(tl->il), "error", (GCallback)thumb_loader_error_cb, tl);
+	if (tl->func_progress) g_signal_connect (G_OBJECT(tl->il), "percent", (GCallback)thumb_loader_percent_cb, tl);
 }
 
 void thumb_loader_set_callbacks(ThumbLoader *tl,
@@ -391,7 +393,8 @@
 		thumb_loader_setup(tl, tl->fd->path);
 		}
 
-	if (!image_loader_start(tl->il, thumb_loader_done_cb, tl))
+	g_signal_connect (G_OBJECT(tl->il), "done", (GCallback)thumb_loader_done_cb, tl);
+	if (!image_loader_start(tl->il))
 		{
 		/* try from original if cache attempt */
 		if (tl->cache_hit)
@@ -400,7 +403,8 @@
 			log_printf("%s", _("Thumbnail image in cache failed to load, trying to recreate.\n"));
 
 			thumb_loader_setup(tl, tl->fd->path);
-			if (image_loader_start(tl->il, thumb_loader_done_cb, tl)) return TRUE;
+			g_signal_connect (G_OBJECT(tl->il), "done", (GCallback)thumb_loader_done_cb, tl);
+			if (image_loader_start(tl->il)) return TRUE;
 			}
 		/* mark failed thumbnail in cache with 0 byte file */
 		if (tl->cache_enable)
--- a/src/thumb_standard.c	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/thumb_standard.c	Fri Aug 29 20:53:53 2008 +0000
@@ -620,13 +620,14 @@
 			}
 		}
 
-	image_loader_set_error_func(tl->il, thumb_loader_std_error_cb, tl);
+	g_signal_connect (G_OBJECT(tl->il), "error", (GCallback)thumb_loader_std_error_cb, tl);
 	if (tl->func_progress)
 		{
-		image_loader_set_percent_func(tl->il, thumb_loader_std_progress_cb, tl);
+		g_signal_connect (G_OBJECT(tl->il), "percent", (GCallback)thumb_loader_std_progress_cb, tl);
 		}
+	g_signal_connect (G_OBJECT(tl->il), "done", (GCallback)thumb_loader_std_done_cb, tl);
 
-	if (image_loader_start(tl->il, thumb_loader_std_done_cb, tl))
+	if (image_loader_start(tl->il))
 		{
 		return TRUE;
 		}
--- a/src/typedefs.h	Fri Aug 29 12:35:13 2008 +0000
+++ b/src/typedefs.h	Fri Aug 29 20:53:53 2008 +0000
@@ -207,43 +207,7 @@
 	gchar *command;
 };
 
-struct _ImageLoader
-{
-	GdkPixbuf *pixbuf;
-	FileData *fd;
-	gchar *path;
-
-	gint bytes_read;
-	gint bytes_total;
-
-	gint preview;
-
-	gint requested_width;
-	gint requested_height;
-	gint shrunk;
-
-	gint done;
-	gint idle_id;
-	gint idle_priority;
-
-	GdkPixbufLoader *loader;
-
-	void (*func_area_ready)(ImageLoader *, guint x, guint y, guint w, guint h, gpointer);
-	void (*func_error)(ImageLoader *, gpointer);
-	void (*func_done)(ImageLoader *, gpointer);
-	void (*func_percent)(ImageLoader *, gdouble, gpointer);
-
-	gpointer data_area_ready;
-	gpointer data_error;
-	gpointer data_done;
-	gpointer data_percent;
-
-	gint idle_done_id;
-
-	guchar *mapped_file;
-	gint read_buffer_size;
-	gint idle_read_loop_count;
-};
+struct _ImageLoader;
 
 typedef void (* ThumbLoaderFunc)(ThumbLoader *tl, gpointer data);