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



Author: tvb
Date: Wed Apr  9 19:06:02 2008
New Revision: 1780
URL: http://svn.gnome.org/viewvc/glade3?rev=1780&view=rev

Log:

	* plugins/gtk+/gtk+.xml.in: Filled in all since, deprecated and
	  builder-unsupported properties.

	* gladeui/glade-widget.c, gladeui/glade-widget.h, gladeui/glade-widget-adaptor.c,
	gladeui/glade-command.c, gladeui/glade-widget-adaptor.h,
	gladeui/glade-utils.h, gladeui/glade-catalog.c, 
	gladeui/glade-catalog.h, gladeui/glade-app.c, gladeui/glade-app.h, 
	gladeui/glade-property-class.c, gladeui/glade-property-class.h, 
	gladeui/glade-project.c, gladeui/glade-project.h:
	Added versioning support, you can always chose the target version of
	your project starting with gtk+ 2.8 - a project preferences dialog has
	been added where you can switch your format, switch your target version
	and test for incompatabilities. incompatability error dialogs are also
	launched on save as. Target versions are saved to the glade file; 
	TODO: patch GtkBuilder to test the required gtk+ version from
	<requires lib="gtk+" version="2.8"> and at least warn, also let
	third party widget developers test thier own versions using builder.

	* gladeui/glade-xml-utils.h, gladeui/glade-xml-utils.c: routines
	for parsing version numbers.


	* gladeui/glade-utils.c: glade_util_ui_message() takes a widget to
	embed arg now.



Modified:
   trunk/ChangeLog
   trunk/gladeui/glade-app.c
   trunk/gladeui/glade-app.h
   trunk/gladeui/glade-catalog.c
   trunk/gladeui/glade-catalog.h
   trunk/gladeui/glade-command.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-utils.c
   trunk/gladeui/glade-utils.h
   trunk/gladeui/glade-widget-adaptor.c
   trunk/gladeui/glade-widget-adaptor.h
   trunk/gladeui/glade-widget.c
   trunk/gladeui/glade-widget.h
   trunk/gladeui/glade-xml-utils.c
   trunk/gladeui/glade-xml-utils.h
   trunk/plugins/gtk+/gtk+.xml.in
   trunk/src/glade-window.c

