diff --git a/gladeui/Makefile.am b/gladeui/Makefile.am
index 6210af1..71cf598 100644
--- a/gladeui/Makefile.am
+++ b/gladeui/Makefile.am
@@ -89,7 +89,8 @@ libgladeui_2_la_SOURCES = \
 	glade-name-context.c \
 	glade-displayable-values.c \
 	glade-signal-model.c \
-	glade-cell-renderer-icon.c
+	glade-cell-renderer-icon.c \
+  glade-preview.c
 
 libgladeui_2_la_CPPFLAGS =  \
 	$(common_defines)   \
diff --git a/gladeui/glade-previewer.c b/gladeui/glade-previewer.c
index 295950b..c22a15f 100644
--- a/gladeui/glade-previewer.c
+++ b/gladeui/glade-previewer.c
@@ -32,6 +32,8 @@
 #include <locale.h>
 #include <glib/gi18n-lib.h>
 
+#include "glade-preview-tokens.h"
+
 static void
 display_help_and_quit (const GOptionEntry * entries)
 {
@@ -171,7 +173,7 @@ get_toplevel (gchar * name, gchar * string, gsize length)
   return toplevel;
 }
 
-static void
+static GtkWidget *
 preview_widget (gchar * name, gchar * buffer, gsize length)
 {
   GtkWidget *widget;
@@ -200,6 +202,8 @@ preview_widget (gchar * name, gchar * buffer, gsize length)
 
   g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
   gtk_widget_show_all (window);
+
+	return widget;
 }
 
 static GIOChannel *
@@ -259,7 +263,7 @@ read_buffer (GIOChannel * source)
     }
 
   /* Check for quit token */
-  if (g_strcmp0 ("<quit>", token) == 0)
+  if (g_strcmp0 (QUIT_TOKEN, token) == 0)
     {
       g_free (token);
       return NULL;
@@ -287,11 +291,116 @@ read_buffer (GIOChannel * source)
   return buffer;
 }
 
