From: Andrea Zagli <azagli@libero.it>
Date: Tue, 30 Aug 2011 07:38:59 +0000 (+0200)
Subject: Ended printing from as GtkTreeModel.
X-Git-Tag: 0.5.0~31
X-Git-Url: https://saetta.ns0.it/gitweb?a=commitdiff_plain;h=refs%2Fheads%2Fgtktreemodel;p=reptool%2Flibreptool

Ended printing from as GtkTreeModel.

closes #35
---

diff --git a/.gitignore b/.gitignore
index e1ac3ef..419f8c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,6 +49,7 @@ tests/test_report.rptr
 tests/test_rptprint
 tests/test_rptreport
 tests/test_rptreport_creation
+tests/test_rptreport_liststore
 tests/test_report_created*
 tests/test_rptprint_mm.rptr
 tests/test_report_newline.rpt
diff --git a/configure.ac b/configure.ac
index 919e9e9..1ecd6c2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.59)
-AC_INIT([libreptool], [0.2.0], [azagli@libero.it])
+AC_INIT([libreptool], [0.2.1], [azagli@libero.it])
 AC_CONFIG_SRCDIR([src/rptprint.c])
 AC_CONFIG_HEADER([config.h])
 
@@ -31,6 +31,11 @@ AC_PROG_LEX
 AC_PROG_LIBTOOL
 GTK_DOC_CHECK
 
