glade3 r1972 - in trunk: . gladeui plugins/gnome plugins/gtk+ src



Author: tvb
Date: Thu Oct 16 14:31:42 2008
New Revision: 1972
URL: http://svn.gnome.org/viewvc/glade3?rev=1972&view=rev

Log:

	* gladeui/Makefile.am, gladeui/glade-name-context.[ch]: Encapsulated name tracking mechanism

	* gladeui/glade-project.c, gladeui/glade-command.c: Now added a naming policy to the project
	with prefs and load/save support + a glade command to set it - also revamped the prefs dialog,
	it also pops up automatically for new projects.

	* gladeui/glade-editor.c, gladeui/glade-editor-property.c, gladeui/glade-property-class.c,
	gladeui/glade-property.c, gladeui/glade-widget.c: All effected since now 
	glade_property_class_make_gvalue_from_string () needs a GladeWidget argument to do
	hierachic context sensitive searches... that and naming is much cleaner now.
	
	* src/glade-window.c: remember to pass ownership of the project to the app.

	* plugins/gtk+/glade-gtk.c, plugins/gtk+/glade-column-types.c, plugins/gtk+/glade-model-data.c:
	BEWARE: Dangerous and still a work in progress.



Added:
   trunk/gladeui/glade-name-context.c
   trunk/gladeui/glade-name-context.h
Modified:
   trunk/ChangeLog
   trunk/gladeui/Makefile.am
   trunk/gladeui/glade-app.c
   trunk/gladeui/glade-command.c
   trunk/gladeui/glade-command.h
   trunk/gladeui/glade-editor-property.c
   trunk/gladeui/glade-editor.c
   trunk/gladeui/glade-project.c
   trunk/gladeui/glade-project.h
   trunk/gladeui/glade-property-class.c
   trunk/gladeui/glade-property-class.h
   trunk/gladeui/glade-property.c
   trunk/gladeui/glade-utils.c
   trunk/gladeui/glade-utils.h
   trunk/gladeui/glade-widget.c
   trunk/gladeui/glade-xml-utils.h
   trunk/plugins/gnome/glade-gnome.c
   trunk/plugins/gtk+/glade-column-types.c
   trunk/plugins/gtk+/glade-gtk.c
   trunk/plugins/gtk+/glade-model-data.c
   trunk/plugins/gtk+/gtk+.xml.in
   trunk/src/glade-window.c

Modified: trunk/gladeui/Makefile.am
==============================================================================
--- trunk/gladeui/Makefile.am	(original)
+++ trunk/gladeui/Makefile.am	Thu Oct 16 14:31:42 2008
@@ -62,7 +62,8 @@
 	glade-catalog.h \
 	glade-marshallers.h \
 	glade-accumulators.h \
-	glade-widget-action.c
+	glade-widget-action.c \
+	glade-name-context.c
 
 libgladeui_1_la_CPPFLAGS =  \
 	$(common_defines)   \
@@ -110,8 +111,9 @@
 	glade-xml-utils.h \
 	glade-signal.h \
 	glade-cursor.h \
-    glade-catalog.h \
-	glade-widget-action.h
+	glade-catalog.h \
+	glade-widget-action.h \
+	glade-name-context.h
 
 
 if PLATFORM_WIN32

Modified: trunk/gladeui/glade-app.c
==============================================================================
--- trunk/gladeui/glade-app.c	(original)
+++ trunk/gladeui/glade-app.c	Thu Oct 16 14:31:42 2008
@@ -936,19 +936,19 @@
 
  	g_return_if_fail (GLADE_IS_PROJECT (project));
 
+	app = glade_app_get ();
+
 	/* If the project was previously loaded, don't re-load */
-	if (glade_app_is_project_loaded (glade_project_get_path (project)))
+	if (g_list_find (app->priv->projects, project) != NULL)
 	{
 		glade_app_set_project (project);
 		return;
 	}
 	glade_app_update_instance_count (project);
-
-	app = glade_app_get ();
-	
-	g_object_ref (project);
 	
-	app->priv->projects = g_list_append (app->priv->projects, project);
+	/* Take a reference for GladeApp here... */
+	app->priv->projects = g_list_append (app->priv->projects, 
+					     g_object_ref (project));
 	
 	/* connect to the project signals so that the editor can be updated */
 	g_signal_connect (G_OBJECT (project), "selection_changed",
@@ -1022,7 +1022,6 @@
 	 * that point.
 	 */
 	g_object_unref (project);
-
 }
 
 

Modified: trunk/gladeui/glade-command.c
==============================================================================
--- trunk/gladeui/glade-command.c	(original)
+++ trunk/gladeui/glade-command.c	Thu Oct 16 14:31:42 2008
@@ -49,6 +49,7 @@
 #include "glade-signal.h"
 #include "glade-app.h"
 #include "glade-fixed.h"
+#include "glade-name-context.h"
 
 /* Concerning placeholders: we do not hold any reference to placeholders,
  * placeholders that are supplied by the backend are not reffed, placeholders
@@ -771,7 +772,8 @@
 	g_return_val_if_fail (me->widget != NULL, TRUE);
 	g_return_val_if_fail (me->name != NULL, TRUE);
 
-	glade_widget_set_name (me->widget, me->name);
+	glade_project_set_widget_name (me->widget->project, 
+				       me->widget, me->name);
 	
 	tmp = me->old_name;
 	me->old_name = me->name;
@@ -1621,7 +1623,10 @@
 	g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
 		
 	/* attempt to create the widget -- widget may be null, e.g. the user clicked cancel on a query */
-	widget = glade_widget_adaptor_create_widget(adaptor, TRUE, "parent", parent, "project", project, NULL);
+	widget = glade_widget_adaptor_create_widget(adaptor, TRUE, 
+						    "parent", parent, 
+						    "project", project, 
+						    NULL);
 	if (widget == NULL)
 	{
 		return NULL;
@@ -2354,3 +2359,147 @@
 }
 
 
+
+/******************************************************************************
+ * 
+ * set project naming policy 
+ * 
+ * This command sets the naming policy on the project.
+ * 
+ *****************************************************************************/
+
+typedef struct {
+	GladeCommand   parent;
+	GladeProject  *project;
+	GladeNamingPolicy policy;
+	GladeNamingPolicy old_policy;
+	gboolean run_once;
+} GladeCommandSetPolicy;
+
+
+GLADE_MAKE_COMMAND (GladeCommandSetPolicy, glade_command_set_policy);
+#define GLADE_COMMAND_SET_POLICY_TYPE			(glade_command_set_policy_get_type ())
+#define GLADE_COMMAND_SET_POLICY(o)	  		(G_TYPE_CHECK_INSTANCE_CAST ((o), GLADE_COMMAND_SET_POLICY_TYPE, GladeCommandSetPolicy))
+#define GLADE_COMMAND_SET_POLICY_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST ((k), GLADE_COMMAND_SET_POLICY_TYPE, GladeCommandSetPolicyClass))
+#define GLADE_IS_COMMAND_SET_POLICY(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GLADE_COMMAND_SET_POLICY_TYPE))
+#define GLADE_IS_COMMAND_SET_POLICY_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GLADE_COMMAND_SET_POLICY_TYPE))
+
+static gboolean
+glade_command_set_policy_execute(GladeCommand *cmd)
+{
+	GladeCommandSetPolicy *me = (GladeCommandSetPolicy *)cmd;
+	GladeNamingPolicy policy;
+
+	/* sanity check */
+	g_return_val_if_fail (me != NULL, TRUE);
+	g_return_val_if_fail (me->project != NULL, TRUE);
+
+	/* set the new policy */
+	glade_project_set_naming_policy (me->project, me->policy, me->run_once == FALSE);
+
+	/* swap the current values with the old values to prepare for undo */
+	policy         = me->policy;
+	me->policy     = me->old_policy;
+	me->old_policy = policy;
+
+	me->run_once = TRUE;
+	
+	return TRUE;
+}
+
+static gboolean
+glade_command_set_policy_undo(GladeCommand *cmd)
+{
+	return glade_command_set_policy_execute(cmd);
+}
+
+static void
+glade_command_set_policy_finalize(GObject *obj)
+{
+/* 	GladeCommandSetPolicy	*me; */
+	
+	g_return_if_fail(GLADE_IS_COMMAND_SET_POLICY(obj));
+	
+	glade_command_finalize(obj);
+}
+
+static gboolean
+glade_command_set_policy_unifies (GladeCommand *this_cmd, GladeCommand *other_cmd)
+{
+/* 	GladeCommandSetPolicy *cmd1; */
+/* 	GladeCommandSetPolicy *cmd2; */
+
+	return FALSE;
+}
+
+static void
+glade_command_set_policy_collapse (GladeCommand *this_cmd, GladeCommand *other_cmd)
+{
+	/* this command is the one that will be used for an undo of the sequence of like commands */
+	//GladeCommandSetPolicy *this = GLADE_COMMAND_SET_POLICY (this_cmd);
+	
+	/* the other command contains the values that will be used for a redo */
+	//GladeCommandSetPolicy *other = GLADE_COMMAND_SET_POLICY (other_cmd);
+
+	g_return_if_fail (GLADE_IS_COMMAND_SET_POLICY (this_cmd) && GLADE_IS_COMMAND_SET_POLICY (other_cmd));
+
+	/* no unify/collapse */
+}
+
+/**
+ * glade_command_set_project_naming_policy:
+ * @project: a #GladeProject
+ * @policy: the #GladeNamingPolicy
+ *
+ * Sets the naming policy of a project
+ */
+void
+glade_command_set_project_naming_policy  (GladeProject       *project,
+					  GladeNamingPolicy   policy)
+
+{
+	GladeCommandSetPolicy *me;
+	
+	g_return_if_fail (GLADE_IS_PROJECT (project));
+
+	if (glade_project_get_naming_policy (project) != policy)
+	{
+		gchar *prj_name = glade_project_get_name (project);
+		glade_command_push_group (_("Setting %s to use a %s naming policy"),
+					  prj_name, 
+					  policy == GLADE_POLICY_PROJECT_WIDE ? 
+					  "project wide" : "toplevel contextual");
+		g_free (prj_name);
+
+		/* load up the command */
+		me = g_object_new(GLADE_COMMAND_SET_POLICY_TYPE, NULL);
+		me->project = project;
+		me->policy = policy;
+		me->old_policy = glade_project_get_naming_policy (project);
+
+		me->run_once = FALSE;
+
+		GLADE_COMMAND(me)->description = g_strdup_printf("dummy string");
+	
+		glade_command_check_group(GLADE_COMMAND(me));
+		
+		/* execute the command and push it on the stack if successful 
+		 * this sets the actual policy
+		 */
+		if (glade_command_set_policy_execute(GLADE_COMMAND(me)))
+		{
+			glade_project_push_undo(glade_app_get_project(), GLADE_COMMAND(me));
+		}
+		else
+		{
+			g_object_unref(G_OBJECT(me));
+		}
+
+		glade_command_pop_group ();
+
+		glade_editor_refresh (glade_app_get_editor ());
+	}
+}
+
+
+

Modified: trunk/gladeui/glade-command.h
==============================================================================
--- trunk/gladeui/glade-command.h	(original)
+++ trunk/gladeui/glade-command.h	Thu Oct 16 14:31:42 2008
@@ -90,6 +90,9 @@
 void           glade_command_set_project_format  (GladeProject       *project,
 						  GladeProjectFormat  fmt);
 
+void           glade_command_set_project_naming_policy  (GladeProject       *project,
+							 GladeNamingPolicy   policy);
+
 /************************** properties *********************************/
 
 void           glade_command_set_property        (GladeProperty *property,     

Modified: trunk/gladeui/glade-editor-property.c
==============================================================================
--- trunk/gladeui/glade-editor-property.c	(original)
+++ trunk/gladeui/glade-editor-property.c	Thu Oct 16 14:31:42 2008
@@ -113,8 +113,9 @@
 
 }
 
