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