+dnl ******************************
+dnl glib-genmarshal
+dnl ******************************
+AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
+
 # Checks for libraries.
 PKG_CHECK_MODULES([REPTOOL], [gtk+-2.0 >= 2.10.0
                               libxml-2.0 >= 2.6.0
diff --git a/src/Makefile.am b/src/Makefile.am
index 15c0e60..9f58721 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,6 +13,12 @@ lib_LTLIBRARIES = libreptool.la
 
 libreptool_la_LDFLAGS = -no-undefined
 
+rptmarshal.c: rptmarshal.h reptool_marshal.list $(GLIB_GENMARSHAL)
+	$(GLIB_GENMARSHAL) reptool_marshal.list --body --prefix=_rpt_marshal > $@
+
+rptmarshal.h: reptool_marshal.list $(GLIB_GENMARSHAL)
+	$(GLIB_GENMARSHAL) reptool_marshal.list --header --prefix=_rpt_marshal > $@
+
 libreptool_la_SOURCES = \
                         rptobject.c \
                         rptobjecttext.c \
diff --git a/src/reptool_marshal.list b/src/reptool_marshal.list
index 2f8088f..e24fac2 100644
--- a/src/reptool_marshal.list
+++ b/src/reptool_marshal.list
@@ -1 +1 @@
-STRING:STRING,POINTER,INT
+STRING:STRING,POINTER,INT,POINTER,POINTER
diff --git a/src/rptmarshal.c b/src/rptmarshal.c
index 3664552..803b1f0 100644
--- a/src/rptmarshal.c
+++ b/src/rptmarshal.c
@@ -21,6 +21,7 @@
 #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)
+#define g_marshal_value_peek_variant(v)  g_value_get_variant (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
@@ -44,30 +45,33 @@
 #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
+#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
 #endif /* !G_ENABLE_DEBUG */
 
 
-/* STRING:STRING,POINTER,INT (reptool_marshal.list:1) */
+/* STRING:STRING,POINTER,INT,POINTER,POINTER (reptool_marshal.list:1) */
 void
-_rpt_marshal_STRING__STRING_POINTER_INT (GClosure     *closure,
-                                         GValue       *return_value,
-                                         guint         n_param_values,
-                                         const GValue *param_values,
-                                         gpointer      invocation_hint,
-                                         gpointer      marshal_data)
+_rpt_marshal_STRING__STRING_POINTER_INT_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 gchar* (*GMarshalFunc_STRING__STRING_POINTER_INT) (gpointer     data1,
-                                                             gpointer     arg_1,
-                                                             gpointer     arg_2,
-                                                             gint         arg_3,
-                                                             gpointer     data2);
-  register GMarshalFunc_STRING__STRING_POINTER_INT callback;
+  typedef gchar* (*GMarshalFunc_STRING__STRING_POINTER_INT_POINTER_POINTER) (gpointer     data1,
+                                                                             gpointer     arg_1,
+                                                                             gpointer     arg_2,
+                                                                             gint         arg_3,
+                                                                             gpointer     arg_4,
+                                                                             gpointer     arg_5,
+                                                                             gpointer     data2);
+  register GMarshalFunc_STRING__STRING_POINTER_INT_POINTER_POINTER 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 == 4);
+  g_return_if_fail (n_param_values == 6);
 
   if (G_CCLOSURE_SWAP_DATA (closure))
     {
@@ -79,12 +83,14 @@ _rpt_marshal_STRING__STRING_POINTER_INT (GClosure     *closure,
       data1 = g_value_peek_pointer (param_values + 0);
       data2 = closure->data;
     }
-  callback = (GMarshalFunc_STRING__STRING_POINTER_INT) (marshal_data ? marshal_data : cc->callback);
+  callback = (GMarshalFunc_STRING__STRING_POINTER_INT_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
 
   v_return = callback (data1,
                        g_marshal_value_peek_string (param_values + 1),
                        g_marshal_value_peek_pointer (param_values + 2),
                        g_marshal_value_peek_int (param_values + 3),
+                       g_marshal_value_peek_pointer (param_values + 4),
+                       g_marshal_value_peek_pointer (param_values + 5),
                        data2);
 
   g_value_take_string (return_value, v_return);
diff --git a/src/rptmarshal.h b/src/rptmarshal.h
index 56bb519..665942c 100644
--- a/src/rptmarshal.h
+++ b/src/rptmarshal.h
@@ -6,13 +6,13 @@
 
 G_BEGIN_DECLS
 
-/* STRING:STRING,POINTER,INT (reptool_marshal.list:1) */
-extern void _rpt_marshal_STRING__STRING_POINTER_INT (GClosure     *closure,
-                                                     GValue       *return_value,
-                                                     guint         n_param_values,
-                                                     const GValue *param_values,
-                                                     gpointer      invocation_hint,
-                                                     gpointer      marshal_data);
+/* STRING:STRING,POINTER,INT,POINTER,POINTER (reptool_marshal.list:1) */
+extern void _rpt_marshal_STRING__STRING_POINTER_INT_POINTER_POINTER (GClosure     *closure,
+                                                                     GValue       *return_value,
+                                                                     guint         n_param_values,
+                                                                     const GValue *param_values,
+                                                                     gpointer      invocation_hint,
+                                                                     gpointer      marshal_data);
 
 G_END_DECLS
 
diff --git a/src/rptreport.c b/src/rptreport.c
index 5545421..7358297 100644
--- a/src/rptreport.c
+++ b/src/rptreport.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2011 Andrea Zagli <azagli@inwind.it>
+ * Copyright (C) 2007-2011 Andrea Zagli <azagli@libero.it>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -51,6 +51,7 @@ typedef struct
 	GdaDataModel *gda_datamodel;
 
 	GtkTreeModel *treemodel;
+	GHashTable *columns_names;
 } Database;
 
 typedef struct
@@ -192,6 +193,8 @@ rpt_report_class_init (RptReportClass *klass)
 	 * @field_name: the name of the field requested.
 	 * @data_model: a #GdaDataModel; or NULL if there's no database source.
 	 * @row: the current @data_model's row; -1 if @data_model is NULL.
+	 * @treemodel: a #GtkTreeModel; or NULL if there's no #GtkTreeModel source.
+	 * @iter: a #GtkTreeIter; or NULL if @treemodel is NULL.
 	 *
 	 * The signal is emitted each time there's into text's attribute source
 	 * a field that doesn't exists.
@@ -202,12 +205,14 @@ rpt_report_class_init (RptReportClass *klass)
 	                                               0,
 	                                               NULL,
 	                                               NULL,
-	                                               _rpt_marshal_STRING__STRING_POINTER_INT,
+	                                               _rpt_marshal_STRING__STRING_POINTER_INT_POINTER_POINTER,
 	                                               G_TYPE_STRING,
-	                                               3,
+	                                               5,
 	                                               G_TYPE_STRING,
 	                                               G_TYPE_POINTER,
-	                                               G_TYPE_INT);
+	                                               G_TYPE_INT,
+	                                               G_TYPE_POINTER,
+	                                               G_TYPE_POINTER);
 }
 
 static void