-void glade_editor_property_commit_no_callback (GladeEditorProperty *eprop,
-					       GValue              *value)
+void
+glade_editor_property_commit_no_callback (GladeEditorProperty *eprop,
+					  GValue              *value)
 {
 	g_return_if_fail (GLADE_IS_EDITOR_PROPERTY (eprop));
 
@@ -1601,7 +1602,7 @@
 	    eprop->property->klass->pspec->value_type == G_TYPE_VALUE_ARRAY)
 	{
 		val = glade_property_class_make_gvalue_from_string 
-			(eprop->property->klass, text, NULL);
+			(eprop->property->klass, text, NULL, NULL);
 	} 
 	else
 	{
@@ -2228,7 +2229,7 @@
 {
 	GladeProject *project = glade_widget_get_project (eprop->property->widget);
 	GValue *value = glade_property_class_make_gvalue_from_string 
-		(eprop->klass, gtk_entry_get_text(entry), project);
+		(eprop->klass, gtk_entry_get_text(entry), project, eprop->property->widget);
 
 	/* Set project resource here where we still have the fullpath.
 	 */
@@ -2287,7 +2288,7 @@
 		basename = g_path_get_basename (file);
 
 		value = glade_property_class_make_gvalue_from_string 
-			(eprop->klass, basename, project);
+			(eprop->klass, basename, project, eprop->property->widget);
 		
 		glade_editor_property_commit (eprop, value);
 		
@@ -2824,7 +2825,7 @@
 		if (selected)
 		{
 			GValue *value = glade_property_class_make_gvalue_from_string
-				(eprop->klass, selected->name, project);
+				(eprop->klass, selected->name, project, eprop->property->widget);
 
 			/* Unparent the widget so we can reuse it for this property */
 			if (eprop->klass->parentless_widget)
@@ -2880,9 +2881,12 @@
 		if ((new_widget = glade_command_create (create_adaptor, NULL, NULL, project)) != NULL)
 		{
 			value = glade_property_class_make_gvalue_from_string
-				(eprop->klass, new_widget->name, project);
+				(eprop->klass, new_widget->name, project, NULL);
 
 			glade_editor_property_commit (eprop, value);
+
+			g_value_unset (value);
+			g_free (value);
 		}
 
 		glade_command_pop_group ();
@@ -2890,7 +2894,7 @@
 	else if (res == GLADE_RESPONSE_CLEAR)
 	{
 		GValue *value = glade_property_class_make_gvalue_from_string
-			(eprop->klass, NULL, project);
+			(eprop->klass, NULL, project, eprop->property->widget);
 		
 		glade_editor_property_commit (eprop, value);
 

Modified: trunk/gladeui/glade-editor.c
==============================================================================
--- trunk/gladeui/glade-editor.c	(original)
+++ trunk/gladeui/glade-editor.c	Thu Oct 16 14:31:42 2008
@@ -18,6 +18,7 @@
  *
  * Authors:
  *   Chema Celorio <chema celorio com>
+ *   Tristan Van Berkom <tvb gnome org>
  */
 
 
@@ -503,7 +504,8 @@
 
 	widget = editor->loaded_widget;
 	new_name = gtk_editable_get_chars (GTK_EDITABLE (editable), 0, -1);
-	if (!glade_project_get_widget_by_name (widget->project, new_name))
+
+	if (glade_project_available_widget_name (widget->project, widget, new_name))
 		glade_command_set_name (widget, new_name);
 	g_free (new_name);
 }

Added: trunk/gladeui/glade-name-context.c
==============================================================================
--- (empty file)
+++ trunk/gladeui/glade-name-context.c	Thu Oct 16 14:31:42 2008
@@ -0,0 +1,241 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * glade-name-context.c
+ *
+ * Copyright (C) 2008 Tristan Van Berkom.
+ *
+ * Authors:
+ *   Tristan Van Berkom <tvb 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "glade-id-allocator.h"
+#include "glade-name-context.h"
+
+struct _GladeNameContext {
+	GHashTable *name_allocators;
+
+	GHashTable *names;
+};
+
+
+
+GladeNameContext *
+glade_name_context_new (void)
+{
+	GladeNameContext *context = g_new0 (GladeNameContext, 1);
+
+	context->name_allocators = g_hash_table_new_full (g_str_hash,
+							  g_str_equal,
+							  g_free, 
+							  (GDestroyNotify) glade_id_allocator_destroy);
+
+	context->names = g_hash_table_new_full (g_str_hash,
+						g_str_equal,
+						g_free, 
+						NULL);
+
+	return context;
+}
+
+void
+glade_name_context_destroy (GladeNameContext *context)
+{
+	g_return_if_fail (context != NULL);
+
+	g_hash_table_destroy (context->name_allocators);
+	g_hash_table_destroy (context->names);
+	g_free (context);
+}
+
+gchar *
+glade_name_context_new_name (GladeNameContext *context,
+			     const gchar      *base_name)
+{
+	GladeIDAllocator *id_allocator;
+	const gchar      *number;
+	gchar            *name = NULL, *freeme = NULL;
+	guint             i = 1;
+	
+	g_return_val_if_fail (context != NULL, NULL);
+	g_return_val_if_fail (base_name && base_name[0], NULL);
+
+	number = base_name + strlen (base_name);
+	while (number > base_name && g_ascii_isdigit (number[-1]))
+		--number;
+
+	if (*number)
+        {
+		freeme = g_strndup (base_name, number - base_name);
+		base_name = freeme;
+	}
+	
+	id_allocator = g_hash_table_lookup (context->name_allocators, base_name);
+
+	if (id_allocator == NULL)
+	{
+		id_allocator = glade_id_allocator_new ();
+		g_hash_table_insert (context->name_allocators,
+				     g_strdup (base_name), id_allocator);
+	}
+	
+	do
+        {
+		g_free (name);
+		i = glade_id_allocator_allocate (id_allocator);
+		name = g_strdup_printf ("%s%u", base_name, i);
+	} 
+	while (glade_name_context_has_name (context, name));
+
+	g_free (freeme);
+	return name;
+}
+
+gchar *
+glade_name_context_dual_new_name (GladeNameContext *context,
+				  GladeNameContext *another_context,
+				  const gchar      *base_name)
+{
+	GladeIDAllocator *id_allocator;
+	const gchar      *number;
+	gchar            *name = NULL, *freeme = NULL;
+	guint             i = 1;
+	
+	g_return_val_if_fail (context != NULL, NULL);
+	g_return_val_if_fail (another_context != NULL, NULL);
+	g_return_val_if_fail (base_name && base_name[0], NULL);
+
+	number = base_name + strlen (base_name);
+	while (number > base_name && g_ascii_isdigit (number[-1]))
+		--number;
+
+	if (*number)
+        {
+		freeme = g_strndup (base_name, number - base_name);
+		base_name = freeme;
+	}
+	
+	id_allocator = g_hash_table_lookup (context->name_allocators, base_name);
+
+	if (id_allocator == NULL)
+	{
+		id_allocator = glade_id_allocator_new ();
+		g_hash_table_insert (context->name_allocators,
+				     g_strdup (base_name), id_allocator);
+	}
+	
+	do
+        {
+		g_free (name);
+		i = glade_id_allocator_allocate (id_allocator);
+		name = g_strdup_printf ("%s%u", base_name, i);
+	} 
+	while (glade_name_context_has_name (context, name) ||
+	       glade_name_context_has_name (another_context, name));
+
+	g_free (freeme);
+	return name;
+}
+
+guint
+glade_name_context_n_names (GladeNameContext *context)
+{
+	g_return_val_if_fail (context != NULL, FALSE);
+
+	return g_hash_table_size (context->names);
+}
+
+gboolean
+glade_name_context_has_name (GladeNameContext *context,
+			     const gchar      *name)
+{
+	g_return_val_if_fail (context != NULL, FALSE);
+	g_return_val_if_fail (name && name[0], FALSE);
+
+	return (g_hash_table_lookup (context->names, name) != NULL);
+}
+
+gboolean
+glade_name_context_add_name (GladeNameContext *context,
+			     const gchar      *name)
+{
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (context != NULL, FALSE);
+	g_return_val_if_fail (name && name[0], FALSE);
+	
+	if (!glade_name_context_has_name (context, name))
+	{
+		g_hash_table_insert (context->names, g_strdup (name), GINT_TO_POINTER (TRUE));
+		ret = TRUE;
+	}
+
+	return ret;
+}
+
+void
+glade_name_context_release_name (GladeNameContext *context,
+				 const gchar      *name)
+{
+
+	const gchar *first_number = name;
+	gchar       *end_number, *base_name;
+	GladeIDAllocator *id_allocator;
+	gunichar ch;
+	gint id;
+
+	g_return_if_fail (context != NULL);
+	g_return_if_fail (name && name[0]);
+
+	/* Remove from name hash first... */
+	g_hash_table_remove (context->names, name);
+
+	do
+	{
+		ch = g_utf8_get_char (first_number);
+
+		if (ch == 0 || g_unichar_isdigit (ch))
+			break;
+
+		first_number = g_utf8_next_char (first_number);
+	}
+	while (TRUE);
+
+	/* if there is a number - then we have to unallocate it... */
+	if (ch == 0) return;
+
+
+	base_name = g_strdup (name);
+	*(base_name + (first_number - name)) = 0;
+	
+	if ((id_allocator =
+	     g_hash_table_lookup (context->name_allocators, base_name)) != NULL)
+	{
+
+		id = (int) strtol (first_number, &end_number, 10);
+		if (*end_number == 0)
+			glade_id_allocator_release (id_allocator, id);
+	}
+
+	g_free (base_name);
+}

Added: trunk/gladeui/glade-name-context.h
==============================================================================
--- (empty file)
+++ trunk/gladeui/glade-name-context.h	Thu Oct 16 14:31:42 2008
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef __GLADE_NAME_CONTEXT_H__
+#define __GLADE_NAME_CONTEXT_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GladeNameContext GladeNameContext;
+
+GladeNameContext  *glade_name_context_new                 (void);
+void               glade_name_context_destroy             (GladeNameContext *context);
+
+gchar             *glade_name_context_new_name            (GladeNameContext *context,
+							   const gchar      *base_name);
+
+gchar             *glade_name_context_dual_new_name       (GladeNameContext *context,
+							   GladeNameContext *another_context,
+							   const gchar      *base_name);
+
+guint              glade_name_context_n_names             (GladeNameContext *context);
+
+gboolean           glade_name_context_has_name            (GladeNameContext *context,
+							   const gchar      *name);
+
+gboolean           glade_name_context_add_name            (GladeNameContext *context,
+							   const gchar      *name);
+
+void               glade_name_context_release_name        (GladeNameContext *context,
+							   const gchar      *name);
+
+G_END_DECLS
+
+#endif /* __GLADE_NAME_CONTEXT_H__ */

Modified: trunk/gladeui/glade-project.c
==============================================================================
--- trunk/gladeui/glade-project.c	(original)
+++ trunk/gladeui/glade-project.c	Thu Oct 16 14:31:42 2008
@@ -48,6 +48,7 @@
 
 #include "glade-project.h"
 #include "glade-command.h"
+#include "glade-name-context.h"
 
 #define GLADE_PROJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GLADE_TYPE_PROJECT, GladeProjectPrivate))
 
@@ -105,12 +106,14 @@
 			   * of #GtkWidget items.
 			   */
 
+	GladeNameContext *toplevel_names; /* Context for uniqueness of names at the toplevel */
+	GList            *toplevels;      /* List of toplevels with thier own naming contexts */
+
+
 	gboolean     has_selection;           /* Whether the project has a selection */
 
 	GList       *undo_stack;              /* A stack with the last executed commands */
 	GList       *prev_redo_item;          /* Points to the item previous to the redo items */
-	GHashTable  *widget_names_allocator;  /* hash table with the used widget names */
-	GHashTable  *widget_old_names;        /* widget -> old name of the widget */
 	
 	gboolean first_modification_is_na; /* the flag indicates that  the first_modification item has been lost */
 	
@@ -135,14 +138,83 @@
 	GHashTable *target_versions_minor; /* target versions by catalog */
 
 	GList *loaded_factory_files;
+
+	GladeNamingPolicy naming_policy;	/* What rules apply to widget names */
+/* Control on the preferences dialog to update buttons etc when properties change */
+	GtkWidget *prefs_dialog;
+	GtkWidget *glade_radio;
+	GtkWidget *builder_radio;
+	GtkWidget *project_wide_radio;
+	GtkWidget *toplevel_contextual_radio;
+	GHashTable *target_radios;
+
 };
 
 typedef struct {
+	GladeWidget      *toplevel;
+	GladeNameContext *names;
+} TopLevelInfo;
+
+typedef struct {
 	gchar *stock;
 	gchar *filename;
 } StockFilePair;
 
 
+static void         glade_project_set_target_version       (GladeProject *project,
+							    const gchar  *catalog,
+							    gint          major,
+							    gint          minor);
+static void         glade_project_get_target_version       (GladeProject *project,
+							    const gchar  *catalog,
+							    gint         *major,
+							    gint         *minor);
+
+static void         glade_project_target_version_for_adaptor (GladeProject        *project, 
+							      GladeWidgetAdaptor  *adaptor,
+							      gint                *major,
+							      gint                *minor);
+
+static void         glade_project_set_readonly             (GladeProject       *project, 
+							    gboolean            readonly);
+
+
+static gboolean     glade_project_verify                   (GladeProject       *project, 
+							    gboolean            saving);
+
+static void         glade_project_verify_adaptor           (GladeProject       *project,
+							    GladeWidgetAdaptor *adaptor,
+							    const gchar        *path_name,
+							    GString            *string,
+							    gboolean            saving,
+							    gboolean            forwidget,
+							    GladeSupportMask   *mask);
+
+static void         glade_project_move_resources           (GladeProject       *project,
+							    const gchar        *old_dir,
+							    const gchar        *new_dir);
+
+static void         glade_project_sync_resources_for_widget (GladeProject      *project, 
+							     GladeProject      *prev_project,
+							     GladeWidget       *gwidget,
+							     gboolean           remove);
+
+GladeWidget        *search_ancestry_by_name                 (GladeWidget       *toplevel, 
+							     const gchar       *name);
+
+static GtkWidget   *glade_project_build_prefs_dialog        (GladeProject      *project);
+
+static void         format_libglade_button_clicked          (GtkWidget         *widget,
+							     GladeProject      *project);
+static void         format_builder_button_clicked           (GtkWidget         *widget,
+							     GladeProject      *project);
+static void         policy_project_wide_button_clicked      (GtkWidget         *widget,
+							     GladeProject      *project);
+static void         policy_toplevel_contextual_button_clicked (GtkWidget       *widget,
+							       GladeProject    *project);
+static void         target_button_clicked                   (GtkWidget         *widget,
+							     GladeProject      *project);
+
 static guint              glade_project_signals[LAST_SIGNAL] = {0};
 
 static GladeIDAllocator  *unsaved_number_allocator = NULL;
@@ -228,6 +300,10 @@
 glade_project_finalize (GObject *object)
 {
 	GladeProject *project = GLADE_PROJECT (object);
+	GList        *list;
+	TopLevelInfo *tinfo;
+	
+	gtk_widget_destroy (project->priv->prefs_dialog);
 
 	g_free (project->priv->path);
 	g_free (project->priv->comment);
@@ -235,11 +311,20 @@
 	if (project->priv->unsaved_number > 0)
 		glade_id_allocator_release (get_unsaved_number_allocator (), project->priv->unsaved_number);
 
-	g_hash_table_destroy (project->priv->widget_names_allocator);
-	g_hash_table_destroy (project->priv->widget_old_names);
 	g_hash_table_destroy (project->priv->resources);
 	g_hash_table_destroy (project->priv->target_versions_major);
 	g_hash_table_destroy (project->priv->target_versions_minor);
+	g_hash_table_destroy (project->priv->target_radios);
+
+	glade_name_context_destroy (project->priv->toplevel_names);
+
+	for (list = project->priv->toplevels; list; list = list->next)
+	{
+		tinfo = list->data;
+		glade_name_context_destroy (tinfo->names);
+		g_free (tinfo);
+	}
+	g_list_free (project->priv->toplevels);
 
 	G_OBJECT_CLASS (glade_project_parent_class)->finalize (object);
 }
@@ -500,251 +585,10 @@
 	glade_app_update_ui ();
 }
 
+
 /*******************************************************************
-                            Initializers
+                          Class Initializers
  *******************************************************************/
-
-static void
-glade_project_get_target_version (GladeProject *project,
-				  const gchar  *catalog,
-				  gint         *major,
-				  gint         *minor)
-{
-	*major = GPOINTER_TO_INT 
-		(g_hash_table_lookup (project->priv->target_versions_major,
-				      catalog));
-	*minor = GPOINTER_TO_INT 
-		(g_hash_table_lookup (project->priv->target_versions_minor,
-				      catalog));
-}
-
-static void
-glade_project_target_version_for_adaptor (GladeProject        *project, 
-					  GladeWidgetAdaptor  *adaptor,
-					  gint                *major,
-					  gint                *minor)
-{
-	gchar   *catalog = NULL;
-
-	g_object_get (adaptor, "catalog", &catalog, NULL);
-	glade_project_get_target_version (project, catalog, major, minor);
-	g_free (catalog);
-}
-
-static void
-glade_project_verify_adaptor (GladeProject       *project,
-			      GladeWidgetAdaptor *adaptor,
-			      const gchar        *path_name,
-			      GString            *string,
-			      gboolean            saving,
-			      gboolean            forwidget,
-			      GladeSupportMask   *mask)
-{
-	GladeSupportMask    support_mask = GLADE_SUPPORT_OK;
-	GladeWidgetAdaptor *adaptor_iter;
-	gint                target_major, target_minor;
-	gchar              *catalog = NULL;
-
-	for (adaptor_iter = adaptor; adaptor_iter;
-	     adaptor_iter = glade_widget_adaptor_get_parent_adaptor (adaptor_iter))
-	{
-
-		g_object_get (adaptor_iter, "catalog", &catalog, NULL);
-		glade_project_target_version_for_adaptor (project, adaptor_iter, 
-							  &target_major,
-							  &target_minor);
-
-		if (target_major < GWA_VERSION_SINCE_MAJOR (adaptor_iter) ||
-		    (target_major == GWA_VERSION_SINCE_MAJOR (adaptor_iter) &&
-		     target_minor < GWA_VERSION_SINCE_MINOR (adaptor_iter)))
-		{
-			if (forwidget)
-			{
-				/* translators: reffers to a widget
-				 * introduced in toolkit version '%s %d.%d',
-				 * and a project targeting toolkit verion '%s %d.%d' */
-				g_string_append_printf
-					(string, 
-					 _("This widget was introduced in %s %d.%d "
-					   "project targets %s %d.%d"),
-					 catalog,
-					 GWA_VERSION_SINCE_MAJOR (adaptor_iter),
-					 GWA_VERSION_SINCE_MINOR (adaptor_iter),
-					 catalog, target_major, target_minor);
-			}
-			else
-				/* translators: reffers to a widget '[%s]'  
-				 * introduced in toolkit version '%s %d.%d' */
-				g_string_append_printf
-					(string, 
-					 _("[%s] Object class '%s' was introduced in %s %d.%d\n"),
-					 path_name, adaptor_iter->title, catalog,
-					 GWA_VERSION_SINCE_MAJOR (adaptor_iter),
-					 GWA_VERSION_SINCE_MINOR (adaptor_iter));
-
-			support_mask |= GLADE_SUPPORT_MISMATCH;
-		}
-
-		if (project->priv->format == GLADE_PROJECT_FORMAT_GTKBUILDER &&
-		    GWA_LIBGLADE_ONLY (adaptor_iter))
-		{
-			if (forwidget)
-			{
-				if (string->len)
-					g_string_append (string, "\n");
-				g_string_append_printf
-					(string,
-					 _("This widget is only supported in libglade format"));
-			}
-			else
-				/* translators: reffers to a widget '[%s]'  
-				 * loaded from toolkit version '%s %d.%d' */
-				g_string_append_printf
-					(string,
-					 _("[%s] Object class '%s' from %s %d.%d "
-					   "is only supported in libglade format\n"),
-					 path_name, adaptor_iter->title, catalog,
-					 target_major, target_minor);
-
-			support_mask |= GLADE_SUPPORT_LIBGLADE_ONLY;
-		}
-		else if (project->priv->format == GLADE_PROJECT_FORMAT_LIBGLADE &&
-			 GWA_LIBGLADE_UNSUPPORTED (adaptor_iter))
-		{
-			if (forwidget)
-			{
-				if (string->len)
-					g_string_append (string, "\n");
-				g_string_append_printf
-					(string,
-					 _("This widget is not supported in libglade format"));
-			}
-			else
-				/* translators: reffers to a widget '[%s]'  
-				 * loaded from toolkit version '%s %d.%d' */
-				g_string_append_printf
-					(string,
-					 _("[%s] Object class '%s' from %s %d.%d "
-					   "is not supported in libglade format\n"),
-					 path_name, adaptor_iter->title, catalog,
-					 target_major, target_minor);
-
-			support_mask |= GLADE_SUPPORT_LIBGLADE_UNSUPPORTED;
-		}
-
-		if (!saving && GWA_DEPRECATED (adaptor_iter))
-		{
-			if (forwidget)
-			{
-				if (string->len)
-					g_string_append (string, "\n");
-				g_string_append_printf
-					(string, _("This widget is deprecated"));
-			}
-			else
-				/* translators: reffers to a widget '[%s]'  
-				 * loaded from toolkit version '%s %d.%d' */
-				g_string_append_printf
-					(string, 
-					 _("[%s] Object class '%s' from %s %d.%d "
-					   "is deprecated\n"),
-					 path_name, adaptor_iter->title, catalog,
-					 target_major, target_minor);
-
-			support_mask |= GLADE_SUPPORT_DEPRECATED;
-		}
-		g_free (catalog);
-	}
-	if (mask)
-		*mask = support_mask;
-}
-
-/**
- * glade_project_verify_widget_adaptor:
- * @project: A #GladeProject
- * @adaptor: the #GladeWidgetAdaptor to verify
- * @mask: a return location for a #GladeSupportMask
- * 
- * Checks the supported state of this widget adaptor
- * and generates a string to show in the UI describing why.
- *
- * Returns: A newly allocated string 
- */
-gchar *
-glade_project_verify_widget_adaptor (GladeProject       *project,
-				     GladeWidgetAdaptor *adaptor,
-				     GladeSupportMask   *mask)
-{
-	GString *string = g_string_new (NULL);
-	gchar   *ret = NULL;
-
-	glade_project_verify_adaptor (project, adaptor, NULL,
-				      string, FALSE, TRUE, mask);
-
-	/* there was a '\0' byte... */
-	if (string->len > 0)
-	{
-		ret = string->str;
-		g_string_free (string, FALSE);
-	}
-	else
-		g_string_free (string, TRUE);
-
-
-	return ret;
-}
-
-
-/**
- * glade_project_verify_project_for_ui:
- * @project: A #GladeProject
- * 
- * Checks the project and updates warning strings in the UI
- */
-void
-glade_project_verify_project_for_ui (GladeProject *project)
-{
-	GList *list;
-	GladeWidget *widget;
-	gchar *warning;
-
-	/* Sync displayable info here */
-	for (list = project->priv->objects; list; list = list->next)
-	{
-		widget = glade_widget_get_from_gobject (list->data);
-
-		warning = glade_project_verify_widget_adaptor (project, widget->adaptor, NULL);
-		glade_widget_set_support_warning (widget, warning);
-
-		if (warning)
-			g_free (warning);
-
-		glade_project_verify_properties (widget);
-	}
-
-	/* refresh palette if this is the active project */
-	if (project == glade_app_get_project ())
-		glade_palette_refresh (glade_app_get_palette ());
-}
-
-static void
-glade_project_set_target_version (GladeProject *project,
-				  const gchar  *catalog,
-				  gint          major,
-				  gint          minor)
-{
-
-	g_hash_table_insert (project->priv->target_versions_major,
-			     g_strdup (catalog),
-			     GINT_TO_POINTER (major));
-	g_hash_table_insert (project->priv->target_versions_minor,
-			     g_strdup (catalog),
-			     GINT_TO_POINTER (minor));
-
-	glade_project_verify_project_for_ui (project);
-
-}
-
 static void
 glade_project_init (GladeProject *project)
 {
@@ -764,12 +608,8 @@
 	priv->first_modification = NULL;
 	priv->first_modification_is_na = FALSE;
 
-	priv->widget_names_allocator = g_hash_table_new_full (g_str_hash,
-							      g_str_equal,
-							      g_free, 
-				       			      (GDestroyNotify) glade_id_allocator_destroy);
-				       
-	priv->widget_old_names = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_free);
+	priv->toplevel_names = glade_name_context_new ();
+	priv->naming_policy = GLADE_POLICY_PROJECT_WIDE;
 
 	priv->accel_group = NULL;
 
@@ -801,6 +641,11 @@
 						  glade_catalog_get_major_version (catalog),
 						  glade_catalog_get_minor_version (catalog));
 	}
+
+	priv->target_radios = g_hash_table_new_full (g_str_hash, g_str_equal,
+						     g_free, NULL);
+	priv->prefs_dialog = glade_project_build_prefs_dialog (project);
+
 }
 
 static void
@@ -1060,37 +905,9 @@
 }
 
 /*******************************************************************
-                                  API
+                    Loading project code here
  *******************************************************************/
 
-static void
-glade_project_set_readonly (GladeProject *project, gboolean readonly)
-{
-	g_assert (GLADE_IS_PROJECT (project));
-	
-	if (project->priv->readonly != readonly)
-	{
-		project->priv->readonly = readonly;
-		g_object_notify (G_OBJECT (project), "read-only");
-	}
-}                                                                                               
-
-/**
- * glade_project_get_readonly:
- * @project: a #GladeProject
- *
- * Gets whether the project is read only or not
- *
- * Returns: TRUE if project is read only
- */
-gboolean
-glade_project_get_readonly (GladeProject *project)
-{
-	g_return_val_if_fail (GLADE_IS_PROJECT (project), FALSE);
-
-	return project->priv->readonly;
-}
-
 /**
  * glade_project_new:
  *
@@ -1101,145 +918,9 @@
 GladeProject *
 glade_project_new (void)
 {
-	return g_object_new (GLADE_TYPE_PROJECT, NULL);
-}
-
-
-static void 
-glade_project_fix_object_props (GladeProject *project)
-{
-	GList         *l, *ll;
-	GValue        *value;
-	GladeWidget   *gwidget;
-	GladeProperty *property;
-	gchar         *txt;
-
-	for (l = project->priv->objects; l; l = l->next)
-	{
-		gwidget = glade_widget_get_from_gobject (l->data);
-
-		for (ll = gwidget->properties; ll; ll = ll->next)
-		{
-			property = GLADE_PROPERTY (ll->data);
-
-			if (glade_property_class_is_object (property->klass, 
-							    project->priv->format) &&
-			    (txt = g_object_get_data (G_OBJECT (property), 
-						      "glade-loaded-object")) != NULL)
-			{
-				/* Parse the object list and set the property to it
-				 * (this magicly works for both objects & object lists)
-				 */
-				value = glade_property_class_make_gvalue_from_string
-					(property->klass, txt, project);
-				
-				glade_property_set_value (property, value);
-				
-				g_value_unset (value);
-				g_free (value);
-				
-				g_object_set_data (G_OBJECT (property), 
-						   "glade-loaded-object", NULL);
-			}
-		}
-	}
-}
-
-
-static gchar *
-glade_project_read_requires_from_comment (GladeXmlNode  *comment,
-					  gint          *major,
-					  gint          *minor)
-{
-	gint maj, min;
-	gchar *value, buffer[256];
-	gchar *required_lib = NULL;
-
-	if (!glade_xml_node_is_comment (comment)) 
-		return FALSE;
-
-	value = glade_xml_get_content (comment);
-	if (value && !strncmp ("interface-requires", value, strlen ("interface-requires")))
-	{
-		if (sscanf (value, "interface-requires %s %d.%d", buffer, &maj, &min) == 3)
-		{
-			if (major) *major = maj;
-			if (minor) *minor = min;
-			required_lib = g_strdup (buffer);
-		}
-	}
-	g_free (value);
-
-	return required_lib;
-}
-					  
-
-static gboolean
-glade_project_read_requires (GladeProject *project,
-			     GladeXmlNode *root_node, 
-			     const gchar  *path)
-{
-
-	GString      *string = g_string_new (NULL);
-	GladeXmlNode *node;
-	gchar        *required_lib = NULL;
-	gboolean      loadable = TRUE;
-	gint          major, minor;
-
-	for (node = glade_xml_node_get_children_with_comments (root_node); 
-	     node; node = glade_xml_node_next_with_comments (node))
-	{
-		/* Skip non "requires" tags */
-		if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_REQUIRES) ||	
-		      (required_lib = 
-		       glade_project_read_requires_from_comment (node, &major, &minor))))
-			continue;
-
-		if (!required_lib)
-		{
-			required_lib =  
-				glade_xml_get_property_string_required (node, GLADE_XML_TAG_LIB, 
-									NULL);
-			glade_xml_get_property_version (node, GLADE_XML_TAG_VERSION, 
-							&major, &minor);
-		}
-
-		if (!required_lib) continue;
-
-		/* Dont mention gtk+ as a required lib in 
-		 * the generated glade file
-		 */
-		if (!glade_catalog_is_loaded (required_lib))
-		{
-			if (!loadable)
-				g_string_append (string, ", ");
-
-			g_string_append (string, required_lib);
-			loadable = FALSE;
-		}
-		else
-			glade_project_set_target_version
-				(project, required_lib, major, minor);
-		
-		g_free (required_lib);
-	}
-
-	if (!loadable)
-		glade_util_ui_message (glade_app_get_window(),
-				       GLADE_UI_ERROR, NULL,
-				       _("Failed to load %s.\n"
-					 "The following required catalogs are unavailable: %s"),
-				       path, string->str);
-	g_string_free (string, TRUE);
-	return loadable;
-}
-
-static void
-glade_project_read_comment (GladeProject *project, GladeXmlDoc *doc)
-{
-	/* TODO Write me !! Find out how to extract root level comments 
-	 * with libxml2 !!! 
-	 */
+	GladeProject *project = g_object_new (GLADE_TYPE_PROJECT, NULL);
+	glade_project_preferences (project);
+	return project;
 }
 
 static GList *