+static void
+copy_window_properties (GtkWindow *old_window, GtkWindow *new_window)
+{
+	GParamSpec **properties_list;
+	guint i, n_properties;
+	gint width, height;
+	GValue copy_value = { 0,};
+
+	if (!old_window || !new_window) return;
+
+	properties_list = g_object_class_list_properties
+			  (G_OBJECT_GET_CLASS (G_OBJECT (new_window)),
+			  &n_properties);
+
+	for (i = 0; i < n_properties; i++)
+	{
+		if (!((properties_list[i]->flags & G_PARAM_READABLE) &&
+		      (properties_list[i]->flags & G_PARAM_WRITABLE) &&
+		      (!(properties_list[i]->flags & G_PARAM_CONSTRUCT_ONLY))
+		    )) continue;
+
+		/* We won't set some properties */
+		if (g_strcmp0 ("parent", properties_list[i]->name) == 0) continue;
+		if (g_strcmp0 ("visible", properties_list[i]->name) == 0) continue;
+
+		g_value_init (&copy_value, properties_list[i]->value_type);
+		g_object_get_property (G_OBJECT (new_window),
+				       properties_list[i]->name,
+				       &copy_value);
+
+		g_object_set_property (G_OBJECT (old_window),
+				       properties_list[i]->name,
+				       &copy_value);
+
+		g_value_unset (&copy_value);
+	}
+
+	/* Special code to copy default size */
+	if (gtk_window_get_resizable (old_window))
+	{
+		gtk_window_get_default_size (new_window, &width, &height);
+		if ((width > 0) && (height > 0))
+			gtk_window_resize (old_window, width, height);
+	}
+
+	if (properties_list) g_free (properties_list);
+}
+
+static void
+update_window (GtkWindow *old_window, GtkWindow *new_window)
+{
+	GtkWidget *window_child;
+	GtkWidget *old_window_child;
+
+	if (!old_window || !new_window) return;
+
+	/* ref the new window child */
+	window_child = gtk_bin_get_child (GTK_BIN (new_window));
+	if (window_child)
+	{
+		g_object_ref (window_child);
+
+		/* remove window child */
+		gtk_container_remove (GTK_CONTAINER (new_window), window_child);
+	}
+
+	/* gtk_widget_destroy the *running preview's* window child */
+	old_window_child = gtk_bin_get_child (GTK_BIN (old_window));
+	if (old_window_child)
+		gtk_widget_destroy (old_window_child);
+
+	/* apply properties from the new window to the
+	 * old window (using GObjectapis)*/
+	copy_window_properties (old_window, new_window);
+
+	/* add new preview's window child to the old preview's window */
+	if (window_child)
+	{
+		gtk_container_add (GTK_CONTAINER (old_window), window_child);
+		/* unref the newly added child (which we added a ref to before) */
+		g_object_unref (window_child);
+	}
+}
+
+static void
+update_window_child (GtkWindow *old_window, GtkWidget *new_widget)
+{
+	GtkWidget *old_window_child;
+
+	if (!old_window) return;
+
+	/* gtk_widget_destroy the *running preview's* window child */
+	old_window_child = gtk_bin_get_child (GTK_BIN (old_window));
+	if (old_window_child)
+		gtk_widget_destroy (old_window_child);
+
+	/* add new widget as child to the old preview's window */
+	if (new_widget)
+		gtk_container_add (GTK_CONTAINER (old_window), new_widget);
+}
+
 static gboolean
 on_data_incoming (GIOChannel * source, GIOCondition condition, gpointer data)
 {
+  printf("on_data_incoming\n");
   gchar *buffer;
   gsize length;
+	static GtkWidget *preview_window = NULL;
+  GtkWidget *new_widget;
+
 
   gchar *toplevel_name = (gchar *) data;
 
@@ -310,7 +419,23 @@ on_data_incoming (GIOChannel * source, GIOCondition condition, gpointer data)
 
   length = strlen (buffer);
 
-  preview_widget (toplevel_name, buffer, length);
+	/* if it is the first time this is called */
+	if (!preview_window)
+	{
+		preview_window = preview_widget (toplevel_name, buffer, length);
+	}
+	else
+	{
+    /* We have an update */
+		new_widget = get_toplevel (toplevel_name, buffer + UPDATE_TOKEN_SIZE,
+					   length - UPDATE_TOKEN_SIZE);
+
+		if (GTK_IS_WINDOW (new_widget))
+			update_window (GTK_WINDOW (preview_window),
+				       GTK_WINDOW (new_widget));
+		else update_window_child (GTK_WINDOW (preview_window), new_widget);
+	}
+
   g_free (buffer);
 
   return TRUE;
diff --git a/gladeui/glade-project.c b/gladeui/glade-project.c
index 5a36957..2044fbc 100644
--- a/gladeui/glade-project.c
+++ b/gladeui/glade-project.c
@@ -45,6 +45,8 @@
 #include "glade-marshallers.h"
 #include "glade-catalog.h"
 
+#include "glade-preview.h"
+
 #include "glade-project.h"
 #include "glade-command.h"
 #include "glade-name-context.h"
@@ -138,8 +140,14 @@ struct _GladeProjectPrivate
   GtkWidget *relative_path_entry;
   GtkWidget *full_path_button;
 
-  /* Store preview processes, so we can kill them on close */
-  GHashTable *preview_channels;
+ 	GtkWidget *auto_update_preview_checkbox;
+
+ 	/* Store previews, so we can kill them on close */
+ 	GHashTable *previews;
+
+ 	/* Wether we should auto-update previews */
+ 	gboolean auto_update_preview;
+
 
   /* For the loading progress bars ("load-progress" signal) */
   gint progress_step;
@@ -165,13 +173,6 @@ typedef struct
   gchar *filename;
 } StockFilePair;
 