@@ -648,7 +653,7 @@ rpt_report_set_database (RptReport *rpt_report,
 		{
 			g_free (priv->db);
 		}
-	priv->db = (Database *)g_malloc0 (sizeof (Database));
+	priv->db = (Database *)g_new0 (Database, 1);
 
 	priv->db->provider_id = g_strstrip (g_strdup (provider_id));
 	priv->db->connection_string = g_strstrip (g_strdup (connection_string));
@@ -656,6 +661,7 @@ rpt_report_set_database (RptReport *rpt_report,
 	priv->db->gda_conn = NULL;
 	priv->db->gda_datamodel = NULL;
 	priv->db->treemodel = NULL;
+	priv->db->columns_names = NULL;
 }
 
 /**
@@ -674,6 +680,11 @@ rpt_report_set_database_from_datamodel (RptReport *rpt_report, GdaDataModel *dat
 
 	if (priv->db != NULL)
 		{
+			if (priv->db->columns_names != NULL)
+				{
+					g_hash_table_destroy (priv->db->columns_names);
+				}
+
 			g_free (priv->db);
 		}
 	priv->db = (Database *)g_new0 (Database, 1);
@@ -684,26 +695,40 @@ rpt_report_set_database_from_datamodel (RptReport *rpt_report, GdaDataModel *dat
 	priv->db->gda_conn = NULL;
 	priv->db->gda_datamodel = data_model;
 	priv->db->treemodel = NULL;
+	priv->db->columns_names = NULL;
 }
 
 /**
  * rpt_report_set_database_as_gtktreemodel:
  * @rpt_report: an #RptReport object.
  * @model: a #GtkTreeModel (for now only #GtkListStore is supported).
+ * @columns_names:
  *
  */
 void
-rpt_report_set_database_as_gtktreemodel (RptReport *rpt_report, GtkTreeModel *model)
+rpt_report_set_database_as_gtktreemodel (RptReport *rpt_report,
+                                         GtkTreeModel *model,
+                                         GHashTable *columns_names)
 {
 	g_return_if_fail (IS_RPT_REPORT (rpt_report));
-	g_return_if_fail (GTK_IS_TREE_MODEL (rpt_report));
+	g_return_if_fail (GTK_IS_TREE_MODEL (model));
+	g_return_if_fail (columns_names != NULL);
 
-	g_return_if_fail (GTK_IS_LIST_STORE (rpt_report));
+	g_return_if_fail (GTK_IS_LIST_STORE (model));
 
 	RptReportPrivate *priv = RPT_REPORT_GET_PRIVATE (rpt_report);
 
 	if (priv->db != NULL)
 		{
+			if (priv->db->gda_datamodel != NULL)
+				{
+					g_object_unref (priv->db->gda_datamodel);
+				}
+			if (priv->db->gda_conn != NULL)
+				{
+					gda_connection_close_no_warning (priv->db->gda_conn);
+				}
+
 			g_free (priv->db);
 		}
 	priv->db = (Database *)g_new0 (Database, 1);
@@ -714,6 +739,7 @@ rpt_report_set_database_as_gtktreemodel (RptReport *rpt_report, GtkTreeModel *mo
 	priv->db->gda_conn = NULL;
 	priv->db->gda_datamodel = NULL;
 	priv->db->treemodel = model;
+	priv->db->columns_names = g_hash_table_ref (columns_names);
 }
 
 /**
@@ -1342,128 +1368,225 @@ xmlDoc
 	if (priv->db != NULL)
 		{
 			gint row;
-			gint rows;
 
-			/* database connection */
-			gda_init ();
-			if (priv->db->gda_datamodel == NULL)
+			if (priv->db->treemodel != NULL)
 				{
-					error = NULL;
-					priv->db->gda_conn = gda_connection_open_from_string (priv->db->provider_id,
-					                                                      priv->db->connection_string,
-					                                                      NULL,
-					                                                      GDA_CONNECTION_OPTIONS_NONE,
-					                                                      &error);
-					if (priv->db->gda_conn == NULL)
+					GtkTreeIter *iter_prec;
+					GtkTreeIter iter;
+
+					if (!gtk_tree_model_get_iter_first (priv->db->treemodel, &iter))
 						{
-							/* TO DO */
-							g_warning ("Unable to establish the connection: %s.",
-							           error != NULL && error->message != NULL ? error->message : "no details");
+							g_warning ("GtkTreeModel is empty.");
 							return NULL;
 						}
-					else
-						{
-							GdaSqlParser *parser = gda_sql_parser_new ();
-							error = NULL;
-							GdaStatement *stmt = gda_sql_parser_parse_string (parser, priv->db->sql, NULL, &error);
 
-							error = NULL;
-							priv->db->gda_datamodel = gda_connection_statement_execute_select (priv->db->gda_conn, stmt, NULL, &error);
-							if (priv->db->gda_datamodel == NULL)
+					row = 0;
+					do
+						{
+							priv->cur_iter = &iter;
+							if (row == 0 ||
+							    priv->body->new_page_after ||
+							    (priv->page_footer != NULL && (cur_y + priv->body->height > priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height)) ||
+							    cur_y > (priv->page->size->height - priv->page->margin->bottom))
 								{
-									/* TO DO */
-									g_warning ("Unable to create the datamodel: %s",
-									           error != NULL && error->message != NULL ? error->message : "no details");
-									return NULL;
+									if (priv->cur_page > 0 && priv->page_footer != NULL)
+										{
+											if ((priv->cur_page == 1 && priv->page_footer->first_page) ||
+											    priv->cur_page > 1)
+												{
+													cur_y = priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height;
+													priv->cur_iter = iter_prec;
+													rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER);
+													priv->cur_iter = &iter;
+												}
+										}
+
+									cur_y = priv->page->margin->top;
+									xpage = rpt_report_rptprint_new_page (rpt_report, xdoc);
+
+									if (priv->page_header != NULL)
+										{
+											if ((priv->cur_page == 1 && priv->page_header->first_page) ||
+											    priv->cur_page > 1)
+												{
+													rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_HEADER);
+												}
+										}
+									if (priv->cur_page == 1 && priv->report_header != NULL)
+										{
+											rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_REPORT_HEADER);
+											if (priv->report_header->new_page_after)
+												{
+													cur_y = 0.0;
+													xpage = rpt_report_rptprint_new_page (rpt_report, xdoc);
+												}
+										}
 								}
-						}
-				}
 