@@ -1444,57 +1125,252 @@
 	return generated;
 }
 
-gboolean
-glade_project_load_from_file (GladeProject *project, const gchar *path)
+
+/* Called when finishing loading a glade file to resolve object type properties
+ */
+static void 
+glade_project_fix_object_props (GladeProject *project)
 {
-	GladeXmlContext *context;
-	GladeXmlDoc     *doc;
-	GladeXmlNode    *root;
-	GladeXmlNode    *node;
-	GladeWidget     *widget;
+	GList         *l, *ll;
+	GValue        *value;
+	GladeWidget   *gwidget;
+	GladeProperty *property;
+	gchar         *txt;
 
-	project->priv->selection = NULL;
-	project->priv->objects = NULL;
-	project->priv->loading = TRUE;
+	for (l = project->priv->objects; l; l = l->next)
+	{
+		gwidget = glade_widget_get_from_gobject (l->data);
 
-	project->priv->path = glade_util_canonical_path (path);	
+		for (ll = gwidget->properties; ll; ll = ll->next)
+		{
+			property = GLADE_PROPERTY (ll->data);
 
-	/* get the context & root node of the catalog file */
-	if (!(context = 
-	      glade_xml_context_new_from_path (path,
-					       NULL, 
-					       NULL)))
-	{
-		g_warning ("Couldn't open glade file [%s].", path);
-		return FALSE;
+			if (glade_property_class_is_object (property->klass, 
+							    project->priv->format) &&
+			    (txt = g_object_get_data (G_OBJECT (property), 
+						      "glade-loaded-object")) != NULL)
+			{
+				/* Parse the object list and set the property to it
+				 * (this magicly works for both objects & object lists)
+				 */
+				value = glade_property_class_make_gvalue_from_string
+					(property->klass, txt, gwidget->project, gwidget);
+				
+				glade_property_set_value (property, value);
+				
+				g_value_unset (value);
+				g_free (value);
+				
+				g_object_set_data (G_OBJECT (property), 
+						   "glade-loaded-object", NULL);
+			}
+		}
 	}
+}
 
-	doc  = glade_xml_context_get_doc (context);
-	root = glade_xml_doc_get_root (doc);
+static gchar *
+glade_project_read_requires_from_comment (GladeXmlNode  *comment,
+					  gint          *major,
+					  gint          *minor)
+{
+	gint maj, min;
+	gchar *value, buffer[256];
+	gchar *required_lib = NULL;
 
-	if (glade_xml_node_verify_silent (root, GLADE_XML_TAG_LIBGLADE_PROJECT))
-		project->priv->format = GLADE_PROJECT_FORMAT_LIBGLADE;
-	else if (glade_xml_node_verify_silent (root, GLADE_XML_TAG_BUILDER_PROJECT))
-		project->priv->format = GLADE_PROJECT_FORMAT_GTKBUILDER;
-	else
-	{
-		g_warning ("Couldnt determine project format, skipping %s", path);
-		glade_xml_context_free (context);
-		return FALSE;
-	}
+	if (!glade_xml_node_is_comment (comment)) 
+		return NULL;
 
-	/* XXX Need to load project->priv->comment ! */
-	glade_project_read_comment (project, doc);
+	value = glade_xml_get_content (comment);
 
-	if (glade_project_read_requires (project, root, path) == FALSE)
+	if (value && !strncmp (" interface-requires", value, strlen (" interface-requires")))
 	{
-		glade_xml_context_free (context);
-		return FALSE;
+		if (sscanf (value, " interface-requires %s %d.%d", buffer, &maj, &min) == 3)
+		{
+			if (major) *major = maj;
+			if (minor) *minor = min;
+			required_lib = g_strdup (buffer);
+		}
 	}
+	g_free (value);
 
-	for (node = glade_xml_node_get_children (root); 
-	     node; node = glade_xml_node_next (node))
-	{
+	return required_lib;
+}
+					  
+
+static gboolean
+glade_project_read_requires (GladeProject *project,
+			     GladeXmlNode *root_node, 
+			     const gchar  *path)
+{
+
+	GString      *string = g_string_new (NULL);
+	GladeXmlNode *node;
+	gchar        *required_lib = NULL;
+	gboolean      loadable = TRUE;
+	gint          major, minor;
+
+	for (node = glade_xml_node_get_children_with_comments (root_node); 
+	     node; node = glade_xml_node_next_with_comments (node))
+	{
+		/* Skip non "requires" tags */
+		if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_REQUIRES) ||	
+		      (required_lib = 
+		       glade_project_read_requires_from_comment (node, &major, &minor))))
+			continue;
+
+		if (!required_lib)
+		{
+			required_lib =  
+				glade_xml_get_property_string_required (node, GLADE_XML_TAG_LIB, 
+									NULL);
+			glade_xml_get_property_version (node, GLADE_XML_TAG_VERSION, 
+							&major, &minor);
+		}
+
+		if (!required_lib) continue;
+
+		/* Dont mention gtk+ as a required lib in 
+		 * the generated glade file
+		 */
+		if (!glade_catalog_is_loaded (required_lib))
+		{
+			if (!loadable)
+				g_string_append (string, ", ");
+
+			g_string_append (string, required_lib);
+			loadable = FALSE;
+		}
+		else
+			glade_project_set_target_version
+				(project, required_lib, major, minor);
+		
+		g_free (required_lib);
+	}
+
+	if (!loadable)
+		glade_util_ui_message (glade_app_get_window(),
+				       GLADE_UI_ERROR, NULL,
+				       _("Failed to load %s.\n"
+					 "The following required catalogs are unavailable: %s"),
+				       path, string->str);
+	g_string_free (string, TRUE);
+	return loadable;
+}
+
+
+static gboolean
+glade_project_read_policy_from_comment (GladeXmlNode      *comment,
+					GladeNamingPolicy *policy)
+{
+	gchar *value, buffer[256];
+	gboolean loaded = FALSE;
+
+	if (!glade_xml_node_is_comment (comment)) 
+		return FALSE;
+
+	value = glade_xml_get_content (comment);
+	if (value && !strncmp (" interface-naming-policy", value, strlen (" interface-naming-policy")))
+	{
+		if (sscanf (value, " interface-naming-policy %s", buffer) == 1)
+		{
+			if (strcmp (buffer, "project-wide") == 0)
+				*policy = GLADE_POLICY_PROJECT_WIDE;
+			else
+				*policy = GLADE_POLICY_TOPLEVEL_CONTEXTUAL;
+			
+			loaded = TRUE;
+		}
+	}
+	g_free (value);
+
+	return loaded;
+}
+
+
+static void
+glade_project_read_naming_policy (GladeProject *project,
+				  GladeXmlNode *root_node)
+{
+	/* A project file with no mention of a policy needs more lax rules 
+	 * (a new project has a project wide policy by default)
+	 */
+	GladeNamingPolicy policy = GLADE_POLICY_TOPLEVEL_CONTEXTUAL;
+	GladeXmlNode *node;
+	
+	for (node = glade_xml_node_get_children_with_comments (root_node); 
+	     node; node = glade_xml_node_next_with_comments (node))
+	{
+		/* Skip non "requires" tags */
+		if (!glade_project_read_policy_from_comment (node, &policy))
+			continue;
+	}
+
+	glade_project_set_naming_policy (project, policy, FALSE);
+}
+
+
+static void
+glade_project_read_comment (GladeProject *project, GladeXmlDoc *doc)
+{
+	/* TODO Write me !! Find out how to extract root level comments 
+	 * with libxml2 !!! 
+	 */
+}
+
+gboolean
+glade_project_load_from_file (GladeProject *project, const gchar *path)
+{
+	GladeXmlContext *context;
+	GladeXmlDoc     *doc;
+	GladeXmlNode    *root;
+	GladeXmlNode    *node;
+	GladeWidget     *widget;
+
+	project->priv->selection = NULL;
+	project->priv->objects = NULL;
+	project->priv->loading = TRUE;
+
+	project->priv->path = glade_util_canonical_path (path);	
+
+	/* get the context & root node of the catalog file */
+	if (!(context = 
+	      glade_xml_context_new_from_path (path,
+					       NULL, 
+					       NULL)))
+	{
+		g_warning ("Couldn't open glade file [%s].", path);
+		return FALSE;
+	}
+
+	doc  = glade_xml_context_get_doc (context);
+	root = glade_xml_doc_get_root (doc);
+
+	if (glade_xml_node_verify_silent (root, GLADE_XML_TAG_LIBGLADE_PROJECT))
+		project->priv->format = GLADE_PROJECT_FORMAT_LIBGLADE;
+	else if (glade_xml_node_verify_silent (root, GLADE_XML_TAG_BUILDER_PROJECT))
+		project->priv->format = GLADE_PROJECT_FORMAT_GTKBUILDER;
+	else
+	{
+		g_warning ("Couldnt determine project format, skipping %s", path);
+		glade_xml_context_free (context);
+		return FALSE;
+	}
+
+	/* XXX Need to load project->priv->comment ! */
+	glade_project_read_comment (project, doc);
+
+
+	if (glade_project_read_requires (project, root, path) == FALSE)
+	{
+		glade_xml_context_free (context);
+		return FALSE;
+	}
+
+	glade_project_read_naming_policy (project, root);
+
+	for (node = glade_xml_node_get_children (root); 
+	     node; node = glade_xml_node_next (node))
+	{
 		/* Skip "requires" tags */
 		if (!glade_xml_node_verify_silent
 		    (node, GLADE_XML_TAG_WIDGET (project->priv->format)))
@@ -1541,55 +1417,351 @@
 
 }
 
+/**
+ * glade_project_load:
+ * @path:
+ * 
+ * Opens a project at the given path.
+ *
+ * Returns: a new #GladeProject for the opened project on success, %NULL on 
+ *          failure
+ */
+GladeProject *
+glade_project_load (const gchar *path)
+{
+	GladeProject *project;
+	gboolean      retval;
+	
+	g_return_val_if_fail (path != NULL, NULL);
+	
+	project = g_object_new (GLADE_TYPE_PROJECT, NULL);
+	
+	retval = glade_project_load_from_file (project, path);
+	
+	if (retval)
+	{
+		gchar *name, *title;
 
+		/* Update prefs dialogs here... */
+		name = glade_project_get_name (project);
+		title = g_strdup_printf (_("%s preferences"), name);
+		gtk_window_set_title (GTK_WINDOW (project->priv->prefs_dialog), title);
+		g_free (title);
+		g_free (name);
 
-static void
-glade_project_verify_property (GladeProject   *project,
-			       GladeProperty  *property, 
-			       const gchar    *path_name,
-			       GString        *string,
-			       gboolean        forwidget)
-{
-	GladeWidgetAdaptor *adaptor;
-	gint target_major, target_minor;
-	gchar *catalog, *tooltip;
+		return project;
+	}
+	else
+	{
+		g_object_unref (project);
+		return NULL;
+	}
+}
 
-	if (glade_property_original_default (property) && !forwidget)
-		return;
+/*******************************************************************
+                    Writing project code here
+ *******************************************************************/
 
-	adaptor = GLADE_WIDGET_ADAPTOR (property->klass->origin_handle);
+#define GLADE_XML_COMMENT "Generated with "PACKAGE_NAME
+
+static gchar *
+glade_project_make_comment ()
+{
+	time_t now = time (NULL);
+	gchar *comment;
+	comment = g_strdup_printf (GLADE_XML_COMMENT" "PACKAGE_VERSION" on %s",
+				   ctime (&now));
+	glade_util_replace (comment, '\n', ' ');
 	
-	g_object_get (adaptor, "catalog", &catalog, NULL);
-	glade_project_target_version_for_adaptor (property->widget->project, adaptor, 
-						  &target_major,
-						  &target_minor);
+	return comment;
+}
+
+static void
+glade_project_update_comment (GladeProject *project)
+{
+	gchar **lines, **l, *comment = NULL;
 	
-	if (project->priv->format == GLADE_PROJECT_FORMAT_LIBGLADE &&
-	    property->klass->libglade_unsupported)
+	/* If project has no comment -> add the new one */
+	if (project->priv->comment == NULL)
 	{
-		if (forwidget)
-			glade_property_set_support_warning
-				(property, TRUE, _("This property is not supported in libglade format"));
-		else
-			/* translators: reffers to a property '%s' of widget '[%s]' 
-			 * introduced in toolkit version '%s %d.%d' */
-			g_string_append_printf
-				(string,
-				 property->klass->packing ?
-				 _("[%s] Packing property '%s' of object class '%s' is not "
-				   "supported in libglade format\n") :
-				 _("[%s] Property '%s' of object class '%s' is not "
-				   "supported in libglade format\n"),
-				 path_name,
-				 property->klass->name, 
-				 adaptor->title);
+		project->priv->comment = glade_project_make_comment ();
+		return;
 	}
-	else if (project->priv->format == GLADE_PROJECT_FORMAT_GTKBUILDER &&
-		 property->klass->libglade_only)
+	
+	for (lines = l = g_strsplit (project->priv->comment, "\n", 0); *l; l++)
 	{
-		if (forwidget)
-			glade_property_set_support_warning
-				(property, TRUE, _("This property is only supported in libglade format"));
+		gchar *start;
+		
+		/* Ignore leading spaces */
+		for (start = *l; *start && g_ascii_isspace (*start); start++);
+		
+		if (g_str_has_prefix (start, GLADE_XML_COMMENT))
+		{
+			/* This line was generated by glade -> updating... */
+			g_free (*l);
+			*l = comment = glade_project_make_comment ();
+		}
+	}
+	
+	if (comment)
+	{
+		g_free (project->priv->comment);
+		project->priv->comment = g_strjoinv ("\n", lines);
+	}
+	
+	g_strfreev (lines);
+}
+
+static void
+glade_project_write_required_libs (GladeProject    *project,
+				   GladeXmlContext *context,
+				   GladeXmlNode    *root)
+{
+	GladeProjectFormat fmt;
+	GladeXmlNode    *req_node;
+	GList           *required, *list;
+	gint             major, minor;
+	gchar           *version;
+
+	fmt = glade_project_get_format (project);
+
+	if ((required = glade_project_required_libs (project)) != NULL)
+	{
+		for (list = required; list; list = list->next)
+		{
+			glade_project_get_target_version (project, (gchar *)list->data, 
+							  &major, &minor);
+			
+			version = g_strdup_printf ("%d.%d", major, minor);
+
+			/* Write the standard requires tag */
+			if (fmt == GLADE_PROJECT_FORMAT_GTKBUILDER ||
+			    (fmt == GLADE_PROJECT_FORMAT_LIBGLADE &&
+			     strcmp ("gtk+", (gchar *)list->data)))
+			{
+				if (GLADE_GTKBUILDER_HAS_VERSIONING (major, minor))
+				{
+					req_node = glade_xml_node_new (context, GLADE_XML_TAG_REQUIRES);
+					glade_xml_node_append_child (root, req_node);
+					glade_xml_node_set_property_string (req_node, 
+									    GLADE_XML_TAG_LIB, 
+									    (gchar *)list->data);
+				}
+				else
+				{
+					gchar *comment = 
+						g_strdup_printf (" interface-requires %s %s ", 
+								 (gchar *)list->data, version);
+					req_node = glade_xml_node_new_comment (context, comment);
+					glade_xml_node_append_child (root, req_node);
+					g_free (comment);
+				}
+
+				if (fmt != GLADE_PROJECT_FORMAT_LIBGLADE)
+					glade_xml_node_set_property_string 
+						(req_node, GLADE_XML_TAG_VERSION, version);
+			}
+
+			/* Add extra metadata for libglade */
+			if (fmt == GLADE_PROJECT_FORMAT_LIBGLADE)
+			{
+				gchar *comment = g_strdup_printf (" interface-requires %s %s ", 
+								  (gchar *)list->data, version);
+				req_node = glade_xml_node_new_comment (context, comment);
+				glade_xml_node_append_child (root, req_node);
+				g_free (comment);
+			}
+			g_free (version);
+
+		}
+		g_list_foreach (required, (GFunc)g_free, NULL);
+		g_list_free (required);
+	}
+
+}
+
+static void
+glade_project_write_naming_policy (GladeProject    *project,
+				   GladeXmlContext *context,
+				   GladeXmlNode    *root)
+{
+	GladeXmlNode *policy_node;
+	gchar *comment = g_strdup_printf (" interface-naming-policy %s ", 
+					  project->priv->naming_policy == GLADE_POLICY_PROJECT_WIDE ? 
+					  "project-wide" : "toplevel-contextual");
+
+	policy_node = glade_xml_node_new_comment (context, comment);
+	glade_xml_node_append_child (root, policy_node);
+	g_free (comment);
+}
+
+static GladeXmlContext *
+glade_project_write (GladeProject *project)
+{
+	GladeXmlContext *context;
+	GladeXmlDoc     *doc;
+	GladeXmlNode    *root, *comment_node;
+	GList           *list;
+
+	doc     = glade_xml_doc_new ();
+	context = glade_xml_context_new (doc, NULL);
+	root    = glade_xml_node_new (context, GLADE_XML_TAG_PROJECT (project->priv->format));
+	glade_xml_doc_set_root (doc, root);
+
+	glade_project_update_comment (project);
+/* 	comment_node = glade_xml_node_new_comment (context, project->priv->comment); */
+
+	/* XXX Need to append this to the doc ! not the ROOT !
+	   glade_xml_node_append_child (root, comment_node); */
+
+	glade_project_write_required_libs (project, context, root);
+
+	glade_project_write_naming_policy (project, context, root);
+
+	/* Any automatically generated stuff goes here */
+	glade_project_generate_nodes (project, context, root);
+
+	for (list = project->priv->objects; list; list = list->next)
+	{
+		GladeWidget *widget;
+
+		widget = glade_widget_get_from_gobject (list->data);
+
+		/* 
+		 * Append toplevel widgets. Each widget then takes
+		 * care of appending its children.
+		 */
+		if (widget->parent == NULL)
+			glade_widget_write (widget, context, root);
+	}
+	
+	return context;
+}
+
+/**
+ * glade_project_save:
+ * @project: a #GladeProject
+ * @path: location to save glade file
+ * @error: an error from the G_FILE_ERROR domain.
+ * 
+ * Saves @project to the given path. 
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ */
+gboolean
+glade_project_save (GladeProject *project, const gchar *path, GError **error)
+{
+	GladeXmlContext *context;
+	GladeXmlDoc     *doc;
+	gchar           *canonical_path;
+	gint             ret;
+
+	if (!glade_project_verify (project, TRUE))
+		return FALSE;
+
+	context = glade_project_write (project);
+	doc     = glade_xml_context_get_doc (context);
+	ret     = glade_xml_doc_save (doc, path);
+	glade_xml_context_destroy (context);
+
+	canonical_path = glade_util_canonical_path (path);
+	g_assert (canonical_path);
+
+	if (project->priv->path == NULL ||
+	    strcmp (canonical_path, project->priv->path))
+        {
+		gchar *old_dir, *new_dir, *name, *title;
+
+		if (project->priv->path)
+		{
+			old_dir = g_path_get_dirname (project->priv->path);
+			new_dir = g_path_get_dirname (canonical_path);
+
+			glade_project_move_resources (project, 
+						      old_dir, 
+						      new_dir);
+			g_free (old_dir);
+			g_free (new_dir);
+		}
+		project->priv->path = (g_free (project->priv->path),
+				 g_strdup (canonical_path));
+
+		/* Update prefs dialogs here... */
+		name = glade_project_get_name (project);
+		title = g_strdup_printf (_("%s preferences"), name);
+		gtk_window_set_title (GTK_WINDOW (project->priv->prefs_dialog), title);
+		g_free (title);
+		g_free (name);
+	}
+
+	glade_project_set_readonly (project, 
+				    !glade_util_file_is_writeable (project->priv->path));
+
+	project->priv->mtime = glade_util_get_file_mtime (project->priv->path, NULL);
+	
+	glade_project_set_modified (project, FALSE);
+
+	if (project->priv->unsaved_number > 0)
+	{
+		glade_id_allocator_release (get_unsaved_number_allocator (), project->priv->unsaved_number);
+		project->priv->unsaved_number = 0;
+        }
+
+	g_free (canonical_path);
+
+	return ret > 0;
+}
+
+/*******************************************************************
+     Verify code here (versioning, incompatability checks)
+ *******************************************************************/
+static void
+glade_project_verify_property (GladeProject   *project,
+			       GladeProperty  *property, 
+			       const gchar    *path_name,
+			       GString        *string,
+			       gboolean        forwidget)
+{
+	GladeWidgetAdaptor *adaptor;
+	gint target_major, target_minor;
+	gchar *catalog, *tooltip;
+
+	if (glade_property_original_default (property) && !forwidget)
+		return;
+
+	adaptor = GLADE_WIDGET_ADAPTOR (property->klass->origin_handle);
+	
+	g_object_get (adaptor, "catalog", &catalog, NULL);
+	glade_project_target_version_for_adaptor (property->widget->project, adaptor, 
+						  &target_major,
+						  &target_minor);
+	
+	if (project->priv->format == GLADE_PROJECT_FORMAT_LIBGLADE &&
+	    property->klass->libglade_unsupported)
+	{
+		if (forwidget)
+			glade_property_set_support_warning
+				(property, TRUE, _("This property is not supported in libglade format"));
+		else
+			/* translators: reffers to a property '%s' of widget '[%s]' 
+			 * introduced in toolkit version '%s %d.%d' */
+			g_string_append_printf
+				(string,
+				 property->klass->packing ?
+				 _("[%s] Packing property '%s' of object class '%s' is not "
+				   "supported in libglade format\n") :
+				 _("[%s] Property '%s' of object class '%s' is not "
+				   "supported in libglade format\n"),
+				 path_name,
+				 property->klass->name, 
+				 adaptor->title);
+	}
+	else if (project->priv->format == GLADE_PROJECT_FORMAT_GTKBUILDER &&
+		 property->klass->libglade_only)
+	{
+		if (forwidget)
+			glade_property_set_support_warning
+				(property, TRUE, _("This property is only supported in libglade format"));
 		else
 			/* translators: reffers to a property '%s' of widget '[%s]' 
 			 * introduced in toolkit version '%s %d.%d' */
@@ -1829,148 +2001,501 @@
 	return ret;
 }
 
-
-/**
- * glade_project_selection_changed:
- * @project: a #GladeProject
- *
- * Causes @project to emit a "selection_changed" signal.
- */
-void
-glade_project_selection_changed (GladeProject *project)
+static void
+glade_project_target_version_for_adaptor (GladeProject        *project, 
+					  GladeWidgetAdaptor  *adaptor,
+					  gint                *major,
+					  gint                *minor)
 {
-	g_return_if_fail (GLADE_IS_PROJECT (project));
-	g_signal_emit (G_OBJECT (project),
-		       glade_project_signals [SELECTION_CHANGED],
-		       0);
+	gchar   *catalog = NULL;
+
+	g_object_get (adaptor, "catalog", &catalog, NULL);
+	glade_project_get_target_version (project, catalog, major, minor);
+	g_free (catalog);
 }
 
 static void
-glade_project_on_widget_notify (GladeWidget *widget, GParamSpec *arg, GladeProject *project)
+glade_project_verify_adaptor (GladeProject       *project,
+			      GladeWidgetAdaptor *adaptor,
+			      const gchar        *path_name,
+			      GString            *string,
+			      gboolean            saving,
+			      gboolean            forwidget,
+			      GladeSupportMask   *mask)
 {
-	g_return_if_fail (GLADE_IS_WIDGET (widget));
-	g_return_if_fail (GLADE_IS_PROJECT (project));
+	GladeSupportMask    support_mask = GLADE_SUPPORT_OK;
+	GladeWidgetAdaptor *adaptor_iter;
+	gint                target_major, target_minor;
+	gchar              *catalog = NULL;
 
-	switch (arg->name[0])
+	for (adaptor_iter = adaptor; adaptor_iter;
+	     adaptor_iter = glade_widget_adaptor_get_parent_adaptor (adaptor_iter))
 	{
-	case 'n':
-		if (strcmp (arg->name, "name") == 0)
-		{
-			const char *old_name = g_hash_table_lookup (project->priv->widget_old_names, widget);
-			glade_project_widget_name_changed (project, widget, old_name);
-			g_hash_table_insert (project->priv->widget_old_names, widget, g_strdup (glade_widget_get_name (widget)));
-		}
-
-	case 'p':
-		if (strcmp (arg->name, "project") == 0)
-			glade_project_remove_object (project, glade_widget_get_object (widget));
-	}
-}
 
+		g_object_get (adaptor_iter, "catalog", &catalog, NULL);
+		glade_project_target_version_for_adaptor (project, adaptor_iter, 
+							  &target_major,
+							  &target_minor);
 
-static void
-gp_sync_resources (GladeProject *project, 
-		   GladeProject *prev_project,
-		   GladeWidget  *gwidget,
-		   gboolean      remove)
-{
-	GList          *prop_list, *l;
-	GladeProperty  *property;
-	gchar          *resource, *full_resource;
+		if (target_major < GWA_VERSION_SINCE_MAJOR (adaptor_iter) ||
+		    (target_major == GWA_VERSION_SINCE_MAJOR (adaptor_iter) &&
+		     target_minor < GWA_VERSION_SINCE_MINOR (adaptor_iter)))
+		{
+			if (forwidget)
+			{
+				/* translators: reffers to a widget
+				 * introduced in toolkit version '%s %d.%d',
+				 * and a project targeting toolkit verion '%s %d.%d' */
+				g_string_append_printf
+					(string, 
+					 _("This widget was introduced in %s %d.%d "
+					   "project targets %s %d.%d"),
+					 catalog,
+					 GWA_VERSION_SINCE_MAJOR (adaptor_iter),
+					 GWA_VERSION_SINCE_MINOR (adaptor_iter),
+					 catalog, target_major, target_minor);
+			}
+			else
+				/* translators: reffers to a widget '[%s]'  
+				 * introduced in toolkit version '%s %d.%d' */
+				g_string_append_printf
+					(string, 
+					 _("[%s] Object class '%s' was introduced in %s %d.%d\n"),
+					 path_name, adaptor_iter->title, catalog,
+					 GWA_VERSION_SINCE_MAJOR (adaptor_iter),
+					 GWA_VERSION_SINCE_MINOR (adaptor_iter));
 
-	prop_list = g_list_copy (gwidget->properties);
-	prop_list = g_list_concat
-		(prop_list, g_list_copy (gwidget->packing_properties));
+			support_mask |= GLADE_SUPPORT_MISMATCH;
+		}
 
-	for (l = prop_list; l; l = l->next)
-	{
-		property = l->data;
-		if (property->klass->resource)
+		if (project->priv->format == GLADE_PROJECT_FORMAT_GTKBUILDER &&
+		    GWA_LIBGLADE_ONLY (adaptor_iter))
 		{
-			GValue value = { 0, };
+			if (forwidget)
+			{
+				if (string->len)
+					g_string_append (string, "\n");
+				g_string_append_printf
+					(string,
+					 _("This widget is only supported in libglade format"));
+			}
+			else
+				/* translators: reffers to a widget '[%s]'  
+				 * loaded from toolkit version '%s %d.%d' */
+				g_string_append_printf
+					(string,
+					 _("[%s] Object class '%s' from %s %d.%d "
+					   "is only supported in libglade format\n"),
+					 path_name, adaptor_iter->title, catalog,
+					 target_major, target_minor);
 
-			if (remove)
+			support_mask |= GLADE_SUPPORT_LIBGLADE_ONLY;
+		}
+		else if (project->priv->format == GLADE_PROJECT_FORMAT_LIBGLADE &&
+			 GWA_LIBGLADE_UNSUPPORTED (adaptor_iter))
+		{
+			if (forwidget)
 			{
-				glade_project_set_resource (project, property, NULL);
-				continue;
+				if (string->len)
+					g_string_append (string, "\n");
+				g_string_append_printf
+					(string,
+					 _("This widget is not supported in libglade format"));
 			}
+			else
+				/* translators: reffers to a widget '[%s]'  
+				 * loaded from toolkit version '%s %d.%d' */
+				g_string_append_printf
+					(string,
+					 _("[%s] Object class '%s' from %s %d.%d "
+					   "is not supported in libglade format\n"),
+					 path_name, adaptor_iter->title, catalog,
+					 target_major, target_minor);
 
-			glade_property_get_value (property, &value);
-			
-			if ((resource = glade_widget_adaptor_string_from_value
-			     (GLADE_WIDGET_ADAPTOR (property->klass->handle),
-			      property->klass, &value, project->priv->format)) != NULL)
+			support_mask |= GLADE_SUPPORT_LIBGLADE_UNSUPPORTED;
+		}
+
+		if (!saving && GWA_DEPRECATED (adaptor_iter))
+		{
+			if (forwidget)
 			{
-				full_resource = glade_project_resource_fullpath
-					(prev_project ? prev_project : project, resource);
-			
-				/* Use a full path here so that the current
-				 * working directory isnt used.
-				 */
-				glade_project_set_resource (project, 
-							    property,
-							    full_resource);
-				
-				g_free (full_resource);
-				g_free (resource);
+				if (string->len)
+					g_string_append (string, "\n");
+				g_string_append_printf
+					(string, _("This widget is deprecated"));
 			}
-			g_value_unset (&value);
+			else
+				/* translators: reffers to a widget '[%s]'  
+				 * loaded from toolkit version '%s %d.%d' */
+				g_string_append_printf
+					(string, 
+					 _("[%s] Object class '%s' from %s %d.%d "
+					   "is deprecated\n"),
+					 path_name, adaptor_iter->title, catalog,
+					 target_major, target_minor);
+
+			support_mask |= GLADE_SUPPORT_DEPRECATED;
 		}
+		g_free (catalog);
 	}
-	g_list_free (prop_list);
+	if (mask)
+		*mask = support_mask;
 }
 
-static void
-glade_project_sync_resources_for_widget (GladeProject *project, 
-					 GladeProject *prev_project,
-					 GladeWidget  *gwidget,
-					 gboolean      remove)
+/**
+ * glade_project_verify_widget_adaptor:
+ * @project: A #GladeProject
+ * @adaptor: the #GladeWidgetAdaptor to verify
+ * @mask: a return location for a #GladeSupportMask
+ * 
+ * Checks the supported state of this widget adaptor
+ * and generates a string to show in the UI describing why.
+ *
+ * Returns: A newly allocated string 
+ */
+gchar *
+glade_project_verify_widget_adaptor (GladeProject       *project,
+				     GladeWidgetAdaptor *adaptor,
+				     GladeSupportMask   *mask)
 {
-	GList *children, *l;
-	GladeWidget *gchild;
+	GString *string = g_string_new (NULL);
+	gchar   *ret = NULL;
 
-	children = glade_widget_adaptor_get_children
-		(gwidget->adaptor, gwidget->object);
+	glade_project_verify_adaptor (project, adaptor, NULL,
+				      string, FALSE, TRUE, mask);
 
-	for (l = children; l; l = l->next)
-		if ((gchild = 
-		     glade_widget_get_from_gobject (l->data)) != NULL)
-			glade_project_sync_resources_for_widget 
-				(project, prev_project, gchild, remove);
-	if (children)
-		g_list_free (children);
+	/* there was a '\0' byte... */
+	if (string->len > 0)
+	{
+		ret = string->str;
+		g_string_free (string, FALSE);
+	}
+	else
+		g_string_free (string, TRUE);
 
-	gp_sync_resources (project, prev_project, gwidget, remove);
+
+	return ret;
 }
 
+
 /**
- * glade_project_add_object:
- * @project: the #GladeProject the widget is added to
- * @old_project: the #GladeProject the widget was previously in
- *               (or %NULL for the clipboard)
- * @object: the #GObject to add
- *
- * Adds an object to the project.
+ * glade_project_verify_project_for_ui:
+ * @project: A #GladeProject
+ * 
+ * Checks the project and updates warning strings in the UI
  */
 void
-glade_project_add_object (GladeProject *project, 
-			  GladeProject *old_project, 
-			  GObject      *object)
+glade_project_verify_project_for_ui (GladeProject *project)
 {
-	GladeWidget   *gwidget;
-	GList         *list, *children;
-	static gint    reentrancy_count = 0;
+	GList *list;
+	GladeWidget *widget;
+	gchar *warning;
 
-	g_return_if_fail (GLADE_IS_PROJECT (project));
-	g_return_if_fail (G_IS_OBJECT      (object));
+	/* Sync displayable info here */
+	for (list = project->priv->objects; list; list = list->next)
+	{
+		widget = glade_widget_get_from_gobject (list->data);
 
-	/* We don't list placeholders */
-	if (GLADE_IS_PLACEHOLDER (object)) 
-		return;
+		warning = glade_project_verify_widget_adaptor (project, widget->adaptor, NULL);
+		glade_widget_set_support_warning (widget, warning);
 
-	/* Only widgets accounted for in the catalog or widgets declared
-	 * in the plugin with glade_widget_new_for_internal_child () are
-	 * usefull in the project.
+		if (warning)
+			g_free (warning);
+
+		glade_project_verify_properties (widget);
+	}
+
+	/* refresh palette if this is the active project */
+	if (project == glade_app_get_project ())
+		glade_palette_refresh (glade_app_get_palette ());
+}
+
+/*******************************************************************
+   Project object tracking code, name exclusivity, resources etc...
+ *******************************************************************/
+static GladeNameContext *
+name_context_by_widget (GladeProject *project, 
+			GladeWidget  *gwidget)
+{
+	TopLevelInfo  *tinfo;
+	GladeWidget   *iter;
+	GList         *list;
+
+	iter = gwidget;
+	while (iter->parent) iter = iter->parent;
+
+	for (list = project->priv->toplevels; list; list = list->next)
+	{
+		tinfo = list->data;
+		if (tinfo->toplevel == iter)
+			return tinfo->names;
+	}
+	return NULL;
+}
+
+GladeWidget *
+search_ancestry_by_name (GladeWidget *toplevel, const gchar *name)
+{
+	GladeWidget *widget = NULL, *iter;
+	GList *list, *children;
+
+	if ((children = glade_widget_adaptor_get_children (toplevel->adaptor,
+							   toplevel->object)) != NULL)
+	{
+		for (list = children; list; list = list->next) 
+			if ((iter = glade_widget_get_from_gobject (list->data)) != NULL)
+			{
+				if (iter->name && strcmp (iter->name, name) == 0)
+				{
+					widget = iter;
+					break;
+				}
+				else if ((widget = search_ancestry_by_name (iter, name)) != NULL)
+					break;
+			}
+
+		g_list_free (children);
+	}
+	return widget;
+}
+
+/**
+ * glade_project_get_widget_by_name:
+ * @project: a #GladeProject
+ * @ancestor: The toplevel project object to search under
+ * @name: The user visible name of the widget we are looking for
+ * 
+ * Searches under @ancestor in @project looking for a #GladeWidget named @name.
+ * 
+ * Returns: a pointer to the widget, %NULL if the widget does not exist
+ */
+GladeWidget *
+glade_project_get_widget_by_name (GladeProject *project, GladeWidget *ancestor, const gchar *name)
+{
+	GladeWidget *toplevel, *widget = NULL;
+	GList *list;
+
+	g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
+	g_return_val_if_fail (name != NULL, NULL);
+	
+	if (ancestor)
+	{
+		toplevel = glade_widget_get_toplevel (ancestor);
+		if ((widget = search_ancestry_by_name (toplevel, name)) != NULL)
+			return widget;
+	}
+
+	/* Now try searching in only toplevel objects... */
+	for (list = project->priv->objects; list; list = list->next) {
+		GladeWidget *widget;
+
+		widget = glade_widget_get_from_gobject (list->data);
+		g_assert (widget->name);
+		if (widget->parent == NULL && strcmp (widget->name, name) == 0)
+			return widget;
+	}
+
+	/* Finally resort to a project wide search. */
+	for (list = project->priv->objects; list; list = list->next) {
+		GladeWidget *widget;
+
+		widget = glade_widget_get_from_gobject (list->data);
+		g_return_val_if_fail (widget->name != NULL, NULL);
+		if (strcmp (widget->name, name) == 0)
+			return widget;
+	}
+
+	return NULL;
+}
+
+static void
+glade_project_release_widget_name (GladeProject *project, GladeWidget *gwidget, const char *widget_name)
+{
+	GladeNameContext *context = NULL;
+	TopLevelInfo     *tinfo = NULL;
+	GladeWidget      *iter;
+	GList            *list;
+
+	/* Search by hand here since we need the tinfo to free... */
+	iter = gwidget;
+	while (iter->parent) iter = iter->parent;
+
+	for (list = project->priv->toplevels; list; list = list->next)
+	{
+		tinfo = list->data;
+		if (tinfo->toplevel == iter)
+		{
+			context = tinfo->names;
+			break;
+		}
+	}
+
+	if (context)
+		glade_name_context_release_name (context, widget_name);
+
+	if (!gwidget->parent)
+	{
+		glade_name_context_release_name (project->priv->toplevel_names, widget_name);
+
+		if (context && glade_name_context_n_names (context) == 0)
+		{
+			glade_name_context_destroy (context);
+			g_free (tinfo);
+			project->priv->toplevels = g_list_remove (project->priv->toplevels, tinfo);
+		}
+	}
+}
+
+/**
+ * glade_project_available_widget_name:
+ * @project: a #GladeProject
+ * @widget: the #GladeWidget intended to recieve a new name
+ * @name: base name of the widget to create
+ *
+ * Checks whether @name is an appropriate name for @widget.
+ *
+ * Returns: whether the name is available or not.
+ */
+gboolean
+glade_project_available_widget_name (GladeProject *project, 
+				     GladeWidget  *widget,
+				     const gchar  *name)
+{
+	GladeNameContext *context;
+
+	g_return_val_if_fail (GLADE_IS_PROJECT (project), FALSE);
+	g_return_val_if_fail (GLADE_IS_WIDGET (widget), FALSE);
+	g_return_val_if_fail (widget->project == project, FALSE);
+
+	if (!name || !name[0])
+		return FALSE;
+
+	context = name_context_by_widget (project, widget);
+	g_assert (context);
+
+	if (!widget->parent)
+		return (!glade_name_context_has_name (context, name) &&
+			!glade_name_context_has_name (project->priv->toplevel_names, name));
+
+	return !glade_name_context_has_name (context, name);
+}
+
+/**
+ * glade_project_new_widget_name:
+ * @project: a #GladeProject
+ * @widget: the #GladeWidget intended to recieve a new name
+ * @base_name: base name of the widget to create
+ *
+ * Creates a new name for a widget that doesn't collide with any of the names 
+ * already in @project. This name will start with @base_name.
+ *
+ * Returns: a string containing the new name, %NULL if there is not enough 
+ *          memory for this string
+ */
+gchar *
+glade_project_new_widget_name (GladeProject *project, 
+			       GladeWidget  *widget,
+			       const gchar  *base_name)
+{
+	GladeNameContext *context;
+	gchar            *name;
+
+	g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
+	g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL);
+	g_return_val_if_fail (widget->project == project, NULL);
+	g_return_val_if_fail (base_name && base_name[0], NULL);
+
+	context = name_context_by_widget (project, widget);
+
+	/* should use dual here to encourage unique names across the file... */
+	if (context && widget->parent)
+		name = glade_name_context_new_name (context, base_name);
+	else if (context)
+		name = glade_name_context_dual_new_name (context, project->priv->toplevel_names, base_name);
+	else
+		name = glade_name_context_new_name (project->priv->toplevel_names, base_name);
+
+	return name;
+}
+
+/**
+ * glade_project_set_widget_name:
+ * @project: a #GladeProject
+ * @widget: the #GladeWidget to set a name on
+ * @name: the name to set.
+ *
+ * Sets @name on @widget in @project, if @name is not
+ * available then a new name will be used.
+ */
+void
+glade_project_set_widget_name (GladeProject *project, 
+			       GladeWidget  *widget, 
+			       const gchar  *name)
+{
+	GladeNameContext *context = NULL;
+	gchar            *new_name;
+
+	g_return_if_fail (GLADE_IS_PROJECT (project));
+	g_return_if_fail (GLADE_IS_WIDGET (widget));
+	g_return_if_fail (widget->project == project);
+	g_return_if_fail (name && name[0]);
+
+	if (strcmp (name, widget->name) == 0)
+		return;
+
+	/* Police the widget name */
+	if (!glade_project_available_widget_name (project, widget, name))
+		new_name = glade_project_new_widget_name (project, widget, name);
+	else
+		new_name = g_strdup (name);
+
+
+	/* Add to name context(s) */
+	context = name_context_by_widget (project, widget);
+	g_assert (context);
+	glade_name_context_add_name (context, new_name);
+	if (!widget->parent)
+		glade_name_context_add_name (project->priv->toplevel_names, new_name);
+
+	/* Release old name and set new widget name */
+	glade_project_release_widget_name (project, widget, widget->name);
+	glade_widget_set_name (widget, new_name);
+	
+	g_free (new_name);
+}
+
+
+
+/**
+ * glade_project_add_object:
+ * @project: the #GladeProject the widget is added to
+ * @old_project: the #GladeProject the widget was previously in
+ *               (or %NULL for the clipboard)
+ * @object: the #GObject to add
+ *
+ * Adds an object to the project.
+ */
+void
+glade_project_add_object (GladeProject *project, 
+			  GladeProject *old_project, 
+			  GObject      *object)
+{
+	GladeNameContext *context;
+	GladeWidget      *gwidget;
+	GList            *list, *children;
+	static gint       reentrancy_count = 0;
+	gchar            *name;
+
+	g_return_if_fail (GLADE_IS_PROJECT (project));
+	g_return_if_fail (G_IS_OBJECT      (object));
+
+	/* We don't list placeholders */
+	if (GLADE_IS_PLACEHOLDER (object)) 
+		return;
+
+	/* Only widgets accounted for in the catalog or widgets declared
+	 * in the plugin with glade_widget_new_for_internal_child () are
+	 * usefull in the project.
 	 */
 	if ((gwidget = glade_widget_get_from_gobject (object)) == NULL)
 		return;
@@ -1979,14 +2504,29 @@
 	if (glade_project_has_object (project, object))
 		return;
 
-	/* Police widget names here (just rename them on the way in the project)
-	 */
-	if (glade_project_get_widget_by_name (project, gwidget->name) != NULL)
-	{ 
-		gchar *name = glade_project_new_widget_name (project, gwidget->name);
+	/* Create a name context for newly added toplevels... */
+	if (!gwidget->parent)
+	{
+		TopLevelInfo *tinfo = g_new0 (TopLevelInfo, 1);
+		tinfo->toplevel     = gwidget;
+		tinfo->names        = glade_name_context_new ();
+		project->priv->toplevels = g_list_prepend (project->priv->toplevels, tinfo);
+	}
+
+	/* Make sure we have an exclusive name first... */
+	if (!glade_project_available_widget_name (project, gwidget, gwidget->name))
+	{
+		name = glade_project_new_widget_name (project, gwidget, gwidget->name);
 		glade_widget_set_name (gwidget, name);
 		g_free (name);
 	}
+
+	/* Now lock down the widget name. */
+	context = name_context_by_widget (project, gwidget);
+	g_assert (context);
+	glade_name_context_add_name (context, gwidget->name);
+	if (!gwidget->parent)
+		glade_name_context_add_name (project->priv->toplevel_names, gwidget->name);
 		
 	/* Code body starts here */
 	reentrancy_count++;
@@ -2001,11 +2541,6 @@
 	}
 
 	glade_widget_set_project (gwidget, (gpointer)project);
-	g_hash_table_insert (project->priv->widget_old_names,
-			     gwidget, g_strdup (glade_widget_get_name (gwidget)));
-
-	g_signal_connect (G_OBJECT (gwidget), "notify",
-			  (GCallback) glade_project_on_widget_notify, project);
 
 	project->priv->objects = g_list_append (project->priv->objects, g_object_ref (object));
 	
@@ -2039,58 +2574,6 @@
 	return (g_list_find (project->priv->objects, object)) != NULL;
 }
 
-/**
- * glade_project_release_widget_name:
- * @project: a #GladeProject
- * @glade_widget:
- * @widget_name:
- *
- * TODO: Write me
- */
-static void
-glade_project_release_widget_name (GladeProject *project, GladeWidget *glade_widget, const char *widget_name)
-{
-	const char *first_number = widget_name;
-	char *end_number;
-	char *base_widget_name;
-	GladeIDAllocator *id_allocator;
-	gunichar ch;
-	int id;
-
-	g_return_if_fail (GLADE_IS_PROJECT (project));
-	g_return_if_fail (GLADE_IS_WIDGET (glade_widget));
-
-	do
-	{
-		ch = g_utf8_get_char (first_number);
-
-		if (ch == 0 || g_unichar_isdigit (ch))
-			break;
-
-		first_number = g_utf8_next_char (first_number);
-	}
-	while (TRUE);
-
-	if (ch == 0)
-		return;
-
-	base_widget_name = g_strdup (widget_name);
-	*(base_widget_name + (first_number - widget_name)) = 0;
-	
-	id_allocator = g_hash_table_lookup (project->priv->widget_names_allocator, base_widget_name);
-	if (id_allocator == NULL)
-		goto lblend;
-
-	id = (int) strtol (first_number, &end_number, 10);
-	if (*end_number != 0)
-		goto lblend;
-
-	glade_id_allocator_release (id_allocator, id);
-
- lblend:
-	g_hash_table_remove (project->priv->widget_old_names, glade_widget);
-	g_free (base_widget_name);
-}
 
 /**
  * glade_project_remove_object:
@@ -2151,133 +2634,192 @@
 		glade_project_sync_resources_for_widget (project, NULL, gwidget, TRUE);
 }
 
-/**
- * glade_project_widget_name_changed:
- * @project: a #GladeProject
- * @widget: a #GladeWidget
- * @old_name:
- *
- * TODO: write me
- */
-void
-glade_project_widget_name_changed (GladeProject *project, GladeWidget *widget, const char *old_name)
+static void
+adjust_naming_policy (GladeProject *project, gboolean use_command)
 {
-	GladeWidget *iter;
-	GList       *l;
-	g_return_if_fail (GLADE_IS_PROJECT (project));
-	g_return_if_fail (GLADE_IS_WIDGET (widget));
-
-	glade_project_release_widget_name (project, widget, old_name);
+	GList *list;
+	GladeWidget *widget;
+	TopLevelInfo *tinfo;
+	GladeNameContext *context;
 
-	/* Police widget names here (just rename them on the way in the project)
-	 */
-	for (l = project->priv->objects; l; l = l->next)
+	if (project->priv->naming_policy == GLADE_POLICY_PROJECT_WIDE)
 	{
-		iter = glade_widget_get_from_gobject (l->data);
-		
-		if (widget != iter &&
-		    !strcmp (widget->name, iter->name))
-		{ 
-			gchar *name = glade_project_new_widget_name (project, widget->name);
-			glade_widget_set_name (widget, name);
-			g_free (name);
-		}
-		
-	}
-	
-	g_signal_emit (G_OBJECT (project),
-		       glade_project_signals [WIDGET_NAME_CHANGED],
-		       0,
-		       widget);
-}
+		for (list = project->priv->objects; list; list = list->next)
+		{
+			widget = glade_widget_get_from_gobject (list->data);
+			
+			if (!widget->parent)
+				continue;
 
-/**
- * glade_project_get_widget_by_name:
- * @project: a #GladeProject
- * @name: The user visible name of the widget we are looking for
- * 
- * Searches through @project looking for a #GladeWidget named @name.
- * 
- * Returns: a pointer to the widget, %NULL if the widget does not exist
- */
-GladeWidget *
-glade_project_get_widget_by_name (GladeProject *project, const gchar *name)
-{
-	GList *list;
+			if (!glade_name_context_has_name (project->priv->toplevel_names, widget->name))
+				glade_name_context_add_name (project->priv->toplevel_names, widget->name);
+			else
+			{
+				gchar *new_name = glade_name_context_new_name (project->priv->toplevel_names, 
+									       widget->name);
 
-	g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
-	g_return_val_if_fail (name != NULL, NULL);
+				if (use_command)
+					glade_command_set_name (widget, new_name);
+				else
+					glade_widget_set_name (widget, new_name);
 
-	for (list = project->priv->objects; list; list = list->next) {
-		GladeWidget *widget;
+				glade_name_context_add_name (project->priv->toplevel_names, new_name);
+				g_free (new_name);
+			}
+		}
 
-		widget = glade_widget_get_from_gobject (list->data);
-		g_return_val_if_fail (widget->name != NULL, NULL);
-		if (strcmp (widget->name, name) == 0)
-			return widget;
+		for (list = project->priv->toplevels; list; list = list->next)
+		{
+			tinfo = list->data;
+			glade_name_context_destroy (tinfo->names);
+			g_free (tinfo);
+		}
+		project->priv->toplevels = 
+			(g_list_free (project->priv->toplevels), NULL);
 	}
+	else
+	{
+		/* First add toplevel names */
+		for (list = project->priv->objects; list; list = list->next)
+		{
+			widget = glade_widget_get_from_gobject (list->data);
 
-	return NULL;
-}
+			if (!widget->parent)
+			{
+				TopLevelInfo *tinfo = g_new0 (TopLevelInfo, 1);
+				tinfo->toplevel     = widget;
+				tinfo->names        = glade_name_context_new ();
+				project->priv->toplevels = g_list_prepend (project->priv->toplevels, tinfo);
 
-/**
- * glade_project_new_widget_name:
- * @project: a #GladeProject
- * @base_name: base name of the widget to create
- *
- * Creates a new name for a widget that doesn't collide with any of the names 
- * already in @project. This name will start with @base_name.
- *
- * Returns: a string containing the new name, %NULL if there is not enough 
- *          memory for this string
- */
-char *
-glade_project_new_widget_name (GladeProject *project, const char *base_name)
+				glade_name_context_add_name (tinfo->names, widget->name);
+			}
+		}
+
+		/* Now add child names */
+		for (list = project->priv->objects; list; list = list->next)
+		{
+			widget = glade_widget_get_from_gobject (list->data);
+
+			if (widget->parent)
+			{
+				context = name_context_by_widget (project, widget);
+				glade_name_context_add_name (context, widget->name);
+				glade_name_context_release_name (project->priv->toplevel_names, widget->name);
+			}
+		}
+	}
+
+}
+
+
+/*******************************************************************
+                        Remaining stubs and api
+ *******************************************************************/
+static void
+glade_project_get_target_version (GladeProject *project,
+				  const gchar  *catalog,
+				  gint         *major,
+				  gint         *minor)
 {
-	GladeIDAllocator *id_allocator;
-	const gchar      *number;
-	gchar            *name = NULL, *freeme = NULL;
-	guint             i = 1;
-	
-	g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
+	*major = GPOINTER_TO_INT 
+		(g_hash_table_lookup (project->priv->target_versions_major,
+				      catalog));
+	*minor = GPOINTER_TO_INT 
+		(g_hash_table_lookup (project->priv->target_versions_minor,
+				      catalog));
+}
 
-	number = base_name + strlen (base_name);
+static void
+glade_project_set_target_version (GladeProject *project,
+				  const gchar  *catalog,
+				  gint          major,
+				  gint          minor)
+{
+	GladeTargetableVersion *version;
+	GSList *radios, *list;
+	GtkWidget *radio;
 
-	while (number > base_name && g_ascii_isdigit (number[-1]))
-		--number;
+	g_hash_table_insert (project->priv->target_versions_major,
+			     g_strdup (catalog),
+			     GINT_TO_POINTER (major));
+	g_hash_table_insert (project->priv->target_versions_minor,
+			     g_strdup (catalog),
+			     GINT_TO_POINTER (minor));
 
-	if (*number)
-        {
-		freeme = g_strndup (base_name, number - base_name);
-		base_name = freeme;
+
+	/* Update prefs dialog from here... */
+	if (project->priv->target_radios && 
+	    (radios = g_hash_table_lookup (project->priv->target_radios, catalog)) != NULL)
+	{
+		for (list = radios; list; list = list->next)
+			g_signal_handlers_block_by_func (G_OBJECT (list->data), 
+							 G_CALLBACK (target_button_clicked),
+							 project);
+
+		for (list = radios; list; list = list->next)
+		{
+			radio = list->data;
+
+			version = g_object_get_data (G_OBJECT (radio), "version");
+			if (version->major == major &&
+			    version->minor == minor)
+			{
+				gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE);
+				break;
+			}
+		}
+
+		for (list = radios; list; list = list->next)
+			g_signal_handlers_unblock_by_func (G_OBJECT (list->data), 
+							   G_CALLBACK (target_button_clicked),
+							   project);
 	}
-	
-	id_allocator = g_hash_table_lookup (project->priv->widget_names_allocator, base_name);
 
-	if (id_allocator == NULL)
+	glade_project_verify_project_for_ui (project);
+}
+
+static void
+glade_project_set_readonly (GladeProject *project, gboolean readonly)
+{
+	g_assert (GLADE_IS_PROJECT (project));
+	
+	if (project->priv->readonly != readonly)
 	{
-		id_allocator = glade_id_allocator_new ();
-		g_hash_table_insert (project->priv->widget_names_allocator,
-				     g_strdup (base_name), id_allocator);
+		project->priv->readonly = readonly;
+		g_object_notify (G_OBJECT (project), "read-only");
 	}
+}                                                                                               
 
-	while (TRUE)
-	{
-		i = glade_id_allocator_allocate (id_allocator);
-		name = g_strdup_printf ("%s%u", base_name, i);
+/**
+ * glade_project_get_readonly:
+ * @project: a #GladeProject
+ *
+ * Gets whether the project is read only or not
+ *
+ * Returns: TRUE if project is read only
+ */
+gboolean
+glade_project_get_readonly (GladeProject *project)
+{
+	g_return_val_if_fail (GLADE_IS_PROJECT (project), FALSE);
 
-		/* ok, there is no widget with this name, so return the name */
-		if (glade_project_get_widget_by_name (project, name) == NULL)
-			return name;
+	return project->priv->readonly;
+}
 
-		/* we already have a widget with this name, so free the name and
-		 * try again with another number */
-		g_free (name);
-		i++;
-	}
 
-	g_free (freeme);
-	return name;
+/**
+ * glade_project_selection_changed:
+ * @project: a #GladeProject
+ *
+ * Causes @project to emit a "selection_changed" signal.
+ */
+void
+glade_project_selection_changed (GladeProject *project)
+{
+	g_return_if_fail (GLADE_IS_PROJECT (project));
+	g_signal_emit (G_OBJECT (project),
+		       glade_project_signals [SELECTION_CHANGED],
+		       0);
 }
 
 static void
@@ -2386,406 +2928,118 @@
  *               a selection change
  *
  * Adds @object to the selection chain of @project
- *
- * If @emit_signal is %TRUE, calls glade_project_selection_changed().
- */
-void
-glade_project_selection_add (GladeProject *project,
-			     GObject      *object,
-			     gboolean      emit_signal)
-{
-	g_return_if_fail (GLADE_IS_PROJECT (project));
-	g_return_if_fail (G_IS_OBJECT      (object));
-	g_return_if_fail (g_list_find (project->priv->objects, object) != NULL);
-
-	if (glade_project_is_selected (project, object) == FALSE)
-	{
-		if (GTK_IS_WIDGET (object))
-			glade_util_add_selection (GTK_WIDGET (object));
-		if (project->priv->selection == NULL)
-			glade_project_set_has_selection (project, TRUE);
-		project->priv->selection = g_list_prepend (project->priv->selection, object);
-		if (emit_signal)
-			glade_project_selection_changed (project);
-	}
-}
-
-/**
- * glade_project_selection_set:
- * @project: a #GladeProject
- * @object:  a #GObject in @project
- * @emit_signal: whether or not to emit a signal 
- *               indicating a selection change
- *
- * Set the selection in @project to @object
- *
- * If @emit_signal is %TRUE, calls glade_project_selection_changed().
- */
-void
-glade_project_selection_set (GladeProject *project,
-			     GObject      *object,
-			     gboolean      emit_signal)
-{
-	g_return_if_fail (GLADE_IS_PROJECT (project));
-	g_return_if_fail (G_IS_OBJECT      (object));
-
-	if (g_list_find (project->priv->objects, object) == NULL)
-		return;
-
-	if (project->priv->selection == NULL)
-		glade_project_set_has_selection (project, TRUE);
-
-	if (glade_project_is_selected (project, object) == FALSE ||
-	    g_list_length (project->priv->selection) != 1)
-	{
-		glade_project_selection_clear (project, FALSE);
-		glade_project_selection_add (project, object, emit_signal);
-	}
-}	
-
-/**
- * glade_project_selection_get:
- * @project: a #GladeProject
- *
- * Returns: a #GList containing the #GtkWidget items currently selected in 
- *          @project
- */
-GList *
-glade_project_selection_get (GladeProject *project)
-{
-	g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
-
-	return project->priv->selection;
-}
-
-/**
- * glade_project_required_libs:
- * @project: a #GladeProject
- *
- * Returns: a #GList of allocated strings which are the names
- * of the required catalogs for this project
- */
-GList *
-glade_project_required_libs (GladeProject *project)
-{
-	GList       *required = NULL, *l, *ll;
-	GladeWidget *gwidget;
-	gboolean     listed;
-
-	for (l = project->priv->objects; l; l = l->next)
-	{
-		gchar *catalog = NULL;
-
-		gwidget = glade_widget_get_from_gobject (l->data);
-		g_assert (gwidget);
-
-		g_object_get (gwidget->adaptor, "catalog", &catalog, NULL);
-
-		if (catalog)
-		{
-			listed = FALSE;
-			for (ll = required; ll; ll = ll->next)
-				if (!strcmp ((gchar *)ll->data, catalog))
-				{
-					listed = TRUE;
-					break;
-				}
-
-			if (!listed)
-				required = g_list_prepend (required, catalog);
-		}
-	}
-	return g_list_reverse (required);
-}
-
-#define GLADE_XML_COMMENT "Generated with "PACKAGE_NAME
-
-static gchar *
-glade_project_make_comment ()
-{
-	time_t now = time (NULL);
-	gchar *comment;
-	comment = g_strdup_printf (GLADE_XML_COMMENT" "PACKAGE_VERSION" on %s",
-				   ctime (&now));
-	glade_util_replace (comment, '\n', ' ');
-	
-	return comment;
-}
-
-static void
-glade_project_update_comment (GladeProject *project)
-{
-	gchar **lines, **l, *comment = NULL;
-	
-	/* If project has no comment -> add the new one */
-	if (project->priv->comment == NULL)
-	{
-		project->priv->comment = glade_project_make_comment ();
-		return;
-	}
-	
-	for (lines = l = g_strsplit (project->priv->comment, "\n", 0); *l; l++)
-	{
-		gchar *start;
-		
-		/* Ignore leading spaces */
-		for (start = *l; *start && g_ascii_isspace (*start); start++);
-		
-		if (g_str_has_prefix (start, GLADE_XML_COMMENT))
-		{
-			/* This line was generated by glade -> updating... */
-			g_free (*l);
-			*l = comment = glade_project_make_comment ();
-		}
-	}
-	
-	if (comment)
-	{
-		g_free (project->priv->comment);
-		project->priv->comment = g_strjoinv ("\n", lines);
-	}
-	
-	g_strfreev (lines);
-}
-
-static void
-glade_project_write_required_libs (GladeProject    *project,
-				   GladeXmlContext *context,
-				   GladeXmlNode    *root)
-{
-	GladeProjectFormat fmt;
-	GladeXmlNode    *req_node;
-	GList           *required, *list;
-	gint             major, minor;
-	gchar           *version;
-
-	fmt = glade_project_get_format (project);
-
-	if ((required = glade_project_required_libs (project)) != NULL)
-	{
-		for (list = required; list; list = list->next)
-		{
-			glade_project_get_target_version (project, (gchar *)list->data, 
-							  &major, &minor);
-			
-			version = g_strdup_printf ("%d.%d", major, minor);
-
-			/* Write the standard requires tag */
-			if (fmt == GLADE_PROJECT_FORMAT_GTKBUILDER ||
-			    (fmt == GLADE_PROJECT_FORMAT_LIBGLADE &&
-			     strcmp ("gtk+", (gchar *)list->data)))
-			{
-				if (GLADE_GTKBUILDER_HAS_VERSIONING (major, minor))
-				{
-					req_node = glade_xml_node_new (context, GLADE_XML_TAG_REQUIRES);
-					glade_xml_node_append_child (root, req_node);
-					glade_xml_node_set_property_string (req_node, 
-									    GLADE_XML_TAG_LIB, 
-									    (gchar *)list->data);
-				}
-				else
-				{
-					gchar *comment = 
-						g_strdup_printf ("interface-requires %s %s", 
-								 (gchar *)list->data, version);
-					req_node = glade_xml_node_new_comment (context, comment);
-					glade_xml_node_append_child (root, req_node);
-					g_free (comment);
-				}
-
-				if (fmt != GLADE_PROJECT_FORMAT_LIBGLADE)
-					glade_xml_node_set_property_string 
-						(req_node, GLADE_XML_TAG_VERSION, version);
-			}
-
-			/* Add extra metadata for libglade */
-			if (fmt == GLADE_PROJECT_FORMAT_LIBGLADE)
-			{
-				gchar *comment = g_strdup_printf ("interface-requires %s %s", 
-								  (gchar *)list->data, version);
-				req_node = glade_xml_node_new_comment (context, comment);
-				glade_xml_node_append_child (root, req_node);
-				g_free (comment);
-			}
-			g_free (version);
-
-		}
-		g_list_foreach (required, (GFunc)g_free, NULL);
-		g_list_free (required);
-	}
-
-}
-
-static GladeXmlContext *
-glade_project_write (GladeProject *project)
-{
-	GladeXmlContext *context;
-	GladeXmlDoc     *doc;
-	GladeXmlNode    *root, *comment_node;
-	GList           *list;
-
-	doc     = glade_xml_doc_new ();
-	context = glade_xml_context_new (doc, NULL);
-	root    = glade_xml_node_new (context, GLADE_XML_TAG_PROJECT (project->priv->format));
-	glade_xml_doc_set_root (doc, root);
-
-	glade_project_update_comment (project);
-/* 	comment_node = glade_xml_node_new_comment (context, project->priv->comment); */
-
-	/* XXX Need to append this to the doc ! not the ROOT !
-	   glade_xml_node_append_child (root, comment_node); */
-
-	glade_project_write_required_libs (project, context, root);
-
-	/* Any automatically generated stuff goes here */
-	glade_project_generate_nodes (project, context, root);
-
-	for (list = project->priv->objects; list; list = list->next)
-	{
-		GladeWidget *widget;
-
-		widget = glade_widget_get_from_gobject (list->data);
-
-		/* 
-		 * Append toplevel widgets. Each widget then takes
-		 * care of appending its children.
-		 */
-		if (widget->parent == NULL)
-			glade_widget_write (widget, context, root);
-	}
-	
-	return context;
-}
-
-/**
- * glade_project_load:
- * @path:
- * 
- * Opens a project at the given path.
- *
- * Returns: a new #GladeProject for the opened project on success, %NULL on 
- *          failure
+ *
+ * If @emit_signal is %TRUE, calls glade_project_selection_changed().
  */
-GladeProject *
-glade_project_load (const gchar *path)
+void
+glade_project_selection_add (GladeProject *project,
+			     GObject      *object,
+			     gboolean      emit_signal)
 {
-	GladeProject *project;
-	gboolean      retval;
-	
-	g_return_val_if_fail (path != NULL, NULL);
-	
-	project = glade_project_new ();
-	
-	retval = glade_project_load_from_file (project, path);
-	
-	if (retval)
-	{
-		return project;
-	}
-	else
+	g_return_if_fail (GLADE_IS_PROJECT (project));
+	g_return_if_fail (G_IS_OBJECT      (object));
+	g_return_if_fail (g_list_find (project->priv->objects, object) != NULL);
+
+	if (glade_project_is_selected (project, object) == FALSE)
 	{
-		g_object_unref (project);
-		return NULL;
+		if (GTK_IS_WIDGET (object))
+			glade_util_add_selection (GTK_WIDGET (object));
+		if (project->priv->selection == NULL)
+			glade_project_set_has_selection (project, TRUE);
+		project->priv->selection = g_list_prepend (project->priv->selection, object);
+		if (emit_signal)
+			glade_project_selection_changed (project);
 	}
 }
 
-static void
-glade_project_move_resources (GladeProject *project,
-			      const gchar  *old_dir,
-			      const gchar  *new_dir)
+/**
+ * glade_project_selection_set:
+ * @project: a #GladeProject
+ * @object:  a #GObject in @project
+ * @emit_signal: whether or not to emit a signal 
+ *               indicating a selection change
+ *
+ * Set the selection in @project to @object
+ *
+ * If @emit_signal is %TRUE, calls glade_project_selection_changed().
+ */
+void
+glade_project_selection_set (GladeProject *project,
+			     GObject      *object,
+			     gboolean      emit_signal)
 {
-	GList *list, *resources;
-	gchar *old_name, *new_name;
+	g_return_if_fail (GLADE_IS_PROJECT (project));
+	g_return_if_fail (G_IS_OBJECT      (object));
 
-	if (old_dir == NULL || /* <-- Cant help you :( */
-	    new_dir == NULL)   /* <-- Unlikely         */
+	if (g_list_find (project->priv->objects, object) == NULL)
 		return;
 
-	if ((resources = /* Nothing to do here */
-	     glade_project_list_resources (project)) == NULL)
-		return;
-	
-	for (list = resources; list; list = list->next)
+	if (project->priv->selection == NULL)
+		glade_project_set_has_selection (project, TRUE);
+
+	if (glade_project_is_selected (project, object) == FALSE ||
+	    g_list_length (project->priv->selection) != 1)
 	{
-		old_name = g_build_filename 
-			(old_dir, (gchar *)list->data, NULL);
-		new_name = g_build_filename 
-			(new_dir, (gchar *)list->data, NULL);
-		glade_util_copy_file (old_name, new_name);
-		g_free (old_name);
-		g_free (new_name);
+		glade_project_selection_clear (project, FALSE);
+		glade_project_selection_add (project, object, emit_signal);
 	}
-	g_list_free (resources);
-}
+}	
 
 /**
- * glade_project_save:
+ * glade_project_selection_get:
  * @project: a #GladeProject
- * @path: location to save glade file
- * @error: an error from the G_FILE_ERROR domain.
- * 
- * Saves @project to the given path. 
  *
- * Returns: %TRUE on success, %FALSE on failure
+ * Returns: a #GList containing the #GtkWidget items currently selected in 
+ *          @project
  */
-gboolean
-glade_project_save (GladeProject *project, const gchar *path, GError **error)
+GList *
+glade_project_selection_get (GladeProject *project)
 {
-	GladeXmlContext *context;
-	GladeXmlDoc     *doc;
-	gchar           *canonical_path;
-	gint             ret;
+	g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
 
-	if (!glade_project_verify (project, TRUE))
-		return FALSE;
+	return project->priv->selection;
+}
 
-	context = glade_project_write (project);
-	doc     = glade_xml_context_get_doc (context);
-	ret     = glade_xml_doc_save (doc, path);
-	glade_xml_context_destroy (context);
+/**
+ * glade_project_required_libs:
+ * @project: a #GladeProject
+ *
+ * Returns: a #GList of allocated strings which are the names
+ * of the required catalogs for this project
+ */
+GList *
+glade_project_required_libs (GladeProject *project)
+{
+	GList       *required = NULL, *l, *ll;
+	GladeWidget *gwidget;
+	gboolean     listed;
 
-	canonical_path = glade_util_canonical_path (path);
-	g_assert (canonical_path);
+	for (l = project->priv->objects; l; l = l->next)
+	{
+		gchar *catalog = NULL;
 
-	if (project->priv->path == NULL ||
-	    strcmp (canonical_path, project->priv->path))
-        {
-		gchar *old_dir, *new_dir;
+		gwidget = glade_widget_get_from_gobject (l->data);
+		g_assert (gwidget);
 
-		if (project->priv->path)
+		g_object_get (gwidget->adaptor, "catalog", &catalog, NULL);
+
+		if (catalog)
 		{
-			old_dir = g_path_get_dirname (project->priv->path);
-			new_dir = g_path_get_dirname (canonical_path);
+			listed = FALSE;
+			for (ll = required; ll; ll = ll->next)
+				if (!strcmp ((gchar *)ll->data, catalog))
+				{
+					listed = TRUE;
+					break;
+				}
 
-			glade_project_move_resources (project, 
-						      old_dir, 
-						      new_dir);
-			g_free (old_dir);
-			g_free (new_dir);
+			if (!listed)
+				required = g_list_prepend (required, catalog);
 		}
-		project->priv->path = (g_free (project->priv->path),
-				 g_strdup (canonical_path));
 	}
-
-	glade_project_set_readonly (project, 
-				    !glade_util_file_is_writeable (project->priv->path));
-
-	project->priv->mtime = glade_util_get_file_mtime (project->priv->path, NULL);
-	
-	glade_project_set_modified (project, FALSE);
-
-	if (project->priv->unsaved_number > 0)
-	{
-		glade_id_allocator_release (get_unsaved_number_allocator (), project->priv->unsaved_number);
-		project->priv->unsaved_number = 0;
-        }
-
-	g_free (canonical_path);
-
-	return ret > 0;
+	return g_list_reverse (required);
 }
 
-
 /**
  * glade_project_undo:
  * @project: a #GladeProject
@@ -3005,47 +3259,154 @@
 				  G_CALLBACK (redo_item_activated), project);
 
 	}
-	
-	return menu;
+	
+	return menu;
+}
+
+
+void
+glade_project_reset_path (GladeProject *project)
+{
+	g_return_if_fail (GLADE_IS_PROJECT (project));
+	project->priv->path = (g_free (project->priv->path), NULL);
+}
+
+/**
+ * glade_project_set_accel_group:
+ * @project: A #GladeProject
+ * @accel_group: The @GtkAccelGroup
+ *
+ * Set @accel_group to every top level widget in @project.
+ */
+void
+glade_project_set_accel_group (GladeProject *project, GtkAccelGroup *accel_group)
+{
+	GList *objects;
+
+	g_return_if_fail (GLADE_IS_PROJECT (project) && GTK_IS_ACCEL_GROUP (accel_group));
+                
+	objects = project->priv->objects;
+	while (objects)
+	{
+		if(GTK_IS_WINDOW (objects->data))
+		{
+			if (project->priv->accel_group)
+				gtk_window_remove_accel_group (GTK_WINDOW (objects->data), project->priv->accel_group);
+			
+			gtk_window_add_accel_group (GTK_WINDOW (objects->data), accel_group);
+		}
+
+		objects = objects->next;
+	}
+	
+	project->priv->accel_group = accel_group;
+}
+
+
+
+
+static void
+gp_sync_resources (GladeProject *project, 
+		   GladeProject *prev_project,
+		   GladeWidget  *gwidget,
+		   gboolean      remove)
+{
+	GList          *prop_list, *l;
+	GladeProperty  *property;
+	gchar          *resource, *full_resource;
+
+	prop_list = g_list_copy (gwidget->properties);
+	prop_list = g_list_concat
+		(prop_list, g_list_copy (gwidget->packing_properties));
+
+	for (l = prop_list; l; l = l->next)
+	{
+		property = l->data;
+		if (property->klass->resource)
+		{
+			GValue value = { 0, };
+
+			if (remove)
+			{
+				glade_project_set_resource (project, property, NULL);
+				continue;
+			}
+
+			glade_property_get_value (property, &value);
+			
+			if ((resource = glade_widget_adaptor_string_from_value
+			     (GLADE_WIDGET_ADAPTOR (property->klass->handle),
+			      property->klass, &value, project->priv->format)) != NULL)
+			{
+				full_resource = glade_project_resource_fullpath
+					(prev_project ? prev_project : project, resource);
+			
+				/* Use a full path here so that the current
+				 * working directory isnt used.
+				 */
+				glade_project_set_resource (project, 
+							    property,
+							    full_resource);
+				
+				g_free (full_resource);
+				g_free (resource);
+			}
+			g_value_unset (&value);
+		}
+	}
+	g_list_free (prop_list);
 }
 
-
-void
-glade_project_reset_path (GladeProject *project)
+static void
+glade_project_sync_resources_for_widget (GladeProject *project, 
+					 GladeProject *prev_project,
+					 GladeWidget  *gwidget,
+					 gboolean      remove)
 {
-	g_return_if_fail (GLADE_IS_PROJECT (project));
-	project->priv->path = (g_free (project->priv->path), NULL);
+	GList *children, *l;
+	GladeWidget *gchild;
+
+	children = glade_widget_adaptor_get_children
+		(gwidget->adaptor, gwidget->object);
+
+	for (l = children; l; l = l->next)
+		if ((gchild = 
+		     glade_widget_get_from_gobject (l->data)) != NULL)
+			glade_project_sync_resources_for_widget 
+				(project, prev_project, gchild, remove);
+	if (children)
+		g_list_free (children);
+
+	gp_sync_resources (project, prev_project, gwidget, remove);
 }
 
-/**
- * glade_project_set_accel_group:
- * @project: A #GladeProject
- * @accel_group: The @GtkAccelGroup
- *
- * Set @accel_group to every top level widget in @project.
- */
-void
-glade_project_set_accel_group (GladeProject *project, GtkAccelGroup *accel_group)
+static void
+glade_project_move_resources (GladeProject *project,
+			      const gchar  *old_dir,
+			      const gchar  *new_dir)
 {
-	GList *objects;
+	GList *list, *resources;
+	gchar *old_name, *new_name;
 
-	g_return_if_fail (GLADE_IS_PROJECT (project) && GTK_IS_ACCEL_GROUP (accel_group));
-                
-	objects = project->priv->objects;
-	while (objects)
-	{
-		if(GTK_IS_WINDOW (objects->data))
-		{
-			if (project->priv->accel_group)
-				gtk_window_remove_accel_group (GTK_WINDOW (objects->data), project->priv->accel_group);
-			
-			gtk_window_add_accel_group (GTK_WINDOW (objects->data), accel_group);
-		}
+	if (old_dir == NULL || /* <-- Cant help you :( */
+	    new_dir == NULL)   /* <-- Unlikely         */
+		return;
 
-		objects = objects->next;
-	}
+	if ((resources = /* Nothing to do here */
+	     glade_project_list_resources (project)) == NULL)
+		return;
 	
-	project->priv->accel_group = accel_group;
+	for (list = resources; list; list = list->next)
+	{
+		old_name = g_build_filename 
+			(old_dir, (gchar *)list->data, NULL);
+		new_name = g_build_filename 
+			(new_dir, (gchar *)list->data, NULL);
+		glade_util_copy_file (old_name, new_name);
+		g_free (old_name);
+		g_free (new_name);
+	}
+	g_list_free (resources);
 }
 
 /**
@@ -3288,6 +3649,48 @@
 	return project->priv->modified;
 }
 
+void
+glade_project_set_naming_policy (GladeProject       *project,
+				 GladeNamingPolicy   policy,
+				 gboolean            use_command)
+{
+	g_return_if_fail (GLADE_IS_PROJECT (project));
+
+	if (project->priv->naming_policy != policy)
+	{
+		project->priv->naming_policy = policy;
+
+		adjust_naming_policy (project, use_command);
+
+		/* Update the toggle button in the prefs dialog here: */
+		g_signal_handlers_block_by_func (project->priv->project_wide_radio,
+						 G_CALLBACK (policy_project_wide_button_clicked), project);
+		g_signal_handlers_block_by_func (project->priv->toplevel_contextual_radio,
+						 G_CALLBACK (policy_toplevel_contextual_button_clicked), project);
+
+		if (policy == GLADE_POLICY_PROJECT_WIDE)
+			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (project->priv->project_wide_radio), TRUE);
+		else
+			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (project->priv->toplevel_contextual_radio), TRUE);
+
+		g_signal_handlers_unblock_by_func (project->priv->project_wide_radio,
+						   G_CALLBACK (policy_project_wide_button_clicked), project);
+		g_signal_handlers_unblock_by_func (project->priv->toplevel_contextual_radio,
+						   G_CALLBACK (policy_toplevel_contextual_button_clicked), project);
+
+	}
+
+
+}
+
+GladeNamingPolicy
+glade_project_get_naming_policy (GladeProject *project)
+{
+	g_return_val_if_fail (GLADE_IS_PROJECT (project), -1);
+
+	return project->priv->naming_policy;
+}
+
 
 /** 
  * glade_project_set_format:
@@ -3307,6 +3710,23 @@
 		project->priv->format = format; 
 		g_object_notify (G_OBJECT (project), "format");
 		glade_project_verify_project_for_ui (project);
+
+		/* Update the toggle button in the prefs dialog here: */
+		g_signal_handlers_block_by_func (project->priv->glade_radio,
+						 G_CALLBACK (format_libglade_button_clicked), project);
+		g_signal_handlers_block_by_func (project->priv->builder_radio,
+						 G_CALLBACK (format_builder_button_clicked), project);
+
+		if (format == GLADE_PROJECT_FORMAT_GTKBUILDER)
+			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (project->priv->builder_radio), TRUE);
+		else
+			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (project->priv->glade_radio), TRUE);
+
+		g_signal_handlers_unblock_by_func (project->priv->glade_radio,
+						   G_CALLBACK (format_libglade_button_clicked), project);
+		g_signal_handlers_unblock_by_func (project->priv->builder_radio,
+						   G_CALLBACK (format_builder_button_clicked), project);
+
 	}
 }
 
