[libgda] Added gda_data_access_wrapper_set_mapping()
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] Added gda_data_access_wrapper_set_mapping()
- Date: Sun, 19 Feb 2012 20:16:37 +0000 (UTC)
commit e91042e41fd06fea19cf3a7b076fb4a6bcaa7c6e
Author: Vivien Malerba <malerba gnome-db org>
Date: Thu Feb 9 22:45:21 2012 +0100
Added gda_data_access_wrapper_set_mapping()
to reorder and/or hide columns using a GdaDataAccessWrapper
doc/C/libgda-sections.txt | 1 +
libgda/gda-data-access-wrapper.c | 174 +++++++++++++++++++++++++++++++++-----
libgda/gda-data-access-wrapper.h | 4 +-
libgda/libgda.symbols | 1 +
4 files changed, 158 insertions(+), 22 deletions(-)
---
diff --git a/doc/C/libgda-sections.txt b/doc/C/libgda-sections.txt
index e44f533..36aa971 100644
--- a/doc/C/libgda-sections.txt
+++ b/doc/C/libgda-sections.txt
@@ -331,6 +331,7 @@ GdaDataAccessWrapper
GdaDataAccessWrapperClass
GdaDataAccessWrapperPrivate
gda_data_access_wrapper_new
+gda_data_access_wrapper_set_mapping
<SUBSECTION Standard>
GDA_DATA_ACCESS_WRAPPER
GDA_DATA_ACCESS_WRAPPER_CLASS
diff --git a/libgda/gda-data-access-wrapper.c b/libgda/gda-data-access-wrapper.c
index 623a89e..abb2c49 100644
--- a/libgda/gda-data-access-wrapper.c
+++ b/libgda/gda-data-access-wrapper.c
@@ -42,13 +42,17 @@ struct _GdaDataAccessWrapperPrivate {
gint iter_row;/* current row of @iter, starting at 0 when created */
GHashTable *rows; /* NULL if @model already is random access */
- gint nb_cols; /* number of columns of @model */
+ gint nb_cols; /* number of columns of @wrapper */
gint last_row;/* row number of the last row which has been read */
gboolean end_of_data; /* TRUE if the end of the data model has been reached by the iterator */
GArray *rows_buffer_array; /* Array of GdaRow */
GArray *rows_buffer_index; /* Array of indexes: GdaRow at index i in @rows_buffer_array
* is indexed in @rows with key rows_buffer_index[i] */
+
+ /* rows mapping */
+ GSList *columns; /* not NULL if a mapping exists */
+ gint *rows_mapping; /* @nb_cols is set when @rows_mapping is set, and @rows_mapping's size is @nb_cols */
};
/* properties */
@@ -212,6 +216,30 @@ model_row_removed_cb (G_GNUC_UNUSED GdaDataModel *mod, gint row, GdaDataAccessWr
}
static void
+clear_internal_state (GdaDataAccessWrapper *model)
+{
+ if (model->priv) {
+ if (model->priv->columns) {
+ g_slist_foreach (model->priv->columns, (GFunc) g_object_unref, NULL);
+ g_slist_free (model->priv->columns);
+ model->priv->columns = NULL;
+ }
+
+ model->priv->nb_cols = 0;
+
+ if (model->priv->rows_buffer_array) {
+ g_array_free (model->priv->rows_buffer_array, TRUE);
+ model->priv->rows_buffer_array = NULL;
+ }
+
+ if (model->priv->rows_buffer_index) {
+ g_array_free (model->priv->rows_buffer_index, TRUE);
+ model->priv->rows_buffer_index = NULL;
+ }
+ }
+}
+
+static void
gda_data_access_wrapper_dispose (GObject *object)
{
GdaDataAccessWrapper *model = (GdaDataAccessWrapper *) object;
@@ -220,6 +248,9 @@ gda_data_access_wrapper_dispose (GObject *object)
/* free memory */
if (model->priv) {
+ /* random access model free */
+ clear_internal_state (model);
+
if (model->priv->iter) {
g_signal_handlers_disconnect_by_func (G_OBJECT (model->priv->iter),
G_CALLBACK (iter_row_changed_cb), model);
@@ -230,7 +261,6 @@ gda_data_access_wrapper_dispose (GObject *object)
model->priv->iter = NULL;
}
- /* random access model free */
if (model->priv->model) {
if (model->priv->rows) {
g_hash_table_destroy (model->priv->rows);
@@ -247,16 +277,6 @@ gda_data_access_wrapper_dispose (GObject *object)
g_object_unref (model->priv->model);
model->priv->model = NULL;
}
-
- if (model->priv->rows_buffer_array) {
- g_array_free (model->priv->rows_buffer_array, TRUE);
- model->priv->rows_buffer_array = NULL;
- }
-
- if (model->priv->rows_buffer_index) {
- g_array_free (model->priv->rows_buffer_index, TRUE);
- model->priv->rows_buffer_index = NULL;
- }
}
/* chain to parent class */
@@ -281,6 +301,38 @@ gda_data_access_wrapper_finalize (GObject *object)
}
static void
+compute_columns (GdaDataAccessWrapper *model)
+{
+ if (model->priv->rows_mapping) {
+ /* use model->priv->rows_mapping to create columns, and correct it if
+ * needed to remove out of range columns */
+ gint *nmapping;
+ gint i, j, nb_cols;
+ g_assert (!model->priv->columns);
+ nmapping = g_new (gint, model->priv->nb_cols);
+ nb_cols = gda_data_model_get_n_columns (model->priv->model);
+ for (i = 0, j = 0; i < model->priv->nb_cols; i++) {
+ gint nb = model->priv->rows_mapping [i];
+ if (nb >= nb_cols)
+ continue;
+ GdaColumn *column;
+ column = gda_data_model_describe_column (model->priv->model, nb);
+ if (!column)
+ continue;
+ model->priv->columns = g_slist_append (model->priv->columns,
+ gda_column_copy (column));
+ nmapping [j] = nb;
+ j++;
+ }
+ model->priv->nb_cols = j;
+ g_free (model->priv->rows_mapping);
+ model->priv->rows_mapping = nmapping;
+ }
+ else
+ model->priv->nb_cols = gda_data_model_get_n_columns (model->priv->model);
+}
+
+static void
gda_data_access_wrapper_set_property (GObject *object,
guint param_id,
const GValue *value,
@@ -292,10 +344,11 @@ gda_data_access_wrapper_set_property (GObject *object,
if (model->priv) {
switch (param_id) {
case PROP_MODEL: {
- GdaDataModel *mod = g_value_get_object(value);
+ GdaDataModel *mod = g_value_get_object (value);
if (mod) {
g_return_if_fail (GDA_IS_DATA_MODEL (mod));
model->priv->model_access_flags = gda_data_model_get_access_flags (mod);
+
if (! (model->priv->model_access_flags & GDA_DATA_MODEL_ACCESS_RANDOM)) {
model->priv->iter = gda_data_model_create_iter (mod);
g_return_if_fail (model->priv->iter);
@@ -322,7 +375,8 @@ gda_data_access_wrapper_set_property (GObject *object,
model->priv->model = mod;
g_object_ref (mod);
- model->priv->nb_cols = gda_data_model_get_n_columns (mod);
+
+ compute_columns (model);
}
break;
}
@@ -376,6 +430,66 @@ gda_data_access_wrapper_new (GdaDataModel *model)
return GDA_DATA_MODEL (retmodel);
}
+/**
+ * gda_data_access_wrapper_set_mapping:
+ * @wrapper: a #GdaDataAccessWrapper object
+ * @mapping: (allow-none) (array length=mapping_size): an array of #gint which represents the mapping between @wrapper's columns
+ * and the columns of the wrapped data model
+ * @mapping_size: the size of @mapping.
+ *
+ * @wrapper will report as many columns as @mapping_size, and for each value at position 'i' in @mapping,
+ * @wrapper will report the 'i'th column, mapped to the wrapped data model column at position mapping[i].
+ * For example if mapping is {3, 4, 0}, then @wrapper will report 3 columns, respectively mapped to the 4th,
+ * 5th and 1st columns of the wrapped data model (as column numbers start at 0).
+ *
+ * If @mapping is %NULL, then no mapping is done and @wrapper's columns will be the same as the wrapped
+ * data model.
+ *
+ * If a column in @mapping does not exist in the wrapped data model, then it is simply ignored (no error
+ * reported).
+ *
+ * Please note that if @wrapper has already been used and if the wrapped data model offers a cursor forward
+ * access mode, then this method will return %FALSE and no action will be done.
+ *
+ * If the mapping is applied, then any existing iterator will be invalid, and @wrapper is reset as if it
+ * had just been created.
+ *
+ * Returns: %TRUE if the mapping actually changed
+ *
+ * Since: 5.2
+ */
+gboolean
+gda_data_access_wrapper_set_mapping (GdaDataAccessWrapper *wrapper, gint *mapping, gint mapping_size)
+{
+ g_return_val_if_fail (GDA_IS_DATA_ACCESS_WRAPPER (wrapper), FALSE);
+
+ if ((! (wrapper->priv->model_access_flags & GDA_DATA_MODEL_ACCESS_CURSOR_BACKWARD)) &&
+ (wrapper->priv->iter_row >= 0)) {
+ /* error */
+ return FALSE;
+ }
+
+ clear_internal_state (wrapper);
+
+ if (mapping) {
+ /* define mapping */
+ wrapper->priv->rows_mapping = g_new (gint, mapping_size);
+ memcpy (wrapper->priv->rows_mapping, mapping, mapping_size * sizeof (gint));
+ wrapper->priv->nb_cols = mapping_size;
+ }
+ else {
+ if (wrapper->priv->rows_mapping) {
+ g_free (wrapper->priv->rows_mapping);
+ wrapper->priv->rows_mapping = NULL;
+ }
+ }
+
+ compute_columns (wrapper);
+ gda_data_model_reset ((GdaDataModel*) wrapper);
+
+ return TRUE;
+}
+
/*
* GdaDataModel interface implementation
*/
@@ -425,8 +539,12 @@ gda_data_access_wrapper_describe_column (GdaDataModel *model, gint col)
imodel = GDA_DATA_ACCESS_WRAPPER (model);
g_return_val_if_fail (imodel->priv, NULL);
- if (imodel->priv->model)
- return gda_data_model_describe_column (imodel->priv->model, col);
+ if (imodel->priv->model) {
+ if (imodel->priv->columns)
+ return g_slist_nth_data (imodel->priv->columns, col);
+ else
+ return gda_data_model_describe_column (imodel->priv->model, col);
+ }
else
return NULL;
}
@@ -454,7 +572,10 @@ create_new_row (GdaDataAccessWrapper *model)
GdaHolder *holder;
GValue *dest;
dest = gda_row_get_value (row, i);
- holder = gda_data_model_iter_get_holder_for_field (model->priv->iter, i);
+ if (model->priv->rows_mapping)
+ holder = gda_data_model_iter_get_holder_for_field (model->priv->iter, model->priv->rows_mapping [i]);
+ else
+ holder = gda_data_model_iter_get_holder_for_field (model->priv->iter, i);
if (holder) {
const GValue *cvalue = gda_holder_get_value (holder);
if (cvalue) {
@@ -494,9 +615,14 @@ gda_data_access_wrapper_get_value_at (GdaDataModel *model, gint col, gint row, G
return NULL;
}
- if (!imodel->priv->rows)
+ if (!imodel->priv->rows) {
/* imodel->priv->model is a random access model, use it */
- return gda_data_model_get_value_at (imodel->priv->model, col, row, error);
+ if (imodel->priv->rows_mapping)
+ return gda_data_model_get_value_at (imodel->priv->model, imodel->priv->rows_mapping [col],
+ row, error);
+ else
+ return gda_data_model_get_value_at (imodel->priv->model, col, row, error);
+ }
else {
GdaRow *gda_row;
gint tmp;
@@ -648,8 +774,14 @@ gda_data_access_wrapper_get_attributes_at (GdaDataModel *model, gint col, gint r
imodel = (GdaDataAccessWrapper *) model;
g_return_val_if_fail (imodel->priv, 0);
- if (imodel->priv->model)
- flags = gda_data_model_get_attributes_at (imodel->priv->model, col, row);
+ if (imodel->priv->model) {
+ if (imodel->priv->rows_mapping)
+ flags = gda_data_model_get_attributes_at (imodel->priv->model, imodel->priv->rows_mapping [col],
+ row);
+ else
+ flags = gda_data_model_get_attributes_at (imodel->priv->model, col, row);
+ }
+
flags |= GDA_VALUE_ATTR_NO_MODIF;
return flags;
diff --git a/libgda/gda-data-access-wrapper.h b/libgda/gda-data-access-wrapper.h
index 06c8fe2..efcae9c 100644
--- a/libgda/gda-data-access-wrapper.h
+++ b/libgda/gda-data-access-wrapper.h
@@ -58,12 +58,14 @@ struct _GdaDataAccessWrapperClass {
* @stability: Stable
* @see_also: #GdaDataModel
*
- * The #GdaDataAccessWrapper object simply wraps around another #GdaDataModel data model object
+ * The #GdaDataAccessWrapper object simply wraps another #GdaDataModel data model object
* and allows data to be accessed in a random way while remaining memory efficient as much as possible.
*/
GType gda_data_access_wrapper_get_type (void) G_GNUC_CONST;
GdaDataModel *gda_data_access_wrapper_new (GdaDataModel *model);
+gboolean gda_data_access_wrapper_set_mapping (GdaDataAccessWrapper *wrapper,
+ gint *mapping, gint mapping_size);
G_END_DECLS
diff --git a/libgda/libgda.symbols b/libgda/libgda.symbols
index 8e40eca..d4d7452 100644
--- a/libgda/libgda.symbols
+++ b/libgda/libgda.symbols
@@ -181,6 +181,7 @@
gda_connection_value_to_sql_string
gda_data_access_wrapper_get_type
gda_data_access_wrapper_new
+ gda_data_access_wrapper_set_mapping
gda_data_comparator_compute_diff
gda_data_comparator_error_get_type
gda_data_comparator_error_quark
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]