Changed the signature of the VARIABLE_CHANGED signal to take the WHAT and OLDVAR...
[pspp] / src / ui / gui / psppire-dict.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2004, 2006, 2007, 2009, 2010, 2011, 2012  Free Software Foundation
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "ui/gui/psppire-dict.h"
20
21 #include <string.h>
22 #include <stdlib.h>
23 #include <gtk/gtk.h>
24
25 #include "data/dictionary.h"
26 #include "data/identifier.h"
27 #include "data/missing-values.h"
28 #include "data/value-labels.h"
29 #include "data/variable.h"
30 #include "libpspp/i18n.h"
31 #include "libpspp/message.h"
32 #include "ui/gui/helper.h"
33 #include "ui/gui/psppire-marshal.h"
34 #include "ui/gui/psppire-var-ptr.h"
35
36 #include <gettext.h>
37 #define _(msgid) gettext (msgid)
38 #define N_(msgid) msgid
39
40 enum  {
41   BACKEND_CHANGED,
42
43   VARIABLE_CHANGED,
44   VARIABLE_RESIZED,
45   VARIABLE_INSERTED,
46   VARIABLE_DELETED,
47   VARIABLE_DISPLAY_WIDTH_CHANGED,
48
49   WEIGHT_CHANGED,
50   FILTER_CHANGED,
51   SPLIT_CHANGED,
52   n_SIGNALS
53 };
54
55
56 /* --- prototypes --- */
57 static void psppire_dict_class_init     (PsppireDictClass       *class);
58 static void psppire_dict_init   (PsppireDict            *dict);
59 static void psppire_dict_dispose        (GObject                *object);
60
61 static void dictionary_tree_model_init (GtkTreeModelIface *iface);
62
63
64 /* --- variables --- */
65 static GObjectClass     *parent_class = NULL;
66
67 static guint signals [n_SIGNALS];
68
69 /* --- functions --- */
70 /**
71  * psppire_dict_get_type:
72  * @returns: the type ID for accelerator groups.
73  */
74 GType
75 psppire_dict_get_type (void)
76 {
77   static GType object_type = 0;
78
79   if (!object_type)
80     {
81       static const GTypeInfo object_info = {
82         sizeof (PsppireDictClass),
83         (GBaseInitFunc) NULL,
84         (GBaseFinalizeFunc) NULL,
85         (GClassInitFunc) psppire_dict_class_init,
86         NULL,   /* class_finalize */
87         NULL,   /* class_data */
88         sizeof (PsppireDict),
89         0,      /* n_preallocs */
90         (GInstanceInitFunc) psppire_dict_init,
91       };
92
93       static const GInterfaceInfo tree_model_info = {
94         (GInterfaceInitFunc) dictionary_tree_model_init,
95         NULL,
96         NULL
97       };
98
99       object_type = g_type_register_static (G_TYPE_OBJECT,
100                                             "PsppireDict",
101                                             &object_info, 0);
102
103       g_type_add_interface_static (object_type, GTK_TYPE_TREE_MODEL,
104                                    &tree_model_info);
105     }
106
107   return object_type;
108 }
109
110
111 static void
112 psppire_dict_class_init (PsppireDictClass *class)
113 {
114   GObjectClass *object_class = G_OBJECT_CLASS (class);
115
116   parent_class = g_type_class_peek_parent (class);
117
118   object_class->dispose = psppire_dict_dispose;
119
120   signals [BACKEND_CHANGED] =
121     g_signal_new ("backend-changed",
122                   G_TYPE_FROM_CLASS (class),
123                   G_SIGNAL_RUN_FIRST,
124                   0,
125                   NULL, NULL,
126                   g_cclosure_marshal_VOID__VOID,
127                   G_TYPE_NONE,
128                   0);
129
130
131   signals [VARIABLE_CHANGED] =
132     g_signal_new ("variable-changed",
133                   G_TYPE_FROM_CLASS (class),
134                   G_SIGNAL_RUN_FIRST,
135                   0,
136                   NULL, NULL,
137                   psppire_marshal_VOID__INT_UINT_POINTER,
138                   G_TYPE_NONE,
139                   3,
140                   G_TYPE_INT,
141                   G_TYPE_UINT,
142                   G_TYPE_POINTER
143                   );
144
145
146
147   signals [VARIABLE_INSERTED] =
148     g_signal_new ("variable-inserted",
149                   G_TYPE_FROM_CLASS (class),
150                   G_SIGNAL_RUN_FIRST,
151                   0,
152                   NULL, NULL,
153                   g_cclosure_marshal_VOID__INT,
154                   G_TYPE_NONE,
155                   1,
156                   G_TYPE_INT);
157
158
159   signals [VARIABLE_DELETED] =
160     g_signal_new ("variable-deleted",
161                   G_TYPE_FROM_CLASS (class),
162                   G_SIGNAL_RUN_FIRST,
163                   0,
164                   NULL, NULL,
165                   psppire_marshal_VOID__POINTER_INT_INT,
166                   G_TYPE_NONE,
167                   3,
168                   G_TYPE_POINTER,
169                   G_TYPE_INT,
170                   G_TYPE_INT);
171
172
173   signals [VARIABLE_RESIZED] =
174     g_signal_new ("dict-size-changed",
175                   G_TYPE_FROM_CLASS (class),
176                   G_SIGNAL_RUN_FIRST,
177                   0,
178                   NULL, NULL,
179                   psppire_marshal_VOID__INT_INT,
180                   G_TYPE_NONE,
181                   2,
182                   G_TYPE_INT,
183                   G_TYPE_INT);
184
185   signals [VARIABLE_DISPLAY_WIDTH_CHANGED] =
186     g_signal_new ("variable-display-width-changed",
187                   G_TYPE_FROM_CLASS (class),
188                   G_SIGNAL_RUN_FIRST,
189                   0,
190                   NULL, NULL,
191                   g_cclosure_marshal_VOID__INT,
192                   G_TYPE_NONE,
193                   1,
194                   G_TYPE_INT);
195
196
197   signals [WEIGHT_CHANGED] =
198     g_signal_new ("weight-changed",
199                   G_TYPE_FROM_CLASS (class),
200                   G_SIGNAL_RUN_FIRST,
201                   0,
202                   NULL, NULL,
203                   g_cclosure_marshal_VOID__INT,
204                   G_TYPE_NONE,
205                   1,
206                   G_TYPE_INT);
207
208
209   signals [FILTER_CHANGED] =
210     g_signal_new ("filter-changed",
211                   G_TYPE_FROM_CLASS (class),
212                   G_SIGNAL_RUN_FIRST,
213                   0,
214                   NULL, NULL,
215                   g_cclosure_marshal_VOID__INT,
216                   G_TYPE_NONE,
217                   1,
218                   G_TYPE_INT);
219
220
221   signals [SPLIT_CHANGED] =
222     g_signal_new ("split-changed",
223                   G_TYPE_FROM_CLASS (class),
224                   G_SIGNAL_RUN_FIRST,
225                   0,
226                   NULL, NULL,
227                   g_cclosure_marshal_VOID__VOID,
228                   G_TYPE_NONE,
229                   0);
230 }
231
232 static void
233 psppire_dict_dispose (GObject *object)
234 {
235   PsppireDict *d = PSPPIRE_DICT (object);
236
237   dict_set_callbacks (d->dict, NULL, NULL);
238
239   G_OBJECT_CLASS (parent_class)->dispose (object);
240 }
241
242 /* Pass on callbacks from src/data/dictionary, as
243    signals in the Gtk library */
244 static void
245 addcb (struct dictionary *d, int idx, void *pd)
246 {
247   PsppireDict *dict = PSPPIRE_DICT (pd);
248
249   if ( ! dict->disable_insert_signal)
250     g_signal_emit (dict, signals [VARIABLE_INSERTED], 0, idx);
251 }
252
253 static void
254 delcb (struct dictionary *d, const struct variable *var,
255        int dict_idx, int case_idx, void *pd)
256 {
257   g_signal_emit (pd, signals [VARIABLE_DELETED], 0,
258                  var, dict_idx, case_idx);
259 }
260
261 static void
262 mutcb (struct dictionary *d, int idx, unsigned int what, const struct variable *oldvar, void *pd)
263 {
264   g_signal_emit (pd, signals [VARIABLE_CHANGED], 0, idx, what, oldvar);
265 }
266
267 static void
268 resize_cb (struct dictionary *d, int idx, int old_width, void *pd)
269 {
270   g_signal_emit (pd, signals [VARIABLE_RESIZED], 0, idx, old_width);
271 }
272
273 static void
274 weight_changed_callback (struct dictionary *d, int idx, void *pd)
275 {
276   g_signal_emit (pd, signals [WEIGHT_CHANGED], 0, idx);
277 }
278
279 static void
280 filter_changed_callback (struct dictionary *d, int idx, void *pd)
281 {
282   g_signal_emit (pd, signals [FILTER_CHANGED], 0, idx);
283 }
284
285 static void
286 split_changed_callback (struct dictionary *d, void *pd)
287 {
288   g_signal_emit (pd, signals [SPLIT_CHANGED], 0);
289 }
290
291 static void
292 variable_display_width_callback (struct dictionary *d, int idx, void *pd)
293 {
294   g_signal_emit (pd, signals [VARIABLE_DISPLAY_WIDTH_CHANGED], 0, idx);
295 }
296
297
298
299 static const struct dict_callbacks gui_callbacks =
300   {
301     addcb,
302     delcb,
303     mutcb,
304     resize_cb,
305     weight_changed_callback,
306     filter_changed_callback,
307     split_changed_callback,
308     variable_display_width_callback
309   };
310
311 static void
312 psppire_dict_init (PsppireDict *psppire_dict)
313 {
314   psppire_dict->stamp = g_random_int ();
315   psppire_dict->disable_insert_signal = FALSE;
316 }
317
318 /**
319  * psppire_dict_new_from_dict:
320  * @returns: a new #PsppireDict object
321  *
322  * Creates a new #PsppireDict.
323  */
324 PsppireDict*
325 psppire_dict_new_from_dict (struct dictionary *d)
326 {
327   PsppireDict *new_dict = g_object_new (PSPPIRE_TYPE_DICT, NULL);
328   new_dict->dict = d;
329
330   dict_set_callbacks (new_dict->dict, &gui_callbacks, new_dict);
331
332   return new_dict;
333 }
334
335
336 void
337 psppire_dict_replace_dictionary (PsppireDict *dict, struct dictionary *d)
338 {
339   struct variable *var =  dict_get_weight (d);
340
341   dict->dict = d;
342
343   weight_changed_callback (d, var ? var_get_dict_index (var) : -1, dict);
344
345   var = dict_get_filter (d);
346   filter_changed_callback (d, var ? var_get_dict_index (var) : -1, dict);
347
348   split_changed_callback (d, dict);
349
350   dict_set_callbacks (dict->dict, &gui_callbacks, dict);
351
352   g_signal_emit (dict, signals [BACKEND_CHANGED], 0);
353 }
354
355
356 /* Stores a valid name for a new variable in DICT into the SIZE bytes in NAME.
357    Returns true if successful, false if SIZE is insufficient. */
358 bool
359 psppire_dict_generate_name (const PsppireDict *dict, char *name, size_t size)
360 {
361   gint d;
362
363   for (d = 1; ; d++)
364     {
365       int len;
366
367       /* TRANSLATORS: This string must be a valid variable name.  That means:
368          - The string must be at most 64 bytes (not characters) long.
369          - The string may not contain whitespace.
370          - The first character may not be '$'
371          - The first character may not be a digit
372          - The final charactor may not be '.' or '_'
373       */
374       len = snprintf (name, size, _("Var%04d"), d);
375       if (len + 1 >= size)
376         return false;
377
378       if (psppire_dict_lookup_var (dict, name) == NULL)
379         return true;
380     }
381
382   return name;
383 }
384
385 /* Insert a new variable at posn IDX, with the name NAME, and return the
386    new variable.
387    If NAME is null, then a name will be automatically assigned.
388 */
389 struct variable *
390 psppire_dict_insert_variable (PsppireDict *d, gint idx, const gchar *name)
391 {
392   struct variable *var;
393   char tmpname[64];
394
395   g_return_val_if_fail (idx >= 0, NULL);
396   g_return_val_if_fail (d, NULL);
397   g_return_val_if_fail (PSPPIRE_IS_DICT (d), NULL);
398
399   if (name == NULL)
400     {
401       if (!psppire_dict_generate_name (d, tmpname, sizeof tmpname))
402         g_return_val_if_reached (NULL);
403
404       name = tmpname;
405     }
406
407   d->disable_insert_signal = TRUE;
408
409   var = dict_create_var (d->dict, name, 0);
410
411   dict_reorder_var (d->dict, var, idx);
412
413   d->disable_insert_signal = FALSE;
414
415   g_signal_emit (d, signals[VARIABLE_INSERTED], 0, idx);
416
417   return var;
418 }
419
420 /* Delete N variables beginning at FIRST */
421 void
422 psppire_dict_delete_variables (PsppireDict *d, gint first, gint n)
423 {
424   gint idx;
425   g_return_if_fail (d);
426   g_return_if_fail (d->dict);
427   g_return_if_fail (PSPPIRE_IS_DICT (d));
428
429   for (idx = 0 ; idx < n ; ++idx )
430     {
431       struct variable *var;
432
433       /* Do nothing if it's out of bounds */
434       if ( first >= dict_get_var_cnt (d->dict))
435         break;
436
437       var = dict_get_var (d->dict, first);
438       dict_delete_var (d->dict, var);
439     }
440 }
441
442
443 gboolean
444 psppire_dict_set_name (PsppireDict* d, gint idx, const gchar *name)
445 {
446   struct variable *var;
447   g_assert (d);
448   g_assert (PSPPIRE_IS_DICT (d));
449
450   if ( ! dict_id_is_valid (d->dict, name, false))
451     return FALSE;
452
453   if ( idx < dict_get_var_cnt (d->dict))
454     {
455       /* This is an existing variable? */
456       var = dict_get_var (d->dict, idx);
457       dict_rename_var (d->dict, var, name);
458     }
459   else
460     {
461       /* new variable */
462       dict_create_var (d->dict, name, 0);
463     }
464
465   return TRUE;
466 }
467
468
469
470 /* Return the IDXth variable.
471    Will return NULL if IDX  exceeds the number of variables in the dictionary.
472  */
473 struct variable *
474 psppire_dict_get_variable (const PsppireDict *d, gint idx)
475 {
476   g_return_val_if_fail (d, NULL);
477   g_return_val_if_fail (d->dict, NULL);
478
479   if ( dict_get_var_cnt (d->dict) <= idx )
480     return NULL;
481
482   return dict_get_var (d->dict, idx);
483 }
484
485
486 /* Return the number of variables in the dictionary */
487 gint
488 psppire_dict_get_var_cnt (const PsppireDict *d)
489 {
490   g_return_val_if_fail (d, -1);
491   g_return_val_if_fail (d->dict, -1);
492
493   return dict_get_var_cnt (d->dict);
494 }
495
496
497 /* Return the number of `union value's in the dictionary */
498 size_t
499 psppire_dict_get_value_cnt (const PsppireDict *d)
500 {
501   g_return_val_if_fail (d, -1);
502   g_return_val_if_fail (d->dict, -1);
503
504   return dict_get_next_value_idx (d->dict);
505 }
506
507
508 /* Returns the prototype for the cases that match the dictionary */
509 const struct caseproto *
510 psppire_dict_get_proto (const PsppireDict *d)
511 {
512   g_return_val_if_fail (d, NULL);
513   g_return_val_if_fail (d->dict, NULL);
514
515   return dict_get_proto (d->dict);
516 }
517
518
519 /* Return a variable by name.
520    Return NULL if it doesn't exist
521 */
522 struct variable *
523 psppire_dict_lookup_var (const PsppireDict *d, const gchar *name)
524 {
525   g_return_val_if_fail (d, NULL);
526   g_return_val_if_fail (d->dict, NULL);
527
528   return dict_lookup_var (d->dict, name);
529 }
530
531 /* Clears the contents of D */
532 void
533 psppire_dict_clear (PsppireDict *d)
534 {
535   g_return_if_fail (d);
536   g_return_if_fail (d->dict);
537
538   {
539     dict_clear (d->dict);
540   }
541 }
542
543
544 /* Return true is NAME would be a valid name of a variable to add to the
545    dictionary.  False otherwise.
546    If REPORT is true, then invalid names will be reported as such as errors
547 */
548 gboolean
549 psppire_dict_check_name (const PsppireDict *dict,
550                          const gchar *name, gboolean report)
551 {
552   if ( ! dict_id_is_valid (dict->dict, name, report ) )
553     return FALSE;
554
555   if (psppire_dict_lookup_var (dict, name))
556     {
557       if ( report )
558         msg (ME, _("Duplicate variable name."));
559       return FALSE;
560     }
561
562   return TRUE;
563 }
564
565
566 gint
567 psppire_dict_get_next_value_idx (const PsppireDict *dict)
568 {
569   return dict_get_next_value_idx (dict->dict);
570 }
571
572
573 void
574 psppire_dict_resize_variable (PsppireDict *d, const struct variable *pv,
575                               gint old_size, gint new_size)
576 {
577   g_return_if_fail (d);
578   g_return_if_fail (d->dict);
579
580   if ( old_size == new_size )
581     return ;
582
583   g_signal_emit (d, signals [VARIABLE_RESIZED], 0,
584                  var_get_dict_index (pv),
585                  new_size - old_size );
586 }
587
588
589 /* Tree Model Stuff */
590
591 static GtkTreeModelFlags tree_model_get_flags (GtkTreeModel *model);
592
593 static gint tree_model_n_columns (GtkTreeModel *model);
594
595 static GType tree_model_column_type (GtkTreeModel *model, gint index);
596
597 static gboolean tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter,
598                                      GtkTreePath *path);
599
600 static gboolean tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter);
601
602 static GtkTreePath * tree_model_get_path (GtkTreeModel *model,
603                                           GtkTreeIter *iter);
604
605 static void tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
606                                   gint column, GValue *value);
607
608 static gboolean tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
609                                       GtkTreeIter *parent, gint n);
610
611 static gint tree_model_n_children (GtkTreeModel *tree_model,
612                                    GtkTreeIter  *iter);
613
614 static gboolean tree_model_iter_children (GtkTreeModel *,
615                                           GtkTreeIter *,
616                                           GtkTreeIter *);
617
618 static gboolean tree_model_iter_parent (GtkTreeModel *tree_model,
619                                         GtkTreeIter *iter,
620                                         GtkTreeIter *child);
621
622 static gboolean tree_model_iter_has_child  (GtkTreeModel *tree_model,
623                                             GtkTreeIter  *iter);
624
625 static void
626 dictionary_tree_model_init (GtkTreeModelIface *iface)
627 {
628   iface->get_flags = tree_model_get_flags;
629   iface->get_n_columns = tree_model_n_columns;
630   iface->get_column_type = tree_model_column_type;
631   iface->get_iter = tree_model_get_iter;
632   iface->iter_next = tree_model_iter_next;
633   iface->get_path = tree_model_get_path;
634   iface->get_value = tree_model_get_value;
635
636   iface->iter_children = tree_model_iter_children ;
637   iface->iter_has_child = tree_model_iter_has_child ;
638   iface->iter_n_children = tree_model_n_children ;
639   iface->iter_nth_child = tree_model_nth_child ;
640   iface->iter_parent = tree_model_iter_parent ;
641 }
642
643 static gboolean
644 tree_model_iter_has_child  (GtkTreeModel *tree_model,
645                             GtkTreeIter  *iter)
646 {
647   return FALSE;
648 }
649
650 static gboolean
651 tree_model_iter_parent (GtkTreeModel *tree_model,
652                         GtkTreeIter *iter,
653                         GtkTreeIter *child)
654 {
655   return TRUE;
656 }
657
658 static GtkTreeModelFlags
659 tree_model_get_flags (GtkTreeModel *model)
660 {
661   g_return_val_if_fail (PSPPIRE_IS_DICT (model), (GtkTreeModelFlags) 0);
662
663   return GTK_TREE_MODEL_LIST_ONLY;
664 }
665
666
667 static gint
668 tree_model_n_columns (GtkTreeModel *model)
669 {
670   return n_DICT_COLS;
671 }
672
673 static GType
674 tree_model_column_type (GtkTreeModel *model, gint index)
675 {
676   g_return_val_if_fail (PSPPIRE_IS_DICT (model), (GType) 0);
677
678   switch (index)
679     {
680     case DICT_TVM_COL_NAME:
681       return G_TYPE_STRING;
682       break;
683     case DICT_TVM_COL_VAR:
684       return PSPPIRE_VAR_PTR_TYPE;
685       break;
686     default:
687       g_return_val_if_reached ((GType)0);
688       break;
689     }
690
691   g_assert_not_reached ();
692   return ((GType)0);
693 }
694
695 static gboolean
696 tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
697 {
698   gint *indices, depth;
699   gint n;
700   struct variable *var;
701
702   PsppireDict *dict = PSPPIRE_DICT (model);
703
704   g_return_val_if_fail (path, FALSE);
705
706   indices = gtk_tree_path_get_indices (path);
707   depth = gtk_tree_path_get_depth (path);
708
709   g_return_val_if_fail (depth == 1, FALSE);
710
711   n = indices [0];
712
713   if ( n < 0 || n >= psppire_dict_get_var_cnt (dict))
714     {
715       iter->stamp = 0;
716       iter->user_data = NULL;
717       return FALSE;
718     }
719
720   var = psppire_dict_get_variable (dict, n);
721
722   g_assert (var_get_dict_index (var) == n);
723
724   iter->stamp = dict->stamp;
725   iter->user_data = var;
726
727   return TRUE;
728 }
729
730
731 static gboolean
732 tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
733 {
734   PsppireDict *dict = PSPPIRE_DICT (model);
735   struct variable *var;
736   gint idx;
737
738   g_return_val_if_fail (iter->stamp == dict->stamp, FALSE);
739
740   if ( iter == NULL || iter->user_data == NULL)
741     return FALSE;
742
743   var = iter->user_data;
744
745   idx = var_get_dict_index (var);
746
747   if ( idx + 1 >= psppire_dict_get_var_cnt (dict))
748     {
749       iter->user_data = NULL;
750       iter->stamp = 0;
751       return FALSE;
752     }
753
754   var = psppire_dict_get_variable (dict, idx + 1);
755
756   g_assert (var_get_dict_index (var) == idx + 1);
757
758   iter->user_data = var;
759
760   return TRUE;
761 }
762
763 static GtkTreePath *
764 tree_model_get_path (GtkTreeModel *model, GtkTreeIter *iter)
765 {
766   GtkTreePath *path;
767   struct variable *var;
768   PsppireDict *dict = PSPPIRE_DICT (model);
769
770   g_return_val_if_fail (iter->stamp == dict->stamp, FALSE);
771
772   var = iter->user_data;
773
774   path = gtk_tree_path_new ();
775   gtk_tree_path_append_index (path, var_get_dict_index (var));
776
777   return path;
778 }
779
780
781 static void
782 tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
783                       gint column, GValue *value)
784 {
785   struct variable *var;
786   PsppireDict *dict = PSPPIRE_DICT (model);
787
788   g_return_if_fail (iter->stamp == dict->stamp);
789
790   var =  iter->user_data;
791
792   switch (column)
793     {
794     case DICT_TVM_COL_NAME:
795       {
796         g_value_init (value, G_TYPE_STRING);
797         g_value_set_string (value, var_get_name (var));
798       }
799       break;
800     case DICT_TVM_COL_VAR:
801       g_value_init (value, PSPPIRE_VAR_PTR_TYPE);
802       g_value_set_boxed (value, var);
803       break;
804     default:
805       g_return_if_reached ();
806       break;
807     }
808 }
809
810 static gboolean
811 tree_model_iter_children (GtkTreeModel *tree_model,
812                           GtkTreeIter *iter,
813                           GtkTreeIter *parent)
814 {
815   return FALSE;
816 }
817
818 static gint
819 tree_model_n_children (GtkTreeModel *model,
820                        GtkTreeIter  *iter)
821 {
822   PsppireDict *dict = PSPPIRE_DICT (model);
823
824   if ( iter == NULL )
825     return psppire_dict_get_var_cnt (dict);
826
827   return 0;
828 }
829
830 static gboolean
831 tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
832                       GtkTreeIter *parent, gint n)
833 {
834   PsppireDict *dict;
835
836   g_return_val_if_fail (PSPPIRE_IS_DICT (model), FALSE);
837
838   dict = PSPPIRE_DICT (model);
839
840   if ( parent )
841     return FALSE;
842
843   if ( n >= psppire_dict_get_var_cnt (dict) )
844     return FALSE;
845
846   iter->stamp = dict->stamp;
847   iter->user_data = psppire_dict_get_variable (dict, n);
848
849   if ( !iter->user_data)
850     return FALSE;
851
852   return TRUE;
853 }
854
855
856 gboolean
857 psppire_dict_rename_var (PsppireDict *dict, struct variable *v,
858                          const gchar *name)
859 {
860   if ( ! dict_id_is_valid (dict->dict, name, false))
861     return FALSE;
862
863   /* Make sure no other variable has this name */
864   if ( NULL != psppire_dict_lookup_var (dict, name))
865     return FALSE;
866
867   dict_rename_var (dict->dict, v, name);
868
869   return TRUE;
870 }
871
872
873 struct variable *
874 psppire_dict_get_weight_variable (const PsppireDict *dict)
875 {
876   return dict_get_weight (dict->dict);
877 }
878
879
880
881 #if DEBUGGING
882 void
883 psppire_dict_dump (const PsppireDict *dict)
884 {
885   gint i;
886   const struct dictionary *d = dict->dict;
887
888   for (i = 0; i < dict_get_var_cnt (d); ++i)
889     {
890       const struct variable *v = psppire_dict_get_variable (dict, i);
891       int di = var_get_dict_index (v);
892       g_print ("`%s' idx=%d, fv=%d\n",
893                var_get_name(v),
894                di,
895                var_get_case_index(v));
896
897     }
898 }
899 #endif
900
901
902
903
904 const gchar *
905 psppire_dict_encoding (const PsppireDict *dict)
906 {
907   return dict_get_encoding (dict->dict);
908 }