@@ -3334,6 +3754,20 @@
 }
 
 static void
+policy_project_wide_button_clicked (GtkWidget *widget,
+				    GladeProject *project)
+{
+	glade_command_set_project_naming_policy (project, GLADE_POLICY_PROJECT_WIDE);
+}
+
+static void
+policy_toplevel_contextual_button_clicked (GtkWidget *widget,
+					   GladeProject *project)
+{
+	glade_command_set_project_naming_policy (project, GLADE_POLICY_TOPLEVEL_CONTEXTUAL);
+}
+
+static void
 target_button_clicked (GtkWidget *widget,
 		       GladeProject *project)
 {
@@ -3369,20 +3803,123 @@
 {
 	GtkWidget *main_box, *button;
 	GtkWidget *vbox, *hbox, *frame;
-	GtkWidget *glade_radio, *builder_radio, *target_radio, *active_radio;
+	GtkWidget *target_radio, *active_radio;
 	GtkWidget *label, *alignment;
 	GList     *list, *targets;
-	gchar     *string = g_strdup_printf ("<b>%s</b>", _("File format"));
+	gchar     *string;
+	GtkWidget *main_frame, *main_alignment;
+	GtkSizeGroup *sizegroup1 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL),
+		*sizegroup2 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
+
+	string = g_strdup_printf ("<big><b>%s</b></big>", _("Set options in your project"));
+	main_frame = gtk_frame_new (NULL);
+	main_alignment = gtk_alignment_new (0.5F, 0.5F, 0.8F, 0.8F);
 	main_box = gtk_vbox_new (FALSE, 0);
 
+	gtk_alignment_set_padding (GTK_ALIGNMENT (main_alignment), 12, 0, 4, 0);
+
+	label = gtk_label_new (string);
+	g_free (string);
+	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+
+	gtk_frame_set_label_widget (GTK_FRAME (main_frame), label);
+	gtk_container_add (GTK_CONTAINER (main_alignment), main_box);
+	gtk_container_add (GTK_CONTAINER (main_frame), main_alignment);
+
+
+	/* Project format */
+	string = g_strdup_printf ("<b>%s</b>", _("File format"));
+	frame = gtk_frame_new (NULL);
+	hbox = gtk_hbox_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);
+
+	project->priv->glade_radio = gtk_radio_button_new_with_label (NULL, "Libglade");
+	project->priv->builder_radio = gtk_radio_button_new_with_label_from_widget
+		(GTK_RADIO_BUTTON (project->priv->glade_radio), "GtkBuilder");
+
+	gtk_size_group_add_widget (sizegroup1, project->priv->builder_radio);
+	gtk_size_group_add_widget (sizegroup2, project->priv->glade_radio);
+
+	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+	gtk_container_add (GTK_CONTAINER (alignment), hbox);
+	gtk_container_add (GTK_CONTAINER (frame), alignment);
+
+	gtk_box_pack_start (GTK_BOX (hbox), project->priv->builder_radio, TRUE, TRUE, 2);
+	gtk_box_pack_start (GTK_BOX (hbox), project->priv->glade_radio, TRUE, TRUE, 2);
+
+	gtk_box_pack_start (GTK_BOX (main_box), frame, TRUE, TRUE, 2);
+
+
+	if (glade_project_get_format (project) == GLADE_PROJECT_FORMAT_GTKBUILDER)
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (project->priv->builder_radio), TRUE);
+	else
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (project->priv->glade_radio), TRUE);
+
+	g_signal_connect (G_OBJECT (project->priv->glade_radio), "clicked",
+			  G_CALLBACK (format_libglade_button_clicked), project);
+
+	g_signal_connect (G_OBJECT (project->priv->builder_radio), "clicked",
+			  G_CALLBACK (format_builder_button_clicked), project);
+
+
+	/* Naming policy format */
+	string = g_strdup_printf ("<b>%s</b>", _("Object names are unique:"));
+	frame = gtk_frame_new (NULL);
+	hbox = gtk_hbox_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);
+
+	project->priv->project_wide_radio = gtk_radio_button_new_with_label (NULL, _("within the project"));
+	project->priv->toplevel_contextual_radio = gtk_radio_button_new_with_label_from_widget
+		(GTK_RADIO_BUTTON (project->priv->project_wide_radio), _("inside toplevels"));
+
+	gtk_size_group_add_widget (sizegroup1, project->priv->project_wide_radio);
+	gtk_size_group_add_widget (sizegroup2, project->priv->toplevel_contextual_radio);
+
+	gtk_box_pack_start (GTK_BOX (hbox), project->priv->project_wide_radio, TRUE, TRUE, 2);
+	gtk_box_pack_start (GTK_BOX (hbox), project->priv->toplevel_contextual_radio, TRUE, TRUE, 2);
+
+	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+	gtk_container_add (GTK_CONTAINER (alignment), hbox);
+	gtk_container_add (GTK_CONTAINER (frame), alignment);
+
+	gtk_box_pack_start (GTK_BOX (main_box), frame, TRUE, TRUE, 6);
+
+	if (project->priv->naming_policy == GLADE_POLICY_PROJECT_WIDE)
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (project->priv->project_wide_radio), TRUE);
+	else
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (project->priv->toplevel_contextual_radio), TRUE);
+
+	g_signal_connect (G_OBJECT (project->priv->project_wide_radio), "clicked",
+			  G_CALLBACK (policy_project_wide_button_clicked), project);
+
+	g_signal_connect (G_OBJECT (project->priv->toplevel_contextual_radio), "clicked",
+			  G_CALLBACK (policy_toplevel_contextual_button_clicked), project);
+
+
 	/* Target versions */
