2 PSPPIRE --- A Graphical User Interface for PSPP
3 Copyright (C) 2004, 2006 Free Software Foundation
4 Written by John Darrington
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 #include "gtkextra-marshal.c"
27 #include "psppire-object.h"
28 #include "psppire-dict.h"
30 #include "dictionary.h"
31 #include "missing-values.h"
32 #include "value-labels.h"
35 #include "message-dialog.h"
36 #include "psppire-variable.h"
38 /* --- prototypes --- */
39 static void psppire_dict_class_init (PsppireDictClass *class);
40 static void psppire_dict_init (PsppireDict *dict);
41 static void psppire_dict_finalize (GObject *object);
44 /* --- variables --- */
45 static GObjectClass *parent_class = NULL;
47 enum {VARIABLE_CHANGED,
53 static guint signal[n_SIGNALS];
57 /* --- functions --- */
59 * psppire_dict_get_type:
60 * @returns: the type ID for accelerator groups.
63 psppire_dict_get_type (void)
65 static GType object_type = 0;
69 static const GTypeInfo object_info = {
70 sizeof (PsppireDictClass),
72 (GBaseFinalizeFunc) NULL,
73 (GClassInitFunc) psppire_dict_class_init,
74 NULL, /* class_finalize */
75 NULL, /* class_data */
78 (GInstanceInitFunc) psppire_dict_init,
81 object_type = g_type_register_static (G_TYPE_PSPPIRE_OBJECT, "PsppireDict",
90 psppire_dict_class_init (PsppireDictClass *class)
92 GObjectClass *object_class = G_OBJECT_CLASS (class);
94 parent_class = g_type_class_peek_parent (class);
96 object_class->finalize = psppire_dict_finalize;
98 signal[VARIABLE_CHANGED] =
99 g_signal_new ("variable_changed",
100 G_TYPE_FROM_CLASS(class),
104 g_cclosure_marshal_VOID__INT,
111 signal[VARIABLE_INSERTED] =
112 g_signal_new ("variable_inserted",
113 G_TYPE_FROM_CLASS(class),
117 g_cclosure_marshal_VOID__INT,
122 signal[VARIABLE_DELETED] =
123 g_signal_new ("variable_deleted",
124 G_TYPE_FROM_CLASS(class),
128 g_cclosure_marshal_VOID__INT,
134 signal[VARIABLES_DELETED] =
135 g_signal_new ("variables_deleted",
136 G_TYPE_FROM_CLASS(class),
140 gtkextra_VOID__INT_INT,
149 psppire_dict_finalize (GObject *object)
152 PsppireDict *d = PSPPIRE_DICT (object);
156 for (v = 0 ; v < psppire_dict_get_var_cnt(d) ; ++v )
157 g_free(d->variables[v]);
159 g_free(d->variables);
162 dict_destroy(d->dict);
164 G_OBJECT_CLASS (parent_class)->finalize (object);
168 psppire_dict_init (PsppireDict *psppire_dict)
170 psppire_dict->dict = dict_create();
172 psppire_dict->variables = 0;
173 psppire_dict->cache_size = 0;
178 * @returns: a new #PsppireDict object
180 * Creates a new #PsppireDict.
183 psppire_dict_new (void)
185 return g_object_new (G_TYPE_PSPPIRE_DICT, NULL);
190 * psppire_dict_new_from_dict:
191 * @returns: a new #PsppireDict object
193 * Creates a new #PsppireDict.
196 psppire_dict_new_from_dict (struct dictionary *d)
198 PsppireDict *new_dict = g_object_new (G_TYPE_PSPPIRE_DICT, NULL);
200 new_dict->cache_size = dict_get_var_cnt(d);
201 new_dict->variables = g_malloc0(sizeof(struct PsppireVariable *) *
202 new_dict->cache_size);
209 /* Returns a valid name for a new variable in DICT.
210 The return value is statically allocated */
212 auto_generate_var_name(PsppireDict *dict)
215 static gchar name[255];
218 while (g_snprintf(name, 255, "VAR%05d",d++),
219 psppire_dict_lookup_var(dict, name))
225 /* Insert a new variable at posn IDX, with the name NAME.
226 If NAME is null, then a name will be automatically assigned.
229 psppire_dict_insert_variable(PsppireDict *d, gint idx, const gchar *name)
233 g_return_if_fail(G_IS_PSPPIRE_DICT(d));
236 /* Invalidate the cache from IDX onwards */
237 for ( i = idx ; i < d->cache_size ; ++i )
239 g_free(d->variables[i]);
243 /* Ensure that the cache is large enough */
244 if ( dict_get_var_cnt(d->dict) >= d->cache_size )
246 d->variables = g_realloc(d->variables, sizeof(struct PsppireVariable*) *
247 (d->cache_size + CACHE_CHUNK));
248 d->cache_size += CACHE_CHUNK;
251 /* Zero the new pointers */
252 for ( ; i < d->cache_size ; ++i )
258 name = auto_generate_var_name(d);
260 struct variable *var =
261 dict_create_var(d->dict, name, 0);
263 dict_reorder_var(d->dict, var, idx);
266 d->variables[idx] = g_malloc(sizeof (struct PsppireVariable));
267 d->variables[idx]->v = var;
268 d->variables[idx]->dict = d;
270 g_signal_emit(d, signal[VARIABLE_INSERTED], 0, idx );
273 /* Delete N variables beginning at FIRST */
275 psppire_dict_delete_variables(PsppireDict *d, gint first, gint n)
279 g_return_if_fail(d->dict);
280 g_return_if_fail(G_IS_PSPPIRE_DICT(d));
282 /* Invalidate all pvs from FIRST onwards */
283 for ( idx = first ; idx < d->cache_size ; ++idx )
285 g_free(d->variables[idx]);
286 d->variables[idx] = 0;
289 for (idx = 0 ; idx < n ; ++idx )
291 struct variable *var;
293 /* Do nothing if it's out of bounds */
294 if ( first >= dict_get_var_cnt (d->dict))
297 var = dict_get_var(d->dict, first);
298 dict_delete_var (d->dict, var);
301 g_signal_emit(d, signal[VARIABLES_DELETED], 0, first, idx );
306 psppire_dict_set_name(PsppireDict* d, gint idx, const gchar *name)
308 struct variable *var;
310 g_assert(G_IS_PSPPIRE_DICT(d));
313 if ( idx < dict_get_var_cnt(d->dict))
315 /* This is an existing variable? */
316 var = dict_get_var(d->dict, idx);
317 dict_rename_var(d->dict, var, name);
318 g_signal_emit(d, signal[VARIABLE_CHANGED], 0, idx);
323 dict_create_var(d->dict, name, 0);
324 g_print("Emitting variable-inserted signal\n");
325 g_signal_emit(d, signal[VARIABLE_INSERTED], 0, idx);
331 /* Return the IDXth variable */
332 struct PsppireVariable *
333 psppire_dict_get_variable(PsppireDict *d, gint idx)
335 g_return_val_if_fail(d, NULL);
336 g_return_val_if_fail(d->dict, NULL);
337 g_return_val_if_fail(d->variables, NULL);
339 if (idx < 0 || idx >= psppire_dict_get_var_cnt(d))
342 struct PsppireVariable *var = d->variables[idx] ;
346 var = g_malloc(sizeof (*var));
348 var->v = dict_get_var(d->dict, idx);
349 d->variables[idx] = var;
356 /* Return the number of variables in the dictionary */
358 psppire_dict_get_var_cnt(const PsppireDict *d)
360 g_return_val_if_fail(d, -1);
361 g_return_val_if_fail(d->dict, -1);
364 return dict_get_var_cnt(d->dict);
368 /* Return a variable by name.
369 Return NULL if it doesn't exist
372 psppire_dict_lookup_var (const PsppireDict *d, const gchar *name)
374 g_return_val_if_fail(d, NULL);
375 g_return_val_if_fail(d->dict, NULL);
377 return dict_lookup_var(d->dict, name);
382 psppire_dict_var_changed(PsppireDict *d, gint idx)
386 g_signal_emit(d, signal[VARIABLE_CHANGED], 0, idx);
390 /* Clears the contents of D */
392 psppire_dict_clear(PsppireDict *d)
395 g_return_if_fail(d->dict);
397 const gint n_vars = dict_get_var_cnt(d->dict);
402 /* Invalidate the entire cache */
403 for ( i = 0 ; i < d->cache_size ; ++i )
405 g_free(d->variables[i]);
409 g_signal_emit(d, signal[VARIABLES_DELETED], 0, 0, n_vars );
414 /* Return true is NAME would be a valid name of a variable to add to the
415 dictionary. False otherwise.
416 If REPORT is true, then invalid names will be reported as such as errors
419 psppire_dict_check_name(const PsppireDict *dict,
420 const gchar *name, gboolean report)
422 if ( ! var_is_valid_name(name, report ) )
425 if (psppire_dict_lookup_var(dict, name))
428 msg(ME,"Duplicate variable name.");