Modified: trunk/gladeui/glade-app.c
==============================================================================
--- trunk/gladeui/glade-app.c	(original)
+++ trunk/gladeui/glade-app.c	Wed Apr  9 19:06:02 2008
@@ -589,7 +589,7 @@
 			/* Config dir exists but is not a directory */
 			glade_util_ui_message
 				(glade_app_get_window(),
-				 GLADE_UI_ERROR,
+				 GLADE_UI_ERROR, NULL,
 				 _("Trying to save private data to %s directory "
 				   "but it is a regular file.\n"
 				   "No private data will be saved in this session"), 
@@ -602,7 +602,7 @@
 			/* Doesnt exist; failed to create */
 			glade_util_ui_message
 				(glade_app_get_window(),
-				 GLADE_UI_ERROR,
+				 GLADE_UI_ERROR, NULL,
 				 _("Failed to create directory %s to save private data.\n"
 				   "No private data will be saved in this session"), config_dir);
 			error_shown = TRUE;
@@ -630,7 +630,7 @@
 			{
 				glade_util_ui_message
 					(glade_app_get_window(),
-					 GLADE_UI_ERROR,
+					 GLADE_UI_ERROR, NULL,
 					 _("Error writing private data to %s (%s).\n"
 					   "No private data will be saved in this session"), 
 					 filename, error->message);
@@ -642,7 +642,7 @@
 		{
 			glade_util_ui_message
 				(glade_app_get_window(),
-				 GLADE_UI_ERROR,
+				 GLADE_UI_ERROR, NULL,
 				 _("Error serializing configuration data to save (%s).\n"
 				   "No private data will be saved in this session"), 
 				 error->message);
@@ -655,7 +655,7 @@
 	{
 		glade_util_ui_message
 			(glade_app_get_window(),
-			 GLADE_UI_ERROR,
+			 GLADE_UI_ERROR, NULL,
 			 _("Error opening %s to write private data (%s).\n"
 			   "No private data will be saved in this session"), 
 			 filename, error->message);
@@ -729,6 +729,35 @@
 	app->priv->window = window;
 }
 
+void
+glade_app_get_catalog_version (const gchar *name, gint *major, gint *minor)
+{
+	GladeApp *app = glade_app_get ();
+	GList    *list;
+
+	for (list = app->priv->catalogs; list; list = list->next)
+	{
+		GladeCatalog *catalog = list->data;
+		if (strcmp (glade_catalog_get_name (catalog), name))
+		{
+			if (major)
+				*major = glade_catalog_get_major_version (catalog);
+			if (minor)
+				*minor = glade_catalog_get_minor_version (catalog);
+			return;
+		}
+	}
+}
+
+GList *
+glade_app_get_catalogs (void)
+{
+	GladeApp *app = glade_app_get ();
+
+	return app->priv->catalogs; 
+}
+
+
 GtkWidget *
 glade_app_get_window (void)
 {
@@ -1114,7 +1143,7 @@
 		{
 			glade_util_ui_message
 				(glade_app_get_window(),
-				 GLADE_UI_WARN,
+				 GLADE_UI_WARN, NULL,
 				 _("You cannot copy a widget "
 				   "internal to a composite widget."));
 			failed = TRUE;
@@ -1129,7 +1158,7 @@
 	}
 	else if (widgets == NULL)
 		glade_util_ui_message (glade_app_get_window(),
-				       GLADE_UI_INFO,
+				       GLADE_UI_INFO, NULL,
 				       _("No widget selected."));
 
 	if (widgets) g_list_free (widgets);
@@ -1167,7 +1196,7 @@
 		{
 			glade_util_ui_message
 				(glade_app_get_window(),
-				 GLADE_UI_WARN,
+				 GLADE_UI_WARN, NULL,
 				 _("You cannot cut a widget "
 				   "internal to a composite widget."));
 			failed = TRUE;
@@ -1182,7 +1211,7 @@
 	}
 	else if (widgets == NULL)
 		glade_util_ui_message (glade_app_get_window(),
-				       GLADE_UI_INFO,
+				       GLADE_UI_INFO, NULL,
 				       _("No widget selected."));
 
 	if (widgets) g_list_free (widgets);
@@ -1226,7 +1255,7 @@
 	    !glade_widget_adaptor_is_container (parent->adaptor))
 	{
 		glade_util_ui_message (glade_app_get_window(),
-				       GLADE_UI_INFO,
+				       GLADE_UI_INFO, NULL,
 				       _("Unable to paste to the selected parent"));
 		return;
 	}
@@ -1237,7 +1266,7 @@
 		if (g_list_length (list) != 1)
 		{
 			glade_util_ui_message (glade_app_get_window(),
-					       GLADE_UI_INFO,
+					       GLADE_UI_INFO, NULL,
 					       _("Unable to paste to multiple widgets"));
 
 			return;
@@ -1247,7 +1276,7 @@
 	/* Check if we have anything to paste */
 	if (g_list_length (clipboard->selection) == 0)
 	{
-		glade_util_ui_message (glade_app_get_window (), GLADE_UI_INFO,
+		glade_util_ui_message (glade_app_get_window (), GLADE_UI_INFO, NULL,
 				    _("No widget selected on the clipboard"));
 
 		return;
@@ -1273,7 +1302,7 @@
 		else if (!GWA_IS_TOPLEVEL (widget->adaptor) && !parent)
 		{
 			glade_util_ui_message (glade_app_get_window (),
-					       GLADE_UI_INFO, 
+					       GLADE_UI_INFO, NULL, 
 					       _("Unable to paste widget %s without a parent"),
 					       widget->name);
 			return;
@@ -1290,7 +1319,7 @@
 	    g_list_length (clipboard->selection) != 1) 
 	{
 		glade_util_ui_message (glade_app_get_window (), 
-				       GLADE_UI_INFO,
+				       GLADE_UI_INFO, NULL,
 				       _("Only one widget can be pasted at a "
 					 "time to this container"));
 		return;
@@ -1302,7 +1331,7 @@
 	    glade_util_count_placeholders (parent) < placeholder_relations)
 	{
 		glade_util_ui_message (glade_app_get_window (), 
-				       GLADE_UI_INFO,
+				       GLADE_UI_INFO, NULL,
 				       _("Insufficient amount of placeholders in "
 					 "target container"));
 		return;
@@ -1341,7 +1370,7 @@
 		{
 			glade_util_ui_message
 				(glade_app_get_window(),
-				 GLADE_UI_WARN,
+				 GLADE_UI_WARN, NULL,
 				 _("You cannot delete a widget "
 				   "internal to a composite widget."));
 			failed = TRUE;
@@ -1356,7 +1385,7 @@
 	}
 	else if (widgets == NULL)
 		glade_util_ui_message (glade_app_get_window(),
-				       GLADE_UI_INFO,
+				       GLADE_UI_INFO, NULL,
 				       _("No widget selected."));
 
 	if (widgets) g_list_free (widgets);
@@ -1377,7 +1406,7 @@
 	clipboard = glade_app_get_clipboard ();
 
 	if (clipboard->selection == NULL)
-		glade_util_ui_message (glade_app_get_window (), GLADE_UI_INFO,
+		glade_util_ui_message (glade_app_get_window (), GLADE_UI_INFO, NULL,
 				    _("No widget selected on the clipboard"));
 
 	for (list = clipboard->selection; list; list = list->next)
@@ -1387,7 +1416,7 @@
 		{
 			glade_util_ui_message
 				(glade_app_get_window(),
-				 GLADE_UI_WARN,
+				 GLADE_UI_WARN, NULL,
 				 _("You cannot delete a widget "
 				   "internal to a composite widget."));
 			return;

Modified: trunk/gladeui/glade-app.h
==============================================================================
--- trunk/gladeui/glade-app.h	(original)
+++ trunk/gladeui/glade-app.h	Wed Apr  9 19:06:02 2008
@@ -98,6 +98,9 @@
  
 GtkWidget*         glade_app_get_window (void);
 
+void               glade_app_get_catalog_version (const gchar *name, gint *major, gint *minor);
+
+GList             *glade_app_get_catalogs (void);
  
 GladeEditor*       glade_app_get_editor (void);
  

Modified: trunk/gladeui/glade-catalog.c
==============================================================================
--- trunk/gladeui/glade-catalog.c	(original)
+++ trunk/gladeui/glade-catalog.c	Wed Apr  9 19:06:02 2008
@@ -37,6 +37,11 @@
 
 struct _GladeCatalog
 {
+	gint   major_version;    /* The catalog version               */
+	gint   minor_version;
+
+	GList *targetable_versions; /* list of suitable version targets */
+
 	gchar *library;          /* Library name for backend support  */
 
 	gchar *name;             /* Symbolic catalog name             */
@@ -141,6 +146,7 @@
 static GladeCatalog *
 catalog_open (const gchar *filename)
 {
+	GladeTargetableVersion *version;
 	GladeCatalog    *catalog;
 	GladeXmlContext *context;
 	GladeXmlDoc     *doc;
@@ -177,7 +183,23 @@
 		catalog_destroy (catalog);
 		return NULL;
 	}
-	
+
+
+	glade_xml_get_property_version (root, GLADE_TAG_VERSION, 
+					&catalog->major_version,
+					&catalog->minor_version);
+
+	/* Make one default suitable target */
+	version = g_new (GladeTargetableVersion, 1);
+	version->major = catalog->major_version;
+	version->minor = catalog->minor_version;
+
+	catalog->targetable_versions = 
+		glade_xml_get_property_targetable_versions
+		(root, GLADE_TAG_TARGETABLE);
+
+	catalog->targetable_versions = g_list_prepend (catalog->targetable_versions, version);
+
 	catalog->library      = glade_xml_get_property_string (root, GLADE_TAG_LIBRARY);
 	catalog->dep_catalog  = glade_xml_get_property_string (root, GLADE_TAG_DEPENDS);
 	catalog->domain       = glade_xml_get_property_string (root, GLADE_TAG_DOMAIN);
@@ -535,6 +557,31 @@
 	return catalog->name;
 }
 
+gint
+glade_catalog_get_major_version (GladeCatalog *catalog)
+{
+	g_return_val_if_fail (catalog != NULL, 0);
+
+	return catalog->major_version;
+}
+
+gint
+glade_catalog_get_minor_version (GladeCatalog *catalog)
+{
+	g_return_val_if_fail (catalog != NULL, 0);
+
+	return catalog->minor_version;
+}
+
+
+GList *
+glade_catalog_get_targets (GladeCatalog *catalog)
+{
+	g_return_val_if_fail (catalog != NULL, NULL);
+
+	return catalog->targetable_versions;
+}
+
 GList *
 glade_catalog_get_widget_groups (GladeCatalog *catalog)
 {

Modified: trunk/gladeui/glade-catalog.h
==============================================================================
--- trunk/gladeui/glade-catalog.h	(original)
+++ trunk/gladeui/glade-catalog.h	Wed Apr  9 19:06:02 2008
@@ -29,18 +29,28 @@
 #define GLADE_CATALOG(c)    ((GladeCatalog *) c)
 #define GLADE_IS_CATALOG(c) (c != NULL)
 
-typedef struct _GladeCatalog GladeCatalog;
 
 #define GLADE_WIDGET_GROUP(g)    ((GladeWidgetGroup *) g)
 #define GLADE_IS_WIDGET_GROUP(g) (g != NULL)
 
+typedef struct _GladeCatalog     GladeCatalog;
 typedef struct _GladeWidgetGroup GladeWidgetGroup;
 
+typedef struct {
+	gint major;
+	gint minor;
+} GladeTargetableVersion;
+
 
 const GList  *glade_catalog_load_all                (void);
 
 const gchar  *glade_catalog_get_name                (GladeCatalog     *catalog);
 
+GList        *glade_catalog_get_targets             (GladeCatalog     *catalog);
+
+gint          glade_catalog_get_major_version       (GladeCatalog     *catalog);
+gint          glade_catalog_get_minor_version       (GladeCatalog     *catalog);
+
 GList        *glade_catalog_get_widget_groups       (GladeCatalog     *catalog);
 
 GList        *glade_catalog_get_adaptors            (GladeCatalog     *catalog);

Modified: trunk/gladeui/glade-command.c
==============================================================================
--- trunk/gladeui/glade-command.c	(original)
+++ trunk/gladeui/glade-command.c	Wed Apr  9 19:06:02 2008
@@ -1026,7 +1026,7 @@
 		if (widget->internal)
 		{
 			glade_util_ui_message (glade_app_get_window(),	
-				       GLADE_UI_WARN,
+					       GLADE_UI_WARN, NULL,
 					       _("You cannot remove a widget internal to a composite widget."));
 			return;
 		}

Modified: trunk/gladeui/glade-project.c
==============================================================================
--- trunk/gladeui/glade-project.c	(original)
+++ trunk/gladeui/glade-project.c	Wed Apr  9 19:06:02 2008
@@ -123,6 +123,9 @@
 	time_t  mtime;         /* last UTC modification time of file, or 0 if it could not be read */
 
 	GladeProjectFormat format; /* file format */
+
+	GHashTable *target_versions_major; /* target versions by catalog */
+	GHashTable *target_versions_minor; /* target versions by catalog */
 };
 
 
@@ -216,6 +219,8 @@
 	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_OBJECT_CLASS (glade_project_parent_class)->finalize (object);
 }
@@ -461,10 +466,39 @@
                             Initializers
  *******************************************************************/
 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));
+}
+
+static void
+glade_project_get_target_version (GladeProject *project,
+				  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_init (GladeProject *project)
 {
 	GladeProjectPrivate *priv;
-	
+	GList *list;
+
 	project->priv = priv = GLADE_PROJECT_GET_PRIVATE (project);	
 
 	priv->path = NULL;
@@ -476,6 +510,7 @@
 	priv->undo_stack = NULL;
 	priv->prev_redo_item = NULL;
 	priv->first_modification = NULL;
+
 	priv->widget_names_allocator = g_hash_table_new_full (g_str_hash,
 							      g_str_equal,
 							      g_free, 
@@ -491,7 +526,28 @@
 
 	priv->unsaved_number = glade_id_allocator_allocate (get_unsaved_number_allocator ());
 
-	priv->format = GLADE_PROJECT_FORMAT_LIBGLADE;
+	priv->format = GLADE_PROJECT_FORMAT_GTKBUILDER;
+
+
+	priv->target_versions_major = g_hash_table_new_full (g_str_hash,
+							     g_str_equal,
+							     g_free,
+							     NULL);
+	priv->target_versions_minor = g_hash_table_new_full (g_str_hash,
+							     g_str_equal,
+							     g_free,
+							     NULL);
+
+	for (list = glade_app_get_catalogs(); list; list = list->next)
+	{
+		GladeCatalog *catalog = list->data;
+
+		/* Set default target to catalog version */
+		glade_project_set_target_version (project,
+						  glade_catalog_get_name (catalog),
+						  glade_catalog_get_major_version (catalog),
+						  glade_catalog_get_minor_version (catalog));
+	}
 }
 
 static void
@@ -805,18 +861,21 @@
 }
 
 static gboolean
-loadable_interface (GladeXmlNode *root_node, const gchar *path)
+glade_project_read_requires (GladeProject *project,
+			     GladeXmlNode *root_node, 
+			     const gchar  *path)
 {
 
 	GString      *string = g_string_new (NULL);
 	GladeXmlNode *node;
 	gchar        *required_lib;
 	gboolean      loadable = TRUE;
+	gint          major, minor;
 
 	for (node = glade_xml_node_get_children (root_node); 
 	     node; node = glade_xml_node_next (node))
 	{
-		/* Skip "requires" tags */
+		/* Skip non "requires" tags */
 		if (!glade_xml_node_verify_silent (node, GLADE_XML_TAG_REQUIRES))
 			continue;
 
@@ -824,6 +883,9 @@
 		     glade_xml_get_property_string_required (node, GLADE_XML_TAG_LIB, 
 							     NULL)) != NULL)
 		{
+			/* Dont mention gtk+ as a required lib in 
+			 * the generated glade file
+			 */
 			if (!glade_catalog_is_loaded (required_lib))
 			{
 				if (!loadable)
@@ -832,13 +894,44 @@
 				g_string_append (string, required_lib);
 				loadable = FALSE;
 			}
-			
+			else if (glade_xml_get_property_version (node, 
+								 GLADE_XML_TAG_VERSION, 
+								 &major, &minor))
+				glade_project_set_target_version
+					(project, required_lib, major, minor);
+
+			g_free (required_lib);
+		}
+	}
+
+
+	/* We use a different tag to save target version metadata in libglade files */
+	for (node = glade_xml_node_get_children (root_node); 
+	     node; node = glade_xml_node_next (node))
+	{
+		/* Skip non "requires" tags */
+		if (!glade_xml_node_verify_silent (node, GLADE_XML_TAG_REQUIRES_LIBGLADE_EXTRA))
+			continue;
+
+		if ((required_lib = 
+		     glade_xml_get_property_string_required (node, GLADE_XML_TAG_LIB, 
+							     NULL)) != NULL)
+		{
+			if (glade_xml_get_property_version (node, 
+							    GLADE_XML_TAG_VERSION, 
+							    &major, &minor))
+				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,
+				       GLADE_UI_ERROR, NULL,
 				       _("Failed to load %s.\n"
 					 "The following required catalogs are unavailable: %s"),
 				       path, string->str);
@@ -897,7 +990,7 @@
 	/* XXX Need to load project->priv->comment ! */
 	glade_project_read_comment (project, doc);
 
-	if (loadable_interface (root, path) == FALSE)
+	if (glade_project_read_requires (project, root, path) == FALSE)
 	{
 		glade_xml_context_free (context);
 		return FALSE;
@@ -1665,10 +1758,13 @@
 static GladeXmlContext *
 glade_project_write (GladeProject *project)
 {
+	GladeProjectFormat fmt;
 	GladeXmlContext *context;
 	GladeXmlDoc     *doc;
 	GladeXmlNode    *root, *req_node, *comment_node;
 	GList           *required, *list;
+	gint             major, minor;
+	gchar           *version;
 
 	doc     = glade_xml_doc_new ();
 	context = glade_xml_context_new (doc, NULL);
@@ -1680,16 +1776,51 @@
 
 	/* XXX Need to append this to the doc ! not the ROOT !
 	   glade_xml_node_append_child (root, comment_node); */
+	fmt = glade_project_get_format (project);
 
 	if ((required = glade_project_required_libs (project)) != NULL)
 	{
 		for (list = required; list; list = list->next)
 		{
-			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);
+			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)))
+			{
+				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);
+			
+
+				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)
+			{
+				req_node = glade_xml_node_new
+					(context, GLADE_XML_TAG_REQUIRES_LIBGLADE_EXTRA);
+				glade_xml_node_append_child (root, req_node);
+
+				glade_xml_node_set_property_string (req_node, 
+								    GLADE_XML_TAG_LIB, 
+								    (gchar *)list->data);
+			
+				glade_xml_node_set_property_string (req_node, 
+								    GLADE_XML_TAG_VERSION, 
+								    version);
+			}
+			g_free (version);
+
 		}
 		g_list_foreach (required, (GFunc)g_free, NULL);
 		g_list_free (required);
@@ -1773,6 +1904,283 @@
 	g_list_free (resources);
 }
 
+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_property (GladeProperty  *property, 
+			       const gchar    *path_name,
+			       GString        *string,
+			       gboolean        packing)
+{
+	GladeWidgetAdaptor *adaptor;
+	gint target_major, target_minor;
+	gchar *catalog;
+
+	if (packing)
+		/* XXX This may be a little incorrect... */
+		adaptor = property->widget->parent->adaptor;
+	else
+		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 (target_major < property->klass->version_since_major ||
+	    (target_major == property->klass->version_since_major &&
+	     target_minor < property->klass->version_since_minor))
+		g_string_append_printf
+				(string,
+				 packing ?
+				 _("(%s) Packing property '%s' of object class '%s' was "
+				   "introduced in %s %d.%d\n") :
+				 _("(%s) Property '%s' of object class '%s' was "
+				   "introduced in %s %d.%d\n"),
+				 path_name,
+				 property->klass->name, 
+				 adaptor->title, catalog,
+				 property->klass->version_since_major,
+				 property->klass->version_since_minor);
+
+	g_free (catalog);
+		
+}
+
+
+static void
+glade_project_verify_properties (GladeWidget  *widget, 
+				 const gchar  *path_name,
+				 GString      *string)
+{
+	GList *list;
+	GladeProperty *property;
+
+	for (list = widget->properties; list; list = list->next)
+	{
+		property = list->data;
+		glade_project_verify_property (property, path_name, string, FALSE);
+	}
+
+	for (list = widget->packing_properties; list; list = list->next)
+	{
+		property = list->data;
+
+		g_assert (widget->parent);
+		property = list->data;
+		glade_project_verify_property (property, path_name, string, FALSE);
+	}
+}
+
+static void
+glade_project_verify_signal (GladeWidget  *widget,
+			     GladeSignal  *signal,
+			     const gchar  *path_name,
+			     GString      *string)
+{
+	GladeSignalClass *signal_class;
+	gint target_major, target_minor;
+	gchar *catalog;
+
+	signal_class = 
+		glade_widget_adaptor_get_signal_class (widget->adaptor,
+						       signal->name);
+	g_assert (signal_class);
+
+	
+			
+	g_object_get (signal_class->adaptor, "catalog", &catalog, NULL);
+	glade_project_target_version_for_adaptor (widget->project, 
+						  signal_class->adaptor, 
+						  &target_major,
+						  &target_minor);
+
+	if (target_major < signal_class->version_since_major ||
+	    (target_major == signal_class->version_since_major &&
+	     target_minor < signal_class->version_since_minor))
+		g_string_append_printf
+			(string, 
+			 _("(%s) Signal '%s' of object class '%s' was "
+			   "introduced in %s %d.%d\n"),
+			 path_name,
+			 signal->name,
+			 signal_class->adaptor->title, 
+			 catalog,
+			 signal_class->version_since_major,
+			 signal_class->version_since_minor);
+
+	g_free (catalog);
+}
+
+
+static void
+glade_project_verify_signals (GladeWidget  *widget, 
+			      const gchar  *path_name,
+			      GString      *string)
+{
+	GladeSignal      *signal;
+	GList *signals, *list;
+	
+	if ((signals = glade_widget_get_signal_list (widget)) != NULL)
+	{
+		for (list = signals; list; list = list->next)
+		{
+			signal = list->data;
+			glade_project_verify_signal (widget, signal, path_name, string);
+		}
+		g_list_free (signals);
+	}	
+}
+
+static gboolean
+glade_project_verify_dialog (GladeProject *project,
+			     GString      *string,
+			     gboolean      saving)
+{
+	GtkWidget     *swindow;
+	GtkWidget     *textview;
+	GtkWidget     *expander;
+	GtkTextBuffer *buffer;
+	gchar         *name;
+	gboolean ret;
+
+	swindow   = gtk_scrolled_window_new (NULL, NULL);
+	textview  = gtk_text_view_new ();
+	buffer    = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
+	expander  = gtk_expander_new (_("Details"));
+
+	gtk_text_buffer_set_text (buffer, string->str, -1);
+
+	gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (swindow),
+					       textview);
+	gtk_container_add (GTK_CONTAINER (expander), swindow);
+	gtk_widget_show_all (expander);
+
+	gtk_widget_set_size_request (swindow, 800, -1);
+	
+	name = glade_project_get_name (project);
+	ret = glade_util_ui_message (glade_app_get_window (),
+				     saving ? GLADE_UI_YES_OR_NO : GLADE_UI_INFO,
+				     expander,
+				     saving ? 
+				     _("Project %s has errors, save anyway ?") :
+				     _("Project %s has deprecated widgets "
+				       "and/or version mismatches."), name);
+	g_free (name);
+
+	return ret;
+}
+
+static void
+glade_project_verify_adaptor_supported (GladeProject       *project,
+					GladeWidgetAdaptor *adaptor,
+					const gchar        *path_name,
+					GString            *string,
+					gboolean            saving)
+{
+	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)))
+			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));
+
+		if (project->priv->format == GLADE_PROJECT_FORMAT_GTKBUILDER &&
+		    GWA_BUILDER_UNSUPPORTED (adaptor_iter))
+			g_string_append_printf
+				(string,
+				 _("(%s) Object class '%s' of catalog '%s' is not supported "
+				   "by GtkBuilder\n"),
+				 path_name, adaptor_iter->title, catalog);
+
+
+		if (!saving && GWA_DEPRECATED (adaptor_iter))
+			g_string_append_printf
+				(string, 
+				 _("(%s) Object class '%s' of catalog '%s' is deprecated\n"),
+				 path_name, adaptor_iter->title, catalog);
+
+		g_free (catalog);
+	}
+
+}
+
+
+static gboolean
+glade_project_verify (GladeProject *project, 
+		      gboolean      saving)
+{
+	GString     *string = g_string_new (NULL);
+	GladeWidget *widget;
+	GList       *list;
+	gboolean     ret = TRUE;
+	gchar       *path_name;
+
+	for (list = project->priv->objects; list; list = list->next)
+	{
+		widget = glade_widget_get_from_gobject (list->data);
+
+		path_name = glade_widget_generate_path_name (widget);
+
+#if 0
+ 		g_print ("Verifying %s target %d.%d widget %d.%d\n",
+			 path_name, target_version_major, target_version_minor,
+			 GWA_VERSION_SINCE_MAJOR (widget->adaptor),
+			 GWA_VERSION_SINCE_MINOR (widget->adaptor));
+#endif
+
+		glade_project_verify_adaptor_supported (project, widget->adaptor, 
+							path_name, string, saving);
+
+		glade_project_verify_properties (widget, path_name, string);
+
+		glade_project_verify_signals (widget, path_name, string);
+
+		g_free (path_name);
+	}
+
+	if (string->len > 0)
+	{
+		ret = glade_project_verify_dialog (project, string, saving);
+
+		if (!saving)
+			ret = FALSE;
+	}
+
+	g_string_free (string, TRUE);
+
+	return ret;
+}
+
+
 /**
  * glade_project_save:
  * @project: a #GladeProject
@@ -1791,6 +2199,9 @@
 	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);
@@ -2355,3 +2766,255 @@
 
 	return project->priv->format;
 }
+
+
+
+static void
+format_libglade_button_clicked (GtkWidget *widget,
+				GladeProject *project)
+{
+	glade_project_set_format (project, GLADE_PROJECT_FORMAT_LIBGLADE);
+}
+
+static void
+format_builder_button_clicked (GtkWidget *widget,
+			       GladeProject *project)
+{
+	glade_project_set_format (project, GLADE_PROJECT_FORMAT_GTKBUILDER);
+}
+
+static void
+target_button_clicked (GtkWidget *widget,
+		       GladeProject *project)
+{
+	GladeTargetableVersion *version = 
+		g_object_get_data (G_OBJECT (widget), "version");
+	gchar *catalog = 
+		g_object_get_data (G_OBJECT (widget), "catalog");
+
+	glade_project_set_target_version (project,
+					  catalog,
+					  version->major,
+					  version->minor);
+}
+
+static void
+verify_clicked (GtkWidget    *button,
+		GladeProject *project)
+{
+	if (glade_project_verify (project, FALSE))
+	{
+		gchar *name = glade_project_get_name (project);
+		glade_util_ui_message (glade_app_get_window(),
+				       GLADE_UI_INFO, NULL,
+				       _("Project %s has no deprecated widgets "
+					 "or version mismatches."),
+				       name);
+		g_free (name);
+	}
+}
+
+static GtkWidget *
+glade_project_build_prefs_box (GladeProject *project)
+{
+	GtkWidget *main_box, *button;
+	GtkWidget *vbox, *hbox, *frame;
+	GtkWidget *glade_radio, *builder_radio, *target_radio, *active_radio;
+	GtkWidget *label, *alignment;
+	GList     *list, *targets;
+	gchar     *string = g_strdup_printf ("<b>%s</b>", _("File format"));
+
+	main_box = gtk_vbox_new (FALSE, 0);
+
+	/* 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_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+	label = gtk_label_new (string);
+	g_free (string);
+	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+	
+	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+	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);
+
+	/* Add stuff to vbox */
+	for (list = glade_app_get_catalogs (); list; list = list->next)
+	{
+		GladeCatalog *catalog = list->data;
+		gint          minor, major;
+
+		/* Skip if theres only one option */
+		if (g_list_length (glade_catalog_get_targets (catalog)) <= 1)
+			continue;
+
+		major = GPOINTER_TO_INT 
+			(g_hash_table_lookup (project->priv->target_versions_major,
+					      glade_catalog_get_name (catalog)));
+		minor = GPOINTER_TO_INT 
+			(g_hash_table_lookup (project->priv->target_versions_minor,
+					      glade_catalog_get_name (catalog)));
+
+		string = g_strdup_printf (_("%s catalog"), 
+					  glade_catalog_get_name (catalog));
+		label = gtk_label_new (string);
+		g_free (string);
+		gtk_misc_set_alignment (GTK_MISC (label), 0.0F, 0.5F);
+		
+		gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 2);
+		hbox = gtk_hbox_new (FALSE, 0);
+
+		active_radio = NULL;
+		target_radio = NULL;
+		
+		for (targets = glade_catalog_get_targets (catalog); 
+		     targets; targets = targets->next)
+		{
+			GladeTargetableVersion *version = targets->data;
+			gchar     *name = g_strdup_printf ("%d.%d", 
+							   version->major,
+							   version->minor);
+
+			if (!target_radio)
+				target_radio = gtk_radio_button_new_with_label (NULL, name);
+			else
+				target_radio = 
+					gtk_radio_button_new_with_label_from_widget 
+					(GTK_RADIO_BUTTON (target_radio), name);
+			g_free (name);
+
+			g_signal_connect (G_OBJECT (target_radio), "clicked",
+					  G_CALLBACK (target_button_clicked), project);
+
+			g_object_set_data (G_OBJECT (target_radio), "version", version);
+			g_object_set_data (G_OBJECT (target_radio), "catalog", 
+					   (gchar *)glade_catalog_get_name (catalog));
+
+			gtk_box_pack_end (GTK_BOX (hbox), target_radio, TRUE, TRUE, 2);
+
+			if (major == version->major &&
+			    minor == version->minor)
+				active_radio = target_radio;
+			
+		}
+
+		if (active_radio)
+			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (active_radio), TRUE);
+		else 
+			g_warning ("Corrupt catalog versions");
+
+		gtk_box_pack_end (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 deprications:"));
+	frame = gtk_frame_new (NULL);
+	alignment = gtk_alignment_new (0.5F, 0.5F, 1.0F, 1.0F);
+	
+	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, 0, 12, 0);
+	
+	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+	label = gtk_label_new (string);
+	g_free (string);
+	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+	
+	gtk_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 (main_box), frame, FALSE, FALSE, 4);
+
+
+	gtk_widget_show_all (main_box);
+
+	return main_box;
+}
+
+/**
+ * glade_project_preferences:
+ * @project: A #GladeProject
+ *
+ * Runs a preferences dialog for @project.
+ */
+void
+glade_project_preferences (GladeProject *project)
+{
+
+	GtkWidget      *dialog, *widget;
+	gchar          *title, *name;
+
+
+	g_return_if_fail (GLADE_IS_PROJECT (project));
+
+	name = glade_project_get_name (project);
+	title = g_strdup_printf ("%s preferences", name);
+
+	dialog = gtk_dialog_new_with_buttons (title,
+					      GTK_WINDOW (glade_app_get_window ()),
+					      GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+					      GTK_STOCK_OK,
+					      GTK_RESPONSE_ACCEPT,
+					      NULL);
+	g_free (title);
+	g_free (name);
+
+	widget = glade_project_build_prefs_box (project);
+	gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
+			  widget, TRUE, TRUE, 2);
+
+	gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
+}