-	string = g_strdup_printf ("<b>%s</b>", _("Target Versions:"));
+	string = g_strdup_printf ("<b>%s</b>", _("Target versions:"));
 	frame = gtk_frame_new (NULL);
 	vbox = gtk_vbox_new (FALSE, 0);
 	alignment = gtk_alignment_new (0.5F, 0.5F, 1.0F, 1.0F);
 	
-	gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 2, 0, 12, 0);
+	gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 8, 0, 12, 0);
 	
 	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
 
@@ -3394,7 +3931,7 @@
 	gtk_container_add (GTK_CONTAINER (alignment), vbox);
 	gtk_container_add (GTK_CONTAINER (frame), alignment);
 	
-	gtk_box_pack_start (GTK_BOX (main_box), frame, TRUE, TRUE, 2);
+	gtk_box_pack_start (GTK_BOX (main_box), frame, TRUE, TRUE, 6);
 
 	/* Add stuff to vbox */
 	for (list = glade_app_get_catalogs (); list; list = list->next)
@@ -3455,105 +3992,50 @@
 		}
 
 		if (active_radio)
+		{
 			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (active_radio), TRUE);
+			g_hash_table_insert (project->priv->target_radios, 
+					     g_strdup (glade_catalog_get_name (catalog)),
+					     gtk_radio_button_get_group (GTK_RADIO_BUTTON (active_radio)));
+		}
 		else 
 			g_warning ("Corrupt catalog versions");
 