-			rows = gda_data_model_get_n_rows (priv->db->gda_datamodel);
-			for (row = 0; row < rows; row++)
-				{
-					priv->cur_row = row;
-					if (row == 0 ||
-					    priv->body->new_page_after ||
-					    (priv->page_footer != NULL && (cur_y + priv->body->height > priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height)) ||
-					    cur_y > (priv->page->size->height - priv->page->margin->bottom))
+							rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_BODY);
+
+							iter_prec = g_memdup (&iter, sizeof (GtkTreeIter));
+							row++;
+						} while (gtk_tree_model_iter_next (priv->db->treemodel, &iter));
+
+					priv->cur_iter = iter_prec;
+					if (priv->cur_page > 0 && priv->report_footer != NULL)
 						{
-							if (priv->cur_page > 0 && priv->page_footer != NULL)
+							if ((cur_y + priv->report_footer->height > priv->page->size->height - priv->page->margin->bottom - (priv->page_footer != NULL ? priv->page_footer->height : 0.0)) ||
+							    priv->report_footer->new_page_before)
 								{
-									if ((priv->cur_page == 1 && priv->page_footer->first_page) ||
-									    priv->cur_page > 1)
+									if (priv->page_header != NULL)
+										{
+											rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_HEADER);
+										}
+
+									cur_y = priv->page->margin->top;
+									xpage = rpt_report_rptprint_new_page (rpt_report, xdoc);
+
+									if (priv->cur_page > 0 && priv->page_footer != NULL)
 										{
 											cur_y = priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height;
-											priv->cur_row = row - 1;
 											rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER);
-											priv->cur_row = row;
 										}
 								}
 