Modified: trunk/gladeui/glade-project.h
==============================================================================
--- trunk/gladeui/glade-project.h	(original)
+++ trunk/gladeui/glade-project.h	Wed Apr  9 19:06:02 2008
@@ -170,6 +170,8 @@
 
 GladeProjectFormat glade_project_get_format  	  (GladeProject *project);
 
+void           glade_project_preferences          (GladeProject *project);
+
 G_END_DECLS
 
 #endif /* __GLADE_PROJECT_H__ */

Modified: trunk/gladeui/glade-property-class.c
==============================================================================
--- trunk/gladeui/glade-property-class.c	(original)
+++ trunk/gladeui/glade-property-class.c	Wed Apr  9 19:06:02 2008
@@ -65,6 +65,7 @@
 	GladePropertyClass *property_class;
 
 	property_class = g_new0 (GladePropertyClass, 1);
+	property_class->origin_handle = handle;
 	property_class->handle = handle;
 	property_class->pspec = NULL;
 	property_class->id = NULL;
@@ -110,8 +111,10 @@
 
 	clone = g_new0 (GladePropertyClass, 1);
 
+	/* copy ints over */
 	memcpy (clone, property_class, sizeof(GladePropertyClass));
 
+	/* Make sure we own our strings */
 	clone->pspec = property_class->pspec;
 	clone->id = g_strdup (clone->id);
 	clone->name = g_strdup (clone->name);