-typedef struct
-{
-  GIOChannel *channel;
-  guint watch;
-} ChannelWatchPair;
-
-
 GType
 glade_pointer_mode_get_type (void)
 {
@@ -217,6 +218,10 @@ static void glade_project_verify_adaptor (GladeProject * project,
 
 static GtkWidget *glade_project_build_prefs_dialog (GladeProject * project);
 
+static void auto_preview_button_toggled (GtkWidget *widget,
+                                         GladeProject *project);
+
+
 static void target_button_clicked (GtkWidget * widget, GladeProject * project);
 static void update_prefs_for_resource_path (GladeProject * project);
 
@@ -644,66 +649,93 @@ glade_project_push_undo_impl (GladeProject * project, GladeCommand * cmd)
 static void
 glade_project_preview_exits (GPid pid, gint status, gpointer data)
 {
-  GladeProject *project = (GladeProject *) data;
-  ChannelWatchPair *channel_watch;
-  GIOChannel *channel;
-  gchar *pidstr = g_strdup_printf ("%d", pid);
-
-  channel_watch = g_hash_table_lookup (project->priv->preview_channels, pidstr);
-  channel = channel_watch->channel;
-  g_io_channel_unref (channel);
-  g_hash_table_remove (project->priv->preview_channels, pidstr);
-
-  g_free (pidstr);
-  g_free (channel_watch);
+ 	GladeProject *project = (GladeProject *)data;
+ 	GladePreview *preview;
+  printf ("glade_project_preview_exits\n");
+ 	gchar *pidstr = g_strdup_printf ("%d", pid);
+  printf ("pid of the preview which exited: %s.\n", pidstr);
+  
+ 	preview = g_hash_table_lookup (project->priv->previews, pidstr);
+ 	g_hash_table_remove (project->priv->previews, pidstr);
+  
+ 	g_free (pidstr);
+ 	g_object_unref (preview);
 }
 
 static void
 glade_project_kill_previews (gpointer key, gpointer value, gpointer user_data)
 {
-  const gchar *quit = "<quit>";
-  GIOChannel *channel;
-  ChannelWatchPair *channel_watch = (ChannelWatchPair *) value;
-  GError *error = NULL;
-  gsize size;
-
-  channel = channel_watch->channel;
-  /* Removing watch, since the child will commit suicide */
-  g_source_remove (channel_watch->watch);
-  g_io_channel_write_chars (channel, quit, strlen (quit), &size, &error);
-
-  if (size != strlen (quit) && error != NULL)
-    {
-      g_printerr ("Error passing quit signal trough pipe: %s", error->message);
-      g_error_free (error);
-    }
-
-  g_io_channel_flush (channel, &error);
-  if (error != NULL)
-    {
-      g_printerr ("Error flushing channel: %s", error->message);
-      g_error_free (error);
-    }
+ 	GladePreview *preview = GLADE_PREVIEW (value);
+  printf ("glade_project_kill_previews\n");
+ 	/* Removing watch, since the child will commit suicide */
+ 	glade_preview_remove_watch (preview);
+/*  g_signal_handlers_block_by_func (
+                            preview,
+                            G_CALLBACK (glade_project_preview_exits),
 
-  g_io_channel_shutdown (channel, TRUE, &error);
-  if (error != NULL)
-    {
-      g_printerr ("Error shutting down channel: %s", error->message);
-      g_error_free (error);
-    }
+                            user_data);*/
 
-  g_io_channel_unref (channel);
-  g_free (channel_watch);
+ 	glade_preview_kill_preview (preview);
+ 	g_object_unref (preview);
 }
 
 static void
 glade_project_close_impl (GladeProject * project)
 {
-  g_hash_table_foreach (project->priv->preview_channels,
+ 	if (!project->priv->previews) return;
+ 	g_hash_table_foreach (project->priv->previews,
                         glade_project_kill_previews, project);
-  g_hash_table_unref (project->priv->preview_channels);
+ 	g_hash_table_unref (project->priv->previews);
+ 	project->priv->previews = NULL;
 }
 
+static GladeXmlContext *glade_project_write (GladeProject *project);
+
+static void
+glade_project_update_previews (gpointer key,
+                     			     gpointer value,
+                     			     gpointer user_data)
+{
+ 	gchar *text;
+ 	GladePreview *preview = GLADE_PREVIEW (value);
+ 	GladeProject *project = GLADE_PROJECT (user_data);
+ 	GladeXmlContext *context;
+
+ 	context = glade_project_write (project);
+ 	text = glade_xml_dump_from_context (context);
+
+ 	glade_preview_update (text, preview);
+ 	g_free (text);
+}
+
+/* We don't want to update previews too often... */
+static gboolean
+glade_project_update_previews_idle (gpointer data)
+{
+ 	static GTimer *update_timer = NULL;
+ 	gboolean ret;
+ 
+ 	if (update_timer == NULL)
+ 	{
+ 		update_timer = g_timer_new();
+ 		ret = TRUE;
+ 	}
+ 	else if (g_timer_elapsed (update_timer, NULL) < 0.100) ret = TRUE;
+ 	else
+ 	{
+ 		GladeProject *project = GLADE_PROJECT (data);
+ 		if (project->priv->previews)
+ 			g_hash_table_foreach (project->priv->previews,
+ 			      		      glade_project_update_previews, project);
+ 		ret = FALSE;
+ 		g_timer_destroy (update_timer);
+ 		update_timer = NULL;
+ 	}
+
+ 	return ret;
+}
+
+
 static void
 glade_project_changed_impl (GladeProject * project,
                             GladeCommand * command, gboolean forward)
@@ -719,6 +751,9 @@ glade_project_changed_impl (GladeProject * project,
       else
         glade_project_set_modified (project, TRUE);
     }
+
+  if ((project->priv->previews) && (project->priv->auto_update_preview))
+ 		g_idle_add (glade_project_update_previews_idle, project);
 }
 
 
@@ -745,8 +780,10 @@ glade_project_init (GladeProject * project)
   priv->first_modification = NULL;
   priv->first_modification_is_na = FALSE;
 
-  priv->preview_channels =
-      g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	priv->previews = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                          g_free, NULL);
+	priv->auto_update_preview = FALSE;
+
   priv->widget_names = glade_name_context_new ();
 
   priv->accel_group = NULL;
@@ -1877,94 +1914,35 @@ glade_project_save (GladeProject * project, const gchar * path, GError ** error)
   return ret > 0;
 }
 