-							cur_y = priv->page->margin->top;
-							xpage = rpt_report_rptprint_new_page (rpt_report, xdoc);
+							rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_REPORT_FOOTER);
+						}
 
-							if (priv->page_header != NULL)
+					if (priv->cur_page > 0 && priv->page_footer != NULL && priv->page_footer->last_page)
+						{
+							cur_y = priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height;
+							rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER);
+						}
+				}
+			else
+				{
+					gint rows;
+
+					/* database connection */
+					gda_init ();
+					if (priv->db->gda_datamodel == NULL)
+						{
+							error = NULL;
+							priv->db->gda_conn = gda_connection_open_from_string (priv->db->provider_id,
+							                                                      priv->db->connection_string,
+							                                                      NULL,
+							                                                      GDA_CONNECTION_OPTIONS_NONE,
+							                                                      &error);
+							if (priv->db->gda_conn == NULL || error != NULL)
 								{
-									if ((priv->cur_page == 1 && priv->page_header->first_page) ||
-									    priv->cur_page > 1)
-										{
-											rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_HEADER);
-										}
+									/* TO DO */
+									g_warning ("Unable to establish the connection: %s.",
+									           error != NULL && error->message != NULL ? error->message : "no details");
+									return NULL;
 								}
-							if (priv->cur_page == 1 && priv->report_header != NULL)
+							else
 								{
-									rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_REPORT_HEADER);
-									if (priv->report_header->new_page_after)
+									GdaSqlParser *parser = gda_sql_parser_new ();
+									error = NULL;
+									GdaStatement *stmt = gda_sql_parser_parse_string (parser, priv->db->sql, NULL, &error);
+
+									error = NULL;
+									priv->db->gda_datamodel = gda_connection_statement_execute_select (priv->db->gda_conn, stmt, NULL, &error);
+									if (priv->db->gda_datamodel == NULL || error != NULL)
 										{
-											cur_y = 0.0;
-											xpage = rpt_report_rptprint_new_page (rpt_report, xdoc);
+											/* TO DO */
+											g_warning ("Unable to create the datamodel: %s",
+											           error != NULL && error->message != NULL ? error->message : "no details");
+											return NULL;
 										}
 								}
 						}
 
-					rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_BODY);
-				}
-
-			if (priv->cur_page > 0 && priv->report_footer != NULL)
-				{
-					if ((cur_y + priv->report_footer->height > priv->page->size->height - priv->page->margin->bottom - (priv->page_footer != NULL ? priv->page_footer->height : 0.0)) ||
-					    priv->report_footer->new_page_before)
+					rows = gda_data_model_get_n_rows (priv->db->gda_datamodel);
+					for (row = 0; row < rows; row++)
 						{
-							if (priv->page_header != NULL)
+							priv->cur_row = row;
+							if (row == 0 ||
+							    priv->body->new_page_after ||
+							    (priv->page_footer != NULL && (cur_y + priv->body->height > priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height)) ||
+							    cur_y > (priv->page->size->height - priv->page->margin->bottom))
 								{
-									priv->cur_row = row - 1;
-									rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_HEADER);
-									priv->cur_row = row;
+									if (priv->cur_page > 0 && priv->page_footer != NULL)
+										{
+											if ((priv->cur_page == 1 && priv->page_footer->first_page) ||
+											    priv->cur_page > 1)
+												{
+													cur_y = priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height;
+													priv->cur_row = row - 1;
+													rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER);
+													priv->cur_row = row;
+												}
+										}
+
+									cur_y = priv->page->margin->top;
+									xpage = rpt_report_rptprint_new_page (rpt_report, xdoc);
+
+									if (priv->page_header != NULL)
+										{
+											if ((priv->cur_page == 1 && priv->page_header->first_page) ||
+											    priv->cur_page > 1)
+												{
+													rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_HEADER);
+												}
+										}
+									if (priv->cur_page == 1 && priv->report_header != NULL)
+										{
+											rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_REPORT_HEADER);
+											if (priv->report_header->new_page_after)
+												{
+													cur_y = 0.0;
+													xpage = rpt_report_rptprint_new_page (rpt_report, xdoc);
+												}
+										}
 								}
 