@@ -1461,17 +1464,16 @@
 	/* Visible lines */
 	glade_xml_get_value_int (node, GLADE_TAG_VISIBLE_LINES,  &klass->visible_lines);
 
+	glade_xml_get_property_version
+		(node, GLADE_TAG_VERSION_SINCE, 
+		 &klass->version_since_major,
+		 &klass->version_since_minor);
+
 	/* Get the Parameters */
 	if ((child = glade_xml_search_child (node, GLADE_TAG_PARAMETERS)) != NULL)
 		klass->parameters = glade_parameter_list_new_from_node (klass->parameters, child);
 		
-	/* Whether or not the property is translatable. This is only used for
-	 * string properties.
-	 */
-	klass->translatable = glade_xml_get_property_boolean (node, GLADE_TAG_TRANSLATABLE, 
-							      klass->translatable);
-
-	/* common, optional, etc */
+	klass->translatable = glade_xml_get_property_boolean (node, GLADE_TAG_TRANSLATABLE, klass->translatable);
 	klass->common      = glade_xml_get_property_boolean (node, GLADE_TAG_COMMON,      klass->common);
 	klass->optional    = glade_xml_get_property_boolean (node, GLADE_TAG_OPTIONAL,    klass->optional);
 	klass->query       = glade_xml_get_property_boolean (node, GLADE_TAG_QUERY,       klass->query);

Modified: trunk/gladeui/glade-property-class.h
==============================================================================
--- trunk/gladeui/glade-property-class.h	(original)
+++ trunk/gladeui/glade-property-class.h	Wed Apr  9 19:06:02 2008
@@ -26,6 +26,14 @@
 	gpointer    handle; /* The GladeWidgetAdaptor that this property class
 			     * was created for.
 			     */
+	gpointer    origin_handle; /* The GladeWidgetAdaptor that this property class
+				    * was introduced in.
+				    */
+
+	gint        version_since_major; /* Version in which this property was
+					  * introduced
+					  */
+	gint        version_since_minor; 
 
 	GParamSpec *pspec; /* The Parameter Specification for this property.
 			    */

Modified: trunk/gladeui/glade-utils.c
==============================================================================
--- trunk/gladeui/glade-utils.c	(original)
+++ trunk/gladeui/glade-utils.c	Wed Apr  9 19:06:02 2008
@@ -186,8 +186,9 @@
 /**
  * glade_util_ui_message:
  * @parent: a #GtkWindow cast as a #GtkWidget
- * @format: a printf style format string
  * @type:   a #GladeUIMessageType
+ * @widget: a #GtkWidget to append to the dialog vbox
+ * @format: a printf style format string
  * @...:    args for the format.
  *
  * Creates a new warning dialog window as a child of @parent containing
@@ -198,9 +199,10 @@
  *          selected "OK", True if the @type was GLADE_UI_YES_OR_NO and
  *          the user selected "YES"; False otherwise.
  */
-gboolean
+gint
 glade_util_ui_message (GtkWidget           *parent, 
 		       GladeUIMessageType   type,
+		       GtkWidget           *widget,
 		       const gchar         *format,
 		       ...)
 {
@@ -254,6 +256,12 @@
 					 buttons_type,
 					 string);
 
+	gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+
+	if (widget)
+		gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
+				  widget, TRUE, TRUE, 2);
+
 	response = gtk_dialog_run (GTK_DIALOG (dialog));
 
 	gtk_widget_destroy (dialog);
@@ -506,7 +514,7 @@
 	GtkWidget *vbox, *frame;
 	GtkWidget *glade_radio, *builder_radio;
 	GtkWidget *label, *alignment;
-	gchar     *string = g_strdup_printf ("<b>%s</b>", _("Select file format"));
+	gchar     *string = g_strdup_printf ("<b>%s</b>", _("File format"));
 
 	frame = gtk_frame_new (NULL);
 	vbox = gtk_vbox_new (FALSE, 0);