-		gtk_box_pack_end (GTK_BOX (vbox), hbox, TRUE, TRUE, 2);
-
+		gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 2);
 	}
 
-	/* Project format */
-	string = g_strdup_printf ("<b>%s</b>", _("File format"));
-	frame = gtk_frame_new (NULL);
-	hbox = gtk_hbox_new (FALSE, 0);
-	alignment = gtk_alignment_new (0.5F, 0.5F, 0.8F, 0.8F);
-
-	gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 2, 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);
-
-	glade_radio = gtk_radio_button_new_with_label (NULL, "Libglade");
-	builder_radio = gtk_radio_button_new_with_label_from_widget
-		(GTK_RADIO_BUTTON (glade_radio), "GtkBuilder");
-
-	if (glade_project_get_format (project) == GLADE_PROJECT_FORMAT_GTKBUILDER)
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (builder_radio), TRUE);
-	else
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_radio), TRUE);
-
-	g_signal_connect (G_OBJECT (glade_radio), "clicked",
-			  G_CALLBACK (format_libglade_button_clicked), project);
-
-	g_signal_connect (G_OBJECT (builder_radio), "clicked",
-			  G_CALLBACK (format_builder_button_clicked), project);
-
-	gtk_box_pack_start (GTK_BOX (hbox), builder_radio, TRUE, TRUE, 2);
-	gtk_box_pack_start (GTK_BOX (hbox), glade_radio, TRUE, TRUE, 2);
-
-	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
-	gtk_container_add (GTK_CONTAINER (alignment), hbox);
-	gtk_container_add (GTK_CONTAINER (frame), alignment);
-
-	gtk_box_pack_start (GTK_BOX (main_box), frame, TRUE, TRUE, 2);
-
-
 	/* Run verify */
