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