@@ -1308,7 +1316,7 @@
 
 	if (g_file_test (dest_path, G_FILE_TEST_IS_REGULAR) != FALSE)
 		if (glade_util_ui_message
-		    (glade_app_get_window(), GLADE_UI_YES_OR_NO,
+		    (glade_app_get_window(), GLADE_UI_YES_OR_NO, NULL,
 		     _("%s exists.\nDo you want to replace it?"), dest_path) == FALSE)
 		    return FALSE;
 
@@ -1336,7 +1344,7 @@
 				if (write_status == G_IO_STATUS_ERROR)
 				{
 					glade_util_ui_message (glade_app_get_window(),
-							       GLADE_UI_ERROR,
+							       GLADE_UI_ERROR, NULL,
 							       _("Error writing to %s: %s"),
 							       dest_path, error->message);
 					error = (g_error_free (error), NULL);
@@ -1350,7 +1358,7 @@
 			if (read_status == G_IO_STATUS_ERROR)
 			{
 				glade_util_ui_message (glade_app_get_window(),
-						       GLADE_UI_ERROR,
+						       GLADE_UI_ERROR, NULL,
 						       _("Error reading %s: %s"),
 						       src_path, error->message);
 				error = (g_error_free (error), NULL);
@@ -1365,7 +1373,7 @@
 			{
 				glade_util_ui_message
 					(glade_app_get_window(),
-					 GLADE_UI_ERROR,
+					 GLADE_UI_ERROR, NULL,
 					 _("Error shutting down I/O channel %s: %s"),
 						       dest_path, error->message);
 				error = (g_error_free (error), NULL);
@@ -1375,7 +1383,7 @@
 		else
 		{
 			glade_util_ui_message (glade_app_get_window(),
-					       GLADE_UI_ERROR,
+					       GLADE_UI_ERROR, NULL,
 					       _("Failed to open %s for writing: %s"), 
 					       dest_path, error->message);
 			error = (g_error_free (error), NULL);
@@ -1386,7 +1394,7 @@
 		if (g_io_channel_shutdown (src, TRUE, &error) != G_IO_STATUS_NORMAL)
 		{
 			glade_util_ui_message (glade_app_get_window(),
-					       GLADE_UI_ERROR,
+					       GLADE_UI_ERROR, NULL,
 					       _("Error shutting down io channel %s: %s"),
 					       src_path, error->message);
 			success = FALSE;
@@ -1395,7 +1403,7 @@
 	else 
 	{
 		glade_util_ui_message (glade_app_get_window(),
-				       GLADE_UI_ERROR,
+				       GLADE_UI_ERROR, NULL,
 				       _("Failed to open %s for reading: %s"), 
 				       src_path, error->message);
 		error = (g_error_free (error), NULL);
@@ -1897,3 +1905,4 @@
 		return info.st_mtime;
 	}
 }
+

Modified: trunk/gladeui/glade-utils.h
==============================================================================
--- trunk/gladeui/glade-utils.h	(original)
+++ trunk/gladeui/glade-utils.h	Wed Apr  9 19:06:02 2008
@@ -6,7 +6,6 @@
 
 G_BEGIN_DECLS
 
-
 typedef enum _GladeUtilFileDialogType
 {
         GLADE_FILE_DIALOG_ACTION_OPEN,
@@ -22,7 +21,6 @@
 	GLADE_UI_YES_OR_NO
 } GladeUIMessageType;
 
-
 void		glade_util_widget_set_tooltip	(GtkWidget *widget, const gchar *str);
 
 GType		glade_util_get_type_from_name	(const gchar *name, gboolean have_func);
@@ -31,6 +29,7 @@
 
 gboolean         glade_util_ui_message           (GtkWidget *parent, 
 						  GladeUIMessageType type,
+						  GtkWidget *widget,
 						  const gchar *format, ...);
 
 void		glade_util_flash_message	(GtkWidget *statusbar, 
@@ -128,6 +127,9 @@
 
 time_t            glade_util_get_file_mtime        (const gchar *filename, GError **error);
 
+
+gboolean        glade_util_version_lesser_than     (gdouble a, gdouble b);            
+
 G_END_DECLS
 
 #endif /* __GLADE_UTILS_H__ */

Modified: trunk/gladeui/glade-widget-adaptor.c
==============================================================================
--- trunk/gladeui/glade-widget-adaptor.c	(original)
+++ trunk/gladeui/glade-widget-adaptor.c	Wed Apr  9 19:06:02 2008
@@ -106,23 +106,6 @@
 /*******************************************************************************
                               Helper functions
  *******************************************************************************/
-static GladeWidgetAdaptor *
-gwa_get_parent_adaptor (GladeWidgetAdaptor *adaptor)
-{
-	GladeWidgetAdaptor *parent_adaptor = NULL;
-	GType               iter_type;
-
-	for (iter_type = g_type_parent (adaptor->type);
-	     iter_type > 0;
-	     iter_type = g_type_parent (iter_type))
-	{
-		if ((parent_adaptor = 
-		     glade_widget_adaptor_get_by_type (iter_type)) != NULL)
-			return parent_adaptor;
-	}
-
-	return NULL;
-}
 
 /*
   This function assignes "weight" to each property in its natural order staring from 1.
@@ -270,6 +253,31 @@
 /*******************************************************************************
                      Base Object Implementation detail
  *******************************************************************************/
+#define gwa_get_parent_adaptor(a) glade_widget_adaptor_get_parent_adaptor (a)
+
+/* XXX DOCME
+ */
+GladeWidgetAdaptor *
+glade_widget_adaptor_get_parent_adaptor (GladeWidgetAdaptor *adaptor)
+{
+	GladeWidgetAdaptor *parent_adaptor = NULL;
+	GType               iter_type;
+
+	g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);
+
+	for (iter_type = g_type_parent (adaptor->type);
+	     iter_type > 0;
+	     iter_type = g_type_parent (iter_type))
+	{
+		if ((parent_adaptor = 
+		     glade_widget_adaptor_get_by_type (iter_type)) != NULL)
+			return parent_adaptor;
+	}
+
+	return NULL;
+}
+
+
 static gint
 gwa_signal_comp (gconstpointer a, gconstpointer b)
 {
@@ -277,8 +285,16 @@
 	return strcmp (signal_b->query.signal_name, signal_a->query.signal_name);
 }
 
+static gint
+gwa_signal_find_comp (gconstpointer a, gconstpointer b)
+{
+	const GladeSignalClass *signal = a;	
+	const gchar            *name = b;
+	return strcmp (name, signal->query.signal_name);
+}
+
 static void
-gwa_add_signals (GList **signals, GType type)
+gwa_add_signals (GladeWidgetAdaptor *adaptor, GList **signals, GType type)
 {
 	guint count, *sig_ids, num_signals;
 	GladeSignalClass *cur;
@@ -299,6 +315,7 @@
 			 */
 			g_assert (cur->query.signal_id != 0);
 
+			cur->adaptor = adaptor;
 			cur->name = (cur->query.signal_name);
 			cur->type = (gchar *) g_type_name (type);
 
@@ -324,12 +341,12 @@
 		parent = g_type_parent (type);
 		
 		/* Add class signals */
-		gwa_add_signals (&signals, type);
+		gwa_add_signals (adaptor, &signals, type);
 	
 		/* Add class interfaces signals */
 		for (i = p = g_type_interfaces (type, NULL); *i; i++)
 			if (!glade_util_class_implements_interface (parent, *i))
-				gwa_add_signals (&signals, *i);
+				gwa_add_signals (adaptor, &signals, *i);
 
 		g_free (p);
 	}
@@ -354,6 +371,13 @@
 			GladePropertyClass *pclass =
 				glade_property_class_clone (list->data);
 			pclass->handle = adaptor;
+
+			/* Reset versioning in derived catalogs just once */
+			if (strcmp (adaptor->priv->catalog, 
+				    parent_adaptor->priv->catalog))
+				pclass->version_since_major =
+					pclass->version_since_major = 0;
+
 			properties = g_list_prepend (properties, pclass);
 		}
 	}
@@ -488,6 +512,42 @@
 	return child_packings;
 }
 
+static void
+gwa_inherit_signals (GladeWidgetAdaptor *adaptor)
+{
+	GladeWidgetAdaptor *parent_adaptor;
+	GList              *list, *node;
+	GladeSignalClass   *signal, *parent_signal;
+
+	if ((parent_adaptor = gwa_get_parent_adaptor (adaptor)) != NULL)
+	{
+		for (list = adaptor->signals; list; list = list->next)
+		{
+			signal = list->data;
+
+			if ((node = g_list_find_custom
+			     (parent_adaptor->signals, signal->name,
+			      (GCompareFunc)gwa_signal_find_comp)) != NULL)
+			{
+				parent_signal = node->data;
+
+				/* Reset versioning in derived catalogs just once */
+				if (strcmp (adaptor->priv->catalog, 
+					    parent_adaptor->priv->catalog))
+					signal->version_since_major =
+						signal->version_since_major = 0;
+				else
+				{
+					signal->version_since_major = 
+						parent_signal->version_since_major;
+					signal->version_since_minor = 
+						parent_signal->version_since_minor;
+				}
+			}
+		}
+	}
+}
+
 static GObject *
 glade_widget_adaptor_constructor (GType                  type,
 				  guint                  n_construct_properties,
@@ -521,12 +581,11 @@
 	{
 		/* Build signals & properties */
 		adaptor->signals = gwa_list_signals (adaptor);
+
+		gwa_inherit_signals (adaptor);
 		gwa_setup_properties (adaptor, object_class, FALSE);
 		gwa_setup_properties (adaptor, object_class, TRUE);
 	}
-	else
-		g_critical ("Failed to get class for type %s\n", 
-			    g_type_name (adaptor->type));
 
 	/* Inherit packing defaults here */
 	adaptor->child_packings = gwa_inherit_child_packing (adaptor);
@@ -536,7 +595,14 @@
 		adaptor->priv->special_child_type =
 			parent_adaptor->priv->special_child_type ?
 			g_strdup (parent_adaptor->priv->special_child_type) : NULL;
-	
+
+
+	/* Reset version numbering if we're in a new catalog just once */
+	if (parent_adaptor &&
+	    strcmp (adaptor->priv->catalog, parent_adaptor->priv->catalog))
+		GLADE_WIDGET_ADAPTOR_GET_CLASS(adaptor)->version_since_major = 
+			GLADE_WIDGET_ADAPTOR_GET_CLASS(adaptor)->version_since_minor = 0;
+
 	/* Copy parent actions */
 	if (parent_adaptor)
 	{
@@ -1389,25 +1455,36 @@
 	
 	/* Load catalog symbols from module */
 	if (module) gwa_extend_with_node_load_sym (adaptor_class, node, module);
-	
+
+	glade_xml_get_property_version
+		(node, GLADE_TAG_VERSION_SINCE, 
+		 &adaptor_class->version_since_major,
+		 &adaptor_class->version_since_minor);
+
+	adaptor_class->deprecated = 
+		glade_xml_get_property_double
+		(node, GLADE_TAG_DEPRECATED, adaptor_class->deprecated);
+
+	adaptor_class->builder_unsupported = 
+		glade_xml_get_property_double
+		(node, GLADE_TAG_BUILDER_UNSUPPORTED, adaptor_class->builder_unsupported);
+
 	adaptor_class->fixed = 
 		glade_xml_get_property_boolean
 		(node, GLADE_TAG_FIXED, adaptor_class->fixed);
 
-	/* Check if this class is toplevel */
 	adaptor_class->toplevel =
 		glade_xml_get_property_boolean
 		(node, GLADE_TAG_TOPLEVEL, adaptor_class->toplevel);
 
-	/* Check if this class uses placeholders for child widgets */
 	adaptor_class->use_placeholders =
 		glade_xml_get_property_boolean
 		(node, GLADE_TAG_USE_PLACEHOLDERS, adaptor_class->use_placeholders);
 
-	/* Check default size when used as a toplevel in the GladeDesignView */
 	adaptor_class->default_width =
 		glade_xml_get_property_int
 		(node, GLADE_TAG_DEFAULT_WIDTH, adaptor_class->default_width);
+
 	adaptor_class->default_height =
 		glade_xml_get_property_int
 		(node, GLADE_TAG_DEFAULT_HEIGHT, adaptor_class->default_height);
@@ -1732,6 +1809,39 @@
 	}
 }
 
+static void
+gwa_set_signals_from_node (GladeWidgetAdaptor *adaptor, 
+			   GladeXmlNode       *node)
+{
+	GladeXmlNode     *child;
+	GladeSignalClass *signal;
+	GList            *list;
+	gchar            *id;
+
+	for (child = glade_xml_node_get_children (node);
+	     child; child = glade_xml_node_next (child))
+	{
+		if (!glade_xml_node_verify (child, GLADE_TAG_SIGNAL))
+			continue;
+
+		if (!(id = glade_xml_get_property_string_required (child, GLADE_TAG_ID, NULL)))
+			continue;
+
+		if ((list = 
+		     g_list_find_custom (adaptor->signals, id,
+					 (GCompareFunc)gwa_signal_find_comp)) != NULL)
+		{
+			signal = list->data;
+			glade_xml_get_property_version
+				(child, GLADE_TAG_VERSION_SINCE, 
+				 &signal->version_since_major,
+				 &signal->version_since_minor);
+		}
+		g_free (id);
+	}
+}
+
+
 static gboolean
 gwa_extend_with_node (GladeWidgetAdaptor *adaptor, 
 		      GladeXmlNode       *node,
@@ -1747,9 +1857,6 @@
 		adaptor->priv->special_child_type =
 			(g_free (adaptor->priv->special_child_type), child_type);
 	
-	/* if we found a <properties> tag on the xml file, we add the properties
-	 * that we read from the xml file to the class.
-	 */
 	if ((child = 
 	     glade_xml_search_child (node, GLADE_TAG_PROPERTIES)) != NULL)
 		gwa_update_properties_from_node
@@ -1764,12 +1871,14 @@
 	     glade_xml_search_child (node, GLADE_TAG_PACKING_DEFAULTS)) != NULL)
 		gwa_set_packing_defaults_from_node (adaptor, child);
 
-	/* Update actions from child node */
+	if ((child = 
+	     glade_xml_search_child (node, GLADE_TAG_SIGNALS)) != NULL)
+		gwa_set_signals_from_node (adaptor, child);
+
 	if ((child = 
 	     glade_xml_search_child (node, GLADE_TAG_ACTIONS)) != NULL)
 		gwa_action_update_from_node (adaptor, FALSE, child, domain, NULL);
 	
-	/* Update packing actions from child node */
 	if ((child = 
 	     glade_xml_search_child (node, GLADE_TAG_PACKING_ACTIONS)) != NULL)
 		gwa_action_update_from_node (adaptor, TRUE, child, domain, NULL);
@@ -1985,6 +2094,7 @@
 	adaptor = g_object_new (adaptor_type, 
 				"type", object_type,
 				"name", name,
+				"catalog", catname,
 				"generic-name", generic_name,
 				"icon-name", adaptor_icon_name,
 				NULL);
@@ -2032,9 +2142,7 @@
 	if (adaptor->generic_name == NULL)
 		adaptor->generic_name = g_strdup ("widget");
 	
-	/* Dont mention gtk+ as a required lib in the generated glade file */
-	if (strcmp (catname, "gtk+"))
-		adaptor->priv->catalog = g_strdup (catname);
+	adaptor->priv->catalog = g_strdup (catname);
 
 	if (book)
 		adaptor->priv->book = g_strdup (book);
@@ -3280,3 +3388,34 @@
 	return GLADE_WIDGET_ADAPTOR_GET_CLASS
 		(adaptor)->string_from_value (adaptor, klass, value);
 }
