Added the ability to sort the working file.
[pspp-builds.git] / src / ui / gui / psppire-dict.c
1 /* 
2     PSPPIRE --- A Graphical User Interface for PSPP
3     Copyright (C) 2004, 2006  Free Software Foundation
4     Written by John Darrington
5
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.
10
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.
15
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
19     02110-1301, USA. */
20
21
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include <gtk/gtk.h>
26 #include <gtksheet/gtkextra-marshal.h>
27
28 #include "psppire-object.h"
29 #include "psppire-dict.h"
30 #include <data/format.h>
31 #include <data/dictionary.h>
32 #include <data/missing-values.h>
33 #include <data/value-labels.h>
34
35
36 #include "message-dialog.h"
37 #include "psppire-variable.h"
38
39 /* --- prototypes --- */
40 static void psppire_dict_class_init     (PsppireDictClass       *class);
41 static void psppire_dict_init   (PsppireDict            *dict);
42 static void psppire_dict_finalize       (GObject                *object);
43
44 static void dictionary_tree_model_init(GtkTreeModelIface *iface);
45
46
47 /* --- variables --- */
48 static GObjectClass     *parent_class = NULL;
49
50 enum  {VARIABLE_CHANGED, 
51        VARIABLE_INSERTED,
52        VARIABLES_DELETED, 
53        n_SIGNALS};
54
55 static guint signal[n_SIGNALS];
56
57 #define CACHE_CHUNK 5
58
59 /* --- functions --- */
60 /**
61  * psppire_dict_get_type:
62  * @returns: the type ID for accelerator groups.
63  */
64 GType
65 psppire_dict_get_type (void)
66 {
67   static GType object_type = 0;
68
69   if (!object_type)
70     {
71       static const GTypeInfo object_info = {
72         sizeof (PsppireDictClass),
73         (GBaseInitFunc) NULL,
74         (GBaseFinalizeFunc) NULL,
75         (GClassInitFunc) psppire_dict_class_init,
76         NULL,   /* class_finalize */
77         NULL,   /* class_data */
78         sizeof (PsppireDict),
79         0,      /* n_preallocs */
80         (GInstanceInitFunc) psppire_dict_init,
81       };
82
83       static const GInterfaceInfo tree_model_info = {
84         (GInterfaceInitFunc) dictionary_tree_model_init, 
85         NULL, 
86         NULL
87       };
88
89       object_type = g_type_register_static (G_TYPE_PSPPIRE_OBJECT, 
90                                             "PsppireDict",
91                                             &object_info, 0);
92
93       g_type_add_interface_static(object_type, GTK_TYPE_TREE_MODEL, 
94                                   &tree_model_info);
95
96
97     }
98
99   return object_type;
100 }
101
102
103 static void
104 psppire_dict_class_init (PsppireDictClass *class)
105 {
106   GObjectClass *object_class = G_OBJECT_CLASS (class);
107
108   parent_class = g_type_class_peek_parent (class);
109
110   object_class->finalize = psppire_dict_finalize;
111
112   signal[VARIABLE_CHANGED] =
113     g_signal_new ("variable_changed",
114                   G_TYPE_FROM_CLASS(class),
115                   G_SIGNAL_RUN_FIRST,
116                   0,
117                   NULL, NULL,
118                   g_cclosure_marshal_VOID__INT,
119                   G_TYPE_NONE, 
120                   1,
121                   G_TYPE_INT);
122
123
124
125   signal[VARIABLE_INSERTED] =
126     g_signal_new ("variable_inserted",
127                   G_TYPE_FROM_CLASS(class),
128                   G_SIGNAL_RUN_FIRST,
129                   0,
130                   NULL, NULL,
131                   g_cclosure_marshal_VOID__INT,
132                   G_TYPE_NONE, 
133                   1,
134                   G_TYPE_INT);
135
136
137   signal[VARIABLES_DELETED] =
138     g_signal_new ("variables_deleted",
139                   G_TYPE_FROM_CLASS(class),
140                   G_SIGNAL_RUN_FIRST,
141                   0,
142                   NULL, NULL,
143                   gtkextra_VOID__INT_INT,
144                   G_TYPE_NONE, 
145                   2,
146                   G_TYPE_INT,
147                   G_TYPE_INT);
148
149 }
150
151 static void
152 psppire_dict_finalize (GObject *object)
153 {
154   gint v;
155   PsppireDict *d = PSPPIRE_DICT (object);
156   
157   for (v = 0 ; v < psppire_dict_get_var_cnt(d) ; ++v ) 
158     g_free(d->variables[v]);
159
160   g_free(d->variables);
161   d->cache_size = 0;
162
163   dict_destroy(d->dict);
164
165   G_OBJECT_CLASS (parent_class)->finalize (object);
166 }
167
168 static void
169 psppire_dict_init (PsppireDict *psppire_dict)
170 {
171   psppire_dict->dict = dict_create();
172
173   psppire_dict->variables = 0; 
174   psppire_dict->cache_size = 0;
175
176   psppire_dict->stamp = g_random_int();
177 }
178
179 /**
180  * psppire_dict_new:
181  * @returns: a new #PsppireDict object
182  * 
183  * Creates a new #PsppireDict. 
184  */
185 PsppireDict*
186 psppire_dict_new (void)
187 {
188   return g_object_new (G_TYPE_PSPPIRE_DICT, NULL);
189 }
190
191
192 /**
193  * psppire_dict_new_from_dict:
194  * @returns: a new #PsppireDict object
195  * 
196  * Creates a new #PsppireDict. 
197  */
198 PsppireDict*
199 psppire_dict_new_from_dict (struct dictionary *d)
200 {
201   PsppireDict *new_dict = g_object_new (G_TYPE_PSPPIRE_DICT, NULL);
202   new_dict->dict = d;
203   new_dict->cache_size = dict_get_var_cnt(d);
204   new_dict->variables = g_malloc0(sizeof(struct PsppireVariable *) * 
205                                   new_dict->cache_size);
206
207
208   return new_dict;
209 }
210
211
212 /* Returns a valid name for a new variable in DICT.
213    The return value is statically allocated */
214 static gchar * 
215 auto_generate_var_name(PsppireDict *dict)
216 {
217   gint d = 0;
218   static gchar name[10];
219
220
221   while (g_snprintf(name, 10, "VAR%05d",d++),
222          psppire_dict_lookup_var(dict, name))
223     ;
224
225   return name;
226 }
227
228 /* Insert a new variable at posn IDX, with the name NAME.
229    If NAME is null, then a name will be automatically assigned.
230  */
231 void
232 psppire_dict_insert_variable(PsppireDict *d, gint idx, const gchar *name)
233 {
234   struct variable *var ;
235   gint i;
236   g_return_if_fail(d);
237   g_return_if_fail(G_IS_PSPPIRE_DICT(d));
238
239
240   /* Invalidate the cache from IDX onwards */
241   for ( i = idx ; i < d->cache_size ; ++i ) 
242     {
243       g_free(d->variables[i]);
244       d->variables[i] = 0;
245     }
246
247   /* Ensure that the cache is large enough */
248   if ( dict_get_var_cnt(d->dict) >= d->cache_size ) 
249     {
250       d->variables = g_realloc(d->variables, sizeof(struct PsppireVariable*) * 
251                                (d->cache_size + CACHE_CHUNK));
252       d->cache_size += CACHE_CHUNK;
253     }
254
255   /* Zero the new pointers */
256   for ( ; i < d->cache_size ; ++i ) 
257     {
258       d->variables[i] = 0;
259     }
260
261   if ( ! name ) 
262     name = auto_generate_var_name(d);
263   
264   var = dict_create_var(d->dict, name, 0);
265
266   dict_reorder_var(d->dict, var, idx);
267
268   d->variables[idx] = g_malloc(sizeof (struct PsppireVariable));
269   d->variables[idx]->v = var;
270   d->variables[idx]->dict = d;
271
272   g_signal_emit(d, signal[VARIABLE_INSERTED], 0, idx );  
273 }
274
275 /* Delete N variables beginning at FIRST */
276 void
277 psppire_dict_delete_variables(PsppireDict *d, gint first, gint n)
278 {
279   gint idx;
280   g_return_if_fail(d);
281   g_return_if_fail(d->dict);
282   g_return_if_fail(G_IS_PSPPIRE_DICT(d));
283
284   /* Invalidate all pvs from FIRST onwards */
285   for ( idx = first ; idx < d->cache_size ; ++idx ) 
286     {
287       g_free(d->variables[idx]);
288       d->variables[idx] = 0;
289     }
290
291   for (idx = 0 ; idx < n ; ++idx ) 
292     {
293       struct variable *var;
294
295       /* Do nothing if it's out of bounds */
296       if ( first >= dict_get_var_cnt (d->dict))
297         break; 
298
299       var = dict_get_var(d->dict, first);
300       dict_delete_var (d->dict, var);
301     }
302
303   g_signal_emit(d, signal[VARIABLES_DELETED], 0, first, idx );  
304 }
305
306
307 void
308 psppire_dict_set_name(PsppireDict* d, gint idx, const gchar *name)
309 {
310   struct variable *var;
311   g_assert(d);
312   g_assert(G_IS_PSPPIRE_DICT(d));
313
314
315   if ( idx < dict_get_var_cnt(d->dict))
316     {
317       /* This is an existing variable? */
318       var = dict_get_var(d->dict, idx);
319       dict_rename_var(d->dict, var, name);
320       g_signal_emit(d, signal[VARIABLE_CHANGED], 0, idx);
321     }
322   else
323     {
324       /* new variable */
325       dict_create_var(d->dict, name, 0);
326       g_signal_emit(d, signal[VARIABLE_INSERTED], 0, idx);
327     }
328 }
329
330
331
332 /* Return the IDXth variable */
333 struct PsppireVariable *
334 psppire_dict_get_variable(PsppireDict *d, gint idx)
335 {
336   struct PsppireVariable *var ;
337   g_return_val_if_fail(d, NULL);
338   g_return_val_if_fail(d->dict, NULL);
339
340   if ( ! d->variables) 
341     return NULL;
342   
343   if (idx < 0 || idx >= psppire_dict_get_var_cnt(d))
344     return NULL;
345
346   var = d->variables[idx] ; 
347
348   if (! var ) 
349     {
350       var = g_malloc(sizeof (*var));
351       var->dict = d;
352       var->v = dict_get_var(d->dict, idx);
353       d->variables[idx] = var;
354     }
355     
356   return var;
357 }
358
359
360 /* Return the number of variables in the dictionary */
361 gint 
362 psppire_dict_get_var_cnt(const PsppireDict *d)
363 {
364   g_return_val_if_fail(d, -1);
365   g_return_val_if_fail(d->dict, -1);
366   
367
368   return dict_get_var_cnt(d->dict);
369 }
370
371
372 /* Return a variable by name.
373    Return NULL if it doesn't exist
374 */
375 struct variable *
376 psppire_dict_lookup_var (const PsppireDict *d, const gchar *name)
377 {
378   g_return_val_if_fail(d, NULL);
379   g_return_val_if_fail(d->dict, NULL);
380
381   return dict_lookup_var(d->dict, name);
382 }
383
384
385 void
386 psppire_dict_var_changed(PsppireDict *d, gint idx)
387 {
388   g_return_if_fail(d);
389
390   g_signal_emit(d, signal[VARIABLE_CHANGED], 0, idx);
391 }
392
393
394 /* Clears the contents of D */
395 void 
396 psppire_dict_clear(PsppireDict *d)
397 {
398   g_return_if_fail(d);
399   g_return_if_fail(d->dict);
400
401   {
402     const gint n_vars = dict_get_var_cnt(d->dict);
403     gint i;
404   
405     dict_clear(d->dict);
406
407     /* Invalidate the entire cache */
408     for ( i = 0 ; i < d->cache_size ; ++i ) 
409       {
410         g_free(d->variables[i]);
411         d->variables[i] = 0;
412       }
413
414     g_signal_emit(d, signal[VARIABLES_DELETED], 0, 0, n_vars );  
415   }
416 }
417
418
419
420 /* Return true is NAME would be a valid name of a variable to add to the 
421    dictionary.  False otherwise. 
422    If REPORT is true, then invalid names will be reported as such as errors
423 */
424 gboolean
425 psppire_dict_check_name(const PsppireDict *dict, 
426                      const gchar *name, gboolean report)
427 {
428   if ( ! var_is_valid_name(name, report ) )
429       return FALSE;
430
431   if (psppire_dict_lookup_var(dict, name))
432     {
433       if ( report ) 
434         msg(ME,"Duplicate variable name.");
435       return FALSE;
436     }
437
438   return TRUE;
439 }
440
441
442 inline gint 
443 psppire_dict_get_next_value_idx (const PsppireDict *dict)
444 {
445   return dict_get_next_value_idx(dict->dict);
446 }
447
448
449
450 /* Tree Model Stuff */
451
452 static GtkTreeModelFlags tree_model_get_flags(GtkTreeModel *model);
453
454 static gint tree_model_n_columns(GtkTreeModel *model);
455
456 static GType tree_model_column_type(GtkTreeModel *model, gint index);
457
458 static gboolean tree_model_get_iter(GtkTreeModel *model, GtkTreeIter *iter, 
459                                     GtkTreePath *path);
460
461 static gboolean tree_model_iter_next(GtkTreeModel *model, GtkTreeIter *iter);
462
463 static GtkTreePath * tree_model_get_path(GtkTreeModel *model, 
464                                          GtkTreeIter *iter);
465
466 static void tree_model_get_value(GtkTreeModel *model, GtkTreeIter *iter,
467                                  gint column, GValue *value);
468
469 static gboolean tree_model_nth_child(GtkTreeModel *model, GtkTreeIter *iter, 
470                                      GtkTreeIter *parent, gint n);
471
472
473 static void
474 dictionary_tree_model_init(GtkTreeModelIface *iface)
475 {
476   iface->get_flags = tree_model_get_flags;
477   iface->get_n_columns = tree_model_n_columns;
478   iface->get_column_type = tree_model_column_type;
479   iface->get_iter = tree_model_get_iter;
480   iface->iter_next = tree_model_iter_next;
481   iface->get_path = tree_model_get_path;
482   iface->get_value = tree_model_get_value;
483
484   iface->iter_children = 0;
485   iface->iter_has_child =0;
486   iface->iter_n_children =0;
487   iface->iter_nth_child = tree_model_nth_child ;
488   iface->iter_parent =0;
489 }
490
491 static GtkTreeModelFlags
492 tree_model_get_flags(GtkTreeModel *model)
493 {
494   g_return_val_if_fail(G_IS_PSPPIRE_DICT(model), (GtkTreeModelFlags) 0);
495
496   return GTK_TREE_MODEL_LIST_ONLY;
497 }
498
499
500 static gint
501 tree_model_n_columns(GtkTreeModel *model)
502 {
503   return n_DICT_COLS;
504 }
505
506 static GType
507 tree_model_column_type(GtkTreeModel *model, gint index)
508 {
509  g_return_val_if_fail(G_IS_PSPPIRE_DICT(model), (GType) 0);
510
511  switch(index) 
512    {
513    case DICT_TVM_COL_NAME:
514      return G_TYPE_STRING;
515      break;
516    case DICT_TVM_COL_VAR:
517      return G_TYPE_POINTER;
518      break;
519    default:
520      g_return_val_if_reached((GType)0);
521      break;
522    }
523
524  g_assert_not_reached();
525  return ((GType)0);
526 }
527
528 static gboolean
529 tree_model_get_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
530 {
531   gint *indices, depth;
532   gint n;
533   struct PsppireVariable *variable;
534
535   PsppireDict *dict = PSPPIRE_DICT (model);
536
537   g_return_val_if_fail(path, FALSE);
538
539   indices = gtk_tree_path_get_indices(path);
540   depth = gtk_tree_path_get_depth(path);
541
542   g_return_val_if_fail(depth == 1, FALSE);
543
544   n = indices[0];
545
546   if ( n < 0 || n >= psppire_dict_get_var_cnt(dict)) 
547     return FALSE;
548
549   variable = psppire_dict_get_variable(dict, n);
550
551   g_assert(psppire_variable_get_index(variable) == n);
552
553   iter->stamp = dict->stamp;
554   iter->user_data = variable; 
555
556   return TRUE;
557 }
558
559
560 static gboolean
561 tree_model_iter_next(GtkTreeModel *model, GtkTreeIter *iter)
562 {
563   PsppireDict *dict = PSPPIRE_DICT (model);
564   struct PsppireVariable *variable;
565   gint idx;
566
567   g_return_val_if_fail(iter->stamp == dict->stamp, FALSE);
568
569   if ( iter == NULL || iter->user_data == NULL)
570     return FALSE;
571
572   variable = (struct PsppireVariable *) iter->user_data;
573
574   idx = psppire_variable_get_index(variable);
575   
576   if ( idx + 1 >= psppire_dict_get_var_cnt(dict))
577     return FALSE;
578
579   variable = psppire_dict_get_variable(dict, idx + 1);
580
581   g_assert(psppire_variable_get_index(variable) == idx + 1);
582   
583   iter->user_data = variable;
584
585   return TRUE;
586 }
587
588 static GtkTreePath *
589 tree_model_get_path(GtkTreeModel *model, GtkTreeIter *iter)
590 {
591   GtkTreePath *path;
592   struct PsppireVariable *variable;
593   PsppireDict *dict = PSPPIRE_DICT (model);
594
595   g_return_val_if_fail(iter->stamp == dict->stamp, FALSE);
596
597   variable = (struct PsppireVariable *) iter->user_data;
598
599   path = gtk_tree_path_new();
600   gtk_tree_path_append_index(path, psppire_variable_get_index(variable));
601
602   return path;
603 }
604
605
606 static void
607 tree_model_get_value(GtkTreeModel *model, GtkTreeIter *iter,
608                      gint column, GValue *value)
609 {
610   struct PsppireVariable *variable;
611   PsppireDict *dict = PSPPIRE_DICT (model);
612
613   g_return_if_fail(iter->stamp == dict->stamp);
614
615   variable = (struct PsppireVariable *) iter->user_data;
616
617   switch(column)
618     {
619     case DICT_TVM_COL_NAME:
620       g_value_init(value, G_TYPE_STRING);
621       g_value_set_string(value, psppire_variable_get_name(variable));
622       break;
623     case DICT_TVM_COL_VAR:
624       g_value_init(value, G_TYPE_POINTER);
625       g_value_set_pointer(value, variable);
626       break;
627     default:
628       g_return_if_reached();
629       break;
630     }
631 }
632
633
634 static gboolean
635 tree_model_nth_child(GtkTreeModel *model, GtkTreeIter *iter, 
636                      GtkTreeIter *parent, gint n)
637 {
638   PsppireDict *dict;
639   g_return_val_if_fail(G_IS_PSPPIRE_DICT(model), FALSE);
640
641   dict = PSPPIRE_DICT(model);
642
643   if ( parent ) 
644     return FALSE;
645
646   if ( n >= psppire_dict_get_var_cnt(dict) ) 
647     return FALSE;
648
649   iter->stamp = dict->stamp;
650   iter->user_data = psppire_dict_get_variable(dict, n);
651
652   if ( !iter->user_data) 
653     return FALSE;
654   
655   
656   return TRUE;
657 }