[libgda] GdaDataModelIter: allow the "data-model" property to be used after construction



commit 9e92187092d333f7173ec40ec3d93ab14e2c0b33
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sat Apr 7 21:31:21 2012 +0200

    GdaDataModelIter: allow the "data-model" property to be used after construction

 configure.ac                 |    1 +
 libgda/gda-data-model-iter.c |   17 ++--
 libgda/gda-data-model-iter.h |   11 +++
 tests/Makefile.am            |    6 +-
 tests/ui/.gitignore          |    1 +
 tests/ui/Makefile.am         |   18 ++++
 tests/ui/check_sets.c        |  191 ++++++++++++++++++++++++++++++++++++++++++
 tests/ui/common.c            |   99 ++++++++++++++++++++++
 tests/ui/common.h            |   28 ++++++
 9 files changed, 364 insertions(+), 8 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 3d2495f..a1e9ad4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -957,6 +957,7 @@ tests/providers/Makefile
 tests/value-holders/Makefile
 tests/meta-store/Makefile
 tests/multi-threading/Makefile
+tests/ui/Makefile
 tests/vala/Makefile
 doc/Makefile
 doc/C/Makefile
diff --git a/libgda/gda-data-model-iter.c b/libgda/gda-data-model-iter.c
index 8b7ef8a..ca3036f 100644
--- a/libgda/gda-data-model-iter.c
+++ b/libgda/gda-data-model-iter.c
@@ -183,7 +183,7 @@ gda_data_model_iter_class_init (GdaDataModelIterClass *class)
 					 g_param_spec_object ("data-model", NULL, "Data model for which the iter is for", 
                                                                GDA_TYPE_DATA_MODEL, 
 							       (G_PARAM_READABLE | G_PARAM_WRITABLE |
-								G_PARAM_CONSTRUCT_ONLY)));
+								G_PARAM_CONSTRUCT)));
 	g_object_class_install_property (object_class, PROP_FORCED_MODEL,
 					 g_param_spec_object ("forced-model", NULL, "Overrides the data model the iter "
 							      "is attached to (reserved for internal usage)", 
@@ -351,12 +351,14 @@ model_reset_cb (GdaDataModel *model, GdaDataModelIter *iter)
 		l2 = g_slist_copy (list);
 		for (list = l2; list; list = list->next)
 			gda_set_remove_holder ((GdaSet*) iter, (GdaHolder *) list->data);
-		g_slist_free (l2);		
+		g_slist_free (l2);
+		row = -1; /* force actual reset of iterator's position */
 	}
 
 	if (i < nbcols) {
 		for (; i < nbcols; i++)
 			define_holder_for_data_model_column (model, i, iter);
+		row = -1; /* force actual reset of iterator's position */
 	}
 
 	gda_data_model_iter_invalidate_contents (iter);
@@ -525,13 +527,13 @@ gda_data_model_iter_set_property (GObject *object,
 			g_return_if_fail (ptr && GDA_IS_DATA_MODEL (ptr));
 			model = GDA_DATA_MODEL (ptr);
 			
-			/* REM: model is actually set in the next property's code (there is no break statement) */
-
-			/* compute parameters */
+			/* REM: model is actually set in the next property's code
+			 * (there is no break statement) */
+			/*
 			ncols = gda_data_model_get_n_columns (model);
-			for (col = 0; col < ncols; col++) {
+			for (col = 0; col < ncols; col++)
 				define_holder_for_data_model_column (model, col, iter);
-			}
+			*/
 		}
 		case PROP_FORCED_MODEL: {
 			GdaDataModel* ptr = g_value_get_object (value);
@@ -556,6 +558,7 @@ gda_data_model_iter_set_property (GObject *object,
 										  G_CALLBACK (model_row_removed_cb), iter);
 			iter->priv->model_changes_signals [2] = g_signal_connect (G_OBJECT (ptr), "reset",
 										  G_CALLBACK (model_reset_cb), iter);
+			model_reset_cb (iter->priv->data_model, iter);
 			break;
                 }
 		case PROP_CURRENT_ROW:
diff --git a/libgda/gda-data-model-iter.h b/libgda/gda-data-model-iter.h
index ff12490..d687a05 100644
--- a/libgda/gda-data-model-iter.h
+++ b/libgda/gda-data-model-iter.h
@@ -112,6 +112,17 @@ struct _GdaDataModelIterClass
  * Note: the new #GdaDataModelIter does not hold any reference to the data model it iterates through (ie.
  * if this data model is destroyed at some point, the new iterator will become useless but in
  * any case it will not prevent the data model from being destroyed).
