/* GDA library * Copyright (C) 1998-2002 The GNOME Foundation. * * AUTHORS: * Rodrigo Moya * * 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. */ #include #include #include #define PARENT_TYPE GDA_TYPE_DATA_MODEL_ARRAY struct _GdaTablePrivate { gchar *name; GHashTable *fields; }; enum { NAME_CHANGED, LAST_SIGNAL }; static void gda_table_class_init (GdaTableClass *klass); static void gda_table_init (GdaTable *table, GdaTableClass *klass); static void gda_table_finalize (GObject *object); static guint gda_table_signals[LAST_SIGNAL]; static GObjectClass *parent_class = NULL; /* * GdaTable class implementation */ typedef struct { GdaTable *table; gint col_to_search; GdaFieldAttributes *fa; } DescColData; static void search_field_in_hash (gpointer key, gpointer value, gpointer user_data) { DescColData *cb_data = user_data; GdaFieldAttributes *fa = value; if (cb_data->fa) return; if (gda_field_attributes_get_position (fa) == cb_data->col_to_search) cb_data->fa = fa; } static GdaFieldAttributes * gda_table_describe_column (GdaDataModel *model, gint col) { DescColData cb_data; GdaFieldAttributes *new_fa; GdaTable *table = (GdaTable *) model; g_return_val_if_fail (GDA_IS_TABLE (table), NULL); if (col >= g_hash_table_size (table->priv->fields)) return NULL; cb_data.table = table; cb_data.col_to_search = col; cb_data.fa = NULL; g_hash_table_foreach (table->priv->fields, (GHFunc) search_field_in_hash, &cb_data); if (!cb_data.fa) return NULL; new_fa = gda_field_attributes_copy (cb_data.fa); return new_fa; } static void gda_table_class_init (GdaTableClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GdaDataModelClass *model_class = GDA_DATA_MODEL_CLASS (klass); parent_class = g_type_class_peek_parent (klass); gda_table_signals[NAME_CHANGED] = g_signal_new ("name_changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GdaTableClass, name_changed), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); object_class->finalize = gda_table_finalize; model_class->describe_column = gda_table_describe_column; } static void gda_table_init (GdaTable *table, GdaTableClass *klass) { g_return_if_fail (GDA_IS_TABLE (table)); /* allocate internal structure */ table->priv = g_new0 (GdaTablePrivate, 1); table->priv->name = NULL; table->priv->fields = g_hash_table_new (g_str_hash, g_str_equal); } static gboolean remove_field_hash (gpointer key, gpointer value, gpointer user_data) { g_free (key); gda_field_attributes_free (value); return TRUE; } static void gda_table_finalize (GObject *object) { GdaTable *table = (GdaTable *) object; g_return_if_fail (GDA_IS_TABLE (table)); /* free memory */ if (table->priv->name) { g_free (table->priv->name); table->priv->name = NULL; } g_hash_table_foreach_remove (table->priv->fields, remove_field_hash, NULL); g_hash_table_destroy (table->priv->fields); table->priv->fields = NULL; g_free (table->priv); table->priv = NULL; /* chain to parent class */ parent_class->finalize (object); } GType gda_table_get_type (void) { static GType type = 0; if (!type) { static const GTypeInfo info = { sizeof (GdaTableClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gda_table_class_init, NULL, NULL, sizeof (GdaTable), 0, (GInstanceInitFunc) gda_table_init }; type = g_type_register_static (PARENT_TYPE, "GdaTable", &info, 0); } return type; } /** * gda_table_new * @name: name for the new table. * * Creates a new #GdaTable object, which is an in-memory representation * of an entire table. It is mainly used by the #GdaXmlDatabase class, * but you can also use it in your applications for whatever you may need * it. * * Returns: the newly created object. */ GdaTable * gda_table_new (const gchar *name) { GdaTable *table; g_return_val_if_fail (name != NULL, NULL); table = g_object_new (GDA_TYPE_TABLE, NULL); table->priv->name = g_strdup (name); return table; } /** * gda_table_new_from_model * @name: name for the new table. * @model: model to create the table from. * @add_data: whether to add model's data or not. * * Creates a #GdaTable object from the given #GdaDataModel. This * is very useful to maintain an in-memory copy of a given * recordset obtained from a database. This is also used when * exporting data to a #GdaXmlDatabase object. * * Returns: the newly created object. */ GdaTable * gda_table_new_from_model (const gchar *name, const GdaDataModel *model, gboolean add_data) { GdaTable *table; gint n; gint cols; g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (GDA_IS_DATA_MODEL (model), NULL); table = gda_table_new (name); if (!table) return NULL; /* add the columns description */ cols = gda_data_model_get_n_columns (GDA_DATA_MODEL (model)); for (n = 0; n < cols; n++) { GdaFieldAttributes *fa; fa = gda_data_model_describe_column (GDA_DATA_MODEL (model), n); gda_table_add_field (table, (const GdaFieldAttributes *) fa); gda_field_attributes_free (fa); } /* add the data */ if (add_data) gda_table_add_data_from_model (table, model); return table; } /** * gda_table_get_name * @table: a #GdaTable object. * * Returns: the name of the given #GdaTable. */ const gchar * gda_table_get_name (GdaTable *table) { g_return_val_if_fail (GDA_IS_TABLE (table), NULL); return (const gchar *) table->priv->name; } /** * gda_table_set_name * @table: a #GdaTable object. * @name: new name for the table. * * Sets the name of the given #GdaTable. */ void gda_table_set_name (GdaTable *table, const gchar *name) { gchar *old_name; g_return_if_fail (GDA_IS_TABLE (table)); g_return_if_fail (name != NULL); old_name = g_strdup (table->priv->name); if (table->priv->name) g_free (table->priv->name); table->priv->name = g_strdup (name); g_signal_emit (G_OBJECT (table), gda_table_signals[NAME_CHANGED], 0, old_name); gda_data_model_changed (GDA_DATA_MODEL (table)); } /** * gda_table_add_field * @table: a #GdaTable object. * @fa: attributes for the new field. * * Adds a field to the given #GdaTable. */ void gda_table_add_field (GdaTable *table, const GdaFieldAttributes *fa) { const gchar *name; GdaFieldAttributes *new_fa; g_return_if_fail (GDA_IS_TABLE (table)); g_return_if_fail (fa != NULL); name = gda_field_attributes_get_name ((GdaFieldAttributes *) fa); if (!name || !*name) return; /* we first look for a field with the same name */ if (g_hash_table_lookup (table->priv->fields, name)) { gda_log_error (_("There is already a field called %s"), name); return; } /* add the new field to the table */ new_fa = gda_field_attributes_new (); gda_field_attributes_set_table (new_fa, table->priv->name); gda_field_attributes_set_position (new_fa, g_hash_table_size (table->priv->fields)); gda_field_attributes_set_defined_size (new_fa, gda_field_attributes_get_defined_size ((GdaFieldAttributes *) fa)); gda_field_attributes_set_name (new_fa, name); gda_field_attributes_set_scale (new_fa, gda_field_attributes_get_scale ((GdaFieldAttributes *) fa)); gda_field_attributes_set_gdatype (new_fa, gda_field_attributes_get_gdatype ((GdaFieldAttributes *) fa)); gda_field_attributes_set_allow_null (new_fa, gda_field_attributes_get_allow_null ((GdaFieldAttributes *) fa)); g_hash_table_insert (table->priv->fields, g_strdup (name), new_fa); gda_data_model_array_set_n_columns (GDA_DATA_MODEL_ARRAY (table), g_hash_table_size (table->priv->fields)); } /** * gda_table_add_data_from_model * @table: a #GdaTable object. * @model: a #GdaDataModel object. * * Adds data in the given @table from the given @model. */ void gda_table_add_data_from_model (GdaTable *table, const GdaDataModel *model) { g_return_if_fail (GDA_IS_TABLE (table)); g_return_if_fail (GDA_IS_DATA_MODEL (model)); /* FIXME: implement me */ }