-							cur_y = priv->page->margin->top;
-							xpage = rpt_report_rptprint_new_page (rpt_report, xdoc);
+							rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_BODY);
+						}
 
-							if (priv->cur_page > 0 && priv->page_footer != NULL)
+					if (priv->cur_page > 0 && priv->report_footer != NULL)
+						{
+							if ((cur_y + priv->report_footer->height > priv->page->size->height - priv->page->margin->bottom - (priv->page_footer != NULL ? priv->page_footer->height : 0.0)) ||
+							    priv->report_footer->new_page_before)
 								{
-									cur_y = priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height;
-									priv->cur_row = row - 1;
-									rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER);
-									priv->cur_row = row;
+									if (priv->page_header != NULL)
+										{
+											priv->cur_row = row - 1;
+											rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_HEADER);
+											priv->cur_row = row;
+										}
+
+									cur_y = priv->page->margin->top;
+									xpage = rpt_report_rptprint_new_page (rpt_report, xdoc);
+
+									if (priv->cur_page > 0 && priv->page_footer != NULL)
+										{
+											cur_y = priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height;
+											priv->cur_row = row - 1;
+											rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER);
+											priv->cur_row = row;
+										}
 								}
+
+							priv->cur_row = row - 1;
+							rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_REPORT_FOOTER);
+							priv->cur_row = row;
+						}
+
+					if (priv->cur_page > 0 && priv->page_footer != NULL && priv->page_footer->last_page)
+						{
+							cur_y = priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height;
+							priv->cur_row = row - 1;
+							rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER);
+							priv->cur_row = row;
 						}
-					priv->cur_row = row - 1;
-					rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_REPORT_FOOTER);
-					priv->cur_row = row;
-				}
-			if (priv->cur_page > 0 && priv->page_footer != NULL && priv->page_footer->last_page)
-				{
-					cur_y = priv->page->size->height - priv->page->margin->bottom - priv->page_footer->height;
-					priv->cur_row = row - 1;
-					rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER);
-					priv->cur_row = row;
 				}
 
 			/* change @Pages */
 			rpt_report_change_specials (rpt_report, xdoc);
 
 			priv->cur_row = -1;