+
+
+/**
+ * glade_widget_adaptor_string_from_value:
+ * @adaptor: A #GladeWidgetAdaptor
+ * @name: the name of the signal class.
+ * 
+ * Looks up signal class @name on @adaptor.
+ *
+ * Returns: a #GladeSignalClass or %NULL
+ */
+GladeSignalClass *
+glade_widget_adaptor_get_signal_class (GladeWidgetAdaptor *adaptor,
+				       const gchar        *name)
+{
+	GList *list;
+	GladeSignalClass *signal;
+
+	g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);
+	g_return_val_if_fail (name != NULL, NULL);
+
+	for (list = adaptor->signals; list; list = list->next)
+	{
+		signal = list->data;
+		if (!strcmp (signal->name, name)) 
+			return signal;
+	}
+
+	return NULL;
+}
+

Modified: trunk/gladeui/glade-widget-adaptor.h
==============================================================================
--- trunk/gladeui/glade-widget-adaptor.h	(original)
+++ trunk/gladeui/glade-widget-adaptor.h	Wed Apr  9 19:06:02 2008
@@ -33,6 +33,42 @@
         ((obj) ? GLADE_WIDGET_ADAPTOR_GET_CLASS(obj)->fixed : FALSE)
 
 /**
+ * GWA_DEPRECATED:
+ * @obj: A #GladeWidgetAdaptor
+ *
+ * Checks whether this widget class is marked as deprecated
+ */
+#define GWA_DEPRECATED(obj) \
+        ((obj) ? GLADE_WIDGET_ADAPTOR_GET_CLASS(obj)->deprecated : FALSE)
+
+/**
+ * GWA_BUILDER_UNSUPPORTED:
+ * @obj: A #GladeWidgetAdaptor
+ *
+ * Checks whether this widget class unsupported by GtkBuilder
+ */
+#define GWA_BUILDER_UNSUPPORTED(obj) \
+        ((obj) ? GLADE_WIDGET_ADAPTOR_GET_CLASS(obj)->builder_unsupported : FALSE)
+
+/**
+ * GWA_VERSION_SINCE_MAJOR:
+ * @obj: A #GladeWidgetAdaptor
+ *
+ * Checks major version in which this widget was introduced
+ */
+#define GWA_VERSION_SINCE_MAJOR(obj)						\
+        ((obj) ? GLADE_WIDGET_ADAPTOR_GET_CLASS(obj)->version_since_major : FALSE)
+
+/**
+ * GWA_VERSION_SINCE_MINOR:
+ * @obj: A #GladeWidgetAdaptor
+ *
+ * Checks minor version in which this widget was introduced
+ */
+#define GWA_VERSION_SINCE_MINOR(obj)						\
+        ((obj) ? GLADE_WIDGET_ADAPTOR_GET_CLASS(obj)->version_since_minor : FALSE)
+
+/**
  * GWA_IS_TOPLEVEL:
  * @obj: A #GladeWidgetAdaptor
  *
@@ -400,8 +436,16 @@
 typedef struct _GladeSignalClass GladeSignalClass; 
 struct _GladeSignalClass
 {
+	GladeWidgetAdaptor *adaptor; /* The adaptor that originated this signal.
+				      */
+
 	GSignalQuery query;
 
+	gint         version_since_major; /* Version in which this signal was
+					   * introduced
+					   */
+	gint         version_since_minor;
+
 	const gchar *name;         /* Name of the signal, eg clicked */
 	gchar       *type;         /* Name of the object class that this signal belongs to
 				    * eg GtkButton */
@@ -462,6 +506,18 @@
 {
 	GObjectClass               parent_class;
 
+	gint                       version_since_major; /* Version in which this widget was
+							 * introduced
+							 */
+	gint                       version_since_minor;
+
+	gboolean                   deprecated;     /* If this widget is currently
+						    * deprecated
+						    */
+	gboolean                   builder_unsupported; /* If this widget is not supported
+							 * by gtkbuilder
+							 */
+
 	gboolean                   fixed;      /* If this is a GtkContainer, use free-form
 						* placement with drag/resize/paste at mouse...
 						*/
@@ -728,6 +784,11 @@
 							      GladePropertyClass *klass,
 							      const GValue       *value);
 
+GladeSignalClass    *glade_widget_adaptor_get_signal_class   (GladeWidgetAdaptor *adaptor,
+							      const gchar        *name);
+
+GladeWidgetAdaptor  *glade_widget_adaptor_get_parent_adaptor (GladeWidgetAdaptor *adaptor);
+
 G_END_DECLS
 
 #endif /* __GLADE_WIDGET_ADAPTOR_H__ */

Modified: trunk/gladeui/glade-widget.c
==============================================================================
--- trunk/gladeui/glade-widget.c	(original)
+++ trunk/gladeui/glade-widget.c	Wed Apr  9 19:06:02 2008
@@ -1970,6 +1970,44 @@
 }
 
 static void
+glade_widget_accum_signal_foreach (const gchar *key,
+				   GPtrArray   *signals,
+				   GList      **list)
+{
+	GladeSignal *signal;
+	gint i;
+
+	for (i = 0; i < signals->len; i++)
+	{
+		signal = (GladeSignal *)signals->pdata[i];
+		*list = g_list_append (*list, signal);
+	}
+}
+
+/**
+ * glade_widget_get_signal_list:
+ * @widget:   a 'dest' #GladeWidget
+ *
+ * Compiles a list of #GladeSignal elements
+ *
+ * Returns: a newly allocated #GList of #GladeSignals, the caller
+ * must call g_list_free() to free the list.
+ */
+GList *
+glade_widget_get_signal_list (GladeWidget *widget)
+{
+	GList *signals = NULL;
+
+	g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL);
+
+	g_hash_table_foreach (widget->signals,
+			      (GHFunc)glade_widget_accum_signal_foreach,
+			      &signals);
+
+	return signals;
+}
+
+static void
 glade_widget_copy_signal_foreach (const gchar *key,
 				  GPtrArray   *signals,
 				  GladeWidget *dest)
@@ -4022,3 +4060,32 @@
 	
 	return eprop;
 }
+
+/**
+ * glade_widget_generate_path_name:
+ * @widget: A #GladeWidget
+ *
+ * Creates a user friendly name to describe project widgets
+ *
+ * Returns: A newly allocated string
+ */
+gchar *
+glade_widget_generate_path_name (GladeWidget *widget)
+{
+	GString     *string;
+	GladeWidget *iter;
+
+	g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL);
+
+	string = g_string_new (widget->name);
+	
+       	for (iter = widget->parent; iter; iter = iter->parent)
+	{
+		gchar *str = g_strdup_printf ("%s / ", iter->name);
+		g_string_prepend (string, str);
+		g_free (str);
+	}
+
+	return g_string_free (string, FALSE);
+}
+

Modified: trunk/gladeui/glade-widget.h
==============================================================================
--- trunk/gladeui/glade-widget.h	(original)
+++ trunk/gladeui/glade-widget.h	Wed Apr  9 19:06:02 2008
@@ -143,6 +143,9 @@
  
 GladeWidget            *glade_widget_dup                    (GladeWidget      *template_widget,
 							     gboolean          exact);
+
+GList                  *glade_widget_get_signal_list        (GladeWidget      *widget);
+
 void                    glade_widget_copy_signals           (GladeWidget      *widget,
 							     GladeWidget      *template_widget);
 void                    glade_widget_copy_properties        (GladeWidget      *widget,
@@ -248,6 +251,7 @@
 							     gboolean          packing,
 							     gboolean          use_command);
 
+gchar                  *glade_widget_generate_path_name     (GladeWidget      *widget);
 /*******************************************************************************
                       Project, object property references
  *******************************************************************************/

Modified: trunk/gladeui/glade-xml-utils.c
==============================================================================
--- trunk/gladeui/glade-xml-utils.c	(original)
+++ trunk/gladeui/glade-xml-utils.c	Wed Apr  9 19:06:02 2008
@@ -26,6 +26,7 @@
 #include <errno.h>
 
 #include "glade-xml-utils.h"
+#include "glade-catalog.h"
 
 #include <libxml/tree.h>
 #include <libxml/parser.h>
@@ -484,6 +485,79 @@
 	return value;
 }
 
+gboolean
+glade_xml_get_property_version (GladeXmlNode *node_in, 
+				const gchar  *name, 
+				gint         *major, 
+				gint         *minor)
+{
+	xmlNodePtr node = (xmlNodePtr) node_in;
+	gchar *value = glade_xml_get_property_string (node_in, name);
+	gchar **split;
+
+	if (!value)
+		return FALSE;
+
+	split = g_strsplit (value, ".", 2);
+
+	if (!split[0] || !split[1])
+	{
+		g_warning ("Malformed version property \"%s\"\n"
+			   "Under the \"%s\" tag (%s)", name, node->name, value);
+		return FALSE;
+	}
+
+	*major = g_ascii_strtoll (split[0], NULL, 10);
+	*minor = g_ascii_strtoll (split[1], NULL, 10);
+	
+	g_strfreev (split);
+	
+	return TRUE;
+}
+
+GList *
+glade_xml_get_property_targetable_versions (GladeXmlNode *node_in, 
+					    const gchar  *name)
+{
+	GladeTargetableVersion *version;
+	GList                  *targetable = NULL;
+	xmlNodePtr              node = (xmlNodePtr) node_in;
+	gchar                  *value;
+	gchar                 **split, **maj_min;
+	gint                    i;
+
+	if (!(value = glade_xml_get_property_string (node_in, name)))
+		return NULL;
+
+	if ((split = g_strsplit (value, ",", 0)) != NULL)
+	{
+		for (i = 0; split[i]; i++)
+		{
+			maj_min = g_strsplit (split[i], ".", 2);
+
+			if (!maj_min[0] || !maj_min[1])
+			{
+				g_warning ("Malformed version property \"%s\"\n"
+					   "Under the \"%s\" tag (%s)", name, node->name, value);
+			}
+			else
+			{
+				version = g_new (GladeTargetableVersion, 1);
+				version->major = g_ascii_strtoll (maj_min[0], NULL, 10);
+				version->minor = g_ascii_strtoll (maj_min[1], NULL, 10);
+				
+				targetable = g_list_append (targetable, version);
+			}			
+			g_strfreev (maj_min);
+		}
+
+		g_strfreev (split);
+	}
+	return targetable;
+}
+
+
+
 /*
  * Search a child by name,
  */