-	string = g_strdup_printf ("<b>%s</b>", _("Verify versions and deprecations:"));
-	frame = gtk_frame_new (NULL);
-	alignment = gtk_alignment_new (0.0F, 0.5F, 0.0F, 0.0F);
-	gtk_container_set_border_width (GTK_CONTAINER (alignment), 4);	
-
+	hbox = gtk_hbox_new (FALSE, 2);
 	button = gtk_button_new_from_stock (GTK_STOCK_EXECUTE);
 	g_signal_connect (G_OBJECT (button), "clicked", 
 			  G_CALLBACK (verify_clicked), project);
 	
-	gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 2, 4, 12, 0);
-	
-	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+	label = gtk_label_new (_("Verify versions and deprecations:"));
 
-	label = gtk_label_new (string);
-	g_free (string);
-	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-	
-	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
-	gtk_container_add (GTK_CONTAINER (alignment), button);
-	gtk_container_add (GTK_CONTAINER (frame), alignment);
+	gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 4);
+	gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 4);
 	
-	gtk_box_pack_start (GTK_BOX (main_box), frame, FALSE, FALSE, 4);
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
 
+	gtk_widget_show_all (main_frame);
 
-	gtk_widget_show_all (main_box);
-
-	return main_box;
+	return main_frame;
 }
 
-/**
- * glade_project_preferences:
- * @project: A #GladeProject
- *
- * Runs a preferences dialog for @project.
- */
-void
-glade_project_preferences (GladeProject *project)
+static GtkWidget *
+glade_project_build_prefs_dialog (GladeProject *project)
 {
-	GtkWidget *dialog = NULL;
-	GtkWidget *widget;
+	GtkWidget *widget, *dialog;
 	gchar     *title, *name;
 
-
-	g_return_if_fail (GLADE_IS_PROJECT (project));
-
 	name = glade_project_get_name (project);
-	title = g_strdup_printf ("%s preferences", name);
+	title = g_strdup_printf (_("%s preferences"), name);
 
 	dialog = gtk_dialog_new_with_buttons (title,
 					      GTK_WINDOW (glade_app_get_window ()),
 					      GTK_DIALOG_DESTROY_WITH_PARENT,
+					      GTK_STOCK_CLOSE,
+					      GTK_RESPONSE_ACCEPT,
 					      NULL);
 	g_free (title);
 	g_free (name);
@@ -3567,13 +4049,34 @@
 
 	gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
 
+	/* HIG spacings */
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2); /* 2 * 5 + 2 = 12 */
+	gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 5);
+	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
+
 
 	/* Were explicitly destroying it anyway */
 	g_signal_connect (G_OBJECT (dialog), "delete-event",
 			  G_CALLBACK (gtk_widget_hide_on_delete), NULL);
 
-	gtk_window_present (GTK_WINDOW (dialog));
+	/* Only one action, used to "close" the dialog */
+	g_signal_connect (G_OBJECT (dialog), "response",
+			  G_CALLBACK (gtk_widget_hide), NULL);
+
+	return dialog;
+}
+
+/**
+ * glade_project_preferences:
+ * @project: A #GladeProject
+ *
+ * Runs a preferences dialog for @project.
+ */
+void
+glade_project_preferences (GladeProject *project)
+{
+	g_return_if_fail (GLADE_IS_PROJECT (project));
 
-	gtk_dialog_run (GTK_DIALOG (dialog));
-	gtk_widget_destroy (dialog);
+	gtk_window_present (GTK_WINDOW (project->priv->prefs_dialog));
 }

Modified: trunk/gladeui/glade-project.h
==============================================================================
--- trunk/gladeui/glade-project.h	(original)
+++ trunk/gladeui/glade-project.h	Thu Oct 16 14:31:42 2008
@@ -22,11 +22,11 @@
 
 typedef enum
 {
-	GLADE_SUPPORT_OK                   = 0x00,
-	GLADE_SUPPORT_DEPRECATED           = 0x01,
-	GLADE_SUPPORT_MISMATCH             = 0x02,
-	GLADE_SUPPORT_LIBGLADE_UNSUPPORTED = 0x04,
-	GLADE_SUPPORT_LIBGLADE_ONLY        = 0x08
+	GLADE_SUPPORT_OK                   = 0,
+	GLADE_SUPPORT_DEPRECATED           = (0x01 << 0),
+	GLADE_SUPPORT_MISMATCH             = (0x01 << 1),
+	GLADE_SUPPORT_LIBGLADE_UNSUPPORTED = (0x01 << 2),
+	GLADE_SUPPORT_LIBGLADE_ONLY        = (0x01 << 3)
 } GladeSupportMask;
 
 struct _GladeProject
@@ -111,16 +111,26 @@
 						  GladeProject *old_project,
 						  GObject      *object);
 
-void           glade_project_remove_object       (GladeProject *project, GObject     *object);
-
-gboolean       glade_project_has_object          (GladeProject *project, GObject     *object);
+void           glade_project_remove_object       (GladeProject *project, 
+						  GObject      *object);
 
-GladeWidget   *glade_project_get_widget_by_name  (GladeProject *project, const char  *name);
+gboolean       glade_project_has_object          (GladeProject *project, 
+						  GObject      *object);
 
-char          *glade_project_new_widget_name     (GladeProject *project, const char  *base_name);
+GladeWidget   *glade_project_get_widget_by_name  (GladeProject *project, 
+						  GladeWidget  *ancestor,
+						  const gchar  *name);
+
+void           glade_project_set_widget_name     (GladeProject *project, 
+						  GladeWidget  *widget, 
+						  const gchar  *name);
+
+gchar         *glade_project_new_widget_name     (GladeProject *project, 
+						  GladeWidget  *widget, 
+						  const gchar  *base_name);
 
-void           glade_project_widget_name_changed (GladeProject *project, GladeWidget *widget,
-						 const char   *old_name);
+gboolean       glade_project_available_widget_name (GladeProject *project, GladeWidget  *widget,
+						    const gchar  *name);
 
 /* Selection */
 
@@ -187,8 +197,13 @@
 gboolean      glade_project_is_loaded_factory_file (GladeProject       *project, 
 						    const gchar        *stock_id);
 
-GList        *glade_project_required_libs          (GladeProject  *project);
+GList        *glade_project_required_libs          (GladeProject       *project);
+
+void          glade_project_set_naming_policy      (GladeProject       *project,
+						    GladeNamingPolicy   policy,
+						    gboolean            use_command);
 
+GladeNamingPolicy glade_project_get_naming_policy  (GladeProject       *project);
 
 G_END_DECLS
 

Modified: trunk/gladeui/glade-property-class.c
==============================================================================
--- trunk/gladeui/glade-property-class.c	(original)
+++ trunk/gladeui/glade-property-class.c	Thu Oct 16 14:31:42 2008
@@ -85,6 +85,7 @@
 	property_class->save = TRUE;
 	property_class->save_always = FALSE;
 	property_class->ignore = FALSE;
+	property_class->needs_sync = FALSE;
 	property_class->resource = FALSE;
 	property_class->themed_icon = FALSE;
 	property_class->translatable = FALSE;
@@ -628,7 +629,8 @@
 static GObject *
 glade_property_class_make_object_from_string (GladePropertyClass *property_class,
 					      const gchar        *string,
-					      GladeProject       *project)
+					      GladeProject       *project,
+					      GladeWidget        *widget)
 {
 	GObject *object = NULL;
 	gchar   *fullpath;
@@ -668,7 +670,7 @@
  
 		g_free (fullpath);
 	}
-	if (glade_project_get_format (project) == GLADE_PROJECT_FORMAT_LIBGLADE &&
+	if (project && glade_project_get_format (project) == GLADE_PROJECT_FORMAT_LIBGLADE &&
 	    property_class->pspec->value_type == GTK_TYPE_ADJUSTMENT)
 	{
 		gdouble value, lower, upper, step_increment, page_increment, page_size;
@@ -687,7 +689,7 @@
 	{
 		GladeWidget *gwidget;
 		if ((gwidget = glade_project_get_widget_by_name 
-			       (project, string)) != NULL)
+		     (project, widget, string)) != NULL)
 			object = gwidget->object;
 	}
 	
@@ -697,7 +699,8 @@
 static GList *
 glade_property_class_make_objects_from_string (GladePropertyClass *property_class,
 					       const gchar        *string,
-					       GladeProject       *project)
+					       GladeProject       *project,
+					       GladeWidget        *widget)
 {
 	GList    *objects = NULL;
 	GObject  *object;
@@ -709,7 +712,7 @@
 		for (i = 0; split[i]; i++)
 		{
 			if ((object = glade_property_class_make_object_from_string
-			     (property_class, split[i], project)) != NULL)
+			     (property_class, split[i], project, widget)) != NULL)
 				objects = g_list_prepend (objects, object);
 		}
 		g_strfreev (split);
@@ -721,8 +724,7 @@
  * glade_property_class_make_gvalue_from_string:
  * @property_class: A #GladePropertyClass
  * @string: a string representation of this property
- * @project: the glade project that the associated property
- *           belongs to.
+ * @widget: the #GladeWidget that the associated property belongs to.
  *
  * Returns: A #GValue created based on the @property_class
  *          and @string criteria.
@@ -730,7 +732,8 @@
 GValue *
 glade_property_class_make_gvalue_from_string (GladePropertyClass *property_class,
 					      const gchar        *string,
-					      GladeProject       *project)
+					      GladeProject       *project,
+					      GladeWidget        *widget)
 {
 	GValue    *value = g_new0 (GValue, 1);
 	gchar    **strv, *fullpath;
@@ -831,13 +834,13 @@
 	else if (G_IS_PARAM_SPEC_OBJECT(property_class->pspec))
 	{
 		GObject *object = glade_property_class_make_object_from_string
-			(property_class, string, project);
+			(property_class, string, project, widget);
 		g_value_set_object (value, object);
 	}
 	else if (GLADE_IS_PARAM_SPEC_OBJECTS (property_class->pspec))
 	{
 		GList *objects = glade_property_class_make_objects_from_string
-			(property_class, string, project);
+			(property_class, string, project, widget);
 		g_value_set_boxed (value, objects);
 	}
 	else
@@ -1459,7 +1462,7 @@
 			g_value_unset (klass->def);
 			g_free (klass->def);
 		}
-		klass->def = glade_property_class_make_gvalue_from_string (klass, buf, NULL);
+		klass->def = glade_property_class_make_gvalue_from_string (klass, buf, NULL, NULL);
 		g_free (buf);
 	}
 
@@ -1519,6 +1522,7 @@
 	klass->save        = glade_xml_get_property_boolean (node, GLADE_TAG_SAVE,        klass->save);
 	klass->visible     = glade_xml_get_property_boolean (node, GLADE_TAG_VISIBLE,     klass->visible);
 	klass->ignore      = glade_xml_get_property_boolean (node, GLADE_TAG_IGNORE,      klass->ignore);
+	klass->needs_sync  = glade_xml_get_property_boolean (node, GLADE_TAG_NEEDS_SYNC,  klass->needs_sync);
 	klass->resource    = glade_xml_get_property_boolean (node, GLADE_TAG_RESOURCE,    klass->resource);
 	klass->themed_icon = glade_xml_get_property_boolean (node, GLADE_TAG_THEMED_ICON, klass->themed_icon);
 	klass->weight      = glade_xml_get_property_double  (node, GLADE_TAG_WEIGHT,      klass->weight);
@@ -1651,6 +1655,8 @@
 	if (G_VALUE_HOLDS_BOXED (value1))
 	{
 		gchar *val1, *val2;
+
+		/* This has got to change... */
 		
 		val1 = glade_widget_adaptor_string_from_value (klass->handle, klass, value1, fmt);
 		val2 = glade_widget_adaptor_string_from_value (klass->handle, klass, value2, fmt);
@@ -1662,6 +1668,9 @@
 		
 		g_free (val1);
 		g_free (val2);
+
+		/* boxed always changed... XXX */
+		return -1;
 	}
 	else
 	{

Modified: trunk/gladeui/glade-property-class.h
==============================================================================
--- trunk/gladeui/glade-property-class.h	(original)
+++ trunk/gladeui/glade-property-class.h	Thu Oct 16 14:31:42 2008
@@ -133,6 +133,12 @@
 			     * changes, or load values from the object.
 			     */
 
+	gboolean needs_sync; /* Virtual properties need to be synchronized after object
+			      * creation, some properties that are not virtual also need
+			      * handling from the backend, if "needs-sync" is true then
+			      * this property will by synced with virtual properties.
+			      */
+
 	gboolean is_modified; /* If true, this property_class has been "modified" from the
 			       * the standard property by a xml file. */
 
@@ -197,7 +203,8 @@
 
 GValue             *glade_property_class_make_gvalue_from_string (GladePropertyClass  *property_class,
 								  const gchar         *string,
-								  GladeProject        *project);
+								  GladeProject        *project,
+								  GladeWidget         *widget);
 
 gchar              *glade_property_class_make_string_from_gvalue (GladePropertyClass  *property_class,
 								  const GValue        *value,

Modified: trunk/gladeui/glade-property.c
==============================================================================
--- trunk/gladeui/glade-property.c	(original)
+++ trunk/gladeui/glade-property.c	Thu Oct 16 14:31:42 2008
@@ -1038,8 +1038,7 @@
 		if (fmt == GLADE_PROJECT_FORMAT_GTKBUILDER)
 		{
 			gboolean is_loaded_value = 
-				glade_project_is_loaded_factory_file
-				(property->widget->project, value);
+				glade_project_is_loaded_factory_file (project, value);
 
 			if (property->klass->factory_stock_id && is_loaded_value)
 				search_name = property->klass->factory_stock_id;
@@ -1085,7 +1084,7 @@
 				}
 
 				gvalue = glade_property_class_make_gvalue_from_string
-					(property->klass, value, project);
+					(property->klass, value, project, property->widget);
 
 				if (property) 
 				{

Modified: trunk/gladeui/glade-utils.c
==============================================================================
--- trunk/gladeui/glade-utils.c	(original)
+++ trunk/gladeui/glade-utils.c	Thu Oct 16 14:31:42 2008
@@ -1943,7 +1943,7 @@
 	gint    value = 0;
 	GValue *gvalue;
 
-	if ((gvalue = glade_utils_value_from_string (enum_type, strval, NULL)) != NULL)
+	if ((gvalue = glade_utils_value_from_string (enum_type, strval, NULL, NULL)) != NULL)
 	{
 		value = g_value_get_enum (gvalue);
 		g_value_unset (gvalue);
@@ -2075,6 +2075,8 @@
  * @type: a #GType to convert with
  * @string: the string to convert
  * @project: the #GladeProject to look for formats of object names when needed
+ * @widget: if the value is a gobject, this #GladeWidget will be used to look
+ *          for an object in the same widget tree.
  *
  * Allocates and sets a #GValue of type @type
  * set to @string (using glade conversion routines) 
@@ -2084,7 +2086,8 @@
 GValue *
 glade_utils_value_from_string (GType               type,
 			       const gchar        *string,
-			       GladeProject       *project)
+			       GladeProject       *project,
+			       GladeWidget        *widget)
 {
 	GladePropertyClass *pclass;
 
@@ -2092,7 +2095,7 @@
 	g_return_val_if_fail (string != NULL, NULL);
 
 	if ((pclass = pclass_from_gtype (type)) != NULL)
-		return glade_property_class_make_gvalue_from_string (pclass, string, project);
+		return glade_property_class_make_gvalue_from_string (pclass, string, project, widget);
 
 	return NULL;
 }

Modified: trunk/gladeui/glade-utils.h
==============================================================================
--- trunk/gladeui/glade-utils.h	(original)
+++ trunk/gladeui/glade-utils.h	Thu Oct 16 14:31:42 2008
@@ -139,12 +139,16 @@
 
 GValue           *glade_utils_value_from_string   (GType               type,
 						   const gchar        *string,
-						   GladeProject       *project);
+						   GladeProject       *project,
+						   GladeWidget        *widget);
+
 gchar            *glade_utils_string_from_value   (const GValue       *value,
 						   GladeProject       *project);
 
 GtkListStore     *glade_utils_liststore_from_enum_type  (GType enum_type, gboolean include_empty);
 
+
+
 G_END_DECLS
 
 #endif /* __GLADE_UTILS_H__ */

Modified: trunk/gladeui/glade-widget.c
==============================================================================
--- trunk/gladeui/glade-widget.c	(original)
+++ trunk/gladeui/glade-widget.c	Thu Oct 16 14:31:42 2008
@@ -619,7 +619,7 @@
 	{
 		GladeProperty *prop  = GLADE_PROPERTY(l->data);
 
-		if (prop->klass->virt)
+		if (prop->klass->virt || prop->klass->needs_sync)
 			glade_property_sync (prop);
 
 	}
@@ -662,6 +662,7 @@
 			{
 				gwidget->name = 
 					glade_project_new_widget_name (gwidget->project, 
+								       gwidget,
 								       name_base);
 				g_free (name_base);
 			}
@@ -671,7 +672,7 @@
 		}
 		else if (gwidget->project)
 			gwidget->name = glade_project_new_widget_name
-				(GLADE_PROJECT (gwidget->project), 
+				(gwidget->project, gwidget,
 				 gwidget->adaptor->generic_name);
 		else
 			gwidget->name = 
@@ -1228,7 +1229,8 @@
 		
 		value = glade_property_class_make_gvalue_from_string (property_class,
 								      def,
-								      child->project);
+								      child->project,
+								      child);
 		
 		glade_widget_child_set_property (container, child,
 						 property_class->id, value);