+ *
+ * Note: when the data model emits the "reset" signal, then:
+ * <itemizedlist>
+ *  <listitem><para>the number of columns of the iterator can change to reflect the new data model
+ *    being itered on. In this case the iterator's position is reset as if it was
+ *    just created</para></listitem>
+ *  <listitem><para>some column types which were unknown (i.e. GDA_TYPE_NULL type), can change
+ *    to their correct type. In this case there is no other iterator change</para></listitem>
+ *  <listitem><para>some column types which were not GDA_TYPE_NULL can change, and in this case
+ *    the iterator's position is reset as if it was just created</para></listitem>
+ * </itemizedlist>
  */
 
 GType             gda_data_model_iter_get_type             (void) G_GNUC_CONST;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0a811fc..f47077a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,7 +8,11 @@ if ENABLE_VALA_EXTENSIONS
     VALA_EXTENSIONS= vala
 endif
 
-SUBDIRS = providers parser value-holders meta-store data-models multi-threading $(VALA_EXTENSIONS)
+if HAVE_UI
+UI_EXTENSION = ui
+endif
+
+SUBDIRS = providers parser value-holders meta-store data-models multi-threading $(UI_EXTENSION) $(VALA_EXTENSIONS)
 
 AM_CPPFLAGS = \
         -I$(top_builddir) \