Modified: trunk/gladeui/glade-xml-utils.h
==============================================================================
--- trunk/gladeui/glade-xml-utils.h	(original)
+++ trunk/gladeui/glade-xml-utils.h	Wed Apr  9 19:06:02 2008
@@ -29,11 +29,25 @@
 	 GLADE_XML_TAG_LIBGLADE_WIDGET : GLADE_XML_TAG_BUILDER_WIDGET)
 
 /* Used for catalog tags and attributes */
+
+
+	gdouble                    version_since; /* Version in which this widget was
+						   * introduced
+						   */
+	gboolean                   deprecated; /* If this widget is currently
+							* deprecated
+							*/
+	gboolean                   builder_unsupported; /* If this widget is not supported
+							 * by gtkbuilder
+							 */
+
 #define GLADE_XML_TAG_LIBGLADE_PROJECT            "glade-interface"
 #define GLADE_XML_TAG_BUILDER_PROJECT             "interface"
 #define GLADE_XML_TAG_LIBGLADE_WIDGET             "widget"
 #define GLADE_XML_TAG_BUILDER_WIDGET              "object"
 
+#define GLADE_XML_TAG_VERSION                     "version"
+#define GLADE_XML_TAG_REQUIRES_LIBGLADE_EXTRA     "requires-version"
 #define GLADE_XML_TAG_REQUIRES                    "requires"
 #define GLADE_XML_TAG_LIB                         "lib"
 #define GLADE_XML_TAG_PROPERTY                    "property"
@@ -52,6 +66,13 @@
 #define GLADE_XML_TAG_SIGNAL_TRUE                 "yes"
 #define GLADE_XML_TAG_TYPE                        "type"
 
+
+#define GLADE_TAG_VERSION                         "version"
+#define GLADE_TAG_TARGETABLE                      "targetable"
+#define GLADE_TAG_VERSION_SINCE                   "since"
+#define GLADE_TAG_DEPRECATED                      "deprecated"
+#define GLADE_TAG_BUILDER_UNSUPPORTED             "builder-unsupported"
+
 #define GLADE_TAG_GLADE_CATALOG                   "glade-catalog"
 #define GLADE_TAG_GLADE_WIDGET_CLASSES            "glade-widget-classes"
 #define GLADE_TAG_GLADE_WIDGET_CLASS              "glade-widget-class"
@@ -62,7 +83,8 @@
 #define GLADE_TAG_DEPENDS                         "depends"
 #define GLADE_TAG_DOMAIN                          "domain"
 #define GLADE_TAG_BOOK                            "book"
-#define GLADE_TAG_SIGNAL_NAME                     "signal-name"
+#define GLADE_TAG_SIGNALS                         "signals"
+#define GLADE_TAG_SIGNAL                          "signal"
 #define GLADE_TAG_DEFAULT                         "default"
 #define GLADE_TAG_DISABLED                        "disabled"
 #define GLADE_TAG_DEFAULT_PALETTE_STATE           "default-palette-state"
@@ -177,6 +199,9 @@
 gboolean glade_xml_get_property_boolean (GladeXmlNode *node_in, const gchar *name, gboolean _default);
 gdouble  glade_xml_get_property_double (GladeXmlNode *node_in, const gchar *name, gdouble _default);
 gint     glade_xml_get_property_int (GladeXmlNode *node_in, const gchar *name, gint _default);
+gboolean glade_xml_get_property_version (GladeXmlNode *node_in, const gchar *name, gint *major, gint *minor);
+GList   *glade_xml_get_property_targetable_versions (GladeXmlNode *node_in, const gchar *name);
+
 
 void glade_xml_node_set_property_string (GladeXmlNode *node_in, const gchar *name, const gchar *string);
 void glade_xml_node_set_property_boolean (GladeXmlNode *node_in, const gchar *name, gboolean value);

Modified: trunk/plugins/gtk+/gtk+.xml.in
==============================================================================
--- trunk/plugins/gtk+/gtk+.xml.in	(original)
+++ trunk/plugins/gtk+/gtk+.xml.in	Wed Apr  9 19:06:02 2008
@@ -1,4 +1,6 @@
 <glade-catalog name="gtk+"
+	       version="2.12"
+	       targetable="2.10,2.8"
                icon-prefix="gtk"
                library="gladegtk"
                domain="glade3"
@@ -16,6 +18,12 @@
       <create-editor-property-function>glade_gtk_widget_create_eprop</create-editor-property-function>
       <string-from-value-function>glade_gtk_widget_string_from_value</string-from-value-function>
 
+      <signals>
+	<signal id="drag-failed" since="2.12"/>
+	<signal id="keynav-failed" since="2.12"/>
+	<signal id="query-tooltip" since="2.12"/>
+      </signals>
+
       <actions>
         <action id="remove_parent" _name="Remove Parent" stock="gtk-remove"/>
         <action id="add_parent" _name="Add Parent" stock="gtk-add">
@@ -36,6 +44,8 @@
 
 
       <properties>
+	<property id="tooltip-text" since="2.12"/>
+	<property id="tooltip-markup" since="2.12"/>
 	<property id="visible" default="True" common="True" ignore="True"/>
 	<property id="width-request"  common="True" optional="True" optional-default="False" default="0"/>
 	<property id="height-request" common="True" optional="True" optional-default="False" default="0"/>
@@ -256,6 +266,10 @@
       <post-create-function>glade_gtk_window_post_create</post-create-function>
 
       <properties> 
+	<property id="opacity" since="2.12"/>
+	<property id="startup-id" since="2.12"/>
+	<property id="deletable" since="2.10"/>
+	<property id="transient-for" since="2.10"/>
 	<property id="visible" default="False"/>
 	<property id="icon-name" themed-icon="True" ignore="True"/>
      	<property common="True" id="gravity">
@@ -326,6 +340,11 @@
       <child-set-property-function>glade_gtk_menu_shell_set_child_property</child-set-property-function>
       <child-get-property-function>glade_gtk_menu_shell_get_child_property</child-get-property-function>
       <action-activate-function>glade_gtk_menu_shell_action_activate</action-activate-function>
+
+      <signals>
+	<signal id="move-selected" since="2.10"/>
+      </signals>
+
       <packing-properties>
         <property id="position" _name="Position" default="-1" save="False">
           <spec>glade_standard_int_spec</spec>
@@ -346,7 +365,7 @@
         <action id="launch_editor" _name="Edit&#8230;" stock="gtk-edit" important="True"/>
       </actions>
       <properties>
-        <property id="submenu" disabled="True"/>
+        <property id="submenu" since="2.12" disabled="True"/>
         <property id="label" _name="Label" translatable="True">
 	  <_tooltip>The text of the menu item</_tooltip>
           <spec>glade_standard_string_spec</spec>
@@ -446,6 +465,7 @@
         <action id="launch_editor" _name="Edit&#8230;" stock="gtk-edit" important="True"/>
       </actions>
       <properties>
+      	<property id="icon-size-set" since="2.10"/>
 	<property id="orientation">
   	  <displayable-values>
 	    <value id="GTK_ORIENTATION_HORIZONTAL" _name="Horizontal"/>
@@ -460,7 +480,7 @@
 	    <value id="GTK_TOOLBAR_BOTH_HORIZ" _name="Text beside icons"/>
 	  </displayable-values>
 	</property>
-      	<property id="icon-size">
+      	<property id="icon-size" since="2.10">
   	  <displayable-values>
 	    <value id="GTK_ICON_SIZE_INVALID" _name="Invalid"/>
 	    <value id="GTK_ICON_SIZE_MENU" _name="Menu"/>
@@ -585,7 +605,7 @@
 	    <value id="PANGO_ELLIPSIZE_END" _name="End"/>
 	  </displayable-values>
 	</property>
-      	<property id="wrap-mode">
+      	<property id="wrap-mode" since="2.10">
   	  <displayable-values>
              <value id="PANGO_WRAP_WORD" _name="Word"/>
 	    <value id="PANGO_WRAP_CHAR" _name="Character"/>
@@ -599,7 +619,9 @@
       <post-create-function>glade_gtk_entry_post_create</post-create-function>
       <properties>
 	<property id="text" translatable="True"/>
-    <property id="shadow-type">
+        <property id="inner-border" since="2.10"/>
+        <property id="truncate-multiline" since="2.10"/>
+	<property id="shadow-type" since="2.12">
   	  <displayable-values>
 	    <value id="GTK_SHADOW_NONE" _name="None"/>
 	    <value id="GTK_SHADOW_IN" _name="In"/>
@@ -742,6 +764,11 @@
     <glade-widget-class name="GtkSpinButton" generic-name="spinbutton" _title="Spin Button">
       <post-create-function>empty</post-create-function>
       <set-property-function>glade_gtk_spin_button_set_property</set-property-function>
+
+      <signals>
+	<signal id="wrapped" since="2.10"/>
+      </signals>
+
       <properties>
         <property id="text" disabled="True"/>
         <property id="value" disabled="True"/>
@@ -765,10 +792,16 @@
     </glade-widget-class>
 
     <glade-widget-class name="GtkFileChooserButton" generic-name="filechooserbutton" _title="File Chooser Button">
+
+      <signals>
+	<signal id="file-set" since="2.12"/>
+      </signals>
+
       <properties>
 	<property id="title" translatable="True"/>
 	<property id="size" disabled="True"/>
 	<property id="dialog" disabled="True"/>
+	<property id="focus-on-click" since="2.10"/>
         <property id="action">
   	  <displayable-values>
 	    <value id="GTK_FILE_CHOOSER_ACTION_SAVE" _name="Save"/>
@@ -783,7 +816,7 @@
       </properties>
     </glade-widget-class>
 
-    <glade-widget-class name="GtkScaleButton" generic-name="scalebutton" _title="Scale Button">
+    <glade-widget-class name="GtkScaleButton" generic-name="scalebutton" _title="Scale Button" since="2.12">
       <properties>
         <property id="size">
   	  <displayable-values>
@@ -847,7 +880,15 @@
     <glade-widget-class name="GtkComboBox" generic-name="combobox" _title="Combo Box">
       <post-create-function>glade_gtk_combo_box_post_create</post-create-function>
       <set-property-function>glade_gtk_combo_box_set_property</set-property-function>
+      <signals>
+	<signal id="move-action" since="2.12"/>
+	<signal id="popdown" since="2.12"/>
+	<signal id="popup" since="2.12"/>
+      </signals>
       <properties>
+        <property id="popup-shown" since="2.10"/>
+        <property id="tearoff-title" since="2.10"/>
+        <property id="model" disabled="True"/>
         <property id="model" disabled="True"/>
         <property id="active" ignore="True"/>
         <property id="column-span-column" ignore="True"/>
@@ -874,7 +915,9 @@
     <glade-widget-class name="GtkTreeView" generic-name="treeview" _title="Tree View">
       <post-create-function>glade_gtk_tree_view_post_create</post-create-function>
       <properties>