+			priv->cur_iter = NULL;
 		}
 	else
 		{
@@ -2458,40 +2581,68 @@ gchar
                        const gchar *field_name)
 {
 	GError *error;
+
 	gint col;
+	GValue *gval;
+
 	gchar *ret = NULL;
 
 	RptReportPrivate *priv = RPT_REPORT_GET_PRIVATE (rpt_report);
 
-	if (priv->db != NULL && priv->db->gda_datamodel != NULL)
+	if (priv->db != NULL)
 		{
-			col = gda_data_model_get_column_index (priv->db->gda_datamodel, field_name);
-
-			if (col > -1)
+			if (priv->db->treemodel != NULL
+			    && priv->db->columns_names != NULL)
 				{
-					GValue *gval;
+					gchar *str_col;
 
-					error = NULL;
-					gval = (GValue *)gda_data_model_get_value_at (priv->db->gda_datamodel, col, priv->cur_row, &error);
-					if (error != NULL)
+					str_col = (gchar *)g_hash_table_lookup (priv->db->columns_names, field_name);
+					if (str_col != NULL)
 						{
-							g_warning ("Error on retrieving field «%s» value: %s.",
-							           field_name,
-							           error->message != NULL ? error->message : "no details");
+							str_col = g_strstrip (g_strdup (str_col));
+							if (g_strcmp0 (str_col, "") != 0)
+								{
+									gval = g_new0 (GValue, 1);
+
+									col = strtol (str_col, NULL, 10);
+									gtk_tree_model_get_value (priv->db->treemodel, priv->cur_iter,
+									                          col, gval);
+
+									ret = (gchar *)gda_value_stringify (gval);
+
+									g_value_unset (gval);
+									g_free (str_col);
+								}
 						}
-					else
+				}
+			else if (priv->db->gda_datamodel != NULL)
+				{
+					col = gda_data_model_get_column_index (priv->db->gda_datamodel, field_name);
+
+					if (col > -1)
 						{
-							if (gda_value_is_null (gval))
+							error = NULL;
+							gval = (GValue *)gda_data_model_get_value_at (priv->db->gda_datamodel, col, priv->cur_row, &error);
+							if (error != NULL)
 								{
-									ret = g_strdup ("");
+									g_warning ("Error on retrieving field «%s» value: %s.",
+									           field_name,
+									           error->message != NULL ? error->message : "no details");
 								}
 							else
 								{
-									ret = (gchar *)gda_value_stringify (gval);
-									if (ret == NULL)
+									if (gda_value_is_null (gval))
 										{
 											ret = g_strdup ("");
 										}
+									else
+										{
+											ret = (gchar *)gda_value_stringify (gval);
+											if (ret == NULL)
+												{
+													ret = g_strdup ("");
+												}
+										}
 								}
 						}
 				}
@@ -2519,10 +2670,24 @@ gchar
 
 	RptReportClass *klass = RPT_REPORT_GET_CLASS (rpt_report);
 
-	if (priv->db != NULL && priv->db->gda_datamodel != NULL)
+	if (priv->db != NULL)
 		{
-			g_signal_emit (rpt_report, klass->field_request_signal_id,
-			               0, field, priv->db->gda_datamodel, priv->cur_row, &ret);
+			if (priv->db->gda_datamodel != NULL)
+				{
+					g_signal_emit (rpt_report, klass->field_request_signal_id,
+					               0, field,
+					               priv->db->gda_datamodel, priv->cur_row,
+					               NULL, NULL,
+					               &ret);
+				}
+			else if (priv->db->treemodel != NULL)
+				{
+					g_signal_emit (rpt_report, klass->field_request_signal_id,
+					               0, field,
+					               NULL, NULL,
+					               priv->db->treemodel, priv->cur_iter,
+					               &ret);
+				}
 		}
 	else
 		{
diff --git a/src/rptreport.h b/src/rptreport.h
index 9b27daa..0f38a3a 100644
--- a/src/rptreport.h
+++ b/src/rptreport.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2011 Andrea Zagli <azagli@inwind.it>
+ * Copyright (C) 2007-2011 Andrea Zagli <azagli@libero.it>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -86,7 +86,9 @@ void rpt_report_set_database (RptReport *rpt_report,
 
 void rpt_report_set_database_from_datamodel (RptReport *rpt_report, GdaDataModel *data_model);
 
-void rpt_report_set_database_as_gtktreemodel (RptReport *rpt_report, GtkTreeModel *model);
+void rpt_report_set_database_as_gtktreemodel (RptReport *rpt_report,
+                                              GtkTreeModel *model,
+                                              GHashTable *columns_names);
 
 RptSize *rpt_report_get_page_size (RptReport *rpt_report);
 void rpt_report_set_page_size (RptReport *rpt_report,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b491e5a..6f43e57 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,11 +8,13 @@ libreptool = $(top_builddir)/src/libreptool.la
 noinst_PROGRAMS = \
                   test_rptreport \
                   test_rptprint \
-                  test_rptreport_creation
+                  test_rptreport_creation \
+                  test_rptreport_liststore
 
 LDADD = $(libreptool)
 
 EXTRA_DIST = \
              test_report.rpt \
              test_report_db.rpt \
-             test_rptprint.rptr
+             test_rptprint.rptr \
+             db_test.db
diff --git a/tests/test_rptreport.c b/tests/test_rptreport.c
index 98ad740..035ad3a 100644
--- a/tests/test_rptreport.c
+++ b/tests/test_rptreport.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2011 Andrea Zagli <azagli@inwind.it>
+ * Copyright (C) 2007-2011 Andrea Zagli <azagli@libero.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@ gchar
                 gchar *field_name,
                 GdaDataModel *data_model,
                 gint row,
+                GtkTreeModel *treemodel,
+                GtkTreeIter *iter,
                 gpointer user_data)
 {
 	gchar *ret = NULL;
@@ -67,6 +69,8 @@ main (int argc, char **argv)
 			rptp = rpt_print_new_from_xml (rptprint);
 			if (rptp != NULL)
 				{
+					g_object_set (G_OBJECT (rptp), "path-relatives-to", "..", NULL);
+
 					rpt_print_set_output_type (rptp, RPT_OUTPUT_PDF);
 					rpt_print_set_output_filename (rptp, "test.pdf");
 					rpt_print_print (rptp, NULL);
diff --git a/tests/test_rptreport_liststore.c b/tests/test_rptreport_liststore.c
new file mode 100644
index 0000000..cc9e22c
--- /dev/null
+++ b/tests/test_rptreport_liststore.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 Andrea Zagli <azagli@libero.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+ */
+
+#include <rptreport.h>
+#include <rptprint.h>
+
+gchar
+*field_request (RptReport *rpt_report,
+                gchar *field_name,
+                GdaDataModel *data_model,
+                gint row,
+                GtkTreeModel *treemodel,
+                GtkTreeIter *iter,
+                gpointer user_data)
+{
+	gchar *ret = NULL;
+
+	if (g_strcmp0 (field_name, "nonexistent") == 0 &&
+	    treemodel != NULL &&
+	    iter != NULL)
+		{
+			gint id;
+			gchar *name;
+
+			gtk_tree_model_get (treemodel, iter,
+			                    0, &id,
+			                    1, &name,
+			                    -1);
+
+			ret = g_strdup_printf ("%d - %s", id, name);
+		}
+
+	return ret;
+}
+
+int
+main (int argc, char **argv)
+{
+	RptReport *rptr;
+	RptPrint *rptp;
+
+	GtkListStore *model;
+	GtkTreeIter iter;
+	GHashTable *columns_names;
+
+	g_type_init ();
+
+	rptr = rpt_report_new_from_file (argv[1]);
+
+	model = gtk_list_store_new (2,
+	                            G_TYPE_INT,
+	                            G_TYPE_STRING);
+
+	gtk_list_store_append (model, &iter);
+	gtk_list_store_set (model, &iter,
+	                    0, 1,
+	                    1, "Mary Jane Red",
+	                    -1);
+
+	gtk_list_store_append (model, &iter);
+	gtk_list_store_set (model, &iter,
+	                    0, 2,
+	                    1, "John Doe",
+	                    -1);
+
+	gtk_list_store_append (model, &iter);
+	gtk_list_store_set (model, &iter,
+	                    0, 3,
+	                    1, "Elene McArty",
+	                    -1);
+
+	gtk_list_store_append (model, &iter);
+	gtk_list_store_set (model, &iter,
+	                    0, 4,
+	                    1, "Raul Bread",
+	                    -1);
+
+	columns_names = g_hash_table_new (g_str_hash, g_str_equal);
+	g_hash_table_insert (columns_names, "id", "0");
+	g_hash_table_insert (columns_names, "name", "1");
+
+	rpt_report_set_database_as_gtktreemodel (rptr, GTK_TREE_MODEL (model), columns_names);
+
+	g_signal_connect (rptr, "field-request", G_CALLBACK (field_request), NULL);
+
+	if (rptr != NULL)
+		{
+			xmlDoc *report = rpt_report_get_xml (rptr);
+			xmlSaveFormatFile ("test_report.rpt", report, 2);
+
+			xmlDoc *rptprint = rpt_report_get_xml_rptprint (rptr);
+			xmlSaveFormatFile ("test_report.rptr", rptprint, 2);
+		
+			rptp = rpt_print_new_from_xml (rptprint);
+			if (rptp != NULL)
+				{
+					g_object_set (G_OBJECT (rptp), "path-relatives-to", "..", NULL);
+
+					rpt_print_set_output_type (rptp, RPT_OUTPUT_PDF);
+					rpt_print_set_output_filename (rptp, "test.pdf");
+					rpt_print_print (rptp, NULL);
+				}
+		}
+
+	return 0;
+}