diff --git a/tests/ui/.gitignore b/tests/ui/.gitignore
new file mode 100644
index 0000000..4bfdf4c
--- /dev/null
+++ b/tests/ui/.gitignore
@@ -0,0 +1 @@
+check_sets
\ No newline at end of file
diff --git a/tests/ui/Makefile.am b/tests/ui/Makefile.am
new file mode 100644
index 0000000..434edf9
--- /dev/null
+++ b/tests/ui/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/libgda \
+	-I$(top_builddir) \
+	$(COREDEPS_CFLAGS) \
+	$(COREDEPS_WFLAGS) \
+	$(GTK_CFLAGS) \
+	-DROOT_DIR=\""$(top_srcdir)"\"
+
+TESTS = check_sets
+check_PROGRAMS = check_sets
+
+check_sets_SOURCES = common.c common.h check_sets.c
+check_sets_LDADD = \
+	$(top_builddir)/libgda/libgda-5.0.la \
+	$(top_builddir)/libgda-ui/libgda-ui-5.0.la \
+	$(COREDEPS_LIBS) \
+	$(GTK_LIBS)
diff --git a/tests/ui/check_sets.c b/tests/ui/check_sets.c
new file mode 100644
index 0000000..f431614
--- /dev/null
+++ b/tests/ui/check_sets.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2012 Vivien Malerba <malerba gnome-db org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include <stdio.h>
+#include <libgda/libgda.h>
+#include <libgda-ui/libgda-ui.h>
+#include "common.h"
+
+GdaConnection *cnc = NULL;
+
+static gboolean test_iter (GdaConnection *cnc);
+
+int 
+main (int argc, char** argv)
+{
+	int number_failed = 0;
+
+	gtk_init (&argc, &argv);
+	gdaui_init ();
+	cnc = ui_tests_common_open_connection ();
+
+	if (!test_iter (cnc))
+		number_failed++;
+	
+	if (number_failed == 0)
+                g_print ("Ok.\n");
+        else
+                g_print ("%d failed\n", number_failed);
+        return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+static void
+dump_iter (GdaDataModelIter *iter)
+{
+	GdaSet *set;
+	GSList *list;
+	set = GDA_SET (iter);
+	g_print ("Dump of GdaDataModelIter %p, @row %d\n", set, gda_data_model_iter_get_row (iter));
+	for (list = set->holders; list; list = list->next) {
+		GdaHolder *h = GDA_HOLDER (list->data);
+		gchar *str;
+		const GValue *cvalue;
+		cvalue = gda_holder_get_value (h);
+		str = gda_value_stringify (cvalue);
+		g_print ("   [%s] type: %s value:[%s]\n", gda_holder_get_id (h),
+			 gda_g_type_to_string (gda_holder_get_g_type (h)), str);
+		g_free (str);
+	}
+}
+
+static gboolean
+compare_iter (GdaDataModelIter *iter, gint exp_row, const gchar **col_ids, const gchar **col_types,
+	      const gchar **col_values)
+{
+	
+	GdaSet *set;
+	GSList *list;
+	gint i;
+	set = GDA_SET (iter);
+
+	if (gda_data_model_iter_get_row (iter) != exp_row) {
+		g_print ("Iter is at wrong row: got %d and expected %d\n",
+			 gda_data_model_iter_get_row (iter), exp_row);
+		return FALSE;
+	}
+
+	if (!col_ids)
+		return TRUE;
+
+	for (i = 0, list = set->holders;
+	     col_ids[i] && list;
+	     i++, list = list->next) {
+		GdaHolder *h = GDA_HOLDER (list->data);
+		gchar *str;
+		const GValue *cvalue;
+		if (strcmp (col_ids[i], gda_holder_get_id (h))) {
+			g_print ("Wrong column %d ID: got [%s] and expected [%s]\n", i,
+				 gda_holder_get_id (h), col_ids[i]);
+			return FALSE;
+		}
+
+		if (strcmp (col_types[i], gda_g_type_to_string (gda_holder_get_g_type (h)))) {
+			g_print ("Wrong column %d type: got [%s] and expected [%s]\n", i,
+				 gda_g_type_to_string (gda_holder_get_g_type (h)),
+				 col_types[i]);
+			return FALSE;
+		}
+
+		cvalue = gda_holder_get_value (h);
+		str = gda_value_stringify (cvalue);
+		if (strcmp (col_values[i], str)) {
+			g_print ("Wrong column %d value: got [%s] and expected [%s]\n", i,
+				 str, col_types[i]);
+			g_free (str);
+			return FALSE;
+		}
+		g_free (str);
+	}
+
+	if (col_ids[i]) {
+		g_print ("Missing at least the [%s] column %d\n", col_ids[i], i);
+		return FALSE;
+	}
+
+	if (list) {
+		GdaHolder *h = GDA_HOLDER (list->data);
+		g_print ("Too much columns, at least [%s] column %d\n",
+			 gda_holder_get_id (h), i);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+test_iter (GdaConnection *cnc)
+{
+	gboolean retval = FALSE;
+	GdaDataModel *model1, *model2;
+	GdaDataModelIter *iter;
+
+	model1 = ui_tests_common_get_products_2cols (cnc, TRUE);
+	model2 = ui_tests_common_get_products (cnc, FALSE);
+	iter = gda_data_model_create_iter (model1);
+
+	const gchar *col_ids[] = {"ref", "category", NULL};
+	const gchar *col_types[] = {"string", "int", NULL};
+	const gchar *col_values[] = {"1", "14", NULL};
+
+	g_assert (gda_data_model_iter_move_next (iter));
+	dump_iter (iter);
+	if (!compare_iter (iter, 0, col_ids, col_types, col_values)) {
+		g_print ("Error, step1\n");
+		goto out;
+	}
+
+	g_object_set (iter, "data-model", model2, NULL);
+	dump_iter (iter);
+	if (!compare_iter (iter, -1, NULL, NULL, NULL)) {
+		g_print ("Error, step2\n");
+		goto out;
+	}
+
+	const gchar *col_ids3[] = {"ref", "category", "name", "price", "wh_stored", NULL};
+	const gchar *col_types3[] = {"string", "int", "string", "gdouble", "int", NULL};
+	const gchar *col_values3[] = {"1", "14", "ACADEMY ACADEMY", "25,990000", "0", NULL};
+
+	g_assert (gda_data_model_iter_move_next (iter));
+	dump_iter (iter);
+	if (!compare_iter (iter, 0, col_ids3, col_types3, col_values3)) {
+		g_print ("Error, step3\n");
+		goto out;
+	}
+
+	g_object_set (iter, "data-model", model1, NULL);
+	dump_iter (iter);
+	if (!compare_iter (iter, -1, NULL, NULL, NULL)) {
+		g_print ("Error, step2\n");
+		goto out;
+	}
+	g_assert (gda_data_model_iter_move_next (iter));
+	dump_iter (iter);
+	if (!compare_iter (iter, 0, col_ids, col_types, col_values)) {
+		g_print ("Error, step3\n");
+		goto out;
+	}
+	
+
+	retval = TRUE;
+
+ out:
+	g_object_unref (model1);
+	g_object_unref (model2);
+	g_object_unref (iter);
+
+	return retval;
+}
diff --git a/tests/ui/common.c b/tests/ui/common.c
new file mode 100644
index 0000000..3e09f72
--- /dev/null
+++ b/tests/ui/common.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2012 Vivien Malerba <malerba gnome-db org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include "common.h"
+#include <sql-parser/gda-sql-parser.h>
+
+GdaConnection *
+ui_tests_common_open_connection (void)
+{
+	GdaConnection *cnc;
+	gchar *cnc_string, *fname;
+	fname = g_build_filename (ROOT_DIR, "data", NULL);
+	cnc_string = g_strdup_printf ("DB_DIR=%s;DB_NAME=sales_test", fname);
+	g_free (fname);
+	cnc = gda_connection_open_from_string ("SQLite", cnc_string, NULL,
+					       GDA_CONNECTION_OPTIONS_READ_ONLY, NULL);
+	if (!cnc) {
+		g_print ("Failed to open connection, cnc_string = %s\n", cnc_string);
+		exit (1);
+	}
+	g_free (cnc_string);
+	return cnc;
+}
+
+static GdaStatement *
+stmt_from_string (const gchar *sql)
+{
+        GdaStatement *stmt;
+        GError *error = NULL;
+
+        static GdaSqlParser *parser = NULL;
+        if (!parser)
+                parser = gda_sql_parser_new ();
+
+        stmt = gda_sql_parser_parse_string (parser, sql, NULL, &error);
+        if (!stmt) {
+                g_print ("Cound not parse SQL: %s\nSQL was: %s\n",
+                         error && error->message ? error->message : "No detail",
+                         sql);
+                exit (EXIT_FAILURE);
+        }
+        return stmt;
+}
+
+GdaDataModel *
+ui_tests_common_get_products (GdaConnection *cnc, gboolean part_only)
+{
+	GError *error = NULL;
+        GdaDataModel *model;
+	GdaStatement *stmt;
+
+	if (part_only)
+		stmt = stmt_from_string ("SELECT * FROM products WHERE price > 20.2 ORDER BY ref, category LIMIT 10");
+	else
+		stmt = stmt_from_string ("SELECT * FROM products ORDER BY ref, category LIMIT 15");
+        model = gda_connection_statement_execute_select (cnc, stmt, NULL, &error);
+	if (!model) {
+		g_print ("Failed to get list of products: %s\n",
+			 error && error->message ? error->message : "No detail");
+		exit (1);
+	}
+
+	return model;
+}
+
+GdaDataModel *
+ui_tests_common_get_products_2cols (GdaConnection *cnc, gboolean part_only)
+{
+	GError *error = NULL;
+        GdaDataModel *model;
+	GdaStatement *stmt;
+
+	if (part_only)
+		stmt = stmt_from_string ("SELECT ref, category FROM products WHERE price > 20.2 ORDER BY ref, category  LIMIT 10");
+	else
+		stmt = stmt_from_string ("SELECT ref, category FROM products ORDER BY ref, category LIMIT 15");
+        model = gda_connection_statement_execute_select (cnc, stmt, NULL, &error);
+	if (!model) {
+		g_print ("Failed to get list of products: %s\n",
+			 error && error->message ? error->message : "No detail");
+		exit (1);
+	}
+
+	return model;
+}
diff --git a/tests/ui/common.h b/tests/ui/common.h
new file mode 100644
index 0000000..86cd415
--- /dev/null
+++ b/tests/ui/common.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Vivien Malerba <malerba gnome-db org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include <libgda/libgda.h>
+#include <string.h>
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+GdaConnection *ui_tests_common_open_connection (void);
+GdaDataModel  *ui_tests_common_get_products (GdaConnection *cnc, gboolean part_only);
+GdaDataModel  *ui_tests_common_get_products_2cols (GdaConnection *cnc, gboolean part_only);
+
+#endif



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