-static GPid
-glade_project_launch_preview (GladeProject * project, gchar * buffer,
-                              GtkWidget * widget)
+static gboolean
+glade_project_check_previewed_widget (gpointer key, gpointer value,
+                                      gpointer user_data)
 {
-  GPid pid;
-  GError *error = NULL;
-  gchar *argv[4];
-  gint child_stdin;
-  GIOChannel *output;
-  guint watch;
-  ChannelWatchPair *channel_watch;
-  GladeWidget *glade_widget;
-
-
-#ifdef WINDOWS
-  argv[0] =
-      g_build_filename (glade_app_get_bin_dir (), "glade-previewer.exe", NULL);
-#else
-  argv[0] =
-      g_build_filename (glade_app_get_bin_dir (), "glade-previewer", NULL);
-#endif
-
-
-  argv[1] = "--listen";
-
-  if (widget != NULL)
-    {
-      glade_widget = glade_widget_get_from_gobject (G_OBJECT (widget));
-      argv[2] = g_strdup_printf ("--toplevel=%s", glade_widget_get_name (glade_widget));
-      argv[3] = NULL;
-    }
-
-  if (g_spawn_async_with_pipes (NULL,
-                                argv,
-                                NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
-                                &pid, &child_stdin, NULL, NULL,
-                                &error) == FALSE)
-    {
-      g_printerr (_("Error launching previewer: %s\n"), error->message);
-      glade_util_ui_message (glade_app_get_window (),
-                             GLADE_UI_ERROR, NULL,
-                             _("Failed to launch preview: %s.\n"),
-                             error->message);
-      g_error_free (error);
-      pid = 0;
-      goto end;
-    }
-
-  /* Store watch so we can remove it later */
-  watch = g_child_watch_add (pid, glade_project_preview_exits, project);
-
-#ifdef WINDOWS
-  output = g_io_channel_win32_new_fd (child_stdin);
-#else
-  output = g_io_channel_unix_new (child_stdin);
-#endif
-
-  gsize bytes_written;
-  g_io_channel_write_chars (output, buffer, strlen (buffer), &bytes_written,
-                            &error);
-
-  if (bytes_written != strlen (buffer) && error != NULL)
-    {
-      g_printerr ("Error passing UI trough pipe: %s", error->message);
-      g_error_free (error);
-    }
-
-  g_io_channel_flush (output, &error);
-  if (error != NULL)
-    {
-      g_printerr ("Error flushing UI trough pipe: %s", error->message);
-      g_error_free (error);
-    }
-
-  if (widget != NULL)
-    g_free (argv[2]);
-
-  /* Adding channel to list of channels */
-  channel_watch = g_new (ChannelWatchPair, 1);
-  channel_watch->channel = output;
-  channel_watch->watch = watch;
-  g_hash_table_insert (project->priv->preview_channels,
-                       g_strdup_printf ("%d", pid), channel_watch);
+ 	if (!key || !value || !user_data) return FALSE;
+ 	GladePreview *preview = GLADE_PREVIEW (value);
+ 	GtkWidget *widget = (GtkWidget *)user_data;
+ 	return glade_preview_get_widget (preview) == widget;
+}
 
