ea67c85ce5c130f122685d5a29574c9a7d1583d6
[pspp] / src / ui / gui / psppire-dict.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2004, 2006, 2007, 2009, 2010, 2011  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_finalize       (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->finalize = psppire_dict_finalize;
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                   g_cclosure_marshal_VOID__INT,
138                   G_TYPE_NONE,
139                   1,
140                   G_TYPE_INT);
141
142
143
144   signals [VARIABLE_INSERTED] =
145     g_signal_new ("variable_inserted",
146                   G_TYPE_FROM_CLASS (class),
147                   G_SIGNAL_RUN_FIRST,
148                   0,
149                   NULL, NULL,
150                   g_cclosure_marshal_VOID__INT,
151                   G_TYPE_NONE,
152                   1,
153                   G_TYPE_INT);
154
155
156   signals [VARIABLE_DELETED] =
157     g_signal_new ("variable-deleted",
158                   G_TYPE_FROM_CLASS (class),
159                   G_SIGNAL_RUN_FIRST,
160                   0,
161                   NULL, NULL,
162                   psppire_marshal_VOID__POINTER_INT_INT,
163                   G_TYPE_NONE,
164                   3,
165                   G_TYPE_POINTER,
166                   G_TYPE_INT,
167                   G_TYPE_INT);
168
169
170   signals [VARIABLE_RESIZED] =
171     g_signal_new ("dict-size-changed",
172                   G_TYPE_FROM_CLASS (class),
173                   G_SIGNAL_RUN_FIRST,
174                   0,
175                   NULL, NULL,
176                   psppire_marshal_VOID__INT_INT,
177                   G_TYPE_NONE,
178                   2,
179                   G_TYPE_INT,
180                   G_TYPE_INT);
181
182   signals [VARIABLE_DISPLAY_WIDTH_CHANGED] =
183     g_signal_new ("variable-display-width-changed",
184                   G_TYPE_FROM_CLASS (class),
185                   G_SIGNAL_RUN_FIRST,
186                   0,
187                   NULL, NULL,
188                   g_cclosure_marshal_VOID__INT,
189                   G_TYPE_NONE,
190                   1,
191                   G_TYPE_INT);
192
193
194   signals [WEIGHT_CHANGED] =
195     g_signal_new ("weight-changed",
196                   G_TYPE_FROM_CLASS (class),
197                   G_SIGNAL_RUN_FIRST,
198                   0,
199                   NULL, NULL,
200                   g_cclosure_marshal_VOID__INT,
201                   G_TYPE_NONE,
202                   1,
203                   G_TYPE_INT);
204
205
206   signals [FILTER_CHANGED] =
207     g_signal_new ("filter-changed",
208                   G_TYPE_FROM_CLASS (class),
209                   G_SIGNAL_RUN_FIRST,
210                   0,
211                   NULL, NULL,
212                   g_cclosure_marshal_VOID__INT,
213                   G_TYPE_NONE,
214                   1,
215                   G_TYPE_INT);
216
217
218   signals [SPLIT_CHANGED] =
219     g_signal_new ("split-changed",
220                   G_TYPE_FROM_CLASS (class),
221                   G_SIGNAL_RUN_FIRST,
222                   0,
223                   NULL, NULL,
224                   g_cclosure_marshal_VOID__VOID,
225                   G_TYPE_NONE,
226                   0);
227 }
228
229 static void
230 psppire_dict_finalize (GObject *object)
231 {
232   PsppireDict *d = PSPPIRE_DICT (object);
233
234   dict_destroy (d->dict);
235
236   G_OBJECT_CLASS (parent_class)->finalize (object);
237 }
238
239 /* Pass on callbacks from src/data/dictionary, as
240    signals in the Gtk library */
241 static void
242 addcb (struct dictionary *d, int idx, void *pd)
243 {
244   PsppireDict *dict = PSPPIRE_DICT (pd);
245
246   if ( ! dict->disable_insert_signal)
247     g_signal_emit (dict, signals [VARIABLE_INSERTED], 0, idx);
248 }
249
250 static void
251 delcb (struct dictionary *d, const struct variable *var,
252        int dict_idx, int case_idx, void *pd)
253 {
254   g_signal_emit (pd, signals [VARIABLE_DELETED], 0,
255                  var, dict_idx, case_idx);
256 }
257
258 static void
259 mutcb (struct dictionary *d, int idx, void *pd)
260 {
261   g_signal_emit (pd, signals [VARIABLE_CHANGED], 0, idx);
262 }
263
264 static void
265 resize_cb (struct dictionary *d, int idx, int old_width, void *pd)
266 {
267   g_signal_emit (pd, signals [VARIABLE_RESIZED], 0, idx, old_width);
268 }
269
270 static void
271 weight_changed_callback (struct dictionary *d, int idx, void *pd)
272 {
273   g_signal_emit (pd, signals [WEIGHT_CHANGED], 0, idx);
274 }
275
276 static void
277 filter_changed_callback (struct dictionary *d, int idx, void *pd)
278 {
279   g_signal_emit (pd, signals [FILTER_CHANGED], 0, idx);
280 }
281
282 static void
283 split_changed_callback (struct dictionary *d, void *pd)
284 {
285   g_signal_emit (pd, signals [SPLIT_CHANGED], 0);
286 }
287
288 static void
289 variable_display_width_callback (struct dictionary *d, int idx, void *pd)
290 {
291   g_signal_emit (pd, signals [VARIABLE_DISPLAY_WIDTH_CHANGED], 0, idx);
292 }
293
294
295
296 static const struct dict_callbacks gui_callbacks =
297   {
298     addcb,
299     delcb,
300     mutcb,
301     resize_cb,
302     weight_changed_callback,
303     filter_changed_callback,
304     split_changed_callback,
305     variable_display_width_callback
306   };
307
308 static void
309 psppire_dict_init (PsppireDict *psppire_dict)
310 {
311   psppire_dict->stamp = g_random_int ();
312   psppire_dict->disable_insert_signal = FALSE;
313 }
314
315 /**
316  * psppire_dict_new_from_dict:
317  * @returns: a new #PsppireDict object
318  *
319  * Creates a new #PsppireDict.
320  */
321 PsppireDict*
322 psppire_dict_new_from_dict (struct dictionary *d)
323 {
324   PsppireDict *new_dict = g_object_new (PSPPIRE_TYPE_DICT, NULL);
325   new_dict->dict = d;
326
327   dict_set_callbacks (new_dict->dict, &gui_callbacks, new_dict);
328
329   return new_dict;
330 }
331
332
333 void
334 psppire_dict_replace_dictionary (PsppireDict *dict, struct dictionary *d)
335 {
336   struct variable *var =  dict_get_weight (d);
337
338   dict->dict = d;
339
340   weight_changed_callback (d, var ? var_get_dict_index (var) : -1, dict);
341
342   var = dict_get_filter (d);
343   filter_changed_callback (d, var ? var_get_dict_index (var) : -1, dict);
344
345   split_changed_callback (d, dict);
346
347   dict_set_callbacks (dict->dict, &gui_callbacks, dict);
348
349   g_signal_emit (dict, signals [BACKEND_CHANGED], 0);
350 }
351
352
353 /* Returns a valid name for a new variable in DICT.
354    The return value is statically allocated */
355 static gchar *
356 auto_generate_var_name (PsppireDict *dict)
357 {
358   gint d = 0;
359   static gchar name[10];
360
361   /* TRANSLATORS: This string must be a valid variable name.  That means:
362      - The string must be at most 64 bytes (not characters) long.
363      - The string may not contain whitespace.
364      - The first character may not be '$'
365      - The first character may not be a digit
366      - The final charactor may not be '.' or '_'
367    */
368   while (g_snprintf (name, 10, _("VAR%05d"), d++),
369          psppire_dict_lookup_var (dict, name))
370     ;
371
372   return name;
373 }
374
375 /* Insert a new variable at posn IDX, with the name NAME.
376    If NAME is null, then a name will be automatically assigned.
377 */
378 void
379 psppire_dict_insert_variable (PsppireDict *d, gint idx, const gchar *name)
380 {
381   struct variable *var ;
382   g_return_if_fail (idx >= 0);
383   g_return_if_fail (d);
384   g_return_if_fail (PSPPIRE_IS_DICT (d));
385
386   if ( ! name )
387     name = auto_generate_var_name (d);
388
389   d->disable_insert_signal = TRUE;
390
391   var = dict_create_var (d->dict, name, 0);
392
393   dict_reorder_var (d->dict, var, idx);
394
395   d->disable_insert_signal = FALSE;
396
397   g_signal_emit (d, signals[VARIABLE_INSERTED], 0, idx);
398 }
399
400 /* Delete N variables beginning at FIRST */
401 void
402 psppire_dict_delete_variables (PsppireDict *d, gint first, gint n)
403 {
404   gint idx;
405   g_return_if_fail (d);
406   g_return_if_fail (d->dict);
407   g_return_if_fail (PSPPIRE_IS_DICT (d));
408
409   for (idx = 0 ; idx < n ; ++idx )
410     {
411       struct variable *var;
412
413       /* Do nothing if it's out of bounds */
414       if ( first >= dict_get_var_cnt (d->dict))
415         break;
416
417       var = dict_get_var (d->dict, first);
418       dict_delete_var (d->dict, var);
419     }
420 }
421
422
423 gboolean
424 psppire_dict_set_name (PsppireDict* d, gint idx, const gchar *name)
425 {
426   struct variable *var;
427   g_assert (d);
428   g_assert (PSPPIRE_IS_DICT (d));
429
430   if ( ! dict_id_is_valid (d->dict, name, false))
431     return FALSE;
432
433   if ( idx < dict_get_var_cnt (d->dict))
434     {
435       /* This is an existing variable? */
436       var = dict_get_var (d->dict, idx);
437       dict_rename_var (d->dict, var, name);
438     }
439   else
440     {
441       /* new variable */
442       dict_create_var (d->dict, name, 0);
443     }
444
445   return TRUE;
446 }
447
448
449
450 /* Return the IDXth variable.
451    Will return NULL if IDX  exceeds the number of variables in the dictionary.
452  */
453 struct variable *
454 psppire_dict_get_variable (const PsppireDict *d, gint idx)
455 {
456   g_return_val_if_fail (d, NULL);
457   g_return_val_if_fail (d->dict, NULL);
458
459   if ( dict_get_var_cnt (d->dict) <= idx )
460     return NULL;
461
462   return dict_get_var (d->dict, idx);
463 }
464
465
466 /* Return the number of variables in the dictionary */
467 gint
468 psppire_dict_get_var_cnt (const PsppireDict *d)
469 {
470   g_return_val_if_fail (d, -1);
471   g_return_val_if_fail (d->dict, -1);
472
473   return dict_get_var_cnt (d->dict);
474 }
475
476
477 /* Return the number of `union value's in the dictionary */
478 size_t
479 psppire_dict_get_value_cnt (const PsppireDict *d)
480 {
481   g_return_val_if_fail (d, -1);
482   g_return_val_if_fail (d->dict, -1);
483
484   return dict_get_next_value_idx (d->dict);
485 }
486
487
488 /* Returns the prototype for the cases that match the dictionary */
489 const struct caseproto *
490 psppire_dict_get_proto (const PsppireDict *d)
491 {
492   g_return_val_if_fail (d, NULL);
493   g_return_val_if_fail (d->dict, NULL);
494
495   return dict_get_proto (d->dict);
496 }
497
498
499 /* Return a variable by name.
500    Return NULL if it doesn't exist
501 */
502 struct variable *
503 psppire_dict_lookup_var (const PsppireDict *d, const gchar *name)
504 {
505   g_return_val_if_fail (d, NULL);
506   g_return_val_if_fail (d->dict, NULL);
507
508   return dict_lookup_var (d->dict, name);
509 }
510
511 /* Clears the contents of D */
512 void
513 psppire_dict_clear (PsppireDict *d)
514 {
515   g_return_if_fail (d);
516   g_return_if_fail (d->dict);
517
518   {
519     dict_clear (d->dict);
520   }
521 }
522
523
524 /* Return true is NAME would be a valid name of a variable to add to the
525    dictionary.  False otherwise.
526    If REPORT is true, then invalid names will be reported as such as errors
527 */
528 gboolean
529 psppire_dict_check_name (const PsppireDict *dict,
530                          const gchar *name, gboolean report)
531 {
532   if ( ! dict_id_is_valid (dict->dict, name, report ) )
533     return FALSE;
534
535   if (psppire_dict_lookup_var (dict, name))
536     {
537       if ( report )
538         msg (ME, _("Duplicate variable name."));
539       return FALSE;
540     }
541
542   return TRUE;
543 }
544
545
546 gint
547 psppire_dict_get_next_value_idx (const PsppireDict *dict)
548 {
549   return dict_get_next_value_idx (dict->dict);
550 }
551
552
553 void
554 psppire_dict_resize_variable (PsppireDict *d, const struct variable *pv,
555                               gint old_size, gint new_size)
556 {
557   g_return_if_fail (d);
558   g_return_if_fail (d->dict);
559
560   if ( old_size == new_size )
561     return ;
562
563   g_signal_emit (d, signals [VARIABLE_RESIZED], 0,
564                  var_get_dict_index (pv),
565                  new_size - old_size );
566 }
567
568
569 /* Tree Model Stuff */
570
571 static GtkTreeModelFlags tree_model_get_flags (GtkTreeModel *model);
572
573 static gint tree_model_n_columns (GtkTreeModel *model);
574
575 static GType tree_model_column_type (GtkTreeModel *model, gint index);
576
577 static gboolean tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter,
578                                      GtkTreePath *path);
579
580 static gboolean tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter);
581
582 static GtkTreePath * tree_model_get_path (GtkTreeModel *model,
583                                           GtkTreeIter *iter);
584
585 static void tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
586                                   gint column, GValue *value);
587
588 static gboolean tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
589                                       GtkTreeIter *parent, gint n);
590
591 static gint tree_model_n_children (GtkTreeModel *tree_model,
592                                    GtkTreeIter  *iter);
593
594 static gboolean tree_model_iter_children (GtkTreeModel *,
595                                           GtkTreeIter *,
596                                           GtkTreeIter *);
597
598 static gboolean tree_model_iter_parent (GtkTreeModel *tree_model,
599                                         GtkTreeIter *iter,
600                                         GtkTreeIter *child);
601
602 static gboolean tree_model_iter_has_child  (GtkTreeModel *tree_model,
603                                             GtkTreeIter  *iter);
604
605 static void
606 dictionary_tree_model_init (GtkTreeModelIface *iface)
607 {
608   iface->get_flags = tree_model_get_flags;
609   iface->get_n_columns = tree_model_n_columns;
610   iface->get_column_type = tree_model_column_type;
611   iface->get_iter = tree_model_get_iter;
612   iface->iter_next = tree_model_iter_next;
613   iface->get_path = tree_model_get_path;
614   iface->get_value = tree_model_get_value;
615
616   iface->iter_children = tree_model_iter_children ;
617   iface->iter_has_child = tree_model_iter_has_child ;
618   iface->iter_n_children = tree_model_n_children ;
619   iface->iter_nth_child = tree_model_nth_child ;
620   iface->iter_parent = tree_model_iter_parent ;
621 }
622
623 static gboolean
624 tree_model_iter_has_child  (GtkTreeModel *tree_model,
625                             GtkTreeIter  *iter)
626 {
627   return FALSE;
628 }
629
630 static gboolean
631 tree_model_iter_parent (GtkTreeModel *tree_model,
632                         GtkTreeIter *iter,
633                         GtkTreeIter *child)
634 {
635   return TRUE;
636 }
637
638 static GtkTreeModelFlags
639 tree_model_get_flags (GtkTreeModel *model)
640 {
641   g_return_val_if_fail (PSPPIRE_IS_DICT (model), (GtkTreeModelFlags) 0);
642
643   return GTK_TREE_MODEL_LIST_ONLY;
644 }
645
646
647 static gint
648 tree_model_n_columns (GtkTreeModel *model)
649 {
650   return n_DICT_COLS;
651 }
652
653 static GType
654 tree_model_column_type (GtkTreeModel *model, gint index)
655 {
656   g_return_val_if_fail (PSPPIRE_IS_DICT (model), (GType) 0);
657
658   switch (index)
659     {
660     case DICT_TVM_COL_NAME:
661       return G_TYPE_STRING;
662       break;
663     case DICT_TVM_COL_VAR:
664       return PSPPIRE_VAR_PTR_TYPE;
665       break;
666     default:
667       g_return_val_if_reached ((GType)0);
668       break;
669     }
670
671   g_assert_not_reached ();
672   return ((GType)0);
673 }
674
675 static gboolean
676 tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
677 {
678   gint *indices, depth;
679   gint n;
680   struct variable *var;
681
682   PsppireDict *dict = PSPPIRE_DICT (model);
683
684   g_return_val_if_fail (path, FALSE);
685
686   indices = gtk_tree_path_get_indices (path);
687   depth = gtk_tree_path_get_depth (path);
688
689   g_return_val_if_fail (depth == 1, FALSE);
690
691   n = indices [0];
692
693   if ( n < 0 || n >= psppire_dict_get_var_cnt (dict))
694     {
695       iter->stamp = 0;
696       iter->user_data = NULL;
697       return FALSE;
698     }
699
700   var = psppire_dict_get_variable (dict, n);
701
702   g_assert (var_get_dict_index (var) == n);
703
704   iter->stamp = dict->stamp;
705   iter->user_data = var;
706
707   return TRUE;
708 }
709
710
711 static gboolean
712 tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
713 {
714   PsppireDict *dict = PSPPIRE_DICT (model);
715   struct variable *var;
716   gint idx;
717
718   g_return_val_if_fail (iter->stamp == dict->stamp, FALSE);
719
720   if ( iter == NULL || iter->user_data == NULL)
721     return FALSE;
722
723   var = iter->user_data;
724
725   idx = var_get_dict_index (var);
726
727   if ( idx + 1 >= psppire_dict_get_var_cnt (dict))
728     {
729       iter->user_data = NULL;
730       iter->stamp = 0;
731       return FALSE;
732     }
733
734   var = psppire_dict_get_variable (dict, idx + 1);
735
736   g_assert (var_get_dict_index (var) == idx + 1);
737
738   iter->user_data = var;
739
740   return TRUE;
741 }
742
743 static GtkTreePath *
744 tree_model_get_path (GtkTreeModel *model, GtkTreeIter *iter)
745 {
746   GtkTreePath *path;
747   struct variable *var;
748   PsppireDict *dict = PSPPIRE_DICT (model);
749
750   g_return_val_if_fail (iter->stamp == dict->stamp, FALSE);
751
752   var = iter->user_data;
753
754   path = gtk_tree_path_new ();
755   gtk_tree_path_append_index (path, var_get_dict_index (var));
756
757   return path;
758 }
759
760
761 static void
762 tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
763                       gint column, GValue *value)
764 {
765   struct variable *var;
766   PsppireDict *dict = PSPPIRE_DICT (model);
767
768   g_return_if_fail (iter->stamp == dict->stamp);
769
770   var =  iter->user_data;
771
772   switch (column)
773     {
774     case DICT_TVM_COL_NAME:
775       {
776         g_value_init (value, G_TYPE_STRING);
777         g_value_set_string (value, var_get_name (var));
778       }
779       break;
780     case DICT_TVM_COL_VAR:
781       g_value_init (value, PSPPIRE_VAR_PTR_TYPE);
782       g_value_set_boxed (value, var);
783       break;
784     default:
785       g_return_if_reached ();
786       break;
787     }
788 }
789
790 static gboolean
791 tree_model_iter_children (GtkTreeModel *tree_model,
792                           GtkTreeIter *iter,
793                           GtkTreeIter *parent)
794 {
795   return FALSE;
796 }
797
798 static gint
799 tree_model_n_children (GtkTreeModel *model,
800                        GtkTreeIter  *iter)
801 {
802   PsppireDict *dict = PSPPIRE_DICT (model);
803
804   if ( iter == NULL )
805     return psppire_dict_get_var_cnt (dict);
806
807   return 0;
808 }
809
810 static gboolean
811 tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
812                       GtkTreeIter *parent, gint n)
813 {
814   PsppireDict *dict;
815
816   g_return_val_if_fail (PSPPIRE_IS_DICT (model), FALSE);
817
818   dict = PSPPIRE_DICT (model);
819
820   if ( parent )
821     return FALSE;
822
823   if ( n >= psppire_dict_get_var_cnt (dict) )
824     return FALSE;
825
826   iter->stamp = dict->stamp;
827   iter->user_data = psppire_dict_get_variable (dict, n);
828
829   if ( !iter->user_data)
830     return FALSE;
831
832   return TRUE;
833 }
834
835
836 gboolean
837 psppire_dict_rename_var (PsppireDict *dict, struct variable *v,
838                          const gchar *name)
839 {
840   if ( ! dict_id_is_valid (dict->dict, name, false))
841     return FALSE;
842
843   /* Make sure no other variable has this name */
844   if ( NULL != psppire_dict_lookup_var (dict, name))
845     return FALSE;
846
847   dict_rename_var (dict->dict, v, name);
848
849   return TRUE;
850 }
851
852
853 struct variable *
854 psppire_dict_get_weight_variable (const PsppireDict *dict)
855 {
856   return dict_get_weight (dict->dict);
857 }
858
859
860
861 #if DEBUGGING
862 void
863 psppire_dict_dump (const PsppireDict *dict)
864 {
865   gint i;
866   const struct dictionary *d = dict->dict;
867
868   for (i = 0; i < dict_get_var_cnt (d); ++i)
869     {
870       const struct variable *v = psppire_dict_get_variable (dict, i);
871       int di = var_get_dict_index (v);
872       g_print ("`%s' idx=%d, fv=%d\n",
873                var_get_name(v),
874                di,
875                var_get_case_index(v));
876
877     }
878 }
879 #endif
880
881
882
883
884 const gchar *
885 psppire_dict_encoding (const PsppireDict *dict)
886 {
887   return dict_get_encoding (dict->dict);
888 }