-        <property id="enable-grid-lines"  ignore="True">
+        <property id="level-indentation" since="2.12"/>
+        <property id="show-expanders" since="2.12"/>
+        <property id="enable-grid-lines" ignore="True">
   	  <displayable-values>
 	    <value id="GTK_TREE_VIEW_GRID_LINES_NONE" _name="None"/>
 	    <value id="GTK_TREE_VIEW_GRID_LINES_HORIZONTAL" _name="Horizontal"/>
@@ -1069,6 +1112,13 @@
       <verify-function>glade_gtk_notebook_verify_property</verify-function>
       <child-action-activate-function>glade_gtk_notebook_child_action_activate</child-action-activate-function>
 
+      <signals>
+	<signal id="page-added" since="2.10"/>
+	<signal id="page-removed" since="2.10"/>
+	<signal id="page-reordered" since="2.10"/>
+	<signal id="create-window" since="2.12"/>
+      </signals>
+
       <packing-actions>
         <action id="insert_page_before" _name="Insert Page Before" stock="gtk-add"/>
         <action id="insert_page_after" _name="Insert Page After" stock="gtk-add"/>
@@ -1076,6 +1126,7 @@
       </packing-actions>
 
       <properties>
+	<property id="group" since="2.12"/>
 	<property id="page" save="False">
 	  <_tooltip>Set the current page (strictly for editing purposes)</_tooltip>
 	</property>
@@ -1135,6 +1186,9 @@
 
     <glade-widget-class name="GtkRange" _title="Range">
       <properties>
+        <property id="fill-level" since="2.12"/>
+        <property id="restrict-to-fill-level" since="2.12"/>
+        <property id="show-fill-level" since="2.12"/>
         <property id="adjustment" default="0 0 100 1 10 10"/>
       	<property id="update-policy">
   	  <displayable-values>
@@ -1325,7 +1379,7 @@
         <property id="can-focus" save-always="True"/>
         <property id="hadjustment" disabled="True"/>
         <property id="vadjustment" disabled="True"/>
-        <property id="window-placement-set" ignore="True"/>
+        <property id="window-placement-set" since="2.10" ignore="True"/>
       	<property id="shadow-type">
   	  <displayable-values>
 	    <value id="GTK_SHADOW_NONE" _name="None"/>
@@ -1367,6 +1421,7 @@
     
    <glade-widget-class name="GtkAboutDialog" generic-name="aboutdialog" _title="About Dialog">
       <properties>
+	<property id="program-name" since="2.12"/>
 	<property id="copyright" translatable="True">
 	  <visible-lines>2</visible-lines>
 	</property>
@@ -1431,6 +1486,13 @@
 	<property common="True" id="can-default"/>
 	<property common="True" id="has-default"/>
 	<property common="True" id="can-focus"/>
+
+	<property id="image" since="2.10"/>
+	<property id="secondary-text" since="2.10"/>
+	<property id="secondary-use-markup" since="2.10"/>
+	<property id="text" since="2.10"/>
+	<property id="use-markup" since="2.10"/>
+
 	<property id="message-type">
   	  <displayable-values>
 	    <value id="GTK_MESSAGE_INFO" _name="Info"/>
@@ -1472,7 +1534,7 @@
     
     <glade-widget-class name="GtkVRuler" generic-name="vruler" _title="Vertical Ruler"/>
 
-    <glade-widget-class name="GtkCombo" generic-name="combo" _title="Combo">
+    <glade-widget-class name="GtkCombo" generic-name="combo" _title="Combo" deprecated="True" builder-unsupported="True">
       <post-create-function>glade_gtk_combo_post_create</post-create-function>
       <get-internal-child-function>glade_gtk_combo_get_internal_child</get-internal-child-function>
       <get-children-function>glade_gtk_combo_get_children</get-children-function>
@@ -1490,7 +1552,7 @@
 
     </glade-widget-class>
     
-    <glade-widget-class name="GtkOptionMenu" generic-name="optionmenu" _title="Option Menu">
+    <glade-widget-class name="GtkOptionMenu" generic-name="optionmenu" _title="Option Menu" deprecated="True" builder-unsupported="True">
       <properties>
 	<!-- Atk press property -->
 	<property id="atk-press" _name="Press" ignore="True" atk-property="True" save="False">
@@ -1501,7 +1563,7 @@
       </properties>
     </glade-widget-class>
 
-    <glade-widget-class name="GtkList" generic-name="list" _title="List">
+    <glade-widget-class name="GtkList" generic-name="list" _title="List" deprecated="True" builder-unsupported="True">
       <add-child-function>glade_gtk_listitem_add_child</add-child-function>
       <remove-child-function>glade_gtk_listitem_remove_child</remove-child-function>
       <properties>
@@ -1517,7 +1579,7 @@
       </properties>
     </glade-widget-class>
 
-    <glade-widget-class name="GtkListItem" generic-name="listitem" _title="List Item">
+    <glade-widget-class name="GtkListItem" generic-name="listitem" _title="List Item" deprecated="True" builder-unsupported="True">
       <post-create-function>glade_gtk_list_item_post_create</post-create-function>
       <set-property-function>glade_gtk_list_item_set_property</set-property-function>
       <get-property-function>glade_gtk_list_item_get_property</get-property-function>
@@ -1529,7 +1591,7 @@
       </properties>
     </glade-widget-class>
 
-    <glade-widget-class name="GtkCList" generic-name="clist" _title="Columned List">
+    <glade-widget-class name="GtkCList" generic-name="clist" _title="Columned List" deprecated="True" builder-unsupported="True">
       <properties>
         <property id="selection-mode">
   	  <displayable-values>
@@ -1585,7 +1647,7 @@
       </properties>
     </glade-widget-class>
 
-    <glade-widget-class name="GtkAssistant" generic-name="assistant" _title="Assistant">
+    <glade-widget-class name="GtkAssistant" generic-name="assistant" _title="Assistant" since="2.10">
       <post-create-function>glade_gtk_assistant_post_create</post-create-function>
       <add-child-function>glade_gtk_assistant_add_child</add-child-function>
       <remove-child-function>glade_gtk_assistant_remove_child</remove-child-function>
@@ -1623,14 +1685,28 @@
       <properties>
         <!-- The pspec of this prop says that the default is http://www.gtk.org but gtk_link_button_init() does not set it up
                do we need to override it to avoid seting a NULL value. -->
-        <property id="uri" default="http://glade.gnome.org"/>
+        <property id="uri" default="http://glade.gnome.org"; since="2.10"/>
       </properties>
    </glade-widget-class>
 
     <glade-widget-class name="GtkRecentChooserWidget" generic-name="recentchooser" _title="Recent Chooser">
+
+      <signals>
+	<signal id="item-activated" since="2.10"/>
+	<signal id="selection-changed" since="2.10"/>
+      </signals>
+
       <properties>
 	<property id="size" disabled="True"/>
-        <property id="sort-type">
+	<property id="filter" since="2.10"/>
+	<property id="limit" since="2.10"/>
+	<property id="local-only" since="2.10"/>
+	<property id="recent-manager" since="2.10"/>
+	<property id="select-multiple" since="2.10"/>
+	<property id="show-icons" since="2.10"/>
+	<property id="show-not-found" since="2.10"/>
+	<property id="show-tips" since="2.10"/>
+        <property id="sort-type" since="2.10">
   	  <displayable-values>
 	    <value id="GTK_RECENT_SORT_NONE" _name="None"/>
 	    <value id="GTK_RECENT_SORT_MRU" _name="Most Recently Used first"/>

Modified: trunk/src/glade-window.c
==============================================================================
--- trunk/src/glade-window.c	(original)
+++ trunk/src/glade-window.c	Wed Apr  9 19:06:02 2008
@@ -1238,7 +1238,7 @@
 	{
 		/* Reset path so future saves will prompt the file chooser */
 		glade_project_reset_path (project);
-		glade_util_ui_message (GTK_WIDGET (window), GLADE_UI_ERROR, 
+		glade_util_ui_message (GTK_WIDGET (window), GLADE_UI_ERROR, NULL, 
 				       _("Failed to save %s: %s"),
 				       display_path, error->message);
 		g_error_free (error);
@@ -1349,7 +1349,7 @@
 		if (project != another_project) {
 
 			glade_util_ui_message (GTK_WIDGET (window), 
-					       GLADE_UI_ERROR,
+					       GLADE_UI_ERROR, NULL,
 				     	       _("Could not save file %s. Another project with that path is open."), 
 					       real_path);
 
@@ -1374,7 +1374,8 @@
 	if (project == NULL)
 	{
 		/* Just in case the menu-item or button is not insensitive */
-		glade_util_ui_message (GTK_WIDGET (window), GLADE_UI_WARN, _("No open projects to save"));
+		glade_util_ui_message (GTK_WIDGET (window), GLADE_UI_WARN, NULL,
+				       _("No open projects to save"));
 		return;
 	}
 
@@ -1442,7 +1443,7 @@
 			{
 
 				glade_util_ui_message
-					(GTK_WIDGET (window), GLADE_UI_ERROR, 
+					(GTK_WIDGET (window), GLADE_UI_ERROR, NULL, 
 					 _("Failed to save %s to %s: %s"),
 					 project_name, glade_project_get_path (project), error->message);
 				g_error_free (error);
@@ -1600,6 +1601,19 @@
 }
 
 static void
+preferences_cb (GtkAction *action, GladeWindow *window)
+{
+	GladeProject *project;
+
+	if (!window->priv->active_view)
+		return;
+
+	project = glade_design_view_get_project (window->priv->active_view);
+
+	glade_project_preferences (project);
+}
+
+static void
 undo_cb (GtkAction *action, GladeWindow *window)
 {
 	if (!glade_app_get_project ())
@@ -2152,6 +2166,8 @@
 "      <menuitem action='Copy'/>"
 "      <menuitem action='Paste'/>"
 "      <menuitem action='Delete'/>"
+"      <separator/>"
+"      <menuitem action='Preferences'/>"
 "    </menu>"
 "    <menu action='ViewMenu'>"
 "      <menuitem action='Clipboard'/>"
@@ -2261,6 +2277,9 @@
 	{ "Delete", GTK_STOCK_DELETE, NULL, "Delete",
 	  N_("Delete the selection"), G_CALLBACK (delete_cb) },
 
+	{ "Preferences", GTK_STOCK_PREFERENCES, NULL, "<control>W",
+	  N_("Modify project preferences"), G_CALLBACK (preferences_cb) },
+
 	/* ViewMenu */
 	
 	{ "Clipboard", NULL, N_("_Clipboard"), NULL,
@@ -2568,7 +2587,7 @@
 	if (!project)
 	{
 		glade_util_ui_message (GTK_WIDGET (window), 
-				       GLADE_UI_ERROR,
+				       GLADE_UI_ERROR, NULL,
 				       _("Could not create a new project."));
 		return;
 	}



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