Introspection non-fixes.
[gnumeric.git] / src / go-data-slicer-field.c
blob7aaf6f0e55730b7717abf059bfbf7d0751a8d512
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * go-data-slicer-field.h : The definition of a content for a data slicer
5 * Copyright (C) 2008 Jody Goldberg (jody@gnome.org)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) version 3.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20 * USA
23 #include <gnumeric-config.h>
24 #include "go-data-slicer-field-impl.h"
25 #include "go-data-slicer-impl.h"
26 #include "go-data-cache-field.h"
27 #include "go-data-cache.h"
29 #include <gsf/gsf-impl-utils.h>
30 #include <glib/gi18n-lib.h>
31 #include <string.h>
33 #define GO_DATA_SLICER_FIELD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GO_DATA_SLICER_FIELD_TYPE, GODataSlicerFieldClass))
34 #define IS_GO_DATA_SLICER_FIELD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GO_DATA_SLICER_FIELD_TYPE))
35 #define GO_DATA_SLICER_FIELD_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GO_DATA_SLICER_FIELD_TYPE, GODataSlicerFieldClass))
37 enum {
38 PROP_0,
39 PROP_SLICER, /* GODataSlicer * */
40 PROP_NAME, /* GOString * */
41 PROP_INDEX, /* int */
42 PROP_DATA_CACHE_FIELD_INDEX, /* int */
43 PROP_AGGREGATIONS
46 static void
47 go_data_slicer_field_init (GODataSlicerField *dsf)
49 int i;
51 dsf->ds = NULL;
52 dsf->name = NULL;
53 dsf->indx = -1;
54 dsf->data_cache_field_indx = -1;
55 dsf->aggregations = 0;
57 for (i = 0 ; i < GDS_FIELD_TYPE_UNSET ; i++)
58 dsf->field_type_pos[i] = -1;
61 static GObjectClass *parent_klass;
62 static void
63 go_data_slicer_field_finalize (GObject *obj)
65 GODataSlicerField *dsf = (GODataSlicerField *)obj;
67 go_string_unref (dsf->name);
68 dsf->name = NULL;
70 parent_klass->finalize (obj);
73 static void
74 go_data_slicer_field_set_property (GObject *obj, guint property_id,
75 GValue const *value, GParamSpec *pspec)
77 GODataSlicerField *dsf = (GODataSlicerField *)obj;
79 switch (property_id) {
80 /* we do not hold a ref */
81 case PROP_SLICER:
82 dsf->ds = g_value_get_object (value);
83 break;
84 case PROP_NAME:
85 go_string_unref (dsf->name);
86 dsf->name = g_value_dup_boxed (value);
87 break;
88 case PROP_DATA_CACHE_FIELD_INDEX:
89 dsf->data_cache_field_indx = g_value_get_int (value);
90 break;
91 case PROP_AGGREGATIONS:
92 dsf->aggregations = g_value_get_uint (value);
93 break;
94 default:
95 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
99 static void
100 go_data_slicer_field_get_property (GObject *obj, guint property_id,
101 GValue *value, GParamSpec *pspec)
103 GODataSlicerField const *dsf = (GODataSlicerField const *)obj;
104 switch (property_id) {
105 case PROP_SLICER:
106 g_value_set_object (value, dsf->ds);
107 break;
108 case PROP_NAME:
109 g_value_set_boxed (value, dsf->name);
110 break; /* actual name, do not fall back to cache */
111 case PROP_INDEX:
112 g_value_set_int (value, dsf->indx);
113 break;
114 case PROP_DATA_CACHE_FIELD_INDEX:
115 g_value_set_int (value, dsf->data_cache_field_indx);
116 break;
117 case PROP_AGGREGATIONS:
118 g_value_set_uint (value, dsf->aggregations);
119 break;
120 default:
121 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
125 static void
126 go_data_slicer_field_class_init (GODataSlicerFieldClass *klass)
128 GObjectClass *gobject_class = (GObjectClass *)klass;
129 gobject_class->finalize = go_data_slicer_field_finalize;
130 gobject_class->set_property = go_data_slicer_field_set_property;
131 gobject_class->get_property = go_data_slicer_field_get_property;
133 g_object_class_install_property (gobject_class, PROP_SLICER,
134 g_param_spec_object ("slicer", NULL, NULL,
135 GO_DATA_SLICER_TYPE, GSF_PARAM_STATIC | G_PARAM_READWRITE));
136 g_object_class_install_property (gobject_class, PROP_NAME,
137 g_param_spec_boxed ("name", NULL, NULL, go_string_get_type (),
138 GSF_PARAM_STATIC | G_PARAM_READWRITE));
139 g_object_class_install_property (gobject_class, PROP_INDEX,
140 g_param_spec_int ("index", NULL,
141 "Index of the field within the GODataSlicer",
142 -1, G_MAXINT, -1,
143 GSF_PARAM_STATIC | G_PARAM_READABLE));
144 g_object_class_install_property (gobject_class, PROP_DATA_CACHE_FIELD_INDEX,
145 g_param_spec_int ("data-cache-field-index", NULL,
146 "Index of the underlying GODataCacheField",
147 -1, G_MAXINT, -1,
148 GSF_PARAM_STATIC | G_PARAM_READWRITE));
149 g_object_class_install_property (gobject_class, PROP_AGGREGATIONS,
150 g_param_spec_uint ("aggregations", NULL,
151 "bitwise OR of the set of aggregations",
152 0, ~0, 0,
153 GSF_PARAM_STATIC | G_PARAM_READWRITE));
155 parent_klass = g_type_class_peek_parent (klass);
158 GSF_CLASS (GODataSlicerField, go_data_slicer_field,
159 go_data_slicer_field_class_init, go_data_slicer_field_init,
160 G_TYPE_OBJECT)
163 * go_data_slicer_field_get_cache_field:
164 * @dsf: #GODataSlicerField const
166 * Returns : the underlying cache field
168 GODataCacheField *
169 go_data_slicer_field_get_cache_field (GODataSlicerField const *dsf)
171 g_return_val_if_fail (IS_GO_DATA_SLICER_FIELD (dsf), NULL);
172 return go_data_cache_get_field (go_data_slicer_get_cache (dsf->ds),
173 dsf->data_cache_field_indx);
177 * go_data_slicer_field_get_name:
178 * @dsf: #GODataSlicerField const
180 * If @dsf has a name return that, otherwise default to the name of the
181 * underlying cache field. If there is a need (e.g. for export) to get the
182 * exact name without the default, use the properties.
184 * Returns: the name of the field.
186 GOString *
187 go_data_slicer_field_get_name (GODataSlicerField const *dsf)
189 g_return_val_if_fail (IS_GO_DATA_SLICER_FIELD (dsf), NULL);
190 if (dsf->name)
191 return dsf->name;
192 return go_data_cache_field_get_name (
193 go_data_slicer_field_get_cache_field (dsf));
197 go_data_slicer_field_get_field_type_pos (GODataSlicerField const *dsf,
198 GODataSlicerFieldType field_type)
200 g_return_val_if_fail (IS_GO_DATA_SLICER_FIELD (dsf), -1);
201 g_return_val_if_fail (field_type > GDS_FIELD_TYPE_UNSET &&
202 field_type < GDS_FIELD_TYPE_MAX, -1);
203 return dsf->field_type_pos[field_type];
207 * go_data_slicer_field_set_field_type_pos:
208 * @dsf: #GODataSlicerField
209 * @field_type: #GODataSlicerFieldType
210 * @pos: >= len => append, else move ahead of @pos, -1 removes
212 * Make @dsf a @field_type, and move it to position @pos other @field_type's
213 * in the slicer.
215 void
216 go_data_slicer_field_set_field_type_pos (GODataSlicerField *dsf,
217 GODataSlicerFieldType field_type,
218 int pos)
220 GArray *headers;
221 int cur_pos, i;
223 g_return_if_fail (IS_GO_DATA_SLICER_FIELD (dsf));
224 g_return_if_fail (IS_GO_DATA_SLICER (dsf->ds));
225 g_return_if_fail (field_type > GDS_FIELD_TYPE_UNSET &&
226 field_type < GDS_FIELD_TYPE_MAX);
228 headers = dsf->ds->fields [field_type];
229 if (pos < 0) pos = -1;
230 else if (pos >= (int)headers->len) pos = headers->len;
232 cur_pos = dsf->field_type_pos[field_type];
233 if (pos == cur_pos) return;
235 /* Remove it */
236 if (cur_pos >= 0) {
237 g_return_if_fail (cur_pos < (int)headers->len);
238 g_return_if_fail (g_array_index (headers, int, cur_pos) == dsf->indx);
240 g_array_remove_index (headers, cur_pos);
241 dsf->field_type_pos[field_type] = -1;
242 for (i = cur_pos; i < (int)headers->len ; i++) {
243 GODataSlicerField *other = go_data_slicer_get_field (dsf->ds,
244 g_array_index (headers, int, i));
245 if (NULL != other && other->field_type_pos[field_type] == (i+1))
246 --(other->field_type_pos[field_type]);
247 else
248 g_warning ("inconsistent field_type_pos");
251 /* adjust target index if our removal would change it */
252 if (cur_pos < pos) pos--;
255 /* put it back in the right place */
256 if (pos >= 0) {
257 if (pos < (int)headers->len) {
258 g_array_insert_val (headers, pos, dsf->indx);
259 for (i = pos; ++i < (int)headers->len ; ) {
260 GODataSlicerField *other = go_data_slicer_get_field (dsf->ds,
261 g_array_index (headers, int, i));
262 if (NULL != other && other->field_type_pos[field_type] == (i-1))
263 ++(other->field_type_pos[field_type]);
264 else
265 g_warning ("inconsistent field_type_pos");
267 } else
268 g_array_append_val (headers, dsf->indx);
270 dsf->field_type_pos[field_type] = pos;