@@ -2377,15 +2379,8 @@
 glade_widget_set_name (GladeWidget *widget, const gchar *name)
 {
 	g_return_if_fail (GLADE_IS_WIDGET (widget));
-	if (widget->name != name) {
-
-		if (widget->project && 
-		    glade_project_get_widget_by_name (widget->project, name))
-		{
-			/* print a warning ? */
-			return;
-		}
-
+	if (widget->name != name) 
+	{
 		if (widget->name)
 			g_free (widget->name);
 		

Modified: trunk/gladeui/glade-xml-utils.h
==============================================================================
--- trunk/gladeui/glade-xml-utils.h	(original)
+++ trunk/gladeui/glade-xml-utils.h	Thu Oct 16 14:31:42 2008
@@ -36,6 +36,12 @@
 } GladeProjectFormat;
 
 
+typedef enum {
+	GLADE_POLICY_PROJECT_WIDE = 0,    /* widget names are unique throughout the project */
+	GLADE_POLICY_TOPLEVEL_CONTEXTUAL  /* toplevel names are unique, and widgets inside a toplevel */
+} GladeNamingPolicy;
+
+
 #define GLADE_XML_TAG_PROJECT(type) \
 	((type == GLADE_PROJECT_FORMAT_LIBGLADE) ? \
 	 GLADE_XML_TAG_LIBGLADE_PROJECT : GLADE_XML_TAG_BUILDER_PROJECT)
@@ -108,6 +114,7 @@
 #define GLADE_TAG_PARENTLESS_WIDGET               "parentless-widget"
 #define GLADE_TAG_DISABLED                        "disabled"
 #define GLADE_TAG_CONSTRUCT_ONLY                  "construct-only"
+#define GLADE_TAG_NEEDS_SYNC                      "needs-sync"
 #define GLADE_TAG_DEFAULT_PALETTE_STATE           "default-palette-state"
 #define GLADE_TAG_PROJECT_CONVERT_FUNCTION        "project-convert-function"
 #define GLADE_TAG_REPLACE_CHILD_FUNCTION          "replace-child-function"

Modified: trunk/plugins/gnome/glade-gnome.c
==============================================================================
--- trunk/plugins/gnome/glade-gnome.c	(original)
+++ trunk/plugins/gnome/glade-gnome.c	Thu Oct 16 14:31:42 2008
@@ -597,7 +597,7 @@
 					  property_name);
 	
 	color = glade_property_class_make_gvalue_from_string (prop->klass,
-							      color_str, NULL);
+							      color_str, NULL, NULL);
 	if (color) glade_property_set_value (prop, color);
 }
 

Modified: trunk/plugins/gtk+/glade-column-types.c
==============================================================================
--- trunk/plugins/gtk+/glade-column-types.c	(original)
+++ trunk/plugins/gtk+/glade-column-types.c	Thu Oct 16 14:31:42 2008
@@ -223,106 +223,31 @@
 }
 
 static void
-eprop_reload_value (GladeEPropColumnTypes *eprop_types)
+eprop_column_append (GladeEditorProperty *eprop,
+		     GType type,
+		     const gchar *column_name)
 {
-	GladeEditorProperty *eprop = GLADE_EDITOR_PROPERTY (eprop_types);
-	GtkTreeModel *model = GTK_TREE_MODEL (eprop_types->store);
-	GValue value = {0, };
-	GtkTreeIter iter;
-	GList *list = NULL, *l;
-	GNode *data_tree = NULL;
-	
-	if (gtk_tree_model_get_iter_first (model, &iter))
-	{
-		do
-		{
-			GladeColumnType *data = g_new0(GladeColumnType, 1);
-
-			gtk_tree_model_get (model, &iter,
-					    COLUMN_COLUMN_NAME, &data->column_name,
-					    COLUMN_GTYPE, &data->type,
-					    -1);
-		
-			list = g_list_append (list, data);
-		} while (gtk_tree_model_iter_next (model, &iter));
-	}
-
-	glade_widget_property_get (eprop->property->widget, "data", &data_tree);
-	if (data_tree)
-	{
-		GNode *row, *iter;
-		gint colnum;
-		data_tree = glade_model_data_tree_copy (data_tree);
-
-		glade_command_push_group (_("Setting columns of %s"), eprop->property->widget->name);
-
-		/* Remove extra columns */
-		for (row = data_tree->children; row; row = row->next)
-		{
-
-			for (colnum = 0, iter = row->children; iter; 
-			     colnum++, iter = iter->next)
-			{
-
-			}
-		}
-
-		g_value_init (&value, GLADE_TYPE_MODEL_DATA_TREE);
-		g_value_take_boxed (&value, data_tree);
-		glade_editor_property_commit (eprop, &value);
-		g_value_unset (&value);
+	GladeEPropColumnTypes *eprop_types = GLADE_EPROP_COLUMN_TYPES (eprop);
+	GList                 *columns = NULL;
+	GladeColumnType       *data;
+	GValue                 value = { 0, };
+
+	glade_property_get (eprop->property, &columns);
+	if (columns)
+		columns = glade_column_list_copy (columns);
+
+	data = g_new0 (GladeColumnType, 1);
+	data->column_name = g_strdup (column_name);
+	data->type = type;
 
-	}
+	columns = g_list_append (columns, data);
 
 	g_value_init (&value, GLADE_TYPE_COLUMN_TYPE_LIST);
-	g_value_take_boxed (&value, list);
+	g_value_take_boxed (&value, columns);
 	glade_editor_property_commit (eprop, &value);
 	g_value_unset (&value);
-
-	if (data_tree)
-	{
-		glade_model_data_tree_free (data_tree);
-		glade_command_pop_group ();
-	}
-}
-
-static void
-eprop_column_append (GladeEPropColumnTypes *eprop_types,
-		     GType type,
-		     const gchar *name,
-		     const gchar *column_name)
-{
-	gtk_list_store_insert_with_values (eprop_types->store, NULL, -1,
-					   COLUMN_NAME, name ? name : g_type_name (type),
-					   COLUMN_GTYPE, type,
-					   COLUMN_COLUMN_NAME, column_name,
-					   -1);
 }
 
-static void
-glade_eprop_column_types_load (GladeEditorProperty *eprop, GladeProperty *property)
-{
-	GladeEditorPropertyClass *parent_class = 
-		g_type_class_peek_parent (GLADE_EDITOR_PROPERTY_GET_CLASS (eprop));
-	GladeEPropColumnTypes *eprop_types = GLADE_EPROP_COLUMN_TYPES (eprop);
-	GList *l, *list;
-	
-	/* Chain up first */
-	parent_class->load (eprop, property);
-	
-	/* Clear Store */
-	gtk_list_store_clear (eprop_types->store);
-	/* We could set the combo to the first item */
-	
-	list = g_value_get_boxed (property->value);
-	
-	for (l = list; l; l = g_list_next (l))
-	{
-		GladeColumnType *data = l->data;
-		
-		eprop_column_append (eprop_types, data->type, NULL, data->column_name);
-	}
-}
 
 static void
 glade_eprop_column_types_add_clicked (GtkWidget *button, 
@@ -340,36 +265,77 @@
 			    COLUMN_GTYPE, &type2add,
 			    -1);
 	
-	eprop_column_append (eprop_types, type2add, name, NULL);
-	eprop_reload_value (eprop_types);
+	eprop_column_append (GLADE_EDITOR_PROPERTY (eprop_types), type2add, NULL);
 }
 
 static void
 glade_eprop_column_types_delete_clicked (GtkWidget *button, 
 					 GladeEPropColumnTypes *eprop_types)
 {
+	/* Remove from list and commit value, dont touch the liststore except in load() */
+
 	GtkTreeIter iter;
 	if (gtk_tree_selection_get_selected (eprop_types->selection, NULL, &iter))
 		gtk_list_store_remove (GTK_LIST_STORE (eprop_types->store), &iter);
 }
 
-static gboolean
-eprop_reload_value_idle (gpointer data)
-{
-	eprop_reload_value (GLADE_EPROP_COLUMN_TYPES (data));
-	return FALSE;
-}
-
 static void
 eprop_treeview_row_deleted (GtkTreeModel *tree_model,
 			    GtkTreePath  *path,
 			    GladeEditorProperty *eprop)
 {
+	GtkTreeIter iter;
 
 	if (eprop->loading) return;
-	eprop_reload_value_idle (eprop);
+
+	/* Find the deleted row and remove that column... */
+	if (!gtk_tree_model_get_iter (tree_model, &iter, path))
+		return;
+
+	/* Get it by name... */
+
+}
+
+
+static void
+eprop_column_load (GladeEPropColumnTypes *eprop_types,
+		   GType type,
+		   const gchar *name,
+		   const gchar *column_name)
+{
+	gtk_list_store_insert_with_values (eprop_types->store, NULL, -1,
+					   COLUMN_NAME, name ? name : g_type_name (type),
+					   COLUMN_GTYPE, type,
+					   COLUMN_COLUMN_NAME, column_name,
+					   -1);
+}
+
+static void
+glade_eprop_column_types_load (GladeEditorProperty *eprop, GladeProperty *property)
+{
+	GladeEditorPropertyClass *parent_class = 
+		g_type_class_peek_parent (GLADE_EDITOR_PROPERTY_GET_CLASS (eprop));
+	GladeEPropColumnTypes *eprop_types = GLADE_EPROP_COLUMN_TYPES (eprop);
+	GList *l, *list;
+	
+	/* Chain up first */
+	parent_class->load (eprop, property);
+	
+	/* Clear Store */
+	gtk_list_store_clear (eprop_types->store);
+	/* We could set the combo to the first item */
+	
+	list = g_value_get_boxed (property->value);
+	
+	for (l = list; l; l = g_list_next (l))
+	{
+		GladeColumnType *data = l->data;
+		
+		eprop_column_load (eprop_types, data->type, NULL, data->column_name);
+	}
 }
 
+
 static GtkWidget *
 glade_eprop_column_types_create_input (GladeEditorProperty *eprop)
 {

Modified: trunk/plugins/gtk+/glade-gtk.c
==============================================================================
--- trunk/plugins/gtk+/glade-gtk.c	(original)
+++ trunk/plugins/gtk+/glade-gtk.c	Thu Oct 16 14:31:42 2008
@@ -479,7 +479,7 @@
 
 			/* Set the parsed value on the property ... */
 			gvalue = glade_property_class_make_gvalue_from_string
-				(property->klass, value, widget->project);
+				(property->klass, value, widget->project, widget);
 			glade_property_set_value (property, gvalue);
 			g_value_unset (gvalue);
 			g_free (gvalue);
@@ -8777,10 +8777,14 @@
 	for (l = g_value_get_boxed (prop->value); l; l = g_list_next (l))
 	{
 		GladeColumnType *data = l->data;
-		GladeXmlNode  *column_node;
-
+		GladeXmlNode  *column_node, *comment_node;
+		
 		/* Write column names in comments... */
-			
+		gchar *comment = g_strdup_printf ("column-name %s", data->column_name);
+		comment_node = glade_xml_node_new_comment (context, comment);
+		glade_xml_node_append_child (columns_node, comment_node);
+		g_free (comment);
+		
 		column_node = glade_xml_node_new (context, GLADE_TAG_COLUMN);
 		glade_xml_node_append_child (columns_node, column_node);
 		glade_xml_node_set_property_string (column_node, GLADE_TAG_TYPE,
@@ -8989,7 +8993,7 @@
 			 * should we be doing this part in "finished" ? ... todo thinkso...
 			 */
 			value_str = glade_xml_get_content (col_node);
-			value     = glade_utils_value_from_string (column_type->type, value_str, widget->project);
+			value     = glade_utils_value_from_string (column_type->type, value_str, widget->project, widget);
 			g_free (value_str);
 
 			data = glade_model_data_new (column_type->type);

Modified: trunk/plugins/gtk+/glade-model-data.c
==============================================================================
--- trunk/plugins/gtk+/glade-model-data.c	(original)
+++ trunk/plugins/gtk+/glade-model-data.c	Thu Oct 16 14:31:42 2008
@@ -286,6 +286,20 @@
 	}
 }
 
+static void
+clear_view (GladeEditorProperty *eprop)
+{
+	GladeEPropModelData *eprop_data = GLADE_EPROP_MODEL_DATA (eprop);
+	GtkTreeViewColumn   *column;
+	
+	/* Clear columns ... */
+	while ((column = gtk_tree_view_get_column (eprop_data->view, 0)) != NULL)
+		gtk_tree_view_remove_column (eprop_data->view, column);
+
+	/* Clear store ... (this will unref the old store) */
+	gtk_tree_view_set_model (eprop_data->view, NULL);
+	
+}
 
 /* User pressed add: append row and commit values  */
 static void
@@ -302,6 +316,8 @@
 	if (!columns)
 		return;
 
+	clear_view (eprop);
+
 	if (!node)
 		node = g_node_new (NULL);
 	else
@@ -313,6 +329,7 @@
 	g_value_take_boxed (&value, node);
 	glade_editor_property_commit (eprop, &value);
 	g_value_unset (&value);
+
 }
 
 /* User pressed delete: remove selected row and commit values  */
@@ -394,7 +411,7 @@
 		iter_data = iter_node->data;
 		g_array_append_val (gtypes, G_VALUE_TYPE (&iter_data->value));
 	}
-	store = gtk_list_store_newv (NUM_COLUMNS + gtypes->len, (GType *)gtypes->data);
+	store = gtk_list_store_newv (gtypes->len, (GType *)gtypes->data);
 	g_array_free (gtypes, TRUE);
 
 	/* Now populate the store with data */
@@ -406,11 +423,11 @@
 		gtk_list_store_append (store, &iter);
 		gtk_list_store_set (store, &iter, COLUMN_ROW, row_num, -1);
 
-		for (column_num = 0, iter_node = row_node->children; iter_node; 
+		for (column_num = NUM_COLUMNS, iter_node = row_node->children; iter_node; 
 		     column_num++, iter_node = iter_node->next)
 		{
 			iter_data = iter_node->data;
-			gtk_list_store_set_value (store, &iter, NUM_COLUMNS + column_num, &iter_data->value);
+			gtk_list_store_set_value (store, &iter, column_num, &iter_data->value);
 		}
 	}
 	return store;
@@ -448,13 +465,48 @@
 	GladeEPropModelData *eprop_data = GLADE_EPROP_MODEL_DATA (eprop);
 	GtkTreeIter          iter;
 	gint                 colnum = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column-number"));
+	gint                 row;
+	GNode               *data_tree = NULL, *node;
+	GValue               value = { 0, };
+	GladeModelData      *data;
 
 	if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (eprop_data->store), &iter, path))
 		return;
 
-	gtk_list_store_set (eprop_data->store, &iter,
-			    NUM_COLUMNS + colnum, new_text,
+
+	gtk_tree_model_get (eprop_data->store, &iter,
+			    COLUMN_ROW, &row,
 			    -1);
+
+	glade_property_get (eprop->property, &data_tree);
+
+	/* if we are editing, then there is data in the datatree */
+	g_assert (data_tree);
+
+	data_tree = glade_model_data_tree_copy (data_tree);
+
+	if ((node = g_node_nth_child (data_tree, row)) != NULL)
+	{
+		if ((node = g_node_nth_child (node, colnum)) != NULL)
+		{
+			data = node->data;
+
+			g_value_set_string (&(data->value), new_text);
+		}
+	}
+
+	g_value_init (&value, GLADE_TYPE_MODEL_DATA_TREE);
+	g_value_take_boxed (&value, data_tree);
+	glade_editor_property_commit (eprop, &value);
+	g_value_unset (&value);
+
+	/* No need to update store, it will be reloaded in load() */
+/* 	gtk_list_store_set (eprop_data->store, &iter, */
+/* 			    NUM_COLUMNS + colnum, new_text, */
+/* 			    -1); */
+
+	/* XXX Set string in data here and commit ! */
+
 }
 
 static GtkTreeViewColumn *
@@ -479,7 +531,6 @@
 		renderer = gtk_cell_renderer_text_new ();
 		g_object_set (G_OBJECT (renderer), 
 			      "editable", TRUE, 
-			      "ellipsize", PANGO_ELLIPSIZE_END,
 			      NULL);
 		gtk_tree_view_column_pack_start (column, renderer, FALSE);
 		gtk_tree_view_column_set_attributes (column, renderer, 
@@ -529,7 +580,6 @@
 		g_object_set (G_OBJECT (renderer), 
 			      "editable", TRUE, 
 			      "adjustment", adjustment, 
-			      "ellipsize", PANGO_ELLIPSIZE_END,
 			      NULL);
 
 		gtk_tree_view_column_pack_start (column, renderer, TRUE);
@@ -589,10 +639,6 @@
 
 	glade_property_get (eprop->property, &data_tree);
 	
-	/* Clear columns ... */
-	while ((column = gtk_tree_view_get_column (eprop_data->view, 0)) != NULL)
-		gtk_tree_view_remove_column (eprop_data->view, column);
-
 	if (!data_tree || !data_tree->children || !data_tree->children->children)
 		return;
 
@@ -614,19 +660,17 @@
 	GladeEditorPropertyClass *parent_class = 
 		g_type_class_peek_parent (GLADE_EDITOR_PROPERTY_GET_CLASS (eprop));
 	GladeEPropModelData *eprop_data = GLADE_EPROP_MODEL_DATA (eprop);
-	
-	/* Chain up first */
+
+	clear_view (eprop);
+
+	/* Chain up in a clean state... */
 	parent_class->load (eprop, property);
-	
-	/* Recreate and populate store */
-	if (eprop_data->store)
-		g_object_unref (G_OBJECT (eprop_data->store));
-		
+
 	if ((eprop_data->store = eprop_model_data_generate_store (eprop)) != NULL)
 	{
 		eprop_data->selection = gtk_tree_view_get_selection (eprop_data->view);
 
-		/* Pass ownership of the store to the model */
+		/* Pass ownership of the store to the view... */
 		gtk_tree_view_set_model (eprop_data->view, GTK_TREE_MODEL (eprop_data->store));
 		g_object_unref (G_OBJECT (eprop_data->store));
 		
@@ -635,7 +679,7 @@
 				  eprop);
 	}
 
-	/* Clear and create new columns with renderers */
+	/* Create new columns with renderers */
 	eprop_model_data_generate_columns (eprop);
 }
 

Modified: trunk/plugins/gtk+/gtk+.xml.in
==============================================================================
--- trunk/plugins/gtk+/gtk+.xml.in	(original)
+++ trunk/plugins/gtk+/gtk+.xml.in	Thu Oct 16 14:31:42 2008
@@ -901,7 +901,7 @@
 	<signal id="popup" since="2.12"/>
       </signals>
       <properties>
-        <property id="model" libglade-unsupported="True"/>
+        <property id="model" libglade-unsupported="True" create-type="GtkListStore"/>
         <property id="popup-shown" since="2.10"/>
         <property id="tearoff-title" since="2.10"/>
         <property id="active" ignore="True"/>
@@ -1068,8 +1068,8 @@
       </packing-actions>
 
       <properties>
-	<property id="n-rows" default="3" query="True"/>
-	<property id="n-columns" default="3" query="True"/>
+	<property id="n-rows" default="3" query="True" needs-sync="True"/>
+	<property id="n-columns" default="3" query="True" needs-sync="True"/>
       </properties>
       
       <packing-properties>

Modified: trunk/src/glade-window.c
==============================================================================
--- trunk/src/glade-window.c	(original)
+++ trunk/src/glade-window.c	Thu Oct 16 14:31:42 2008
@@ -1705,7 +1705,6 @@
 			     GladeWindow *window)
 {
 	GladeProject   *project;
-	GladeInspector *inspector;
 
 	--window->priv->num_tabs;
 
@@ -1721,13 +1720,12 @@
 					      G_CALLBACK (project_selection_changed_cb),
 					      window);
 
-	/* FIXME: this function needs to be preferably called somewhere else */
-	glade_app_remove_project (project);
-
-	inspector = (GladeInspector *) gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->priv->inspectors_notebook), page_num);
 
 	gtk_notebook_remove_page (GTK_NOTEBOOK (window->priv->inspectors_notebook), page_num);
 
+	/* FIXME: this function needs to be preferably called somewhere else */
+	glade_app_remove_project (project);
+
 	refresh_projects_list_menu (window);
 
 	refresh_title (window);
@@ -2501,7 +2499,9 @@
  	view = glade_design_view_new (project);	
 	gtk_widget_show (view);
 
+	/* Pass ownership of the project to the app */
 	glade_app_add_project (project);
+	g_object_unref (project);
 
 	gtk_notebook_append_page (GTK_NOTEBOOK (window->priv->notebook), GTK_WIDGET (view), NULL);
 	gtk_notebook_set_current_page (GTK_NOTEBOOK (window->priv->notebook), -1);	



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