diff -urN libgnomedb/libgnomedb/data-entries/gnome-db-data-cell-renderer-combo.c libgnomedbnew/libgnomedb/data-entries/gnome-db-data-cell-renderer-combo.c
--- libgnomedb/libgnomedb/data-entries/gnome-db-data-cell-renderer-combo.c	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/data-entries/gnome-db-data-cell-renderer-combo.c	2009-04-19 18:38:14.000000000 +0200
@@ -87,8 +87,8 @@
 
 struct _GnomeDbDataCellRendererComboPrivate
 {
-	GdaSet       *paramlist;
-	GdaSetSource *source;
+	GnomeDbSet       *paramlist;
+	GnomeDbSetSource *source;
 	guint         focus_out_id;
 	guint         attributes;
 	gboolean      to_be_deleted;
@@ -299,7 +299,7 @@
 					/* if (gnome_db_data_model_get_status (datacell->priv->data_model) &  */
 /* 					    GNOME_DB_DATA_MODEL_NEEDS_INIT_REFRESH) */
 /* 						gnome_db_data_model_refresh (datacell->priv->data_model, NULL); */
-					row = gda_data_model_get_row_from_values (datacell->priv->source->data_model,
+					row = gda_data_model_get_row_from_values (datacell->priv->source->source->data_model,
 										  values,
 										  datacell->priv->source->ref_cols_index);
 					if (row >= 0) {
@@ -310,7 +310,7 @@
 						for (i = 0; i < datacell->priv->source->shown_n_cols; i++) {
 							const GValue *value;
 							
-							value = gda_data_model_get_value_at (datacell->priv->source->data_model,
+							value = gda_data_model_get_value_at (datacell->priv->source->source->data_model,
 											     datacell->priv->source->shown_cols_index [i],
 											     row, NULL);
 							dsplay_values = g_list_append (dsplay_values, (GValue *) value);
@@ -369,14 +369,14 @@
 		if (datacell->priv->paramlist)
 			g_object_unref (datacell->priv->paramlist);
 
-		datacell->priv->paramlist = GDA_SET(g_value_get_object(value));
+		datacell->priv->paramlist = GNOME_DB_SET (g_value_get_object(value));
 		if(datacell->priv->paramlist)
 			g_object_ref(datacell->priv->paramlist);
 
 		g_object_ref (G_OBJECT (datacell->priv->paramlist)); 
 		break;
 	case PROP_PARAMLISTSOURCE:
-		datacell->priv->source = GDA_SET_SOURCE(g_value_get_pointer(value));
+		datacell->priv->source = GNOME_DB_SET_SOURCE (g_value_get_pointer(value));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -426,7 +426,7 @@
 /**
  * gnome_db_data_cell_renderer_combo_new
  * @paramlist: a #GdaSet object
- * @source: a #GdaSetSource structure listed in @paramlist->sources_list
+ * @source: a #GnomeDbSetSource structure listed in @paramlist->sources_list
  * 
  * Creates a new #GnomeDbDataCellRendererCombo which will fill the parameters listed in
  * @source->nodes with values available from @source->data_model.
@@ -434,7 +434,7 @@
  * Return value: the new cell renderer
  **/
 GtkCellRenderer *
-gnome_db_data_cell_renderer_combo_new (GdaSet *paramlist, GdaSetSource *source)
+gnome_db_data_cell_renderer_combo_new (GnomeDbSet *paramlist, GnomeDbSetSource *source)
 {
 	GObject *obj;
 
@@ -557,7 +557,7 @@
 	if (cell_text->editable == FALSE)
 		return NULL;
 
-	combo = gnome_db_combo_new_with_model (GDA_DATA_MODEL (datacell->priv->source->data_model),
+	combo = gnome_db_combo_new_with_model (GDA_DATA_MODEL (datacell->priv->source->source->data_model),
 					       datacell->priv->source->shown_n_cols, 
 					       datacell->priv->source->shown_cols_index);
 	
diff -urN libgnomedb/libgnomedb/data-entries/gnome-db-data-cell-renderer-combo.h libgnomedbnew/libgnomedb/data-entries/gnome-db-data-cell-renderer-combo.h
--- libgnomedb/libgnomedb/data-entries/gnome-db-data-cell-renderer-combo.h	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/data-entries/gnome-db-data-cell-renderer-combo.h	2009-04-19 18:38:14.000000000 +0200
@@ -25,6 +25,7 @@
 #include <gtk/gtk.h>
 #include <pango/pango.h>
 #include <libgnomedb/gnome-db-decl.h>
+#include <libgnomedb/gnome-db-set.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -59,7 +60,7 @@
 };
 
 GType            gnome_db_data_cell_renderer_combo_get_type (void) G_GNUC_CONST;
-GtkCellRenderer *gnome_db_data_cell_renderer_combo_new      (GdaSet *paramlist, GdaSetSource *source);
+GtkCellRenderer *gnome_db_data_cell_renderer_combo_new      (GnomeDbSet *paramlist, GnomeDbSetSource *source);
 
 #ifdef __cplusplus
 }
diff -urN libgnomedb/libgnomedb/data-entries/gnome-db-data-cell-renderer-info.c libgnomedbnew/libgnomedb/data-entries/gnome-db-data-cell-renderer-info.c
--- libgnomedb/libgnomedb/data-entries/gnome-db-data-cell-renderer-info.c	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/data-entries/gnome-db-data-cell-renderer-info.c	2009-04-19 18:38:14.000000000 +0200
@@ -74,16 +74,16 @@
 	PROP_VALUE_ATTRIBUTES,
 	PROP_EDITABLE,
 	PROP_TO_BE_DELETED,
-  PROP_STORE,
-  PROP_ITER,
-  PROP_GROUP
+	PROP_STORE,
+	PROP_ITER,
+	PROP_GROUP
 };
 
 struct _GnomeDbDataCellRendererInfoPriv {
 	/* attributes valid for the while life of the object */
 	GnomeDbDataStore      *store;
 	GdaDataModelIter      *iter;
-	GdaSetGroup *group;
+	GnomeDbSetGroup       *group;
 
 	/* attribute valid only for drawing */
 	gboolean               active;
@@ -287,7 +287,7 @@
 		g_object_ref (G_OBJECT (cellinfo->priv->iter));
     		break;
 	case PROP_GROUP:
-		cellinfo->priv->group = GDA_SET_GROUP(g_value_get_pointer(value));
+		cellinfo->priv->group = GNOME_DB_SET_GROUP (g_value_get_pointer(value));
    		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -313,16 +313,16 @@
  **/
 GtkCellRenderer *
 gnome_db_data_cell_renderer_info_new (GnomeDbDataStore *store, 
-				      GdaDataModelIter *iter, GdaSetGroup *group)
+				      GdaDataModelIter *iter, GnomeDbSetGroup *group)
 {
 	GObject *obj;
 
 	g_return_val_if_fail (GNOME_DB_IS_DATA_STORE (store), NULL);
 	g_return_val_if_fail (GDA_IS_SET (iter), NULL);
-	g_return_val_if_fail (group && g_slist_find (((GdaSet *) iter)->groups_list, group), NULL);
+	g_return_val_if_fail (group, NULL);
 
 	obj = g_object_new (GNOME_DB_TYPE_DATA_CELL_RENDERER_INFO, 
-                      "store", store, "iter", iter, "group", group, NULL);
+			    "store", store, "iter", iter, "group", group, NULL);
 
 	return (GtkCellRenderer *) obj;
 }
@@ -469,7 +469,7 @@
 		gtk_tree_path_free (treepath);
 
 		/* we want the attributes */
-		if (! cellinfo->priv->group->nodes_source) {
+		if (! cellinfo->priv->group->group->nodes_source) {
 			gint col;
 			GdaDataModel *proxied_model;
 			GdaDataProxy *proxy;
@@ -477,9 +477,9 @@
 			proxy = gnome_db_data_store_get_proxy (cellinfo->priv->store);
 			proxied_model = gda_data_proxy_get_proxied_model (proxy);
 
-			g_assert (g_slist_length (cellinfo->priv->group->nodes) == 1);
+			g_assert (g_slist_length (cellinfo->priv->group->group->nodes) == 1);
 			col = g_slist_index (GDA_SET (cellinfo->priv->iter)->holders,
-					     GDA_SET_NODE (cellinfo->priv->group->nodes->data)->holder);
+					     GDA_SET_NODE (cellinfo->priv->group->group->nodes->data)->holder);
 
 			gtk_tree_model_get (GTK_TREE_MODEL (cellinfo->priv->store), &iter, 
 					    gda_data_model_get_n_columns (proxied_model) + col, 
@@ -487,9 +487,9 @@
 		}
 		else 
 			attributes = gnome_db_utility_proxy_compute_attributes_for_group (cellinfo->priv->group, 
-										 cellinfo->priv->store,
-										 cellinfo->priv->iter,
-										 &iter, NULL);
+											  cellinfo->priv->store,
+											  cellinfo->priv->iter,
+											  &iter, NULL);
 		
 		/* build the popup menu */
 		menu = gnome_db_utility_entry_build_actions_menu (G_OBJECT (cellinfo), attributes, 
diff -urN libgnomedb/libgnomedb/data-entries/gnome-db-data-cell-renderer-info.h libgnomedbnew/libgnomedb/data-entries/gnome-db-data-cell-renderer-info.h
--- libgnomedb/libgnomedb/data-entries/gnome-db-data-cell-renderer-info.h	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/data-entries/gnome-db-data-cell-renderer-info.h	2009-04-19 18:38:14.000000000 +0200
@@ -26,6 +26,7 @@
 #include <libgnomedb/gnome-db-decl.h>
 #include <libgda/gda-enums.h>
 #include <libgda/gda-decl.h>
+#include <libgnomedb/gnome-db-set.h>
 
 G_BEGIN_DECLS
 
@@ -60,7 +61,7 @@
 GType            gnome_db_data_cell_renderer_info_get_type  (void) G_GNUC_CONST;
 GtkCellRenderer *gnome_db_data_cell_renderer_info_new       (GnomeDbDataStore *store,
 							     GdaDataModelIter *iter, 
-							     GdaSetGroup *group);
+							     GnomeDbSetGroup *group);
 G_END_DECLS
 
 #endif /* __GNOME_DB_DATA_CELL_RENDERER_INFO_H__ */
diff -urN libgnomedb/libgnomedb/data-entries/gnome-db-entry-combo.c libgnomedbnew/libgnomedb/data-entries/gnome-db-entry-combo.c
--- libgnomedb/libgnomedb/data-entries/gnome-db-entry-combo.c	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/data-entries/gnome-db-entry-combo.c	2009-04-19 18:38:14.000000000 +0200
@@ -55,6 +55,9 @@
 static gboolean        gnome_db_entry_combo_expand_in_layout  (GnomeDbDataEntry *de);
 static void            gnome_db_entry_combo_grab_focus        (GnomeDbDataEntry *de);
 
+static void           _gnome_db_entry_combo_construct(GnomeDbEntryCombo* combo, 
+						      GnomeDbSet *paramlist, GnomeDbSetSource *source);
+
 /* properties */
 enum
 {
@@ -78,8 +81,8 @@
         GtkWidget              *combo_entry;
 	GSList                 *combo_nodes; /* list of ComboNode structures */
 
-	GdaSet       *paramlist;
-	GdaSetSource *source;	
+	GnomeDbSet             *paramlist; // useless?
+	GnomeDbSetSource       *source;	
 	
 	gboolean                data_valid;
 	gboolean                null_forced;
@@ -213,8 +216,8 @@
 
 /**
  * gnome_db_entry_combo_new
- * @paramlist: a #GdaSet object
- * @source: a #GdaSetSource structure, part of @paramlist
+ * @paramlist: a #GnomeDbSet object
+ * @source: a #GnomeDbSetSource structure, part of @paramlist
  *
  * Creates a new #GnomeDbEntryCombo widget. The widget is a combo box which displays a
  * selectable list of items (the items come from the 'source->data_model' data model)
@@ -225,7 +228,7 @@
  * Returns: the new widget
  */
 GtkWidget *
-gnome_db_entry_combo_new (GdaSet *paramlist, GdaSetSource *source)
+gnome_db_entry_combo_new (GnomeDbSet *paramlist, GnomeDbSetSource *source)
 {
 	GObject *obj;
 
@@ -246,7 +249,7 @@
  * TODO: This is just a work-around for language bindings. Ideally we would use construction
  * properties instead.
  */
-void _gnome_db_entry_combo_construct (GnomeDbEntryCombo* combo, GdaSet *paramlist, GdaSetSource *source)
+void _gnome_db_entry_combo_construct (GnomeDbEntryCombo* combo, GnomeDbSet *paramlist, GnomeDbSetSource *source)
 {
 	GSList *list;
 	GSList *values;
@@ -265,7 +268,7 @@
 	 * and use the values provided by the parameters to display the correct row */
 	null_possible = TRUE;
 	values = NULL;
-	list = source->nodes;
+	list = source->source->nodes;
 	while (list) {
 		ComboNode *cnode = g_new0 (ComboNode, 1);
 		
@@ -282,7 +285,7 @@
 	combo->priv->null_possible = null_possible;
 
 	/* create the combo box itself */
-	entry = gnome_db_combo_new_with_model (GDA_DATA_MODEL (source->data_model), 
+	entry = gnome_db_combo_new_with_model (GDA_DATA_MODEL (source->source->data_model), 
 					       combo->priv->source->shown_n_cols, 
 					       combo->priv->source->shown_cols_index);
 	g_signal_connect (G_OBJECT (entry), "changed",
@@ -616,7 +619,7 @@
 			GdaColumn *attrs;
 			GType type=GDA_TYPE_NULL;
 			
-			attrs = gda_data_model_describe_column (combo->priv->source->data_model, 
+			attrs = gda_data_model_describe_column (combo->priv->source->source->data_model, 
 								COMBO_NODE (nodes->data)->node->source_column);
 			arg_value = (GValue*) (argptr->data);
 			
diff -urN libgnomedb/libgnomedb/data-entries/gnome-db-entry-combo.h libgnomedbnew/libgnomedb/data-entries/gnome-db-entry-combo.h
--- libgnomedb/libgnomedb/data-entries/gnome-db-entry-combo.h	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/data-entries/gnome-db-entry-combo.h	2009-04-19 18:38:14.000000000 +0200
@@ -24,6 +24,7 @@
 #include <gtk/gtk.h>
 #include "gnome-db-entry-shell.h"
 #include <libgnomedb/gnome-db-data-entry.h>
+#include <libgnomedb/gnome-db-set.h>
 
 G_BEGIN_DECLS
 
@@ -53,7 +54,7 @@
 
 
 GType           gnome_db_entry_combo_get_type          (void) G_GNUC_CONST;
-GtkWidget      *gnome_db_entry_combo_new               (GdaSet *paramlist, GdaSetSource *source);
+GtkWidget      *gnome_db_entry_combo_new               (GnomeDbSet *paramlist, GnomeDbSetSource *source);
 
 gboolean        gnome_db_entry_combo_set_values        (GnomeDbEntryCombo *combo, GSList *values);
 GSList         *gnome_db_entry_combo_get_values        (GnomeDbEntryCombo *combo);
@@ -62,9 +63,6 @@
 GSList         *gnome_db_entry_combo_get_values_orig   (GnomeDbEntryCombo *combo);
 void            gnome_db_entry_combo_set_values_default(GnomeDbEntryCombo *combo, GSList *values);
 
-void _gnome_db_entry_combo_construct(GnomeDbEntryCombo* combo, 
-                                     GdaSet *paramlist, GdaSetSource *source);
-
 G_END_DECLS
 
 #endif


diff -urN libgnomedb/libgnomedb/data_layout.dtd libgnomedbnew/libgnomedb/data_layout.dtd
--- libgnomedb/libgnomedb/data_layout.dtd	1970-01-01 01:00:00.000000000 +0100
+++ libgnomedbnew/libgnomedb/data_layout.dtd	2009-04-19 18:38:14.000000000 +0200
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+DTD for data layout.
+TODO: Make sure that all the comments list all the attributes and their meaning.
+-->
+
+<!-- data layouts determine the order of items and sorting of the fields. There are many
+     different ways that they are grouped with the various data_layout* possibilities, but the idea is
+     the same. They all have a sequence, which tells when they are displayed. In addition, there is a column_count
+     on the grouping subnodes, which is the number of columns wide the element should be. 
+     The name of the data_layout will be either "list" or "details".-->
+
+<!ELEMENT data_layouts (data_layout_details | data_layout_list | data_layout)* >
+
+<!ELEMENT data_layout (data_layout_groups)>
+<!ATTLIST data_layout
+          name CDATA #REQUIRED
+          parent_table CDATA #IMPLIED >
+
+<!ELEMENT data_layout_groups (data_layout_group)*>
+<!ATTLIST data_layout_groups>
+
+<!-- a data_layout_group is just a the setup of fields to be shown. It encapsulates everything else. -->
+
+<!ELEMENT data_layout_group (trans_set | data_layout_group | data_layout_item | data_layout_portal |
+          data_layout_item_groupby | data_layout_button | data_layout_notebook | data_layout_item_header | 
+          trans_set | data_layout_text)* >
+<!ATTLIST data_layout_group
+          name CDATA #REQUIRED
+          title CDATA #IMPLIED
+          sequence CDATA #IMPLIED
+          columns_count CDATA #REQUIRED >
+
+<!-- a data_layout_notebook is the tabbed display of tables in the interface. -->
+
+<!ELEMENT data_layout_notebook (data_layout_group|data_layout_portal)*>
+<!ATTLIST data_layout_notebook
+          name CDATA #REQUIRED
+          columns_count CDATA #REQUIRED
+          sequence CDATA #IMPLIED
+          title CDATA #IMPLIED >
+
+<!-- a data_layout_item_groupby is a data_layout_group that sorts -->
+
+<!ELEMENT data_layout_item_groupby (trans_set | groupby | sortby | data_layout_group | data_layout_item |
+          data_layout_portal | data_layout_button | data_layout_item_groupby | secondary_fields | 
+          data_layout_item_summary | data_layout_item_verticalgroup)* >
+<!ATTLIST data_layout_item_groupby
+          name CDATA #REQUIRED
+          title CDATA #IMPLIED
+          sequence CDATA #IMPLIED
+          columns_count CDATA #REQUIRED
+          border_width CDATA #IMPLIED >
+
+<!-- data_layout_text and text are for displaying text. -->
+
+<!ELEMENT data_layout_text (text)*>
+<!ATTLIST data_layout_text
+          sequence CDATA #REQUIRED >
+
+<!ELEMENT text EMPTY>
+<!ATTLIST text
+          title CDATA #REQUIRED >
+
+<!-- sortby describes what a data_layout_item_groupby sorts by. -->
+
+<!ELEMENT sortby (data_layout_item)*>
+<!ATTLIST sortby>
+
+<!-- data_layout_item_verticalgroup is used to display a vertical group of fields. -->
+
+<!ELEMENT data_layout_item_verticalgroup (data_layout_item)*>
+<!ATTLIST data_layout_item_verticalgroup
+          name CDATA #REQUIRED
+          columns_count CDATA #REQUIRED
+          sequence CDATA #REQUIRED >
+
+<!-- data_layout_item_summary and data_layout_item_fieldsummary summarize other
+     fields. -->
+
+<!ELEMENT data_layout_item_summary (data_layout_item_fieldsummary)*>
+<!ATTLIST data_layout_item_summary
+          name CDATA #REQUIRED
+          columns_count CDATA #REQUIRED
+          sequence CDATA #IMPLIED >
+
+<!ELEMENT data_layout_item_fieldsummary (formatting)>
+<!ATTLIST data_layout_item_fieldsummary
+          name CDATA #REQUIRED
+          editable (true|false) "false"
+          use_default_formatting (true|false) "true"
+          sequence CDATA #IMPLIED
+          summarytype CDATA #REQUIRED >
+
+<!-- groupby is used to determine how data_layout_item_groupby items group. -->
+
+<!ELEMENT groupby (formatting|title_custom)*>
+<!ATTLIST groupby
+          name CDATA #REQUIRED
+          editable (true|false) "false"
+          use_default_formatting (true|false) "true"
+          relationship CDATA #IMPLIED >
+
+<!-- secondary fields are fields derived from other fields, this is a list of them. -->
+
+<!ELEMENT secondary_fields (data_layout_group)>
+<!ATTLIST secondary_fields>
+
+
+<!-- trans_set and trans are used for translating. They describe a set of alternatives
+     for different languages. -->
+
+<!ELEMENT trans_set (trans*)>
+<!ATTLIST trans_set>
+
+<!ELEMENT trans EMPTY>
+<!ATTLIST trans
+          loc CDATA #REQUIRED
+          val CDATA #REQUIRED >
+
+<!-- A data_layout_item is a single entry in the display formatting, which tells how a single
+     field is displayed. -->
+
+<!ELEMENT data_layout_item (formatting|title_custom)* >
+<!ATTLIST data_layout_item
+          name CDATA #REQUIRED
+          relationship CDATA #IMPLIED
+          group CDATA #IMPLIED
+          sequence CDATA #IMPLIED
+          editable CDATA #IMPLIED
+          use_default_formatting (true|false) "true"
+          related_relationship CDATA #IMPLIED
+          sort_ascending (true|false) "false" >
+
+<!-- a data_layout_item_header is the items that go at the very top of the database (e.g. the
+     organization name and logo). -->
+
+<!ELEMENT data_layout_item_header (data_layout_item)*>
+<!ATTLIST data_layout_item_header
+          name CDATA #REQUIRED
+          columns_count CDATA #REQUIRED
+          sequence CDATA #REQUIRED >
+
+<!-- data_layout_button is a way to have a custom script (python) control the
+     display and effect of a button in the database. -->
+
+<!ELEMENT data_layout_button (script?)>
+<!ATTLIST data_layout_button
+          title CDATA #REQUIRED
+          sequence CDATA #IMPLIED
+          script CDATA #IMPLIED >
+
+<!-- a script node is used to embed python code into the custom button. -->
+
+<!ELEMENT script ANY>
+<!ATTLIST script>
+
+<!-- a title_custom is used to give a different name next to a field than normal. -->
+
+<!ELEMENT title_custom ANY>
+<!ATTLIST title_custom
+          title CDATA #IMPLIED
+          use_custom (true|false) "true" >
+
+<!-- a data_layout_portal is the essential information, a short and quick list of values
+     that are probably of interest to others (e.g. contact information, name, etc). -->
+
+<!ELEMENT data_layout_portal ANY >
+<!ATTLIST data_layout_portal
+          name CDATA #REQUIRED
+          relationship CDATA #REQUIRED
+          sequence CDATA #REQUIRED
+          hide CDATA #IMPLIED
+          columns_count CDATA #IMPLIED >
+
+<!-- reports and data reports make short sheets of important information that
+     distill a larger database. data_report(s) is the old interface; use reports if you are
+     writing a new XML document. -->
+
+<!ELEMENT data_reports (data_report)* >
+
+<!ELEMENT data_report (data_layout_groups)>
+<!ATTLIST data_report
+          name CDATA #REQUIRED
+          title CDATA #REQUIRED >
+
+<!ELEMENT reports (report)*>
+<!ATTLIST reports>
+
+<!ELEMENT report (data_layout_groups|trans_set)*>
+<!ATTLIST report
+          name CDATA #REQUIRED
+          title CDATA #IMPLIED
+          show_table_title (true|false) "false" >
diff -urN libgnomedb/libgnomedb/gnome-db-basic-form.c libgnomedbnew/libgnomedb/gnome-db-basic-form.c
--- libgnomedb/libgnomedb/gnome-db-basic-form.c	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/gnome-db-basic-form.c	2009-04-19 18:38:14.000000000 +0200
@@ -28,6 +28,8 @@
 #include "utility.h"
 #include "gnome-db-data-entry.h"
 #include <libgnomedb/data-entries/gnome-db-entry-combo.h>
+#include <libgnomedb/gnome-db-data-widget.h>
+#include <libgnomedb/gnome-db-raw-form.h>
 
 static void gnome_db_basic_form_class_init (GnomeDbBasicFormClass * class);
 static void gnome_db_basic_form_init (GnomeDbBasicForm *wid);
@@ -48,7 +50,7 @@
 static void gnome_db_basic_form_clean (GnomeDbBasicForm *form);
 
 static void get_rid_of_set (GdaSet *paramlist, GnomeDbBasicForm *form);
-static void paramlist_public_data_changed_cb (GdaSet *paramlist, GnomeDbBasicForm *form);
+static void paramlist_public_data_changed_cb (GnomeDbSet *paramlist, GnomeDbBasicForm *form);
 static void paramlist_param_attr_changed_cb (GdaSet *paramlist, GdaHolder *param, 
 					     const gchar *att_name, const GValue *att_value, GnomeDbBasicForm *form);
 
@@ -69,6 +71,7 @@
 {
         PROP_0,
 	PROP_LAYOUT_SPEC,
+	PROP_DATA_LAYOUT,
 	PROP_PARAMLIST,
 	PROP_HEADERS_SENSITIVE,
 	PROP_SHOW_ACTIONS,
@@ -78,6 +81,7 @@
 struct _GnomeDbBasicFormPriv
 {
 	GdaSet                 *set;
+	GnomeDbSet             *set_info;
 	gulong                 *signal_ids; /* array of signal ids */
 
 	GSList                 *entries;/* list of GnomeDbDataEntry widgets */
@@ -87,6 +91,7 @@
 	GtkWidget              *entries_table;
 	GtkWidget              *entries_glade;
 	GSList                 *hidden_entries;
+	GtkScrolledWindow      *scrolled_window;  /* Window child. */
 
 	gboolean                headers_sensitive;
 	gboolean                forward_param_updates; /* forward them to the GnomeDbDataEntry widgets ? */
@@ -169,6 +174,10 @@
 					 g_param_spec_pointer ("layout_spec", 
 							       _("Pointer to a GnomeDbFormLayoutSpec structure"), NULL,
 							       G_PARAM_WRITABLE));
+	g_object_class_install_property (object_class, PROP_DATA_LAYOUT,
+					 g_param_spec_pointer ("data_layout", 
+							       _("Pointer to an XML data layout specification"), NULL,
+							       G_PARAM_WRITABLE));
 	g_object_class_install_property (object_class, PROP_PARAMLIST,
 					 g_param_spec_pointer ("paramlist", 
 							       _("List of parameters to show in the form"), NULL,
@@ -301,7 +310,7 @@
 	form->priv->signal_ids = NULL;
 
 	/* unref the paramlist */
-	g_signal_handlers_disconnect_by_func (paramlist,
+	g_signal_handlers_disconnect_by_func (form->priv->set_info,
 					      G_CALLBACK (paramlist_public_data_changed_cb), form);
 	g_signal_handlers_disconnect_by_func (paramlist,
 					      G_CALLBACK (paramlist_param_attr_changed_cb), form);
@@ -309,6 +318,11 @@
 	g_object_unref (form->priv->set);
 	form->priv->set = NULL;
 
+	if (form->priv->set_info) {
+		g_object_unref (form->priv->set_info);
+		form->priv->set_info = NULL;
+	}
+
 	/* render all the entries non sensitive */
 	list = form->priv->entries;
 	while (list) {
@@ -318,7 +332,7 @@
 }
 
 static void
-paramlist_public_data_changed_cb (GdaSet *paramlist, GnomeDbBasicForm *form)
+paramlist_public_data_changed_cb (GnomeDbSet *paramlist, GnomeDbBasicForm *form)
 {
 	/* here we want to re-define all the data entry widgets */
 	gnome_db_basic_form_clean (form);
@@ -369,14 +383,14 @@
 				hidden_params = g_slist_prepend (hidden_params, param);
 			else {
 				/* multiple parameters, take the 1st param */
-				GdaSetGroup *group;				
-				group = g_object_get_data (G_OBJECT (list->data), "group");
-				hidden_params = g_slist_prepend (hidden_params, GDA_SET_NODE (group->nodes->data)->holder);
+				GnomeDbSetGroup *group;
+				group = g_object_get_data (G_OBJECT (list->data), "__gnome_db_group");
+				hidden_params = g_slist_prepend (hidden_params, GDA_SET_NODE (group->group->nodes->data)->holder);
 			}
 		}
 
 		/* re-create entries */
-		paramlist_public_data_changed_cb (paramlist, form);
+		paramlist_public_data_changed_cb (form->priv->set_info, form);
 
 		/* hide entries which were hidden */
 		for (list = hidden_params; list; list = list->next) 
@@ -413,6 +427,759 @@
 }
 
 static void
+load_xml_data_layout_button (GnomeDbBasicForm  *form,
+			     xmlNodePtr         node,
+			     gpointer           data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (form && GNOME_DB_IS_BASIC_FORM (form));
+	g_return_if_fail (data && GTK_IS_TABLE(data));
+
+	gchar *title = NULL;
+	gchar *script = NULL;
+	gint sequence = 0;
+
+	xmlChar *str;
+	str = xmlGetProp (node, "title");
+	if (str) {
+		title = g_strdup (str);
+		g_print ("title: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "script");
+	if (str) {
+		script = g_strdup (str);
+		g_print ("script: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "sequence");
+	if (str) {
+		sequence = atoi (str);
+		g_print ("sequence: %s\n", str);
+		xmlFree (str);
+	}
+
+	GtkButton *button = (GtkButton *) gtk_button_new_with_mnemonic (title);
+	gtk_widget_show (GTK_WIDGET(button));
+
+	gint n_columns, n_rows;
+	g_object_get (G_OBJECT(data), "n-columns", &n_columns, NULL);
+	g_object_get (G_OBJECT(data), "n-rows", &n_rows, NULL);
+
+	gint col, row;
+	col = 2 * ((sequence - 1) / n_rows);
+	row = (sequence - 1) % n_rows;
+
+	gtk_table_attach (GTK_TABLE(data), GTK_WIDGET(button),
+			  col, col + 2, row, row + 1,
+			  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND),
+			  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0);
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "script")) {
+			// load_data_layout_button_script (table, child);
+		}
+	}
+}
+
+static void
+load_xml_data_layout_item (GnomeDbBasicForm  *form,
+			   xmlNodePtr         node,
+			   gpointer           data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (form && GNOME_DB_IS_BASIC_FORM (form));
+	g_return_if_fail (data && GTK_IS_TABLE(data));
+
+	gchar *name = NULL;
+	gint sequence = 0;
+	gboolean editable = FALSE;
+	gboolean sort_ascending = FALSE;
+
+	xmlChar *str;
+	str = xmlGetProp (node, "name");
+	if (str) {
+		name = g_strdup (str);
+		g_print ("name: %s\n", str);
+		xmlFree (str);
+	}
+
+	/* str = xmlGetProp (node, "relationship"); */
+	/* if (str) { */
+	/* 	g_print ("relationship: %s\n", str); */
+	/* 	xmlFree (str); */
+	/* } */
+
+	/* str = xmlGetProp (node, "related_relationship"); */
+	/* if (str) { */
+	/* 	g_print ("related_relationship: %s\n", str); */
+	/* 	xmlFree (str); */
+	/* } */
+
+	str = xmlGetProp (node, "sequence");
+	if (str) {
+		sequence = atoi (str);
+		g_print ("sequence: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "editable");
+	if (str) {
+		editable = (*str == 't' || *str == 'T') ? TRUE : FALSE;
+		g_print ("editable: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "sort_ascending");
+	if (str) {
+		sort_ascending = (*str == 't' || *str == 'T') ? TRUE : FALSE;
+		g_print ("sort_ascending: %s\n", str);
+		xmlFree (str);
+	}
+
+	/* GSList *slist = form->priv->set->holders; */
+	/* while (slist != NULL) { */
+	/* 	GdaHolder *holder = slist->data; */
+	/* 	g_print ("SET HOLDER=%s\n", gda_holder_get_id (holder)); */
+	/* 	slist = g_slist_next (slist); */
+	/* } */
+
+	gint n_columns, n_rows;
+	g_object_get (G_OBJECT(data), "n-columns", &n_columns, NULL);
+	g_object_get (G_OBJECT(data), "n-rows", &n_rows, NULL);
+
+	gint col, row;
+	col = 2 * ((sequence - 1) / n_rows);
+	row = (sequence - 1) % n_rows;
+
+	GdaHolder *holder = gda_set_get_holder (form->priv->set, name);
+	g_return_if_fail (holder != NULL);
+
+	/* const gchar *id = gda_holder_get_id (holder); */
+
+	/* const gchar *text; */
+	/* const GValue *value = gda_holder_get_attribute (holder, GDA_ATTRIBUTE_DESCRIPTION); */
+	/* if (value != NULL && G_VALUE_HOLDS(value, G_TYPE_STRING)) */
+	/* 	text = g_value_get_string (value); */
+	/* else */
+	/* 	text = id; */
+	const gchar *text = NULL;
+	if (GNOME_DB_IS_RAW_FORM (form)) {
+		GdaDataModel *model = gnome_db_data_widget_get_gda_model (GNOME_DB_DATA_WIDGET (form));
+		if (model && GDA_IS_DATA_SELECT (model))
+			text = gda_utility_data_model_find_column_description (GDA_DATA_SELECT (model), name);
+	}
+	if (! text)
+		text = gda_holder_get_id (holder);
+
+	GtkLabel *label = GTK_LABEL(gtk_label_new (text));
+	gtk_widget_show (GTK_WIDGET(label));
+	gtk_table_attach (GTK_TABLE(data), GTK_WIDGET(label),
+			  col, col + 1, row, row + 1,
+			  (GtkAttachOptions) GTK_FILL,
+			  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0);
+	gtk_misc_set_alignment (GTK_MISC(label), 0, /* 0 */ 0.5);
+
+	GtkAlignment *alignment = GTK_ALIGNMENT(gtk_alignment_new (0.5, 0.5, 1, 1));
+	gtk_widget_show (GTK_WIDGET(alignment));
+	gtk_table_attach (GTK_TABLE(data), GTK_WIDGET(alignment),
+			  col + 1, col + 2, row, row + 1,
+			  (GtkAttachOptions) (GTK_EXPAND|GTK_FILL),
+			  (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0);
+	gtk_alignment_set_padding (GTK_ALIGNMENT(alignment), 0, 0, 12, 0);
+
+	GtkHBox *hbox = GTK_HBOX(gtk_hbox_new (FALSE, /* 0 */ 6));
+	gtk_widget_show (GTK_WIDGET(hbox));
+	gtk_container_add (GTK_CONTAINER(alignment), GTK_WIDGET(hbox));
+
+	// name hbox (both name and id are equals)
+	gtk_widget_set_name (GTK_WIDGET(hbox), name);
+
+	g_free (name);
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		/* if (child->type == XML_ELEMENT_NODE && */
+		/*     !xmlStrcmp (child->name, (const xmlChar *) "formatting")) { */
+		/* } */
+
+		/* if (child->type == XML_ELEMENT_NODE && */
+		/*     !xmlStrcmp (child->name, (const xmlChar *) "title_custom")) { */
+		/* } */
+	}
+}
+
+static gint
+count_items (xmlNodePtr  node)
+{
+	gint n = 0;
+
+	g_return_val_if_fail (node->type == XML_ELEMENT_NODE &&
+			      (!xmlStrcmp (node->name, (const xmlChar *) "data_layout_group") ||
+			       !xmlStrcmp (node->name, (const xmlChar *) "data_layout_portal") ||
+			       !xmlStrcmp (node->name, (const xmlChar *) "data_layout_notebook")), -1);
+
+	if (node->children) {
+		xmlNodePtr child;
+		child = node->children;
+		while (child) {
+			if (child->type == XML_ELEMENT_NODE &&
+			    (!xmlStrcmp (child->name, (const xmlChar *) "data_layout_group") ||
+			     !xmlStrcmp (child->name, (const xmlChar *) "data_layout_item") ||
+			     !xmlStrcmp (child->name, (const xmlChar *) "data_layout_portal") ||
+			     !xmlStrcmp (node->name, (const xmlChar *) "data_layout_notebook") ||
+			     !xmlStrcmp (child->name, (const xmlChar *) "data_layout_button"))) {
+				n++;
+			}
+			child = child->next;
+		}
+	}
+
+	return n;
+}
+
+static void
+load_xml_data_layout_portal (GnomeDbBasicForm  *form,
+			     xmlNodePtr         node,
+			     gpointer           data)
+{
+	g_return_if_fail (form && GNOME_DB_IS_BASIC_FORM (form));
+
+	gchar *name = NULL;
+	gchar *relationship = NULL;
+	gint sequence = 0;
+	gboolean hidden = FALSE;
+	gint columns_count = 1;
+
+	xmlChar *str;
+	str = xmlGetProp (node, "name");
+	if (str) {
+		name = g_strdup (str);
+		g_print ("name: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "relationship");
+	if (str) {
+		relationship = g_strdup (str);
+		g_print ("relationship: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "sequence");
+	if (str) {
+		sequence = atoi (str);
+		g_print ("sequence: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "hidden");
+	if (str) {
+		hidden = *str == 't' || *str == 'T' ? TRUE : FALSE;
+		g_print ("hidden: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "columns_count");
+	if (str) {
+		columns_count = atoi (str);
+		g_print ("columns_count: %s\n", str);
+		xmlFree (str);
+	}
+
+	GtkWidget *vbox;
+	vbox = gtk_vbox_new (FALSE, 0);
+	gtk_widget_show (vbox);
+
+	gint n_columns, n_rows;
+	g_object_get (G_OBJECT(data), "n-columns", &n_columns, NULL);
+	g_object_get (G_OBJECT(data), "n-rows", &n_rows, NULL);
+
+	gint col, row;
+	col = 2 * ((sequence - 1) / n_rows);
+	row = (sequence - 1) % n_rows;
+
+	gtk_table_attach (GTK_TABLE (data), vbox,
+			  col, col + 2, row, row + 1,
+			  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND),
+			  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0);
+
+	gtk_widget_set_name (vbox, name);
+
+	if (!xmlStrcmp (node->parent->name, (const xmlChar *) "data_layout_group")) {
+
+
+		gint n_columns, n_rows;
+		g_object_get (G_OBJECT(data), "n-columns", &n_columns, NULL);
+		g_object_get (G_OBJECT(data), "n-rows", &n_rows, NULL);
+
+		gint col, row;
+		col = 2 * ((sequence - 1) / n_rows);
+		row = (sequence - 1) % n_rows;
+
+		gtk_table_attach (GTK_TABLE(data), GTK_WIDGET(vbox),
+				  col, col + 2, row, row + 1,
+				  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND),
+				  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0);
+	} else
+	if (!xmlStrcmp (node->parent->name, (const xmlChar *) "data_layout_notebook")) {
+
+		GtkLabel *label;
+		gchar *markup = g_strdup_printf ("<b>%s</b>", (name != NULL) ? name : "");
+		label = GTK_LABEL(gtk_label_new (markup));
+		g_free (markup);
+		gtk_widget_show (GTK_WIDGET(label));
+		gtk_label_set_use_markup (label, TRUE);
+
+		gtk_container_add (GTK_CONTAINER(data), GTK_WIDGET(vbox));
+
+		gtk_notebook_set_tab_label (GTK_NOTEBOOK(data),
+					    gtk_notebook_get_nth_page
+					    (GTK_NOTEBOOK(data), sequence - 1),
+					    GTK_WIDGET(label));
+	}
+
+	g_free (name);
+	g_free (relationship);
+}
+
+static void
+load_xml_data_layout_group (GnomeDbBasicForm  *form,
+			    xmlNodePtr         node,
+			    gpointer           data);
+
+static void
+load_xml_data_layout_notebook (GnomeDbBasicForm  *form,
+			       xmlNodePtr         node,
+			       gpointer           data)
+{
+	g_return_if_fail (form && GNOME_DB_IS_BASIC_FORM (form));
+
+	gchar *name = NULL;
+	gint sequence = 0;
+	gchar *title = NULL;
+
+	xmlChar *str;
+	str = xmlGetProp (node, "name");
+	if (str) {
+		g_print ("name: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "title");
+	if (str) {
+		g_print ("title: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "sequence");
+	if (str) {
+		sequence = atoi (str);
+		g_print ("sequence: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "columns_count");
+	if (str) {
+		g_print ("columns_count: %s\n", str);
+		xmlFree (str);
+	}
+
+	/* GtkLabel *label; */
+	/* gchar *markup = g_strdup_printf ("<b>%s</b>", (title != NULL) ? title : ""); */
+	/* label = GTK_LABEL(gtk_label_new (markup)); */
+	/* g_free (markup); */
+	/* gtk_widget_show (GTK_WIDGET(label)); */
+	/* gtk_label_set_use_markup (label, TRUE); */
+
+	GtkWidget *notebook;
+	notebook = gtk_notebook_new ();
+	gtk_widget_show (notebook);
+
+	gint n_columns, n_rows;
+	g_object_get (G_OBJECT(data), "n-columns", &n_columns, NULL);
+	g_object_get (G_OBJECT(data), "n-rows", &n_rows, NULL);
+
+	gint col, row;
+	col = 2 * ((sequence - 1) / n_rows);
+	row = (sequence - 1) % n_rows;
+
+	gtk_table_attach (GTK_TABLE(data), notebook,
+			  col, col + 2, row, row + 1,
+			  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND),
+			  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0);
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_group")) {
+			load_xml_data_layout_group (form, child, /* data */ notebook);
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_portal")) {
+			load_xml_data_layout_portal (form, child, /* data */ notebook);
+		}
+	}
+
+	g_free (name);
+	g_free (title);
+}
+
+static void
+load_xml_data_layout_group (GnomeDbBasicForm  *form,
+			    xmlNodePtr         node,
+			    gpointer           data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (form && GNOME_DB_IS_BASIC_FORM (form));
+	g_return_if_fail (form->priv->scrolled_window != NULL);
+
+	gchar *name = NULL;
+	gint sequence = 0;
+	gint columns_count = 1;
+	gchar *title = NULL;
+
+	xmlChar *str;
+	str = xmlGetProp (node, "name");
+	if (str) {
+		name = g_strdup (str);
+		g_print ("name: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "sequence");
+	if (str) {
+		sequence = atoi (str);
+		g_print ("sequence: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "columns_count");
+	if (str) {
+		columns_count = atoi (str);
+		g_print ("columns_count: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "title");
+	if (str) {
+		title = g_strdup (str);
+		g_print ("title: %s\n", str);
+		xmlFree (str);
+	}
+
+	GtkLabel *label;
+	label = GTK_LABEL(gtk_label_new (NULL));
+	gtk_widget_show (GTK_WIDGET(label));
+
+	gint n = count_items (node);
+
+	gint cols, rows;
+	cols = 2 * columns_count;
+	rows = n / columns_count + n % columns_count;
+
+	GtkTable *table;
+	table = GTK_TABLE(gtk_table_new (rows, cols, FALSE));
+	gtk_widget_show (GTK_WIDGET(table));
+
+	gtk_container_set_border_width (GTK_CONTAINER(table), 6);
+	gtk_table_set_row_spacings (table, 3);
+	gtk_table_set_col_spacings (table, 3);
+
+	if (!xmlStrcmp (node->parent->name, (const xmlChar *) "data_layout_groups")) {
+
+		GtkFrame *frame = GTK_FRAME(gtk_frame_new (NULL));
+		gtk_widget_show (GTK_WIDGET(frame));
+		gtk_frame_set_shadow_type (frame, GTK_SHADOW_NONE);
+
+		GtkAlignment *alignment = GTK_ALIGNMENT(gtk_alignment_new (0.5, 0.5, 1, 1));
+		gtk_widget_show (GTK_WIDGET(alignment));
+		gtk_container_add (GTK_CONTAINER(frame), GTK_WIDGET(alignment));
+		gtk_alignment_set_padding (alignment, 0, 0, 12, 0);
+
+		gtk_container_add (GTK_CONTAINER(alignment), GTK_WIDGET(table));
+
+		gchar *markup = g_strdup_printf ("<b>%s</b>", (title != NULL) ? title : "");
+		gtk_label_set_text (label, markup);
+		g_free (markup);
+		gtk_label_set_use_markup (label, TRUE);
+
+		gtk_frame_set_label_widget (frame, GTK_WIDGET(label));
+
+
+		gtk_box_pack_start (GTK_BOX(data), GTK_WIDGET(frame), FALSE, TRUE, 0);
+	} else
+	if (!xmlStrcmp (node->parent->name, (const xmlChar *) "data_layout_group")) {
+
+		GtkFrame *frame = GTK_FRAME(gtk_frame_new (NULL));
+		gtk_widget_show (GTK_WIDGET(frame));
+		gtk_frame_set_shadow_type (frame, GTK_SHADOW_NONE);
+
+		GtkAlignment *alignment = GTK_ALIGNMENT(gtk_alignment_new (0.5, 0.5, 1, 1));
+		gtk_widget_show (GTK_WIDGET(alignment));
+		gtk_container_add (GTK_CONTAINER(frame), GTK_WIDGET(alignment));
+		gtk_alignment_set_padding (alignment, 0, 0, 12, 0);
+
+		gtk_container_add (GTK_CONTAINER(alignment), GTK_WIDGET(table));
+
+		gchar *markup = g_strdup_printf ("<b>%s</b>", (title != NULL) ? title : "");
+		gtk_label_set_text (label, markup);
+		g_free (markup);
+		gtk_label_set_use_markup (label, TRUE);
+
+		gtk_frame_set_label_widget (frame, GTK_WIDGET(label));
+
+
+		gint n_columns, n_rows;
+		g_object_get (G_OBJECT(data), "n-columns", &n_columns, NULL);
+		g_object_get (G_OBJECT(data), "n-rows", &n_rows, NULL);
+
+		gint col, row;
+		col = 2 * ((sequence - 1) / n_rows);
+		row = (sequence - 1) % n_rows;
+
+		gtk_table_attach (GTK_TABLE(data), GTK_WIDGET(frame),
+				  col, col + 2, row, row + 1,
+				  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND),
+				  (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), 0, 0);
+	} else
+	if (!xmlStrcmp (node->parent->name, (const xmlChar *) "data_layout_notebook")) {
+
+		gchar *text = g_strdup ((title != NULL) ? title : "");
+		gtk_label_set_text (label, text);
+		g_free (text);
+
+		gtk_container_add (GTK_CONTAINER(data), GTK_WIDGET(table));
+
+		gtk_notebook_set_tab_label (GTK_NOTEBOOK(data),
+					    gtk_notebook_get_nth_page
+					    (GTK_NOTEBOOK(data), sequence - 1),
+					    GTK_WIDGET(label));
+	}
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_group")) {
+			load_xml_data_layout_group (form, child, /* data */ table);
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_item")) {
+			load_xml_data_layout_item (form, child, /* data */ table);
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_portal")) {
+			load_xml_data_layout_portal (form, child, /* data */ table);
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_notebook")) {
+			load_xml_data_layout_notebook (form, child, /* data */ table);
+		}
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "trans_set")) {
+			/* load_data_layout_group_trans_set (form, child, data); */
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_button")) {
+			load_xml_data_layout_button (form, child, /* data */ table);
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_item_groupby")) {
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_item_header")) {
+		}
+	}
+
+	g_free (name);
+	g_free (title);
+}
+
+static void
+load_xml_data_layout_groups (GnomeDbBasicForm  *form,
+			     xmlNodePtr         node,
+			     gpointer           data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (form && GNOME_DB_IS_BASIC_FORM (form));
+	g_return_if_fail (form->priv->scrolled_window == NULL);
+
+	form->priv->scrolled_window = GTK_SCROLLED_WINDOW
+		(gtk_scrolled_window_new (NULL, NULL));
+	gtk_scrolled_window_set_policy (form->priv->scrolled_window,
+					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_container_border_width (GTK_CONTAINER(form->priv->scrolled_window), 6);
+	gtk_widget_show (GTK_WIDGET(form->priv->scrolled_window));
+
+	GtkVBox *vbox = GTK_VBOX(gtk_vbox_new (FALSE, 0));
+	gtk_widget_show (GTK_WIDGET(vbox));
+
+	gtk_scrolled_window_add_with_viewport (form->priv->scrolled_window,
+					       (GtkWidget *) vbox);
+	/* gtk_box_pack_start (GTK_BOX(form), (GtkWidget *) form->priv->scrolled_window, */
+	/* 		    TRUE, TRUE, 0); */
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_group")) {
+			load_xml_data_layout_group (form, child, /* data */ vbox);
+		}
+	}
+
+}
+
+static void
+load_xml_data_layout (GnomeDbBasicForm  *form,
+		      xmlNodePtr         node,
+		      gpointer           data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (form && GNOME_DB_IS_BASIC_FORM (form));
+
+	gchar *parent_table = NULL;
+	gchar *name = NULL;
+
+	xmlChar *str;
+	str = xmlGetProp (node, "parent_table");
+	if (str) {
+		parent_table = g_strdup (str);
+		g_print ("parent_table: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "name");
+	if (str) {
+		name = g_strdup (str);
+		g_print ("name: %s\n", str);
+		xmlFree (str);
+	}
+
+	// Don't recurse unnecessarily
+	gboolean retval = FALSE;
+	if (strcmp ((const gchar *) data, parent_table) != 0 ||
+	    strcmp ("details", name) != 0) {
+		retval = TRUE;
+	}
+	g_free (parent_table);
+	g_free (name);
+	if (retval)
+		return;
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_groups")) {
+			load_xml_data_layout_groups (form, child, data);
+		}
+	}
+
+}
+
+static void
+load_xml_data_layouts (GnomeDbBasicForm  *form,
+		       xmlNodePtr         node,
+		       gpointer           data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (form && GNOME_DB_IS_BASIC_FORM (form));
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout")) {
+			load_xml_data_layout (form, child, data);
+		}
+	}
+}
+
+/* static void */
+/* load_xml_table (GnomeDbBasicForm  *form, */
+/* 		xmlNodePtr         node, */
+/* 		gpointer           data) */
+/* { */
+/* 	g_print ("%s:\n", __func__); */
+
+/* 	xmlChar *str; */
+/* 	str = xmlGetProp (node, "name"); */
+/* 	if (str) { */
+/* 		g_print ("name: %s\n", str); */
+/* 		xmlFree (str); */
+/* 	} */
+
+/* 	/\* str = xmlGetProp (node, "title"); *\/ */
+/* 	/\* if (str) { *\/ */
+/* 	/\* 	g_print ("title: %s\n", str); *\/ */
+/* 	/\* 	xmlFree (str); *\/ */
+/* 	/\* } *\/ */
+
+/* 	/\* str = xmlGetProp (node, "hidden"); *\/ */
+/* 	/\* if (str) { *\/ */
+/* 	/\* 	g_print ("hidden: %s\n", str); *\/ */
+/* 	/\* 	xmlFree (str); *\/ */
+/* 	/\* } *\/ */
+
+/* 	/\* str = xmlGetProp (node, "default"); *\/ */
+/* 	/\* if (str) { *\/ */
+/* 	/\* 	g_print ("default: %s\n", str); *\/ */
+/* 	/\* 	xmlFree (str); *\/ */
+/* 	/\* } *\/ */
+
+/* 	xmlNodePtr child; */
+/* 	for (child = node->children; child != NULL; child = child->next) { */
+
+/* 		/\* if (child->type == XML_ELEMENT_NODE && *\/ */
+/* 		/\*     !xmlStrcmp (child->name, (const xmlChar *) "fields")) { *\/ */
+
+/* 		/\* 	load_xml_fields (table, child, data); *\/ */
+/* 		/\* } *\/ */
+
+/* 		/\* if (child->type == XML_ELEMENT_NODE && *\/ */
+/* 		/\*     !xmlStrcmp (child->name, (const xmlChar *) "relationships")) { *\/ */
+
+/* 		/\* 	load_xml_relationships (table, child, data); *\/ */
+/* 		/\* } *\/ */
+
+/* 		if (child->type == XML_ELEMENT_NODE && */
+/* 		    !xmlStrcmp (child->name, (const xmlChar *) "data_layouts")) { */
+
+/* 			load_xml_data_layouts (form, child, data); */
+/* 		} */
+
+/* 		/\* if (child->type == XML_ELEMENT_NODE && *\/ */
+/* 		/\*     !xmlStrcmp (child->name, (const xmlChar *) "reports")) { *\/ */
+
+/* 		/\* 	load_xml_reports (table, child, data); *\/ */
+/* 		/\* } *\/ */
+
+/* 		/\* if (child->type == XML_ELEMENT_NODE && *\/ */
+/* 		/\*     !xmlStrcmp (child->name, (const xmlChar *) "trans_set")) { *\/ */
+
+/* 		/\* 	load_xml_table_trans_set (table, child, data); *\/ */
+/* 		/\* } *\/ */
+/* 	} */
+
+/* } */
+
+static void
 gnome_db_basic_form_set_property (GObject *object,
 				  guint param_id,
 				  const GValue *value,
@@ -467,6 +1234,28 @@
 			g_warning (_("Libglade support not built."));
 #endif
 			break;
+		case PROP_DATA_LAYOUT:
+			{
+				xmlNodePtr node = g_value_get_pointer (value);
+
+				gnome_db_basic_form_clean (form);
+
+				xmlNodePtr child;
+				for (child = node->children; child != NULL; child = child->next) {
+
+					if (child->type == XML_ELEMENT_NODE &&
+					    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_groups")) {
+						load_xml_data_layout_groups (form, child, NULL);
+					}
+				}
+
+				if (form->priv->scrolled_window != NULL) {
+					g_print ("Loaded XML file, reinit interface\n");
+				}
+				gnome_db_basic_form_fill (form);
+	
+			}
+			break;
 		case PROP_PARAMLIST:
 			if (form->priv->set) {
 #ifdef HAVE_LIBGLADE
@@ -516,7 +1305,9 @@
 				g_return_if_fail (GDA_IS_SET (form->priv->set));
 								
 				g_object_ref (form->priv->set);
-				g_signal_connect (form->priv->set, "public_data_changed",
+				form->priv->set_info = gnome_db_set_new (GDA_SET (form->priv->set));
+
+				g_signal_connect (form->priv->set_info, "public_data_changed",
 						  G_CALLBACK (paramlist_public_data_changed_cb), form);
 				g_signal_connect (form->priv->set, "holder-attr-changed",
 						  G_CALLBACK (paramlist_param_attr_changed_cb), form);
@@ -582,13 +1373,10 @@
 	gint i = 0;
 
 	if (form->priv->set) {
-		list = form->priv->set->holders;
-		while (list) {
+		for (i = 0, list = form->priv->set->holders; 
+		     list; 
+		     i++, list = list->next)
 			g_signal_handler_disconnect (G_OBJECT (list->data), form->priv->signal_ids[i]);
-			
-			list = g_slist_next (list);
-			i++;
-		}
 		g_free (form->priv->signal_ids);
 		form->priv->signal_ids = NULL;
 	}
@@ -616,6 +1404,11 @@
 
 	g_slist_free (form->priv->hidden_entries);
 	form->priv->hidden_entries = NULL;
+
+	if (form->priv->scrolled_window) {
+		gtk_widget_destroy (GTK_WIDGET(form->priv->scrolled_window));
+		form->priv->scrolled_window = NULL;
+	}
 }
 
 static void
@@ -634,6 +1427,23 @@
 static void entry_destroyed_cb (GtkWidget *entry, GnomeDbBasicForm *form);
 static void label_destroyed_cb (GtkWidget *label, GnomeDbBasicForm *form);
 
+static GtkCallback
+find_hbox (GtkWidget  *widget,
+	   gpointer    data)
+{
+	gpointer *d = data;
+
+	if (GTK_IS_CONTAINER(widget)) {
+		const gchar *name = gtk_widget_get_name (widget);
+		if (GTK_IS_HBOX(widget) &&
+		    strcmp (name, (gchar *) *d) == 0)
+			*(++d) = widget;
+		else
+			gtk_container_foreach (GTK_CONTAINER(widget),
+					       (GtkCallback) find_hbox, data);
+	}
+}
+
 /*
  * create the entries in the widget
  */
@@ -645,7 +1455,7 @@
 	gboolean form_expand = FALSE;
 	
 	/* parameters list management */
-	if (!form->priv->set || !form->priv->set->groups_list)
+	if (!form->priv->set || !form->priv->set_info->groups_list)
 		/* nothing to do */
 		return;
 
@@ -654,13 +1464,12 @@
 	i = 0;
 
 	/* creating all the data entries, and putting them into the form->priv->entries list */
-	list = form->priv->set->groups_list;
-	while (list) {
-		GdaSetGroup *group;
+	for (list = form->priv->set_info->groups_list; list; list = list->next) {
+		GnomeDbSetGroup *group;
 		GtkWidget *entry = NULL;
 
-		group = GDA_SET_GROUP (list->data);
-		if (! group->nodes_source) { 
+		group = GNOME_DB_SET_GROUP (list->data);
+		if (! group->group->nodes_source) { 
 			/* there is only one non-constrained parameter */
 			GdaHolder *param;
 			GType type;
@@ -669,9 +1478,9 @@
 			const gchar *plugin = NULL;
 			const GValue *plugin_val;
 
-			g_assert (g_slist_length (group->nodes) == 1);
+			g_assert (g_slist_length (group->group->nodes) == 1);
 
-			param = GDA_HOLDER (GDA_SET_NODE (group->nodes->data)->holder);
+			param = GDA_HOLDER (GDA_SET_NODE (group->group->nodes->data)->holder);
 
 			val = gda_holder_get_value (param);
 			default_val = gda_holder_get_default_value (param);
@@ -730,14 +1539,14 @@
 			GSList *plist;
 			gboolean nnul = TRUE;
 
-			entry = gnome_db_entry_combo_new (form->priv->set, group->nodes_source);
-			g_object_set_data (G_OBJECT (entry), "group", group);
+			entry = gnome_db_entry_combo_new (form->priv->set_info, group->source);
+			g_object_set_data (G_OBJECT (entry), "__gnome_db_group", group);
 			g_object_set_data (G_OBJECT (entry), "form", form);
 			form->priv->entries = g_slist_append (form->priv->entries, entry);
 			g_signal_connect (entry, "destroy", G_CALLBACK (entry_destroyed_cb), form);
 
 			/* connect to the parameter's changes */
-			for (plist = group->nodes; plist; plist = plist->next) {
+			for (plist = group->group->nodes; plist; plist = plist->next) {
 				GdaHolder *param;
 
 				param = GDA_SET_NODE (plist->data)->holder;
@@ -758,7 +1567,6 @@
 				  G_CALLBACK (entry_contents_modified), form);
 		g_signal_connect (G_OBJECT (entry), "contents_activated",
 				  G_CALLBACK (entry_contents_activated), form);
-		list = g_slist_next (list);
 	}
 
 
@@ -814,11 +1622,58 @@
 	}
 #endif
 
+	if (form->priv->scrolled_window != NULL) {
+
+		gtk_box_pack_start (GTK_BOX(form),
+				    (GtkWidget *) form->priv->scrolled_window,
+				    TRUE, TRUE, 0);
+
+		GSList *holders = form->priv->set->holders;
+		GSList *entries = form->priv->entries;
+		while (holders && entries) {
+			GdaHolder *holder = holders->data;
+			GnomeDbDataEntry *entry = entries->data;
+
+			const gchar *id = gda_holder_get_id (holder);
+
+			gpointer d[2];
+			d[0] = (gchar *) id;
+			d[1] = NULL;
+
+			gtk_container_foreach (GTK_CONTAINER(form->priv->scrolled_window),
+					       (GtkCallback) find_hbox, d);
+
+			GtkHBox *hbox = d[1];
+			g_print ("Hbox for: %s -- %p\n", id, hbox);
+
+			if (hbox != NULL) {
+				gboolean expand = gnome_db_data_entry_expand_in_layout
+					(GNOME_DB_DATA_ENTRY (entry));
+				form_expand = form_expand || expand;
+
+				gtk_box_pack_start (GTK_BOX(hbox), GTK_WIDGET(entry),
+						    expand, TRUE, 0);
+				gtk_widget_show (GTK_WIDGET(entry));
+
+				if (!g_object_get_data (G_OBJECT(hbox), "show_actions"))
+					gnome_db_data_entry_set_attributes
+						(GNOME_DB_DATA_ENTRY(entry),
+						 0, GDA_VALUE_ATTR_ACTIONS_SHOWN);
+			}
+
+			holders = g_slist_next (holders);
+			entries = g_slist_next (entries);
+		}
+
+		g_assert (holders == NULL && entries == NULL);
+		gtk_widget_show (GTK_WIDGET(form->priv->scrolled_window));
+	}
+
 	/* 
 	 * There is no layout spec (or the provided one could not be used),
 	 * so use the default tables arrangment
 	 */
-	if (!form->priv->layout_spec) {
+	if (!form->priv->layout_spec && form->priv->scrolled_window == NULL) {
 		GtkWidget *table, *label;
 
 		/* creating a table for all the entries */
@@ -878,10 +1733,10 @@
 				GtkWidget *evbox;
 				gboolean nullok = TRUE;
 				GSList *params;
-				GdaSetGroup *group;
+				GnomeDbSetGroup *group;
 
-				group = g_object_get_data (G_OBJECT (list->data), "group");
-				for (params = group->nodes; params; params = params->next) {
+				group = g_object_get_data (G_OBJECT (list->data), "__gnome_db_group");
+				for (params = group->group->nodes; params; params = params->next) {
 					if (nullok && gda_holder_get_not_null (GDA_SET_NODE (params->data)->holder))
 						nullok = FALSE;
 					if (!title)
@@ -890,7 +1745,7 @@
 				}
 				
 				if (!title) {
-					str = g_object_get_data (G_OBJECT (group->nodes_source->data_model), 
+					str = g_object_get_data (G_OBJECT (group->group->nodes_source->data_model), 
 								 "name");
 					if (str)
 						title = g_strdup (str);
@@ -913,7 +1768,7 @@
 				gtk_widget_show (label);
 				entry_label = evbox;
 				
-				title = g_object_get_data (G_OBJECT (group->nodes_source->data_model), "descr");
+				title = g_object_get_data (G_OBJECT (group->group->nodes_source->data_model), "descr");
 				if (title && *title)
 					gtk_tooltips_set_tip (form->priv->tooltips, evbox, title, NULL);
 			}
@@ -1044,15 +1899,14 @@
 	else { /* multiple parameters */
 		GSList *params;
 		GSList *values, *list;
-		GdaSetGroup *group;
+		GnomeDbSetGroup *group;
 
-		group = g_object_get_data (G_OBJECT (entry), "group");
-		params = group->nodes;
+		group = g_object_get_data (G_OBJECT (entry), "__gnome_db_group");
+		params = group->group->nodes;
 		values = gnome_db_entry_combo_get_values (GNOME_DB_ENTRY_COMBO (entry));
 		g_assert (g_slist_length (params) == g_slist_length (values));
 
-		list = values;
-		while (list) {
+		for (list = values; list; list = list->next, params = params->next) {
 			/* REM: if there is more than one value in 'params', then a 
 			 * signal is emitted for each param that is changed, 
 			 * and there is no way for the listener of that signal to know if it
@@ -1080,9 +1934,6 @@
 			else
 				TO_IMPLEMENT;
 			form->priv->forward_param_updates = TRUE;
-
-			list = g_slist_next (list);
-			params = g_slist_next (params);
 		}
 		g_slist_free (values);
 
@@ -1127,7 +1978,7 @@
 parameter_changed_cb (GdaHolder *param, GnomeDbDataEntry *entry)
 {
 	GnomeDbBasicForm *form = g_object_get_data (G_OBJECT (entry), "form");
-	GdaSetGroup *group = g_object_get_data (G_OBJECT (entry), "group");
+	GnomeDbSetGroup *group = g_object_get_data (G_OBJECT (entry), "__gnome_db_group");
 	const GValue *value = gda_holder_get_value (param);
 
 	if (form->priv->forward_param_updates) {
@@ -1150,7 +2001,7 @@
 		}
 		if (group) {
 			GSList *values = NULL;
-			GSList *list = group->nodes;
+			GSList *list = group->group->nodes;
 			gboolean allnull = TRUE;
 
 			while (list) {
@@ -1228,14 +2079,14 @@
 	g_return_if_fail (form->priv);
 
 	for (list = form->priv->entries; list; list = list->next) {
-		GdaSetGroup *group;
+		GnomeDbSetGroup *group;
 
-		group = g_object_get_data (G_OBJECT (list->data), "group");
+		group = g_object_get_data (G_OBJECT (list->data), "__gnome_db_group");
 
 		if (group) {
 			/* Combo entry */
 			GSList *values = NULL;
-			GSList *params = group->nodes;
+			GSList *params = group->group->nodes;
 			gboolean allnull = TRUE;
 			
 			while (params) {
@@ -1601,10 +2452,10 @@
 		else {
 			/* multiple parameters */
 			GSList *params;
-			GdaSetGroup *group;
+			GnomeDbSetGroup *group;
 
-			group = g_object_get_data (G_OBJECT (entries->data), "group");
-			for (params = group->nodes; params; params = params->next) {
+			group = g_object_get_data (G_OBJECT (entries->data), "__gnome_db_group");
+			for (params = group->group->nodes; params; params = params->next) {
 				if (GDA_SET_NODE (params->data)->holder == (gpointer) param) {
 					entry = GTK_WIDGET (entries->data);
 					break;
diff -urN libgnomedb/libgnomedb/gnome-db-data-widget.c libgnomedbnew/libgnomedb/gnome-db-data-widget.c
--- libgnomedb/libgnomedb/gnome-db-data-widget.c	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/gnome-db-data-widget.c	2009-04-19 18:38:14.000000000 +0200
@@ -373,3 +373,19 @@
 	else 
 		return GNOME_DB_DATA_WIDGET_WRITE_ON_DEMAND;
 }
+
+/**
+ * gnome_db_data_widget_set_data_layout
+ * @iface: an object which implements the #GnomeDbDataWidget interface
+ * @string: xml string
+ *
+ * Sets a data layout according an XML string in the @iface widget .
+ */
+void 
+gnome_db_data_widget_set_data_layout (GnomeDbDataWidget *iface, const gpointer data)
+{
+	g_return_if_fail (GNOME_DB_IS_DATA_WIDGET (iface));
+
+	if (GNOME_DB_DATA_WIDGET_GET_IFACE (iface)->set_data_layout)
+		(GNOME_DB_DATA_WIDGET_GET_IFACE (iface)->set_data_layout) (iface, data);	
+}
diff -urN libgnomedb/libgnomedb/gnome-db-data-widget.h libgnomedbnew/libgnomedb/gnome-db-data-widget.h
--- libgnomedb/libgnomedb/gnome-db-data-widget.h	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/gnome-db-data-widget.h	2009-04-19 18:38:14.000000000 +0200
@@ -59,6 +59,7 @@
 	void                 (* set_gda_model)       (GnomeDbDataWidget *iface, GdaDataModel *model);
 	gboolean             (* set_write_mode)      (GnomeDbDataWidget *iface, GnomeDbDataWidgetWriteMode mode);
 	GnomeDbDataWidgetWriteMode (* get_write_mode)(GnomeDbDataWidget *iface);
+	void                 (* set_data_layout)     (GnomeDbDataWidget *iface, const gpointer data);
 
 	/* signals */
 	void                 (* proxy_changed)       (GnomeDbDataWidget *iface, GdaDataProxy *proxy);
@@ -84,6 +85,8 @@
 gboolean          gnome_db_data_widget_set_write_mode            (GnomeDbDataWidget *iface, GnomeDbDataWidgetWriteMode mode);
 GnomeDbDataWidgetWriteMode gnome_db_data_widget_get_write_mode   (GnomeDbDataWidget *iface);
 
+void              gnome_db_data_widget_set_data_layout           (GnomeDbDataWidget *iface, const gpointer data);
+
 G_END_DECLS
 
 #endif
diff -urN libgnomedb/libgnomedb/gnome-db-raw-form.c libgnomedbnew/libgnomedb/gnome-db-raw-form.c
--- libgnomedb/libgnomedb/gnome-db-raw-form.c	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/gnome-db-raw-form.c	2009-04-19 18:38:14.000000000 +0200
@@ -62,6 +62,7 @@
 static void            gnome_db_raw_form_widget_set_gda_model (GnomeDbDataWidget *iface, GdaDataModel *model);
 static gboolean        gnome_db_raw_form_widget_set_write_mode (GnomeDbDataWidget *iface, GnomeDbDataWidgetWriteMode mode);
 static GnomeDbDataWidgetWriteMode gnome_db_raw_form_widget_get_write_mode (GnomeDbDataWidget *iface);
+static void gnome_db_raw_form_set_data_layout (GnomeDbDataWidget  *iface, gpointer  data);
 
 struct _GnomeDbRawFormPriv
 {
@@ -134,6 +135,7 @@
 	iface->set_gda_model = gnome_db_raw_form_widget_set_gda_model;
 	iface->set_write_mode = gnome_db_raw_form_widget_set_write_mode;
 	iface->get_write_mode = gnome_db_raw_form_widget_get_write_mode;
+	iface->set_data_layout = gnome_db_raw_form_set_data_layout;
 }
 
 static void
@@ -1022,3 +1024,15 @@
 
 	return form->priv->write_mode;
 }
+
+static void
+gnome_db_raw_form_set_data_layout (GnomeDbDataWidget  *iface, gpointer  data)
+{
+	GnomeDbRawForm *raw_form;
+	
+	g_return_if_fail (GNOME_DB_IS_RAW_FORM (iface));
+	raw_form = GNOME_DB_RAW_FORM (iface);
+	g_return_if_fail (raw_form->priv);
+
+	g_object_set (G_OBJECT (raw_form), "data_layout", data, NULL);
+}
diff -urN libgnomedb/libgnomedb/gnome-db-raw-grid.c libgnomedbnew/libgnomedb/gnome-db-raw-grid.c
--- libgnomedb/libgnomedb/gnome-db-raw-grid.c	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/gnome-db-raw-grid.c	2009-04-19 18:38:14.000000000 +0200
@@ -1,6 +1,6 @@
 /* gnome-db-raw-grid.c
  *
- * Copyright (C) 2002 - 2008 Vivien Malerba
+ * Copyright (C) 2002 - 2009 Vivien Malerba
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -50,7 +50,7 @@
 static void proxy_sample_changed_cb (GdaDataProxy *proxy, gint sample_start, gint sample_end, GnomeDbRawGrid *grid);
 static void proxy_row_updated_cb (GdaDataProxy *proxy, gint proxy_row, GnomeDbRawGrid *grid);
 static void proxy_reset_cb (GdaDataProxy *proxy, GnomeDbRawGrid *grid);
-static void paramlist_public_data_changed_cb (GdaSet *paramlist, GnomeDbRawGrid *grid);
+static void paramlist_public_data_changed_cb (GnomeDbSet *paramlist, GnomeDbRawGrid *grid);
 static void paramlist_param_attr_changed_cb (GdaSet *paramlist, GdaHolder *param, 
 					     const gchar *att_name, const GValue *att_value, GnomeDbRawGrid *grid);
 static GError *iter_validate_set_cb (GdaDataModelIter *iter, GnomeDbRawGrid *grid);
@@ -69,28 +69,33 @@
 static void            gnome_db_raw_grid_widget_set_gda_model             (GnomeDbDataWidget *iface, GdaDataModel *model);
 static gboolean        gnome_db_raw_grid_widget_set_write_mode (GnomeDbDataWidget *iface, GnomeDbDataWidgetWriteMode mode);
 static GnomeDbDataWidgetWriteMode gnome_db_raw_grid_widget_get_write_mode (GnomeDbDataWidget *iface);
+static void            gnome_db_raw_grid_set_data_layout (GnomeDbDataWidget  *iface, gpointer  data);
 
 typedef struct {
-	GdaSetGroup     *group;
+	GnomeDbSetGroup *group;
 	GtkCellRenderer *data_cell;
 	GtkCellRenderer *info_cell;
 	gboolean         info_shown;
 	gboolean         data_locked; /* TRUE if no modification allowed on that column */
+        gchar           *tooltip_text;
 } ColumnData;
 
 #define COLUMN_DATA(x) ((ColumnData *)(x))
 
-static ColumnData *get_column_data (GnomeDbRawGrid *grid, GdaSetGroup *group);
+static ColumnData *get_column_data (GnomeDbRawGrid *grid, GnomeDbSetGroup *group);
 
 struct _GnomeDbRawGridPriv
 {
 	GdaDataModel               *data_model;  /* data model provided by set_model() */
 	GdaDataModelIter           *iter;        /* iterator for @store, used for its structure */
+	GnomeDbSet                 *iter_info;
 	GnomeDbDataStore           *store;       /* GtkTreeModel interface, using @proxy */
 	GdaDataProxy               *proxy;       /* proxy data model, proxying @data_model */
 
 	GSList                     *columns_data; /* list of ColumnData */
 
+	GSList                     *reordered_indexes;  /* Indexes of the reordered columns. */
+
 	gboolean                    default_show_info_cell;
 	gboolean                    default_show_global_actions;
 
@@ -123,6 +128,7 @@
 {
         PROP_0,
 	PROP_MODEL,
+	PROP_DATA_LAYOUT,
 	PROP_INFO_CELL_VISIBLE,
 	PROP_GLOBAL_ACTIONS_VISIBLE
 };
@@ -215,6 +221,7 @@
 	iface->set_gda_model = gnome_db_raw_grid_widget_set_gda_model;
 	iface->set_write_mode = gnome_db_raw_grid_widget_set_write_mode;
 	iface->get_write_mode = gnome_db_raw_grid_widget_get_write_mode;	
+	iface->set_data_layout = gnome_db_raw_grid_set_data_layout;
 }
 
 static void
@@ -256,6 +263,11 @@
 	g_object_class_install_property (object_class, PROP_MODEL,
                                          g_param_spec_object ("model", _("Data to display"), NULL, GDA_TYPE_DATA_MODEL,
 							      G_PARAM_READABLE | G_PARAM_WRITABLE));
+	
+	g_object_class_install_property (object_class, PROP_DATA_LAYOUT,
+					 g_param_spec_pointer ("data_layout", 
+							       _("Pointer to an XML data layout specification"), NULL,
+							       G_PARAM_WRITABLE));
 	g_object_class_install_property (object_class, PROP_INFO_CELL_VISIBLE,
                                          g_param_spec_boolean ("info_cell_visible", NULL, _("Info cell visible"), FALSE,
                                                                G_PARAM_READABLE | G_PARAM_WRITABLE));
@@ -358,6 +370,340 @@
 }
 
 static void
+load_xml_data_layout_item (GnomeDbRawGrid  *grid,
+			   xmlNodePtr       node,
+			   gpointer         data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (grid && GNOME_DB_IS_RAW_GRID (grid));
+
+	gchar *name = NULL;
+	gint sequence = 0;
+	gboolean editable = FALSE;
+	gboolean sort_ascending = FALSE;
+
+	xmlChar *str;
+	str = xmlGetProp (node, "name");
+	if (str) {
+		name = g_strdup (str);
+		g_print ("name: %s\n", str);
+		xmlFree (str);
+	}
+
+	/* str = xmlGetProp (node, "relationship"); */
+	/* if (str) { */
+	/* 	g_print ("relationship: %s\n", str); */
+	/* 	xmlFree (str); */
+	/* } */
+
+	/* str = xmlGetProp (node, "related_relationship"); */
+	/* if (str) { */
+	/* 	g_print ("related_relationship: %s\n", str); */
+	/* 	xmlFree (str); */
+	/* } */
+
+	str = xmlGetProp (node, "sequence");
+	if (str) {
+		sequence = atoi (str);
+		g_print ("sequence: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "editable");
+	if (str) {
+		editable = (*str == 't' || *str == 'T') ? TRUE : FALSE;
+		g_print ("editable: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "sort_ascending");
+	if (str) {
+		sort_ascending = (*str == 't' || *str == 'T') ? TRUE : FALSE;
+		g_print ("sort_ascending: %s\n", str);
+		xmlFree (str);
+	}
+
+	/* GSList *slist = grid->priv->set->holders; */
+	/* while (slist != NULL) { */
+	/* 	GdaHolder *holder = slist->data; */
+	/* 	g_print ("SET HOLDER=%s\n", gda_holder_get_id (holder)); */
+	/* 	slist = g_slist_next (slist); */
+	/* } */
+
+	//GdaHolder *holder = gda_set_get_holder (grid->priv->set, name);
+	GdaHolder *holder = gda_set_get_holder (GDA_SET (grid->priv->iter), name);
+	g_return_if_fail (holder != NULL);
+
+	gint index = g_slist_index (GDA_SET (grid->priv->iter)->holders, holder);
+
+	grid->priv->reordered_indexes = g_slist_insert (grid->priv->reordered_indexes,
+						     GINT_TO_POINTER(index),
+						     sequence - 1);
+
+        GnomeDbSetGroup *group = _gnome_db_set_get_group (grid->priv->iter_info, holder);
+        if (!group)
+		return;
+
+        ColumnData *column_data = get_column_data (grid, group);
+        g_return_if_fail (column_data);
+
+        column_data->tooltip_text = g_strdup ((const gchar *) data);
+        //g_print ("*** %s\n", column_data->tooltip_text);
+
+	gint position = g_slist_index (GDA_SET (grid->priv->iter)->holders, holder);
+	GtkTreeViewColumn *column = gtk_tree_view_get_column (GTK_TREE_VIEW (grid), position);
+	g_return_if_fail (column != NULL);
+
+	// ((GdaDataSelect *) model)->prep_stmt
+	GdaDataModel *model = grid->priv->data_model;
+
+	const gchar *text = NULL;
+	if (GDA_IS_DATA_SELECT (model))
+		text = gda_utility_data_model_find_column_description (GDA_DATA_SELECT (model), name);
+	if (!text)
+		text = gda_holder_get_id (holder);
+
+	gtk_tree_view_column_set_title (column, text);
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		/* if (child->type == XML_ELEMENT_NODE && */
+		/*     !xmlStrcmp (child->name, (const xmlChar *) "formatting")) { */
+		/* } */
+
+		/* if (child->type == XML_ELEMENT_NODE && */
+		/*     !xmlStrcmp (child->name, (const xmlChar *) "title_custom")) { */
+		/* } */
+	}
+
+}
+
+static void
+load_xml_data_layout_group (GnomeDbRawGrid  *grid,
+			    xmlNodePtr       node,
+			    gpointer         data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (grid && GNOME_DB_IS_RAW_GRID (grid));
+
+	gchar *name = NULL;
+	gint sequence = 0;
+	gint columns_count = 1;
+	gchar *title = NULL;
+
+	xmlChar *str;
+	str = xmlGetProp (node, "name");
+	if (str) {
+		name = g_strdup (str);
+		g_print ("name: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "sequence");
+	if (str) {
+		sequence = atoi (str);
+		g_print ("sequence: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "columns_count");
+	if (str) {
+		columns_count = atoi (str);
+		g_print ("columns_count: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "title");
+	if (str) {
+		title = g_strdup (str);
+		g_print ("title: %s\n", str);
+		xmlFree (str);
+	}
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_group")) {
+			load_xml_data_layout_group (grid, child, data);
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_item")) {
+			load_xml_data_layout_item (grid, child, /* data *//* table */ title);
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_portal")) {
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_notebook")) {
+		}
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "trans_set")) {
+			/* load_xml_trans_set (grid, child, data); */
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_button")) {
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_item_groupby")) {
+		}
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_item_header")) {
+		}
+	}
+
+	g_free (name);
+	g_free (title);
+}
+
+static void
+load_xml_data_layout_groups (GnomeDbRawGrid  *grid,
+			     xmlNodePtr       node,
+			     gpointer         data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (grid && GNOME_DB_IS_RAW_GRID (grid));
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_group")) {
+			load_xml_data_layout_group (grid, child, /* data */ NULL);
+		}
+	}
+
+}
+
+static void
+load_xml_data_layout (GnomeDbRawGrid  *grid,
+		      xmlNodePtr       node,
+		      gpointer         data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (grid && GNOME_DB_IS_RAW_GRID (grid));
+
+	gchar *parent_table = NULL;
+	gchar *name = NULL;
+
+	xmlChar *str;
+	str = xmlGetProp (node, "parent_table");
+	if (str) {
+		parent_table = g_strdup (str);
+		g_print ("parent_table: %s\n", str);
+		xmlFree (str);
+	}
+
+	str = xmlGetProp (node, "name");
+	if (str) {
+		name = g_strdup (str);
+		g_print ("name: %s\n", str);
+		xmlFree (str);
+	}
+
+	// Don't recurse unnecessarily
+	gboolean retval = FALSE;
+	if (strcmp ((const gchar *) data, parent_table) != 0 ||
+	    strcmp ("list", name) != 0) {
+		retval = TRUE;
+	}
+	g_free (parent_table);
+	g_free (name);
+	if (retval)
+		return;
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_groups")) {
+			load_xml_data_layout_groups (grid, child, data);
+		}
+	}
+
+}
+
+static void
+load_xml_data_layouts (GnomeDbRawGrid  *grid,
+		       xmlNodePtr       node,
+		       gpointer         data)
+{
+	g_print ("%s:\n", __func__);
+	g_return_if_fail (grid && GNOME_DB_IS_RAW_GRID (grid));
+
+	xmlNodePtr child;
+	for (child = node->children; child != NULL; child = child->next) {
+
+		if (child->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (child->name, (const xmlChar *) "data_layout")) {
+			load_xml_data_layout (grid, child, data);
+		}
+
+	}
+
+}
+
+static gboolean
+gnome_db_raw_grid_query_tooltip (GtkWidget   *widget,
+				 gint         x,
+				 gint         y,
+				 gboolean     keyboard_tip,
+				 GtkTooltip  *tooltip,
+				 gpointer     data)
+{
+	GtkTreeView *tree_view = GTK_TREE_VIEW(widget);
+
+	if (!gtk_tree_view_get_tooltip_context (tree_view, &x, &y,
+						keyboard_tip,
+						NULL, NULL, NULL))
+		return FALSE;
+
+	gint position = 0;
+	guint col_x = 0;
+	GList *columns = gtk_tree_view_get_columns (tree_view), *list = columns;
+	while (list != NULL) {
+		GtkTreeViewColumn *column = list->data;
+		if (x >= col_x && x < (col_x + column->width)) {
+			break;
+		} else
+			col_x += column->width;
+		++position;
+		list = g_list_next (list);
+	}
+	if (list == NULL)
+		return FALSE;
+
+	GnomeDbRawGrid *grid = GNOME_DB_RAW_GRID(tree_view);
+	ColumnData *column_data = (ColumnData *)
+		(g_slist_nth (grid->priv->columns_data, position)->data);
+	g_return_val_if_fail (column_data, FALSE);
+
+	g_list_free (columns);
+
+	if (column_data->tooltip_text == NULL)
+		return FALSE;
+
+	gchar *markup = g_strdup_printf ("<i>%s</i> <b>%s</b>",
+					 _("Group:"), column_data->tooltip_text);
+	gtk_tooltip_set_markup (tooltip, markup);
+	g_free (markup);
+        /* GSList *slist = grid->priv->columns_data; */
+        /* while (slist) { */
+        /*         g_print ("--- %s\n", COLUMN_DATA (slist->data)->tooltip_text); */
+        /*         slist = g_slist_next (slist); */
+        /* } */
+
+	return TRUE;
+}
+
+static void
 gnome_db_raw_grid_set_property (GObject *object,
 				guint param_id,
 				const GValue *value,
@@ -368,64 +714,130 @@
         grid = GNOME_DB_RAW_GRID (object);
         if (grid->priv) {
                 switch (param_id) {
-		case PROP_MODEL:
-			{
-				GdaDataModel *model = GDA_DATA_MODEL (g_value_get_object (value));
-				if (model)
-					g_return_if_fail (GDA_IS_DATA_MODEL (model));
-	
-				gnome_db_raw_grid_clean (grid);
-				if (!model)
-					return;
-	
-				grid->priv->store = GNOME_DB_DATA_STORE (gnome_db_data_store_new (model));
-				grid->priv->proxy = gnome_db_data_store_get_proxy (grid->priv->store);
-				grid->priv->data_model = gda_data_proxy_get_proxied_model (grid->priv->proxy);
-				
-				g_object_ref (G_OBJECT (grid->priv->proxy));
-				g_signal_connect (grid->priv->proxy, "sample_changed",
-						  G_CALLBACK (proxy_sample_changed_cb), grid);
-				g_signal_connect (grid->priv->proxy, "row_updated",
-						  G_CALLBACK (proxy_row_updated_cb), grid);
-				g_signal_connect (grid->priv->proxy, "reset",
-						  G_CALLBACK (proxy_reset_cb), grid);
+		case PROP_MODEL: {
+			GdaDataModel *model = GDA_DATA_MODEL (g_value_get_object (value));
+			if (model)
+				g_return_if_fail (GDA_IS_DATA_MODEL (model));
+			
+			gnome_db_raw_grid_clean (grid);
+			if (!model)
+				return;
+			
+			grid->priv->store = GNOME_DB_DATA_STORE (gnome_db_data_store_new (model));
+			grid->priv->proxy = gnome_db_data_store_get_proxy (grid->priv->store);
+			grid->priv->data_model = gda_data_proxy_get_proxied_model (grid->priv->proxy);
+			
+			g_object_ref (G_OBJECT (grid->priv->proxy));
+			g_signal_connect (grid->priv->proxy, "sample_changed",
+					  G_CALLBACK (proxy_sample_changed_cb), grid);
+			g_signal_connect (grid->priv->proxy, "row_updated",
+					  G_CALLBACK (proxy_row_updated_cb), grid);
+			g_signal_connect (grid->priv->proxy, "reset",
+					  G_CALLBACK (proxy_reset_cb), grid);
 				
-				grid->priv->iter = gda_data_model_create_iter (GDA_DATA_MODEL (grid->priv->proxy));
+			grid->priv->iter = gda_data_model_create_iter (GDA_DATA_MODEL (grid->priv->proxy));
+			grid->priv->iter_info = gnome_db_set_new (GDA_SET (grid->priv->iter));
 				
-				g_signal_connect (grid->priv->iter, "public_data_changed",
-						  G_CALLBACK (paramlist_public_data_changed_cb), grid);
-				g_signal_connect (grid->priv->iter, "holder-attr-changed",
-						  G_CALLBACK (paramlist_param_attr_changed_cb), grid);
-
-				g_signal_connect (grid->priv->iter, "row_changed",
-						  G_CALLBACK (iter_row_changed_cb), grid);
-				g_signal_connect (grid->priv->iter, "validate-set",
-						  G_CALLBACK (iter_validate_set_cb), grid);
+			g_signal_connect (grid->priv->iter_info, "public_data_changed",
+					  G_CALLBACK (paramlist_public_data_changed_cb), grid);
+			g_signal_connect (grid->priv->iter, "holder-attr-changed",
+					  G_CALLBACK (paramlist_param_attr_changed_cb), grid);
+
+			g_signal_connect (grid->priv->iter, "row_changed",
+					  G_CALLBACK (iter_row_changed_cb), grid);
+			g_signal_connect (grid->priv->iter, "validate-set",
+					  G_CALLBACK (iter_validate_set_cb), grid);
 
-				gda_data_model_iter_invalidate_contents (grid->priv->iter);
+			gda_data_model_iter_invalidate_contents (grid->priv->iter);
 							
-				gtk_tree_view_set_model ((GtkTreeView *) grid, GTK_TREE_MODEL (grid->priv->store));
-				init_tree_view (grid);
+			gtk_tree_view_set_model ((GtkTreeView *) grid, GTK_TREE_MODEL (grid->priv->store));
+			init_tree_view (grid);
 	
-				g_signal_emit_by_name (object, "proxy_changed", grid->priv->proxy);
-				g_signal_emit_by_name (object, "iter_changed", grid->priv->iter);
+			g_signal_emit_by_name (object, "proxy_changed", grid->priv->proxy);
+			g_signal_emit_by_name (object, "iter_changed", grid->priv->iter);
 				
-				break;
-			}
+			break;
+		}
 				
-		case PROP_INFO_CELL_VISIBLE: 
-			{
-				GSList *list = grid->priv->columns_data;
-				gboolean show = g_value_get_boolean (value);
-				grid->priv->default_show_info_cell = show;
-	
-				while (list) {
-					COLUMN_DATA (list->data)->info_shown = show;
-					g_object_set (G_OBJECT (COLUMN_DATA (list->data)->info_cell), "visible", 
-						      show, NULL);
-					list = g_slist_next (list);
+		case PROP_DATA_LAYOUT: {
+			xmlNodePtr node = g_value_get_pointer (value);
+
+			xmlNodePtr child;
+			for (child = node->children; child != NULL; child = child->next) {
+
+				if (child->type == XML_ELEMENT_NODE &&
+				    !xmlStrcmp (child->name, (const xmlChar *) "data_layout_groups")) {
+					load_xml_data_layout_groups (grid, child, NULL);
+				}
+			}
+
+			if (grid->priv->reordered_indexes != NULL) {
+				g_print ("Loaded XML file, reinit interface\n");
+
+				GList *columns = gtk_tree_view_get_columns (GTK_TREE_VIEW(grid));
+
+				GtkTreeViewColumn *prev_column = NULL;
+				GSList *columns_data = NULL;
+
+				GSList *reordered_indexes = grid->priv->reordered_indexes;
+				while (reordered_indexes != NULL) {
+					gint position = GPOINTER_TO_INT(reordered_indexes->data);
+
+					GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN
+						(g_list_nth (columns, position)->data);
+
+					gtk_tree_view_move_column_after (GTK_TREE_VIEW(grid),
+									 column, prev_column);
+					prev_column = column;
+
+					// Data columns are handled
+					ColumnData *column_data = (ColumnData *)
+						(g_slist_nth (grid->priv->columns_data, position)->data);
+					columns_data = g_slist_append (columns_data, column_data);
+
+					reordered_indexes = g_slist_next (reordered_indexes);
 				}
+				g_list_free (columns);
+
+				g_slist_free (grid->priv->columns_data);
+				grid->priv->columns_data = columns_data;
+
+				// Remove unnecessary columns according layout
+				columns = gtk_tree_view_get_columns (GTK_TREE_VIEW(grid));
+
+				gint num_columns = g_list_length (columns);
+				gint num_reordered_indexes = g_slist_length (grid->priv->reordered_indexes);
+				if (num_reordered_indexes < num_columns) {
+					gint i;
+					for (i = num_reordered_indexes; i < num_columns; ++i) {
+						GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN
+							(g_list_nth (columns, i)->data);
+						gtk_tree_view_remove_column (GTK_TREE_VIEW(grid), column);
+					}
+				}
+				g_list_free (columns);
+
+				g_object_set (G_OBJECT(grid), "has-tooltip", TRUE, NULL);
+				g_signal_connect (G_OBJECT(grid), "query-tooltip",
+						  G_CALLBACK(gnome_db_raw_grid_query_tooltip), NULL);
+			}
+
+		}
+
+			break;
+				
+		case PROP_INFO_CELL_VISIBLE: {
+			GSList *list = grid->priv->columns_data;
+			gboolean show = g_value_get_boolean (value);
+			grid->priv->default_show_info_cell = show;
+	
+			while (list) {
+				COLUMN_DATA (list->data)->info_shown = show;
+				g_object_set (G_OBJECT (COLUMN_DATA (list->data)->info_cell), "visible", 
+					      show, NULL);
+				list = g_slist_next (list);
 			}
+		}
 			break;
 			
 		case PROP_GLOBAL_ACTIONS_VISIBLE:
@@ -558,16 +970,16 @@
 	tree_view = GTK_TREE_VIEW (grid);
 
 	/* Creation of the columns in the treeview, to fit the parameters in grid->priv->iter param list */
-	list = GDA_SET (grid->priv->iter)->groups_list;
-	i = 0;
-	while (list) {
+	for (i = 0, list = grid->priv->iter_info->groups_list;
+	     list;
+	     i++, list = list->next) {
 		GdaHolder *param;
-		GdaSetGroup *group;
+		GnomeDbSetGroup *group;
 		GtkTreeViewColumn *column;
 		GtkCellRenderer *renderer;
 		ColumnData *column_data;
 
-		group = GDA_SET_GROUP (list->data);
+		group = GNOME_DB_SET_GROUP (list->data);
 
 		/* update the list of columns data */
 		column_data = get_column_data (grid, group);
@@ -576,17 +988,18 @@
 			column_data->group = group;
 			column_data->info_shown = grid->priv->default_show_info_cell;
 			column_data->data_locked = FALSE;
+			column_data->tooltip_text = NULL;
 			grid->priv->columns_data = g_slist_append (grid->priv->columns_data, column_data);
 		}
 
 		/* create renderers */
-		if (group->nodes_source) {
+		if (group->source) {
 			/* parameters depending on a GdaDataModel */
 			gchar *title;
 			gboolean nullok = TRUE;
 			GSList *nodes;
 			
-			nodes = group->nodes;
+			nodes = group->group->nodes;
 			while (nodes && nullok) {
 				if (gda_holder_get_not_null (GDA_HOLDER (GDA_SET_NODE (nodes->data)->holder)))
 					nullok = FALSE;
@@ -594,11 +1007,11 @@
 			}
 			
 			/* determine title */
-			if (g_slist_length (group->nodes) == 1)
-				title = (gchar *) g_object_get_data (G_OBJECT (GDA_SET_NODE (group->nodes->data)->holder),
+			if (g_slist_length (group->group->nodes) == 1)
+				title = (gchar *) g_object_get_data (G_OBJECT (GDA_SET_NODE (group->group->nodes->data)->holder),
 								     "name");
 			else 
-				title = (gchar *) g_object_get_data (G_OBJECT (group->nodes_source->data_model),
+				title = (gchar *) g_object_get_data (G_OBJECT (group->group->nodes_source->data_model),
 								     "name");
 
 			if (title)
@@ -609,7 +1022,7 @@
 
 			/* FIXME: if nullok is FALSE, then set the column title in bold */
 
-			renderer = gnome_db_data_cell_renderer_combo_new (GDA_SET (grid->priv->iter), group->nodes_source);
+			renderer = gnome_db_data_cell_renderer_combo_new (grid->priv->iter_info, group->source);
 			column_data->data_cell = renderer;
 			gtk_tree_view_insert_column_with_data_func (tree_view, i, title, renderer,
 								    (GtkTreeCellDataFunc) cell_renderer_value_set_attributes, 
@@ -620,7 +1033,7 @@
 			g_signal_connect (G_OBJECT (renderer), "changed", 
 					  G_CALLBACK (data_cell_values_changed), grid);
 
-			g_object_set_data (G_OBJECT (column), "source", group->nodes_source);
+			g_object_set_data (G_OBJECT (column), "source", group->group->nodes_source);
 		}
 		else {
 			/* single direct parameter */
@@ -629,7 +1042,7 @@
 			const GValue *plugin_val;
 			gchar *title;
 			
-			param = GDA_HOLDER (GDA_SET_NODE (group->nodes->data)->holder);
+			param = GDA_HOLDER (GDA_SET_NODE (group->group->nodes->data)->holder);
 			g_type = gda_holder_get_g_type (param);
 
 			g_object_get (G_OBJECT (param), "name", &title, NULL);
@@ -667,8 +1080,8 @@
 		g_object_set (G_OBJECT (renderer), "editable", !column_data->data_locked, NULL);
 		if (g_object_class_find_property (G_OBJECT_GET_CLASS (renderer), "set_default_if_invalid"))
 			g_object_set (G_OBJECT (renderer), "set_default_if_invalid", TRUE, NULL);
-		g_object_set_data (G_OBJECT (renderer), "group", group);
-		g_object_set_data (G_OBJECT (column), "group", group);
+		g_object_set_data (G_OBJECT (renderer), "__gnome_db_group", group);
+		g_object_set_data (G_OBJECT (column), "__gnome_db_group", group);
 
 		/* Adding the GValue's information cell as another GtkCellRenderer */
 		renderer = gnome_db_data_cell_renderer_info_new (grid->priv->store, grid->priv->iter, group);
@@ -680,15 +1093,12 @@
 		g_signal_connect (G_OBJECT (renderer), "status_changed",
 				  G_CALLBACK (data_cell_status_changed), grid);
 		g_object_set (G_OBJECT (renderer), "visible", column_data->info_shown, NULL);
-		g_object_set_data (G_OBJECT (renderer), "group", group);
+		g_object_set_data (G_OBJECT (renderer), "__gnome_db_group", group);
 
 		/* Sorting data */
 		gtk_tree_view_column_set_clickable (column, TRUE);
 		g_signal_connect (G_OBJECT (column), "clicked",
 				  G_CALLBACK (treeview_column_clicked_cb), grid);
-
-		list = g_slist_next (list);
-		i++;
 	}
 }
 
@@ -702,15 +1112,15 @@
 				    GtkTreeModel *tree_model,
 				    GtkTreeIter *iter, GnomeDbRawGrid *grid)
 {
-	GdaSetGroup *group;
+	GnomeDbSetGroup *group;
 	guint attributes;
 	gboolean to_be_deleted = FALSE;
 	ColumnData *column_data;
 
-	group = g_object_get_data (G_OBJECT (tree_column), "group");
+	group = g_object_get_data (G_OBJECT (tree_column), "__gnome_db_group");
 	column_data = get_column_data (grid, group);
 	
-	if (group->nodes_source) {
+	if (group->group->nodes_source) {
 		/* parameters depending on a GdaDataModel */
 		GList *values = NULL;
 		GdaSetSource *source;
@@ -730,9 +1140,9 @@
 		 * external events and we can't know when it has changed.
 		 */
 		attributes = gnome_db_utility_proxy_compute_attributes_for_group (group, grid->priv->store, grid->priv->iter,
-									 iter, &to_be_deleted);
+										  iter, &to_be_deleted);
 		values = gnome_db_utility_proxy_compute_values_for_group (group, grid->priv->store, grid->priv->iter, iter,
-								 TRUE);
+									  TRUE);
 		if (!values) {
 			values = gnome_db_utility_proxy_compute_values_for_group (group, grid->priv->store, 
 									 grid->priv->iter, iter, FALSE);
@@ -773,9 +1183,9 @@
 
 		offset = gda_data_model_get_n_columns (gda_data_proxy_get_proxied_model (grid->priv->proxy));
 
-		g_assert (g_slist_length (group->nodes) == 1);
+		g_assert (g_slist_length (group->group->nodes) == 1);
 		col = g_slist_index (((GdaSet *)grid->priv->iter)->holders,
-				     GDA_SET_NODE (group->nodes->data)->holder);
+				     GDA_SET_NODE (group->group->nodes->data)->holder);
 		gtk_tree_model_get (GTK_TREE_MODEL (grid->priv->store), iter, 
 				    DATA_STORE_COL_TO_DELETE, &to_be_deleted,
 				    DATA_STORE_COL_MODEL_ROW, &row,
@@ -803,22 +1213,22 @@
 				   GtkTreeModel *tree_model,
 				   GtkTreeIter *iter, GnomeDbRawGrid *grid)
 {
-	GdaSetGroup *group;
+	GnomeDbSetGroup *group;
 	guint attributes;
 	gboolean to_be_deleted = FALSE;
 	ColumnData *column_data;
 
-	group = g_object_get_data (G_OBJECT (tree_column), "group");
+	group = g_object_get_data (G_OBJECT (tree_column), "__gnome_db_group");
 	column_data = get_column_data (grid, group);
 	
-	if (group->nodes_source) {
+	if (group->group->nodes_source) {
 		/* parameters depending on a GdaDataModel */
 		GdaSetSource *source;
 
 		source = g_object_get_data (G_OBJECT (tree_column), "source");
 
 		attributes = gnome_db_utility_proxy_compute_attributes_for_group (group, grid->priv->store, grid->priv->iter, 
-									 iter, &to_be_deleted);
+										  iter, &to_be_deleted);
 		g_object_set (G_OBJECT (cell), 
 			      "editable", !column_data->data_locked && !(attributes & GDA_VALUE_ATTR_NO_MODIF),
 			      "value_attributes", attributes,
@@ -836,9 +1246,9 @@
 		
 		offset = gda_data_model_get_n_columns (gda_data_proxy_get_proxied_model (grid->priv->proxy));
 
-		g_assert (g_slist_length (group->nodes) == 1);
+		g_assert (g_slist_length (group->group->nodes) == 1);
 		col = g_slist_index (((GdaSet *)grid->priv->iter)->holders,
-				     GDA_SET_NODE (group->nodes->data)->holder);
+				     GDA_SET_NODE (group->group->nodes->data)->holder);
 		gtk_tree_model_get (GTK_TREE_MODEL (grid->priv->store), iter, 
 				    DATA_STORE_COL_TO_DELETE, &to_be_deleted,
 				    DATA_STORE_COL_MODEL_ROW, &row,
@@ -865,15 +1275,15 @@
 data_cell_value_changed (GtkCellRenderer *renderer, const gchar *path, const GValue *new_value, GnomeDbRawGrid *grid)
 {
 	GtkTreeIter iter;
-	GdaSetGroup *group;
+	GnomeDbSetGroup *group;
 	
-	group = g_object_get_data (G_OBJECT (renderer), "group");
-	g_assert (g_slist_length (group->nodes) == 1);
+	group = g_object_get_data (G_OBJECT (renderer), "__gnome_db_group");
+	g_assert (g_slist_length (group->group->nodes) == 1);
 
 	if (set_iter_from_path (grid, path, &iter)) {
 		    gint col;
 		    col = g_slist_index (((GdaSet *)grid->priv->iter)->holders,
-					 GDA_SET_NODE (group->nodes->data)->holder);
+					 GDA_SET_NODE (group->group->nodes->data)->holder);
 		    gnome_db_data_store_set_value (grid->priv->store, &iter, col, new_value);
 	}
 }
@@ -889,13 +1299,13 @@
 			  GSList *new_values, GSList *all_new_values, GnomeDbRawGrid *grid)
 {
 	GtkTreeIter iter;
-	GdaSetGroup *group;
+	GnomeDbSetGroup *group;
 	
-	group = g_object_get_data (G_OBJECT (renderer), "group");
-	g_assert (group->nodes_source);
+	group = g_object_get_data (G_OBJECT (renderer), "__gnome_db_group");
+	g_assert (group->group->nodes_source);
 
 	if (new_values)
-		g_return_if_fail (g_slist_length (group->nodes) == g_slist_length (new_values));
+		g_return_if_fail (g_slist_length (group->group->nodes) == g_slist_length (new_values));
 	else
 		/* the reason for not having any value is that the GnomeDbDataCellRendererCombo had no selected item */
 		return;
@@ -907,7 +1317,7 @@
 		proxy_row = gnome_db_data_store_get_row_from_iter (grid->priv->store, &iter);
 
 		/* update the GnomeDbDataStore */
-		for (params = group->nodes, list = new_values; 
+		for (params = group->group->nodes, list = new_values; 
 		     list; 
 		     params = params->next, list = list->next) {
 			col = g_slist_index (((GdaSet *)grid->priv->iter)->holders,
@@ -918,13 +1328,13 @@
 #ifdef PROXY_STORE_EXTRA_VALUES
 		/* call gda_data_proxy_set_model_row_value() */
 		gint i;
-		for (i = 0; i < group->nodes_source->shown_n_cols; i++) {
+		for (i = 0; i < group->source->shown_n_cols; i++) {
 			GValue *value;
 
 			col = group->nodes_source->shown_cols_index[i];
 			value = (GValue *) g_slist_nth_data (all_new_values, col);
 			gda_data_proxy_set_model_row_value (grid->priv->proxy,
-							    group->nodes_source->data_model,
+							    group->group->nodes_source->data_model,
 							    proxy_row, col, value);
 		}
 #endif
@@ -952,13 +1362,13 @@
 static void
 treeview_column_clicked_cb (GtkTreeViewColumn *tree_column, GnomeDbRawGrid *grid)
 {
-	GdaSetGroup *group;
+	GnomeDbSetGroup *group;
 	GSList *nodes;
 
-	group = g_object_get_data (G_OBJECT (tree_column), "group");
+	group = g_object_get_data (G_OBJECT (tree_column), "__gnome_db_group");
 	g_assert (group);
 
-	for (nodes = group->nodes; nodes; nodes = nodes->next) {
+	for (nodes = group->group->nodes; nodes; nodes = nodes->next) {
 		GdaHolder *param = ((GdaSetNode*) nodes->data)->holder;
 		gint pos;
 		g_assert (param);
@@ -980,7 +1390,7 @@
 {
 	GtkTreePath *treepath;
 	GtkTreeIter iter;
-	GdaSetGroup *group;
+	GnomeDbSetGroup *group;
 	GtkTreeModel *tree_model;
 	gint col;
 	gint offset;
@@ -988,7 +1398,7 @@
 
 	offset = gda_data_model_get_n_columns (gda_data_proxy_get_proxied_model (grid->priv->proxy));
 
-	group = g_object_get_data (G_OBJECT (renderer), "group");
+	group = g_object_get_data (G_OBJECT (renderer), "__gnome_db_group");
 	tree_model = GTK_TREE_MODEL (grid->priv->store);
 
 	treepath = gtk_tree_path_new_from_string (path);
@@ -1000,13 +1410,13 @@
 	gtk_tree_path_free (treepath);
 	
 	g_value_set_uint (attribute = gda_value_new (G_TYPE_UINT), requested_action);
-	if (group->nodes_source) {
+	if (group->group->nodes_source) {
 		/* parameters depending on a GdaDataModel */
 		gint proxy_row;
 		GSList *list;
 		proxy_row = gnome_db_data_store_get_row_from_iter (grid->priv->store, &iter);
 
-		for (list = group->nodes; list; list = list->next) {
+		for (list = group->group->nodes; list; list = list->next) {
 			col = g_slist_index (((GdaSet *)grid->priv->iter)->holders,
 					     GDA_SET_NODE (list->data)->holder);
 			gnome_db_data_store_set_value (grid->priv->store, &iter, offset + col, attribute);
@@ -1042,9 +1452,9 @@
 		/* single direct parameter */
 		gint col;
 
-		g_assert (g_slist_length (group->nodes) == 1);
+		g_assert (g_slist_length (group->group->nodes) == 1);
 		col = g_slist_index (((GdaSet *)grid->priv->iter)->holders,
-				     GDA_SET_NODE (group->nodes->data)->holder);
+				     GDA_SET_NODE (group->group->nodes->data)->holder);
 		gnome_db_data_store_set_value (grid->priv->store, &iter, offset + col, attribute);
 	}
 	gda_value_free (attribute);
@@ -1650,11 +2060,11 @@
 		list = columns;
 		while (list) {
 			if (gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (list->data))) {
-				GdaSetGroup *group;
+				GnomeDbSetGroup *group;
 				GSList *params;
 
-				group = g_object_get_data (G_OBJECT (list->data), "group");
-				for (params = group->nodes; params; nb_cols ++, params = params->next) 
+				group = g_object_get_data (G_OBJECT (list->data), "__gnome_db_group");
+				for (params = group->group->nodes; params; nb_cols ++, params = params->next) 
 					cols [nb_cols] = g_slist_index (((GdaSet *)grid->priv->iter)->holders,
 									GDA_SET_NODE (params->data)->holder);
 			}
@@ -1887,18 +2297,15 @@
 }
 
 static ColumnData *
-get_column_data (GnomeDbRawGrid *grid, GdaSetGroup *group)
+get_column_data (GnomeDbRawGrid *grid, GnomeDbSetGroup *group)
 {
-	ColumnData *retval = NULL;
-	GSList *list = grid->priv->columns_data;
-	while (list && !retval) {
+	GSList *list;
+	for (list = grid->priv->columns_data; list; list = list->next) {
 		if (COLUMN_DATA (list->data)->group == group)
-			retval = COLUMN_DATA (list->data);
-
-		list = g_slist_next (list);
+			return COLUMN_DATA (list->data);
 	}
 
-	return retval;
+	return NULL;
 }
 
 /**
@@ -1953,7 +2360,7 @@
 	GnomeDbRawGrid *grid;
 	GdaHolder *param;
 	ColumnData *column_data;
-	GdaSetGroup *group;
+	GnomeDbSetGroup *group;
 
 	g_return_if_fail (iface && GNOME_DB_IS_RAW_GRID (iface));
 	grid = GNOME_DB_RAW_GRID (iface);
@@ -1965,7 +2372,7 @@
 		param = gda_data_model_iter_get_holder_for_field (grid->priv->iter, column);
 		g_return_if_fail (param);
 
-		group = gda_set_get_group (GDA_SET (grid->priv->iter), param);
+		group = _gnome_db_set_get_group (grid->priv->iter_info, param);
 		g_return_if_fail (group);
 
 		column_data = get_column_data (grid, group);
@@ -1989,14 +2396,14 @@
 
 	if (column >= 0) {
 		GdaHolder *param;
-		GdaSetGroup *group;
+		GnomeDbSetGroup *group;
 		ColumnData *cdata;
 
 		/* setting applies only to the @column column */
 		param = gda_data_model_iter_get_holder_for_field (grid->priv->iter, column);
 		g_return_if_fail (param);
 		
-		group = gda_set_get_group (GDA_SET (grid->priv->iter), param);
+		group = _gnome_db_set_get_group (grid->priv->iter_info, param);
 		g_return_if_fail (group);
 
 		cdata = get_column_data (grid, group);
@@ -2087,7 +2494,7 @@
 }
 
 static void
-paramlist_public_data_changed_cb (GdaSet *paramlist, GnomeDbRawGrid *grid)
+paramlist_public_data_changed_cb (GnomeDbSet *info, GnomeDbRawGrid *grid)
 {
 	GList *columns, *list;
 
@@ -2095,6 +2502,7 @@
 	if (grid->priv->columns_data) {
 		GSList *list = grid->priv->columns_data;
 		while (list) {
+                        g_free (((ColumnData *) (list->data))->tooltip_text);
 			g_free (list->data);
 			list = g_slist_next (list);
 		}
@@ -2136,7 +2544,7 @@
 		g_list_free (cols);
 
 		/* re-create columns */
-		paramlist_public_data_changed_cb (paramlist, grid);
+		paramlist_public_data_changed_cb (grid->priv->iter_info, grid);
 
 		/* hide columns which were hidden */
 		cols = gtk_tree_view_get_columns (GTK_TREE_VIEW (grid));
@@ -2283,6 +2691,7 @@
 	if (grid->priv->columns_data) {
 		GSList *list = grid->priv->columns_data;
 		while (list) {
+                        g_free (((ColumnData *) (list->data))->tooltip_text);
 			g_free (list->data);
 			list = g_slist_next (list);
 		}
@@ -2292,7 +2701,7 @@
 	
 	/* private data set */
 	if (grid->priv->iter) {
-		g_signal_handlers_disconnect_by_func (grid->priv->iter,
+		g_signal_handlers_disconnect_by_func (grid->priv->iter_info,
 						      G_CALLBACK (paramlist_public_data_changed_cb), grid);
 		g_signal_handlers_disconnect_by_func (grid->priv->iter,
 						      G_CALLBACK (paramlist_param_attr_changed_cb), grid);
@@ -2301,7 +2710,9 @@
 		g_signal_handlers_disconnect_by_func (grid->priv->iter,
 						      G_CALLBACK (iter_validate_set_cb), grid);
 		g_object_unref (grid->priv->iter);
+		g_object_unref (grid->priv->iter_info);
 		grid->priv->iter = NULL;
+		grid->priv->iter_info = NULL;
 	}
 	
 	/* proxy */
@@ -2354,3 +2765,16 @@
 
 	return grid->priv->write_mode;
 }
+
+static void
+gnome_db_raw_grid_set_data_layout (GnomeDbDataWidget  *iface, gpointer  data)
+{
+	GnomeDbRawGrid *raw_grid;
+	
+	g_return_if_fail (GNOME_DB_IS_RAW_GRID (iface));
+	raw_grid = GNOME_DB_RAW_GRID (iface);
+	g_return_if_fail (raw_grid->priv);
+
+	g_object_set (G_OBJECT (raw_grid), "data_layout", data, NULL);
+}
+
diff -urN libgnomedb/libgnomedb/gnome-db-set.c libgnomedbnew/libgnomedb/gnome-db-set.c
--- libgnomedb/libgnomedb/gnome-db-set.c	1970-01-01 01:00:00.000000000 +0100
+++ libgnomedbnew/libgnomedb/gnome-db-set.c	2009-04-19 18:38:14.000000000 +0200
@@ -0,0 +1,407 @@
+/* gnome-db-set.c
+ *
+ * Copyright (C) 2009 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/libgda.h>
+#include <libgnomedb/gnome-db-set.h>
+#include "marshal.h"
+
+static void gnome_db_set_class_init (GnomeDbSetClass * class);
+static void gnome_db_set_init (GnomeDbSet *wid);
+static void gnome_db_set_dispose (GObject *object);
+
+static void gnome_db_set_set_property (GObject *object,
+				       guint param_id,
+				       const GValue *value,
+				       GParamSpec *pspec);
+static void gnome_db_set_get_property (GObject *object,
+				       guint param_id,
+				       GValue *value,
+				       GParamSpec *pspec);
+
+static void wrapped_set_public_data_changed_cb (GdaSet *wset, GnomeDbSet *set);
+static void clean_public_data (GnomeDbSet *set);
+static void compute_public_data (GnomeDbSet *set);
+static void compute_shown_columns_index (GnomeDbSetSource *dsource);
+static void compute_ref_columns_index (GnomeDbSetSource *dsource);
+
+
+struct _GnomeDbSetPriv
+{
+	GdaSet *set;
+};
+
+/* get a pointer to the parents to be able to call their destructor */
+static GObjectClass *parent_class = NULL;
+
+/* properties */
+enum
+{
+        PROP_0,
+	PROP_SET
+};
+
+/* signals */
+enum
+{
+        PUBLIC_DATA_CHANGED,
+        LAST_SIGNAL
+};
+
+static gint gnome_db_set_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gnome_db_set_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo info = {
+			sizeof (GnomeDbSetClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gnome_db_set_class_init,
+			NULL,
+			NULL,
+			sizeof (GnomeDbSet),
+			0,
+			(GInstanceInitFunc) gnome_db_set_init
+		};		
+
+		type = g_type_register_static (G_TYPE_OBJECT, "GnomeDbSet", &info, 0);
+	}
+
+	return type;
+}
+
+static void
+gnome_db_set_class_init (GnomeDbSetClass *class)
+{
+	GObjectClass   *object_class = G_OBJECT_CLASS (class);
+	
+	parent_class = g_type_class_peek_parent (class);
+	object_class->dispose = gnome_db_set_dispose;
+
+	/**
+         * GnomeDbSet::public-data-changed
+         * @set: the #GnomeDbSet
+         * 
+         * Gets emitted when @set's public data (#GnomeDbSetGroup or #GnomeDbSetSource values) have changed
+         */
+        gnome_db_set_signals[PUBLIC_DATA_CHANGED] =
+                g_signal_new ("public-data-changed",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (GnomeDbSetClass, public_data_changed),
+                              NULL, NULL,
+                              gnome_db_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+        class->public_data_changed = NULL;
+
+	/* Properties */
+        object_class->set_property = gnome_db_set_set_property;
+        object_class->get_property = gnome_db_set_get_property;
+	g_object_class_install_property (object_class, PROP_SET,
+                                         g_param_spec_object ("set", NULL, NULL, 
+							      GDA_TYPE_SET,
+							      G_PARAM_READABLE | G_PARAM_WRITABLE |
+							      G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gnome_db_set_init (GnomeDbSet *set)
+{
+	set->priv = g_new0 (GnomeDbSetPriv, 1);
+	set->priv->set = NULL;
+}
+
+/**
+ * gnome_db_set_new
+ * @set: a #GdaSet
+ *
+ * Creates a new #GnomeDbSet which wraps @set's properties
+ *
+ *  Returns: the new widget
+ */
+GnomeDbSet *
+gnome_db_set_new (GdaSet *set)
+{
+	g_return_val_if_fail (GDA_IS_SET (set), NULL);
+
+	return (GnomeDbSet *) g_object_new (GNOME_DB_TYPE_SET, "set", set, NULL);
+}
+
+static void
+gnome_db_set_dispose (GObject *object)
+{
+        GnomeDbSet *set;
+
+        g_return_if_fail (GNOME_DB_IS_SET (object));
+
+        set = GNOME_DB_SET (object);
+
+        if (set->priv) {
+                if (set->priv->set) {
+                        g_signal_handlers_disconnect_by_func (G_OBJECT (set->priv->set),
+                                                              G_CALLBACK (wrapped_set_public_data_changed_cb), set);
+                        g_object_unref (set->priv->set);
+                        set->priv->set = NULL;
+                }
+
+		clean_public_data (set);
+
+                g_free (set->priv);
+                set->priv = NULL;
+        }
+
+        /* for the parent class */
+        parent_class->dispose (object);
+}
+
+static void
+gnome_db_set_set_property (GObject *object,
+			   guint param_id,
+			   const GValue *value,
+			   GParamSpec *pspec)
+{
+	GnomeDbSet *set;
+	
+	set = GNOME_DB_SET (object);
+	
+	switch (param_id) {
+	case PROP_SET:
+		set->priv->set = g_value_get_object (value);
+		if (set->priv->set) {
+			g_object_ref (set->priv->set);
+			compute_public_data (set);
+			g_signal_connect (set->priv->set, "public-data-changed",
+					  G_CALLBACK (wrapped_set_public_data_changed_cb), set);
+		}
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+		break;
+	}
+}
+
+static void
+wrapped_set_public_data_changed_cb (GdaSet *wset, GnomeDbSet *set)
+{
+	clean_public_data (set);
+	compute_public_data (set);
+	g_signal_emit (set, gnome_db_set_signals[PUBLIC_DATA_CHANGED], 0);
+}
+
+static void
+clean_public_data (GnomeDbSet *set)
+{
+	TO_IMPLEMENT;
+	GSList *list;
+	
+	for (list = set->sources_list; list; list = list->next) {
+		GnomeDbSetSource *dsource = (GnomeDbSetSource*) list->data;
+		g_free (dsource->shown_cols_index);
+		g_free (dsource->ref_cols_index);
+		g_free (dsource);
+	}
+	g_slist_free (set->sources_list);
+	set->sources_list = NULL;
+
+	for (list = set->groups_list; list; list = list->next) {
+		GnomeDbSetGroup *dgroup = (GnomeDbSetGroup*) list->data;
+		g_free (dgroup);
+	}
+	g_slist_free (set->groups_list);
+	set->groups_list = NULL;
+}
+
+static void
+compute_public_data (GnomeDbSet *set)
+{
+	GSList *list;
+	GdaSet *aset = GDA_SET (set->priv->set);
+	GHashTable *hash;
+	
+	/* scan GdaSetSource list */
+	hash = g_hash_table_new (NULL, NULL);
+	for (list = aset->sources_list; list; list = list->next) {
+		GnomeDbSetSource *dsource;
+		dsource = g_new0 (GnomeDbSetSource, 1);
+		set->sources_list = g_slist_prepend (set->sources_list, dsource);
+		g_hash_table_insert (hash, list->data, dsource);
+
+		dsource->source = GDA_SET_SOURCE (list->data);
+		compute_shown_columns_index (dsource);
+		compute_ref_columns_index (dsource);
+	}
+	set->sources_list = g_slist_reverse (set->sources_list);
+
+	/* scan GdaSetGroup list */
+	for (list = aset->groups_list; list; list = list->next) {
+		GnomeDbSetGroup *dgroup;
+		dgroup = g_new0 (GnomeDbSetGroup, 1);
+		set->groups_list = g_slist_prepend (set->groups_list, dgroup);
+		dgroup->group = GDA_SET_GROUP (list->data);
+		dgroup->source = g_hash_table_lookup (hash, GDA_SET_GROUP (list->data)->nodes_source);
+	}
+	set->groups_list = g_slist_reverse (set->groups_list);
+
+	g_hash_table_destroy (hash);
+}
+
+static void
+compute_shown_columns_index (GnomeDbSetSource *dsource)
+{
+       gint ncols, nholders;
+       gint *mask = NULL, masksize = 0;
+
+       nholders = g_slist_length (dsource->source->nodes);
+       g_return_if_fail (nholders > 0);
+       ncols = gda_data_model_get_n_columns (GDA_DATA_MODEL (dsource->source->data_model));
+       g_return_if_fail (ncols > 0);
+
+       if (ncols > nholders) {
+               /* we only want columns which are not holders */
+               gint i, current = 0;
+
+               masksize = ncols - nholders;
+               mask = g_new0 (gint, masksize);
+               for (i = 0; i < ncols ; i++) {
+                       GSList *list = dsource->source->nodes;
+                       gboolean found = FALSE;
+                       while (list && !found) {
+                               if (GDA_SET_NODE (list->data)->source_column == i)
+                                       found = TRUE;
+                               else
+                                       list = g_slist_next (list);
+                       }
+                       if (!found) {
+                               mask[current] = i;
+                               current ++;
+                       }
+               }
+               masksize = current;
+       }
+       else {
+               /* we want all the columns */
+               gint i;
+
+               masksize = ncols;
+               mask = g_new0 (gint, masksize);
+               for (i=0; i<ncols; i++) {
+                       mask[i] = i;
+               }
+       }
+
+       dsource->shown_n_cols = masksize;
+       dsource->shown_cols_index = mask;
+}
+
+void
+compute_ref_columns_index (GnomeDbSetSource *dsource)
+{
+       gint ncols, nholders;
+       gint *mask = NULL, masksize = 0;
+
+       nholders = g_slist_length (dsource->source->nodes);
+       g_return_if_fail (nholders > 0);
+       ncols = gda_data_model_get_n_columns (GDA_DATA_MODEL (dsource->source->data_model));
+       g_return_if_fail (ncols > 0);
+
+       if (ncols > nholders) {
+               /* we only want columns which are holders */
+               gint i, current = 0;
+
+               masksize = ncols - nholders;
+               mask = g_new0 (gint, masksize);
+               for (i=0; i<ncols ; i++) {
+                       GSList *list = dsource->source->nodes;
+                       gboolean found = FALSE;
+                       while (list && !found) {
+                               if (GDA_SET_NODE (list->data)->source_column == i)
+                                       found = TRUE;
+                               else
+                                       list = g_slist_next (list);
+                       }
+                       if (found) {
+                               mask[current] = i;
+                               current ++;
+                       }
+               }
+               masksize = current;
+       }
+       else {
+               /* we want all the columns */
+               gint i;
+
+               masksize = ncols;
+               mask = g_new0 (gint, masksize);
+               for (i=0; i<ncols; i++) {
+                       mask[i] = i;
+               }
+       }
+
+       dsource->ref_n_cols = masksize;
+       dsource->ref_cols_index = mask;
+}
+
+
+static void
+gnome_db_set_get_property (GObject *object,
+				 guint param_id,
+				 GValue *value,
+				 GParamSpec *pspec)
+{
+	GnomeDbSet *set;
+
+	set = GNOME_DB_SET (object);
+	
+	switch (param_id) {
+	case PROP_SET:
+		g_value_set_object (value, set->priv->set);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+		break;
+	}	
+}
+
+/**
+ * _gnome_db_set_get_group
+ */
+GnomeDbSetGroup  *
+_gnome_db_set_get_group (GnomeDbSet *dbset, GdaHolder *holder)
+{
+	GdaSetGroup *agroup;
+	GSList *list;
+	g_return_val_if_fail (GNOME_DB_IS_SET (dbset), NULL);
+	g_return_val_if_fail (GDA_IS_HOLDER (holder), NULL);
+
+	agroup = gda_set_get_group (dbset->priv->set, holder);
+	if (!agroup)
+		return NULL;
+	
+	for (list = dbset->groups_list; list; list = list->next) {
+		if (GNOME_DB_SET_GROUP (list->data)->group == agroup)
+			return GNOME_DB_SET_GROUP (list->data);
+	}
+	return NULL;
+}
diff -urN libgnomedb/libgnomedb/gnome-db-set.h libgnomedbnew/libgnomedb/gnome-db-set.h
--- libgnomedb/libgnomedb/gnome-db-set.h	1970-01-01 01:00:00.000000000 +0100
+++ libgnomedbnew/libgnomedb/gnome-db-set.h	2009-04-19 18:38:14.000000000 +0200
@@ -0,0 +1,104 @@
+/* gnome-db-set.h
+ *
+ * Copyright (C) 2009 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef __GNOME_DB_SET__
+#define __GNOME_DB_SET__
+
+#include <gtk/gtk.h>
+#include <libgda/gda-decl.h>
+
+G_BEGIN_DECLS
+
+#define GNOME_DB_TYPE_SET          (gnome_db_set_get_type())
+#define GNOME_DB_SET(obj)          G_TYPE_CHECK_INSTANCE_CAST (obj, gnome_db_set_get_type(), GnomeDbSet)
+#define GNOME_DB_SET_CLASS(klass)  G_TYPE_CHECK_CLASS_CAST (klass, gnome_db_set_get_type (), GnomeDbSetClass)
+#define GNOME_DB_IS_SET(obj)       G_TYPE_CHECK_INSTANCE_TYPE (obj, gnome_db_set_get_type ())
+
+
+typedef struct _GnomeDbSet      GnomeDbSet;
+typedef struct _GnomeDbSetClass GnomeDbSetClass;
+typedef struct _GnomeDbSetPriv  GnomeDbSetPriv;
+
+typedef struct _GnomeDbSetGroup GnomeDbSetGroup;
+typedef struct _GnomeDbSetSource GnomeDbSetSource;
+
+struct _GnomeDbSetGroup {
+        GdaSetGroup      *group;
+        GnomeDbSetSource *source; /* if NULL, then @group->nodes contains exactly one entry */
+
+        /* Padding for future expansion */
+        gpointer      _gda_reserved1;
+        gpointer      _gda_reserved2;
+};
+
+#define GNOME_DB_SET_GROUP(x) ((GnomeDbSetGroup*)(x))
+
+struct _GnomeDbSetSource {
+        GdaSetSource   *source;
+
+	/* displayed columns in 'source->data_model' */
+ 	gint shown_n_cols;
+ 	gint *shown_cols_index;
+
+ 	/* columns used as a reference (corresponding to PK values) in 'source->data_model' */
+ 	gint ref_n_cols;
+ 	gint *ref_cols_index; 
+
+        /* Padding for future expansion */
+        gpointer        _gda_reserved1;
+        gpointer        _gda_reserved2;
+        gpointer        _gda_reserved3;
+        gpointer        _gda_reserved4;
+};
+
+#define GNOME_DB_SET_SOURCE(x) ((GnomeDbSetSource*)(x))
+
+/* struct for the object's data */
+struct _GnomeDbSet
+{
+	GObject         object;
+	GnomeDbSetPriv *priv;
+
+	/*< public >*/
+	GSList         *sources_list; /* list of GnomeDbSetSource */
+        GSList         *groups_list;  /* list of GnomeDbSetGroup */
+};
+
+/* struct for the object's class */
+struct _GnomeDbSetClass
+{
+	GObjectClass       parent_class;
+	void             (*public_data_changed)   (GnomeDbSet *set);
+};
+
+/* 
+ * Generic widget's methods 
+ */
+GType             gnome_db_set_get_type            (void) G_GNUC_CONST;
+
+GnomeDbSet       *gnome_db_set_new                 (GdaSet *set);
+GnomeDbSetGroup  *_gnome_db_set_get_group           (GnomeDbSet *dbset, GdaHolder *holder);
+
+G_END_DECLS
+
+#endif
+
+
+
diff -urN libgnomedb/libgnomedb/libgnomedb.h libgnomedbnew/libgnomedb/libgnomedb.h
--- libgnomedb/libgnomedb/libgnomedb.h	2008-12-31 18:30:29.000000000 +0100
+++ libgnomedbnew/libgnomedb/libgnomedb.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,86 +0,0 @@
-/* GNOME DB library
- * Copyright (C) 1999 - 2008 The GNOME Foundation.
- *
- * AUTHORS:
- * 	Rodrigo Moya <rodrigo@gnome-db.org>
- *      Vivien Malerba <malerba@gnome-db.org>
- *
- * This Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this Library; see the file COPYING.LIB.  If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
- 
-#ifndef __LIBGNOME_DB_H_
-#define __LIBGNOME_DB_H_
-
-#include <libgda/libgda.h>
-#include <sql-parser/gda-sql-parser.h>
-#include <libgnomedb/gnome-db-decl.h>
-#include <libgnomedb/gnome-db-tools.h>
-
-/* interfaces */
-#include <libgnomedb/gnome-db-data-entry.h>
-#include <libgnomedb/gnome-db-data-widget.h>
-
-/* data data-entries widgets and cell renderers */
-#include <libgnomedb/data-entries/gnome-db-data-cell-renderer-boolean.h>
-#include <libgnomedb/data-entries/gnome-db-data-cell-renderer-combo.h>
-#include <libgnomedb/data-entries/gnome-db-data-cell-renderer-info.h>
-#include <libgnomedb/data-entries/gnome-db-data-cell-renderer-textual.h>
-#include <libgnomedb/data-entries/gnome-db-entry-boolean.h>
-#include <libgnomedb/data-entries/gnome-db-entry-combo.h>
-#include <libgnomedb/data-entries/gnome-db-entry-none.h>
-#include <libgnomedb/data-entries/gnome-db-entry-shell.h>
-#include <libgnomedb/data-entries/gnome-db-entry-string.h>
-#include <libgnomedb/data-entries/gnome-db-entry-common-time.h>
-#include <libgnomedb/data-entries/gnome-db-entry-time.h>
-#include <libgnomedb/data-entries/gnome-db-entry-date.h>
-#include <libgnomedb/data-entries/gnome-db-entry-timestamp.h>
-#include <libgnomedb/data-entries/gnome-db-entry-wrapper.h>
-#include <libgnomedb/data-entries/gnome-db-format-entry.h>
-
-/* widgets and objects */
-#include <libgnomedb/gnome-db-basic-form.h>
-#include <libgnomedb/gnome-db-combo.h>
-#include <libgnomedb/gnome-db-connection-properties.h>
-#include <libgnomedb/gnome-db-data-store.h>
-#include <libgnomedb/gnome-db-form.h>
-#include <libgnomedb/gnome-db-data-import.h>
-#include <libgnomedb/gnome-db-data-widget-info.h>
-#include <libgnomedb/gnome-db-dsn-selector.h>
-#include <libgnomedb/gnome-db-dsn-editor.h>
-#include <libgnomedb/gnome-db-dsn-assistant.h>
-#include <libgnomedb/gnome-db-provider-selector.h>
-#include <libgnomedb/gnome-db-provider-spec-editor.h>
-#include <libgnomedb/gnome-db-provider-auth-editor.h>
-#include <libgnomedb/gnome-db-raw-form.h>
-#include <libgnomedb/gnome-db-raw-grid.h>
-#include <libgnomedb/gnome-db-grid.h>
-#include <libgnomedb/gnome-db-find-dialog.h>
-#include <libgnomedb/gnome-db-login-dialog.h>
-#include <libgnomedb/gnome-db-login.h>
-#include <libgnomedb/gnome-db-provider-selector.h>
-#include <libgnomedb/gnome-db-stock.h>
-#include <libgnomedb/gnome-db-server-operation.h>
-#include <libgnomedb/gnome-db-transaction-status.h>
-#include <libgnomedb/gnome-db-dsn-assistant.h>
-
-G_BEGIN_DECLS
-
-void   gnome_db_init (void);
-gchar *gnome_db_get_application_exec_path (const gchar *app_name);
-
-G_END_DECLS
-
-#endif
diff -urN libgnomedb/libgnomedb/Makefile.am libgnomedbnew/libgnomedb/Makefile.am
--- libgnomedb/libgnomedb/Makefile.am	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/Makefile.am	2009-04-19 18:38:14.000000000 +0200
@@ -51,6 +51,7 @@
 	gnome-db-raw-form.h \
 	gnome-db-raw-grid.h \
 	gnome-db-server-operation.h \
+	gnome-db-set.h \
 	gnome-db-stock.h \
 	gnome-db-tools.h \
 	gnome-db-transaction-status.h \
@@ -92,6 +93,7 @@
 	gnome-db-raw-form.c \
 	gnome-db-raw-grid.c \
 	gnome-db-server-operation.c \
+	gnome-db-set.c \
 	gnome-db-stock.c \
 	gnome-db-tools.c \
 	gnome-db-transaction-status.c \
@@ -163,5 +165,9 @@
 marshal.c: marshal.list $(GLIB_GENMARSHAL)
 	$(GLIB_GENMARSHAL) $< --body --prefix=gnome_db_marshal > $@
 
-EXTRA_DIST =  marshal.list
+DTD_FILES = data_layout.dtd
+dtddir=$(LIBGNOMEDB_DTDDIR)
+dtd_DATA=$(DTD_FILES)
+
+EXTRA_DIST = $(DTD_FILES) marshal.list
 

diff -urN libgnomedb/libgnomedb/marshal.c libgnomedbnew/libgnomedb/marshal.c
--- libgnomedb/libgnomedb/marshal.c	2008-12-31 18:31:29.000000000 +0100
+++ libgnomedbnew/libgnomedb/marshal.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,476 +0,0 @@
-
-#include	<glib-object.h>
-
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v)     g_value_get_char (v)
-#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
-#define g_marshal_value_peek_int(v)      g_value_get_int (v)
-#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
-#define g_marshal_value_peek_long(v)     g_value_get_long (v)
-#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
-#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
-#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
-#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
-#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
-#define g_marshal_value_peek_float(v)    g_value_get_float (v)
-#define g_marshal_value_peek_double(v)   g_value_get_double (v)
-#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
-#define g_marshal_value_peek_param(v)    g_value_get_param (v)
-#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
-#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
-#define g_marshal_value_peek_object(v)   g_value_get_object (v)
-#else /* !G_ENABLE_DEBUG */
-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
- *          Do not access GValues directly in your code. Instead, use the
- *          g_value_get_*() functions
- */
-#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
-#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
-#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
-#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
-#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
-#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
-#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
-#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
-#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
-#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
-#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-/* VOID:VOID (marshal.list:27) */
-
-/* VOID:VOID,VOID (marshal.list:28) */
-void
-gnome_db_marshal_VOID__VOID_VOID (GClosure     *closure,
-                                  GValue       *return_value G_GNUC_UNUSED,
-                                  guint         n_param_values,
-                                  const GValue *param_values,
-                                  gpointer      invocation_hint G_GNUC_UNUSED,
-                                  gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__VOID_VOID) (gpointer     data1,
-                                                gpointer     data2);
-  register GMarshalFunc_VOID__VOID_VOID callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 1);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__VOID_VOID) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            data2);
-}
-
-/* VOID:POINTER (marshal.list:29) */
-
-/* VOID:POINTER,POINTER (marshal.list:30) */
-void
-gnome_db_marshal_VOID__POINTER_POINTER (GClosure     *closure,
-                                        GValue       *return_value G_GNUC_UNUSED,
-                                        guint         n_param_values,
-                                        const GValue *param_values,
-                                        gpointer      invocation_hint G_GNUC_UNUSED,
-                                        gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__POINTER_POINTER) (gpointer     data1,
-                                                      gpointer     arg_1,
-                                                      gpointer     arg_2,
-                                                      gpointer     data2);
-  register GMarshalFunc_VOID__POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_pointer (param_values + 1),
-            g_marshal_value_peek_pointer (param_values + 2),
-            data2);
-}
-
-/* VOID:POINTER,UINT,UINT (marshal.list:31) */
-void
-gnome_db_marshal_VOID__POINTER_UINT_UINT (GClosure     *closure,
-                                          GValue       *return_value G_GNUC_UNUSED,
-                                          guint         n_param_values,
-                                          const GValue *param_values,
-                                          gpointer      invocation_hint G_GNUC_UNUSED,
-                                          gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__POINTER_UINT_UINT) (gpointer     data1,
-                                                        gpointer     arg_1,
-                                                        guint        arg_2,
-                                                        guint        arg_3,
-                                                        gpointer     data2);
-  register GMarshalFunc_VOID__POINTER_UINT_UINT callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 4);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__POINTER_UINT_UINT) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_pointer (param_values + 1),
-            g_marshal_value_peek_uint (param_values + 2),
-            g_marshal_value_peek_uint (param_values + 3),
-            data2);
-}
-
-/* VOID:BOOLEAN (marshal.list:32) */
-
-/* VOID:ULONG (marshal.list:33) */
-
-/* VOID:OBJECT (marshal.list:34) */
-
-/* VOID:OBJECT,BOOL (marshal.list:35) */
-void
-gnome_db_marshal_VOID__OBJECT_BOOLEAN (GClosure     *closure,
-                                       GValue       *return_value G_GNUC_UNUSED,
-                                       guint         n_param_values,
-                                       const GValue *param_values,
-                                       gpointer      invocation_hint G_GNUC_UNUSED,
-                                       gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__OBJECT_BOOLEAN) (gpointer     data1,
-                                                     gpointer     arg_1,
-                                                     gboolean     arg_2,
-                                                     gpointer     data2);
-  register GMarshalFunc_VOID__OBJECT_BOOLEAN callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__OBJECT_BOOLEAN) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_object (param_values + 1),
-            g_marshal_value_peek_boolean (param_values + 2),
-            data2);
-}
-
-/* VOID:INT (marshal.list:36) */
-
-/* VOID:STRING,STRING (marshal.list:37) */
-void
-gnome_db_marshal_VOID__STRING_STRING (GClosure     *closure,
-                                      GValue       *return_value G_GNUC_UNUSED,
-                                      guint         n_param_values,
-                                      const GValue *param_values,
-                                      gpointer      invocation_hint G_GNUC_UNUSED,
-                                      gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__STRING_STRING) (gpointer     data1,
-                                                    gpointer     arg_1,
-                                                    gpointer     arg_2,
-                                                    gpointer     data2);
-  register GMarshalFunc_VOID__STRING_STRING callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__STRING_STRING) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_string (param_values + 1),
-            g_marshal_value_peek_string (param_values + 2),
-            data2);
-}
-
-/* VOID:STRING,BOXED (marshal.list:38) */
-void
-gnome_db_marshal_VOID__STRING_BOXED (GClosure     *closure,
-                                     GValue       *return_value G_GNUC_UNUSED,
-                                     guint         n_param_values,
-                                     const GValue *param_values,
-                                     gpointer      invocation_hint G_GNUC_UNUSED,
-                                     gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__STRING_BOXED) (gpointer     data1,
-                                                   gpointer     arg_1,
-                                                   gpointer     arg_2,
-                                                   gpointer     data2);
-  register GMarshalFunc_VOID__STRING_BOXED callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__STRING_BOXED) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_string (param_values + 1),
-            g_marshal_value_peek_boxed (param_values + 2),
-            data2);
-}
-
-/* VOID:STRING,POINTER,POINTER (marshal.list:39) */
-void
-gnome_db_marshal_VOID__STRING_POINTER_POINTER (GClosure     *closure,
-                                               GValue       *return_value G_GNUC_UNUSED,
-                                               guint         n_param_values,
-                                               const GValue *param_values,
-                                               gpointer      invocation_hint G_GNUC_UNUSED,
-                                               gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__STRING_POINTER_POINTER) (gpointer     data1,
-                                                             gpointer     arg_1,
-                                                             gpointer     arg_2,
-                                                             gpointer     arg_3,
-                                                             gpointer     data2);
-  register GMarshalFunc_VOID__STRING_POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 4);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__STRING_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_string (param_values + 1),
-            g_marshal_value_peek_pointer (param_values + 2),
-            g_marshal_value_peek_pointer (param_values + 3),
-            data2);
-}
-
-/* VOID:STRING,ENUM (marshal.list:40) */
-void
-gnome_db_marshal_VOID__STRING_ENUM (GClosure     *closure,
-                                    GValue       *return_value G_GNUC_UNUSED,
-                                    guint         n_param_values,
-                                    const GValue *param_values,
-                                    gpointer      invocation_hint G_GNUC_UNUSED,
-                                    gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__STRING_ENUM) (gpointer     data1,
-                                                  gpointer     arg_1,
-                                                  gint         arg_2,
-                                                  gpointer     data2);
-  register GMarshalFunc_VOID__STRING_ENUM callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__STRING_ENUM) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_string (param_values + 1),
-            g_marshal_value_peek_enum (param_values + 2),
-            data2);
-}
-
-/* VOID:STRING (marshal.list:41) */
-
-/* STRING:STRING (marshal.list:42) */
-void
-gnome_db_marshal_STRING__STRING (GClosure     *closure,
-                                 GValue       *return_value G_GNUC_UNUSED,
-                                 guint         n_param_values,
-                                 const GValue *param_values,
-                                 gpointer      invocation_hint G_GNUC_UNUSED,
-                                 gpointer      marshal_data)
-{
-  typedef gchar* (*GMarshalFunc_STRING__STRING) (gpointer     data1,
-                                                 gpointer     arg_1,
-                                                 gpointer     data2);
-  register GMarshalFunc_STRING__STRING callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gchar* v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 2);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_STRING__STRING) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_string (param_values + 1),
-                       data2);
-
-  g_value_take_string (return_value, v_return);
-}
-
-/* BOOLEAN:POINTER (marshal.list:43) */
-void
-gnome_db_marshal_BOOLEAN__POINTER (GClosure     *closure,
-                                   GValue       *return_value G_GNUC_UNUSED,
-                                   guint         n_param_values,
-                                   const GValue *param_values,
-                                   gpointer      invocation_hint G_GNUC_UNUSED,
-                                   gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER) (gpointer     data1,
-                                                     gpointer     arg_1,
-                                                     gpointer     data2);
-  register GMarshalFunc_BOOLEAN__POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 2);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_pointer (param_values + 1),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* VOID:POINTER,POINTER (marshal.list:46) */
-
-/* VOID:STRING,POINTER (marshal.list:47) */
-void
-gnome_db_marshal_VOID__STRING_POINTER (GClosure     *closure,
-                                       GValue       *return_value G_GNUC_UNUSED,
-                                       guint         n_param_values,
-                                       const GValue *param_values,
-                                       gpointer      invocation_hint G_GNUC_UNUSED,
-                                       gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__STRING_POINTER) (gpointer     data1,
-                                                     gpointer     arg_1,
-                                                     gpointer     arg_2,
-                                                     gpointer     data2);
-  register GMarshalFunc_VOID__STRING_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__STRING_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_string (param_values + 1),
-            g_marshal_value_peek_pointer (param_values + 2),
-            data2);
-}
-

diff -urN libgnomedb/libgnomedb/utility.c libgnomedbnew/libgnomedb/utility.c
--- libgnomedb/libgnomedb/utility.c	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/utility.c	2009-04-19 18:38:14.000000000 +0200
@@ -25,6 +25,8 @@
 #include <glib/gi18n-lib.h>
 #include "gnome-db-data-entry.h"
 #include "gnome-db-decl.h"
+#include "libgnomedb.h"
+#include <libgnomedb/binreloc/gnome-db-binreloc.h>
 
 /**
  * gnome_db_utility_entry_build_actions_menu
@@ -215,9 +217,9 @@
  * Returns: the attributes
  */
 guint
-gnome_db_utility_proxy_compute_attributes_for_group (GdaSetGroup *group, GnomeDbDataStore *store, 
-					    GdaDataModelIter *model_iter, GtkTreeIter *tree_iter, 
-					    gboolean *to_be_deleted)
+gnome_db_utility_proxy_compute_attributes_for_group (GnomeDbSetGroup *group, GnomeDbDataStore *store, 
+						     GdaDataModelIter *model_iter, GtkTreeIter *tree_iter, 
+						     gboolean *to_be_deleted)
 {
 	guint attributes = GDA_VALUE_ATTR_IS_NULL | GDA_VALUE_ATTR_CAN_BE_NULL |
                 GDA_VALUE_ATTR_IS_DEFAULT | GDA_VALUE_ATTR_CAN_BE_DEFAULT |
@@ -232,14 +234,14 @@
 	proxy = gnome_db_data_store_get_proxy (store);
         offset = gda_data_proxy_get_proxied_model_n_cols (proxy);
 
-        /* list the values in proxy_model for each param in GDA_SET_NODE (group->nodes->data)->params */
+        /* list the values in proxy_model for each param in GDA_SET_NODE (group->group->nodes->data)->params */
 	attributes = 0;
-        for (list = group->nodes; list; list = list->next) {
+        for (list = group->group->nodes; list; list = list->next) {
 		col = g_slist_index (((GdaSet*)model_iter)->holders, GDA_SET_NODE (list->data)->holder);
                 gtk_tree_model_get (GTK_TREE_MODEL (store), tree_iter,
                                     DATA_STORE_COL_TO_DELETE, &local_to_del,
                                     offset + col, &localattr, -1);
-		if (list == group->nodes)
+		if (list == group->group->nodes)
 			attributes = localattr;
 		else
 			attributes &= localattr;
@@ -267,7 +269,7 @@
  * freed.
  */
 GList *
-gnome_db_utility_proxy_compute_values_for_group (GdaSetGroup *group, GnomeDbDataStore *store, 
+gnome_db_utility_proxy_compute_values_for_group (GnomeDbSetGroup *group, GnomeDbDataStore *store, 
 						 GdaDataModelIter *model_iter, 
 						 GtkTreeIter *tree_iter, gboolean model_values)
 {
@@ -281,7 +283,7 @@
 		GSList *list;
 		GValue *value;
 
-		for (list = group->nodes; list; list = list->next) {
+		for (list = group->group->nodes; list; list = list->next) {
 			gint col;
 
 			col = g_slist_index (((GdaSet*)model_iter)->holders, GDA_SET_NODE (list->data)->holder);
@@ -291,13 +293,13 @@
 	}
 	else {
 		gint col, i, proxy_row;
-		GdaSetSource *source;
+		GnomeDbSetSource *source;
 		const GValue *value;
 		gboolean slow_way = FALSE;
 		gboolean ret_null = FALSE;
 
 		proxy_row = gnome_db_data_store_get_row_from_iter (store, tree_iter);
-		source = group->nodes_source;
+		source = group->source;
 		for (i = 0 ; (i < source->shown_n_cols)  && !ret_null; i++) {
 			col = source->shown_cols_index[i];
 #ifdef PROXY_STORE_EXTRA_VALUES
@@ -323,8 +325,8 @@
 				GSList *list;
 				gint j;
 				
-				cols_index = g_new0 (gint, g_slist_length (group->nodes));
-				for (list = group->nodes, j = 0; list; list = list->next, j++) {
+				cols_index = g_new0 (gint, g_slist_length (group->group->nodes));
+				for (list = group->group->nodes, j = 0; list; list = list->next, j++) {
 					gint colno;
 					colno = g_slist_index (((GdaSet*)model_iter)->holders, 
 							       GDA_SET_NODE (list->data)->holder);
@@ -334,10 +336,10 @@
 					key_values = g_slist_append (key_values, (GValue *) value);
 				}
 				
-				row = gda_data_model_get_row_from_values (GDA_DATA_MODEL (source->data_model), 
+				row = gda_data_model_get_row_from_values (GDA_DATA_MODEL (source->source->data_model), 
 									  key_values, cols_index);
 				if (row >= 0) {
-					value = gda_data_model_get_value_at (GDA_DATA_MODEL (source->data_model),
+					value = gda_data_model_get_value_at (GDA_DATA_MODEL (source->source->data_model),
 									     col, row, NULL);
 					retval = g_list_append (retval, (GValue *) value);
 				}
@@ -501,3 +503,89 @@
 	gtk_dialog_run (GTK_DIALOG (dlg));
 	gtk_widget_destroy (dlg);
 }
+
+/**
+ * gnome_db_utility_set_data_layout_from_file
+ * @data_widget:
+ * @file_name: XML data layout file
+ *
+ * Set a data layout to @data_widget according specifications in @file_name
+ */
+void
+gnome_db_utility_set_data_layout_from_file (GnomeDbDataWidget  *data_widget, const gchar  *file_name, const gchar  *parent_table)
+{
+	g_return_if_fail (file_name != NULL);
+	g_return_if_fail (parent_table != NULL);
+
+	xmlDocPtr doc;
+	doc = xmlParseFile (file_name);
+	if (doc == NULL) {
+		g_warning (_("'%s' Document not parsed successfully\n"), file_name);
+		return;
+	}
+
+	xmlDtdPtr dtd = NULL;
+
+	gchar *file = gnome_db_gbr_get_file_path (GNOME_DB_DATA_DIR,
+						  LIBGNOMEDB_ABI_NAME,
+						  "dtd",
+						  "data_layout.dtd",
+						  NULL);
+	if (g_file_test (file, G_FILE_TEST_EXISTS))
+		dtd = xmlParseDTD (NULL, file);
+	if (dtd == NULL) {
+		g_warning (_("'%s' DTD not parsed successfully. "
+			     "XML data layout validation will not be "
+			     "performed (some errors may occur)"), file);
+	}
+	g_free (file);
+
+	/* Get the root element node */
+	xmlNodePtr root_node = NULL;
+	root_node = xmlDocGetRootElement (doc);
+
+	/* Must have root element, a name and the name must be "data_layouts" */
+	if (!root_node ||
+	    !root_node->name ||
+	    xmlStrcmp (root_node->name, "data_layouts")) {
+		xmlFreeDoc (doc);
+		return;
+	}
+
+	xmlNodePtr node;
+	for (node = root_node->children; node != NULL; node = node->next) {
+
+		if (node->type == XML_ELEMENT_NODE &&
+		    !xmlStrcmp (node->name, (const xmlChar *) "data_layout")) {
+			gboolean retval = FALSE;
+			xmlChar *str;
+
+			str = xmlGetProp (node, "parent_table");
+			if (str) {
+				if (strcmp (str, parent_table) == 0)
+					retval = TRUE;
+				//g_print ("parent_table: %s\n", str);
+				xmlFree (str);
+			}
+
+			str = xmlGetProp (node, "name");
+			if (str) {
+				if (retval == TRUE &&
+				    ((GNOME_DB_IS_RAW_GRID(data_widget) &&
+				      strcmp (str, "list") == 0) ||
+				     (GNOME_DB_IS_RAW_FORM(data_widget) &&
+				      strcmp (str, "details") == 0)))  // Now proceed
+					gnome_db_data_widget_set_data_layout (data_widget, node);
+				//g_print ("name: %s\n", str);
+				xmlFree (str);
+			}
+		}
+	}
+
+	/* Free the document */
+	xmlFreeDoc (doc);
+
+	/* Free the global variables that may
+	 * have been allocated by the parser */
+	xmlCleanupParser ();
+}
diff -urN libgnomedb/libgnomedb/utility.h libgnomedbnew/libgnomedb/utility.h
--- libgnomedb/libgnomedb/utility.h	2008-12-30 11:22:49.000000000 +0100
+++ libgnomedbnew/libgnomedb/utility.h	2009-04-19 18:38:14.000000000 +0200
@@ -22,6 +22,7 @@
 #include <libgda/gda-set.h>
 #include "gnome-db-data-entry.h"
 #include "gnome-db-data-store.h"
+#include "gnome-db-set.h"
 
 /*
  *
@@ -37,16 +38,17 @@
  * corresponding to the columns for the parameters in @group (as described by @model_iter), 
  * at row pointed by @tree_iter
  */
-guint            gnome_db_utility_proxy_compute_attributes_for_group (GdaSetGroup *group, 
-							     GnomeDbDataStore *store, GdaDataModelIter *model_iter, 
-							     GtkTreeIter *tree_iter, 
-							     gboolean *to_be_deleted);
-GList           *gnome_db_utility_proxy_compute_values_for_group     (GdaSetGroup *group, 
-							     GnomeDbDataStore *store, GdaDataModelIter *model_iter, 
-							     GtkTreeIter *tree_iter, gboolean model_values);
+guint            gnome_db_utility_proxy_compute_attributes_for_group (GnomeDbSetGroup *group, 
+								      GnomeDbDataStore *store, GdaDataModelIter *model_iter, 
+								      GtkTreeIter *tree_iter, 
+								      gboolean *to_be_deleted);
+GList           *gnome_db_utility_proxy_compute_values_for_group     (GnomeDbSetGroup *group, 
+								      GnomeDbDataStore *store, GdaDataModelIter *model_iter, 
+								      GtkTreeIter *tree_iter, gboolean model_values);
 
 /*
  * Some dialogs used by GnomeDbDataWidget widgets
  */
 gboolean   gnome_db_utility_display_error_with_keep_or_discard_choice (GnomeDbDataWidget *form, GError *filled_error);
 void       gnome_db_utility_display_error                             (GnomeDbDataWidget *form, gboolean can_discard, GError *filled_error);
+void       gnome_db_utility_set_data_layout_from_file (GnomeDbDataWidget  *data_widget, const gchar  *file_name,  const gchar  *parent_table);