-end:
-  g_free (argv[0]);
-  return pid;
+static GladePreview*
+glade_project_has_preview (GladeProject *project, GtkWidget *widget)
+{
+ 	if (!project->priv->previews) return FALSE;
+ 	return g_hash_table_find(
+ 			project->priv->previews,
+ 			glade_project_check_previewed_widget,
+ 			widget);
 }
+  
+static void
+glade_project_add_preview (GladePreview *preview, GladeProject *project)
+{
+  printf ("glade_project_add_preview\n");
+ 	g_hash_table_insert (project->priv->previews,
+ 			     g_strdup_printf("%d", glade_preview_get_pid (preview)),
+ 			     preview);
+}
+
 
 /**
  * glade_project_preview:
@@ -1982,6 +1960,10 @@ glade_project_preview (GladeProject * project, GladeWidget * gwidget)
   GladeXmlContext *context;
   gchar *text;
   GtkWidget *widget;
+	GladePreview *preview;
+
+  printf ("glade_project_preview\n");
+
 
   g_return_if_fail (GLADE_IS_PROJECT (project));
 
@@ -1994,7 +1976,37 @@ glade_project_preview (GladeProject * project, GladeWidget * gwidget)
     return;
   widget = GTK_WIDGET (glade_widget_get_object (gwidget));
 
-  glade_project_launch_preview (project, text, widget);
+ 	preview = glade_project_has_preview (project, widget);
+ 	if(!preview)
+  {
+    printf ("Here!\n");
+ 		preview = glade_preview_launch_preview (text, widget);
+ 		glade_preview_add_watch (preview, glade_project_preview_exits, project);
+    printf ("Watch really added.\n");
+    /*g_signal_connect (preview, "exits",
+                      G_CALLBACK (glade_project_preview_exits),
+                      project);*/
+
+    /*printf ("Connecting instance %p to callback %p with data %p.\n",
+            preview, glade_project_preview_exit_callback, project);
+
+    g_signal_connect (preview, "exits",
+                      G_CALLBACK (glade_project_preview_exit_callback),
+                      project);
+
+    // Just to test it, we'll block it.
+    g_signal_handlers_block_by_func (
+                            preview,
+                            G_CALLBACK (glade_project_preview_exit_callback),
+                            project);*/
+    
+ 		/* Add preview to list of previews */
+ 		glade_project_add_preview (preview, project);
+ 	}
+ 	else
+ 	{
+ 		glade_preview_update (text, preview);
+	}
 
   g_free (text);
 }
@@ -2810,6 +2822,7 @@ glade_project_remove_object (GladeProject * project, GObject * object)
 {
   GladeWidget *gwidget;
   GList *list, *children;
+	GladePreview *preview = NULL;
 
   g_return_if_fail (GLADE_IS_PROJECT (project));
   g_return_if_fail (G_IS_OBJECT (object));
@@ -2850,6 +2863,15 @@ glade_project_remove_object (GladeProject * project, GObject * object)
   glade_widget_set_project (gwidget, NULL);
   glade_widget_set_in_project (gwidget, FALSE);
   g_object_unref (gwidget);
+
+ 	/* Check if there is a preview of such object */
+ 	if (project->priv->previews)
+ 	preview = g_hash_table_find (project->priv->previews,
+                    				   glade_project_check_previewed_widget,
+                    				   GTK_WIDGET(object));
+
+ 	if (preview)
+  	glade_preview_kill_preview (preview);
 }
 
 /*******************************************************************
@@ -3638,6 +3660,25 @@ resource_full_path_set (GtkFileChooserButton * button, GladeProject * project)
   glade_project_set_resource_path (project, text);
 }
 
+static void
+auto_preview_button_toggled (GtkWidget *widget,
+			     GladeProject *project)
+{
+	GtkToggleButton *auto_update_preview =
+          GTK_TOGGLE_BUTTON (project->priv->auto_update_preview_checkbox);
+	printf("Changed!\n");
+
+	project->priv->auto_update_preview =
+      gtk_toggle_button_get_active (auto_update_preview);
+
+	if (project->priv->auto_update_preview)
+	{
+		if ((project->priv->previews) && (project->priv->auto_update_preview))
+			g_idle_add (glade_project_update_previews_idle, project);
+		printf("marked!\n");
+	}
+}
+
 
 static void
 update_prefs_for_resource_path (GladeProject * project)
@@ -3719,6 +3760,39 @@ glade_project_build_prefs_box (GladeProject * project)
   gtk_container_add (GTK_CONTAINER (main_alignment), main_box);
   gtk_container_add (GTK_CONTAINER (main_frame), main_alignment);
 
+	/* Preview auto update */
+	string    = g_strdup_printf ("<b>%s</b>", _("Previews auto update:"));
+	frame     = gtk_frame_new (NULL);
+	vbox      = gtk_vbox_new (FALSE, 0);
+	alignment = gtk_alignment_new (0.5F, 0.5F, 0.8F, 0.8F);
+	gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 8, 0, 12, 0);
+	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+	label = gtk_label_new (string);
+	g_free (string);
+	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+
+	gtk_box_pack_start (GTK_BOX (main_box), frame, TRUE, TRUE, 2);
+	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+	gtk_container_add (GTK_CONTAINER (frame), alignment);
+	gtk_container_add (GTK_CONTAINER (alignment), vbox);
+
+	/* Project auto update previews... */
+	hbox = gtk_hbox_new (FALSE, 0);
+	project->priv->auto_update_preview_checkbox =
+      gtk_check_button_new_with_label (_("Auto update previews"));
+
+	gtk_box_pack_start (GTK_BOX (hbox),
+                      project->priv->auto_update_preview_checkbox,
+                      TRUE, TRUE, 0);
+
+	project->priv->relative_path_entry = gtk_entry_new ();
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+	gtk_size_group_add_widget (sizegroup, hbox);
+
+	g_signal_connect (G_OBJECT (project->priv->auto_update_preview_checkbox),
+                    "toggled",
+                    G_CALLBACK (auto_preview_button_toggled), project);
+
   /* Resource path */
   string =
       g_strdup_printf ("<b>%s</b>", _("Image resources are loaded locally:"));
