Remove unnecessary gpointer variable from gsheet-row-iface
[pspp-builds.git] / src / ui / gui / psppire-var-store.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2006  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 #include <string.h>
19 #include <stdlib.h>
20 #include <gettext.h>
21 #define _(msgid) gettext (msgid)
22 #define N_(msgid) msgid
23
24
25
26 #include <gobject/gvaluecollector.h>
27
28 #include <gtksheet/gsheetmodel.h>
29
30 #include "psppire-var-store.h"
31 #include <gtksheet/gsheet-row-iface.h>
32 #include "helper.h"
33
34 #include <data/dictionary.h>
35 #include <data/variable.h>
36 #include <data/missing-values.h>
37
38 #include "val-labs-dialog.h"
39 #include "missing-val-dialog.h"
40 #include <data/value-labels.h>
41
42 #include "var-display.h"
43
44 enum
45   {
46     PSPPIRE_VAR_STORE_TRAILING_ROWS = 1,
47     PSPPIRE_VAR_STORE_FORMAT_TYPE
48   };
49
50 static void         psppire_var_store_init            (PsppireVarStore      *var_store);
51 static void         psppire_var_store_class_init      (PsppireVarStoreClass *class);
52 static void         psppire_var_store_sheet_model_init (GSheetModelIface *iface);
53 static void         psppire_var_store_finalize        (GObject           *object);
54
55
56 gchar * missing_values_to_string (const struct variable *pv, GError **err);
57
58
59 static gchar *psppire_var_store_get_string (const GSheetModel *sheet_model, glong row, glong column);
60
61 static gboolean  psppire_var_store_clear (GSheetModel *model,  glong row, glong col);
62
63
64 static gboolean psppire_var_store_set_string (GSheetModel *model,
65                                           const gchar *text, glong row, glong column);
66
67 static glong psppire_var_store_get_row_count (const GSheetModel * model);
68 static glong psppire_var_store_get_column_count (const GSheetModel * model);
69
70 static gchar *text_for_column (const struct variable *pv, gint c, GError **err);
71
72
73 static void psppire_var_store_sheet_row_init (GSheetRowIface *iface);
74
75
76
77 static GObjectClass *parent_class = NULL;
78
79 GType
80 psppire_var_store_format_type_get_type (void)
81 {
82   static GType etype = 0;
83   if (etype == 0)
84     {
85       static const GEnumValue values[] =
86         {
87           { PSPPIRE_VAR_STORE_INPUT_FORMATS,
88             "PSPPIRE_VAR_STORE_INPUT_FORMATS",
89             "input" },
90           { PSPPIRE_VAR_STORE_OUTPUT_FORMATS,
91             "PSPPIRE_VAR_STORE_OUTPUT_FORMATS",
92             "output" },
93           { 0, NULL, NULL }
94         };
95
96       etype = g_enum_register_static
97         (g_intern_static_string ("PsppireVarStoreFormatType"), values);
98
99     }
100   return etype;
101 }
102
103 GType
104 psppire_var_store_get_type (void)
105 {
106   static GType var_store_type = 0;
107
108   if (!var_store_type)
109     {
110       static const GTypeInfo var_store_info =
111       {
112         sizeof (PsppireVarStoreClass),
113         NULL,           /* base_init */
114         NULL,           /* base_finalize */
115         (GClassInitFunc) psppire_var_store_class_init,
116         NULL,           /* class_finalize */
117         NULL,           /* class_data */
118         sizeof (PsppireVarStore),
119         0,
120         (GInstanceInitFunc) psppire_var_store_init,
121       };
122
123       static const GInterfaceInfo sheet_model_info =
124       {
125         (GInterfaceInitFunc) psppire_var_store_sheet_model_init,
126         NULL,
127         NULL
128       };
129
130       static const GInterfaceInfo sheet_row_info =
131       {
132         (GInterfaceInitFunc) psppire_var_store_sheet_row_init,
133         NULL,
134         NULL
135       };
136
137       var_store_type = g_type_register_static (G_TYPE_OBJECT, "PsppireVarStore", &var_store_info, 0);
138
139       g_type_add_interface_static (var_store_type,
140                                    G_TYPE_SHEET_MODEL,
141                                    &sheet_model_info);
142
143       g_type_add_interface_static (var_store_type,
144                                    G_TYPE_SHEET_ROW,
145                                    &sheet_row_info);
146
147
148     }
149
150   return var_store_type;
151 }
152
153 static void
154 psppire_var_store_set_property (GObject      *object,
155                                 guint         property_id,
156                                 const GValue *value,
157                                 GParamSpec   *pspec)
158 {
159   PsppireVarStore *self = (PsppireVarStore *) object;
160
161   switch (property_id)
162     {
163     case PSPPIRE_VAR_STORE_TRAILING_ROWS:
164       self->trailing_rows = g_value_get_int (value);
165       break;
166
167     case PSPPIRE_VAR_STORE_FORMAT_TYPE:
168       self->format_type = g_value_get_enum (value);
169       break;
170
171     default:
172       G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
173       break;
174     }
175 }
176
177 static void
178 psppire_var_store_get_property (GObject      *object,
179                         guint         property_id,
180                         GValue       *value,
181                         GParamSpec   *pspec)
182 {
183   PsppireVarStore *self = (PsppireVarStore *) object;
184
185   switch (property_id)
186     {
187     case PSPPIRE_VAR_STORE_TRAILING_ROWS:
188       g_value_set_int (value, self->trailing_rows);
189       break;
190
191     case PSPPIRE_VAR_STORE_FORMAT_TYPE:
192       g_value_set_enum (value, self->format_type);
193       break;
194
195     default:
196       G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
197       break;
198     }
199 }
200
201
202 static void
203 psppire_var_store_class_init (PsppireVarStoreClass *class)
204 {
205   GObjectClass *object_class;
206   GParamSpec *pspec;
207
208   parent_class = g_type_class_peek_parent (class);
209   object_class = (GObjectClass*) class;
210
211   object_class->finalize = psppire_var_store_finalize;
212   object_class->set_property = psppire_var_store_set_property;
213   object_class->get_property = psppire_var_store_get_property;
214
215   /* The minimum value for trailing-rows is 1 to prevent the
216      var-store from ever having 0 rows, which breaks invariants
217      in gtksheet. */
218   pspec = g_param_spec_int ("trailing-rows",
219                             "Trailing rows",
220                             "Number of rows displayed after last variable",
221                             1  /* minimum value */,
222                             100 /* maximum value */,
223                             40  /* default value */,
224                             G_PARAM_READWRITE);
225   g_object_class_install_property (object_class,
226                                    PSPPIRE_VAR_STORE_TRAILING_ROWS,
227                                    pspec);
228
229   pspec = g_param_spec_enum ("format-type",
230                              "Variable format type",
231                              ("Whether variables have input or output "
232                               "formats"),
233                              G_TYPE_PSPPIRE_VAR_STORE_FORMAT_TYPE,
234                              PSPPIRE_VAR_STORE_OUTPUT_FORMATS,
235                              G_PARAM_READWRITE);
236   g_object_class_install_property (object_class,
237                                    PSPPIRE_VAR_STORE_FORMAT_TYPE,
238                                    pspec);
239 }
240
241 static void
242 psppire_var_store_init (PsppireVarStore *var_store)
243 {
244   GdkColormap *colormap = gdk_colormap_get_system ();
245
246   g_assert (gdk_color_parse ("gray", &var_store->disabled));
247
248   gdk_colormap_alloc_color (colormap, &var_store->disabled, FALSE, TRUE);
249
250   var_store->dict = 0;
251   var_store->trailing_rows = 40;
252   var_store->format_type = PSPPIRE_VAR_STORE_OUTPUT_FORMATS;
253 }
254
255 static gboolean
256 psppire_var_store_item_editable (PsppireVarStore *var_store, glong row, glong column)
257 {
258   const struct fmt_spec *write_spec ;
259
260   struct variable *pv = psppire_var_store_get_var (var_store, row);
261
262   if ( !pv )
263     return TRUE;
264
265   if ( var_is_alpha (pv) && column == PSPPIRE_VAR_STORE_COL_DECIMALS )
266     return FALSE;
267
268   write_spec = var_get_print_format (pv);
269
270   switch ( write_spec->type )
271     {
272     case FMT_DATE:
273     case FMT_EDATE:
274     case FMT_SDATE:
275     case FMT_ADATE:
276     case FMT_JDATE:
277     case FMT_QYR:
278     case FMT_MOYR:
279     case FMT_WKYR:
280     case FMT_DATETIME:
281     case FMT_TIME:
282     case FMT_DTIME:
283     case FMT_WKDAY:
284     case FMT_MONTH:
285       if ( column == PSPPIRE_VAR_STORE_COL_DECIMALS || column == PSPPIRE_VAR_STORE_COL_WIDTH)
286         return FALSE;
287       break;
288     default:
289       break;
290     }
291
292   return TRUE;
293 }
294
295
296 struct variable *
297 psppire_var_store_get_var (PsppireVarStore *store, glong row)
298 {
299   return psppire_dict_get_variable (store->dict, row);
300 }
301
302 static gboolean
303 psppire_var_store_is_editable (const GSheetModel *model, glong row, glong column)
304 {
305   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
306   return psppire_var_store_item_editable (store, row, column);
307 }
308
309
310 static const GdkColor *
311 psppire_var_store_get_foreground (const GSheetModel *model, glong row, glong column)
312 {
313   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
314
315   if ( ! psppire_var_store_item_editable (store, row, column) )
316     return &store->disabled;
317
318   return NULL;
319 }
320
321
322 const PangoFontDescription *
323 psppire_var_store_get_font_desc (const GSheetModel *model,
324                               glong row, glong column)
325 {
326   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
327
328   return store->font_desc;
329 }
330
331
332
333
334 static void
335 psppire_var_store_sheet_model_init (GSheetModelIface *iface)
336 {
337   iface->get_row_count = psppire_var_store_get_row_count;
338   iface->get_column_count = psppire_var_store_get_column_count;
339   iface->free_strings = TRUE;
340   iface->get_string = psppire_var_store_get_string;
341   iface->set_string = psppire_var_store_set_string;
342   iface->clear_datum = psppire_var_store_clear;
343   iface->is_editable = psppire_var_store_is_editable;
344   iface->is_visible = NULL;
345   iface->get_foreground = psppire_var_store_get_foreground;
346   iface->get_background = NULL;
347   iface->get_font_desc = psppire_var_store_get_font_desc;
348   iface->get_cell_border = NULL;
349 }
350
351
352
353 /**
354  * psppire_var_store_new:
355  * @dict: The dictionary for this var_store.
356  *
357  *
358  * Return value: a new #PsppireVarStore
359  **/
360 PsppireVarStore *
361 psppire_var_store_new (PsppireDict *dict)
362 {
363   PsppireVarStore *retval;
364
365   retval = g_object_new (GTK_TYPE_VAR_STORE, NULL);
366
367   psppire_var_store_set_dictionary (retval, dict);
368
369   return retval;
370 }
371
372 static void
373 var_change_callback (GtkWidget *w, gint n, gpointer data)
374 {
375   GSheetModel *model = G_SHEET_MODEL (data);
376
377   g_sheet_model_range_changed (model,
378                                  n, 0, n, PSPPIRE_VAR_STORE_n_COLS);
379 }
380
381
382 static void
383 var_delete_callback (GtkWidget *w, gint dict_idx, gint case_idx, gint val_cnt, gpointer data)
384 {
385   GSheetModel *model = G_SHEET_MODEL (data);
386
387   g_sheet_model_rows_deleted (model, dict_idx, 1);
388 }
389
390
391
392 static void
393 var_insert_callback (GtkWidget *w, glong row, gpointer data)
394 {
395   GSheetModel *model = G_SHEET_MODEL (data);
396
397   g_sheet_model_rows_inserted (model, row, 1);
398 }
399
400 static void
401 refresh (PsppireDict  *d, gpointer data)
402 {
403   PsppireVarStore *vs = data;
404
405   g_sheet_model_range_changed (G_SHEET_MODEL (vs), -1, -1, -1, -1);
406 }
407
408 /**
409  * psppire_var_store_replace_set_dictionary:
410  * @var_store: The variable store
411  * @dict: The dictionary to set
412  *
413  * If a dictionary is already associated with the var-store, then it will be
414  * destroyed.
415  **/
416 void
417 psppire_var_store_set_dictionary (PsppireVarStore *var_store, PsppireDict *dict)
418 {
419   if ( var_store->dict ) g_object_unref (var_store->dict);
420
421   var_store->dict = dict;
422
423   g_signal_connect (dict, "variable-changed", G_CALLBACK (var_change_callback),
424                    var_store);
425
426   g_signal_connect (dict, "variable-deleted", G_CALLBACK (var_delete_callback),
427                    var_store);
428
429   g_signal_connect (dict, "variable-inserted",
430                     G_CALLBACK (var_insert_callback), var_store);
431
432   g_signal_connect (dict, "backend-changed", G_CALLBACK (refresh),
433                     var_store);
434
435   /* The entire model has changed */
436   g_sheet_model_range_changed (G_SHEET_MODEL (var_store), -1, -1, -1, -1);
437 }
438
439 static void
440 psppire_var_store_finalize (GObject *object)
441 {
442   /* must chain up */
443   (* parent_class->finalize) (object);
444 }
445
446 static gchar *
447 psppire_var_store_get_string (const GSheetModel *model, glong row, glong column)
448 {
449   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
450
451   struct variable *pv;
452
453   if ( row >= psppire_dict_get_var_cnt (store->dict))
454     return 0;
455
456   pv = psppire_dict_get_variable (store->dict, row);
457
458   return text_for_column (pv, column, 0);
459 }
460
461
462 /* Clears that part of the variable store, if possible, which corresponds
463    to ROW, COL.
464    Returns true if anything was updated, false otherwise.
465 */
466 static gboolean
467 psppire_var_store_clear (GSheetModel *model,  glong row, glong col)
468 {
469   struct variable *pv ;
470
471   PsppireVarStore *var_store = PSPPIRE_VAR_STORE (model);
472
473   if ( row >= psppire_dict_get_var_cnt (var_store->dict))
474       return FALSE;
475
476   pv = psppire_var_store_get_var (var_store, row);
477
478   if ( !pv )
479     return FALSE;
480
481   switch (col)
482     {
483     case PSPPIRE_VAR_STORE_COL_LABEL:
484       var_set_label (pv, 0);
485       return TRUE;
486       break;
487     }
488
489   return FALSE;
490 }
491
492 /* Attempts to update that part of the variable store which corresponds
493    to ROW, COL with  the value TEXT.
494    Returns true if anything was updated, false otherwise.
495 */
496 static gboolean
497 psppire_var_store_set_string (GSheetModel *model,
498                           const gchar *text, glong row, glong col)
499 {
500   struct variable *pv ;
501
502   PsppireVarStore *var_store = PSPPIRE_VAR_STORE (model);
503
504   if ( row >= psppire_dict_get_var_cnt (var_store->dict))
505       return FALSE;
506
507   pv = psppire_var_store_get_var (var_store, row);
508
509   if ( !pv )
510     return FALSE;
511
512   switch (col)
513     {
514     case PSPPIRE_VAR_STORE_COL_NAME:
515       return psppire_dict_rename_var (var_store->dict, pv, text);
516       break;
517     case PSPPIRE_VAR_STORE_COL_COLUMNS:
518       if ( ! text) return FALSE;
519       var_set_display_width (pv, atoi (text));
520       return TRUE;
521       break;
522     case PSPPIRE_VAR_STORE_COL_WIDTH:
523       {
524         int width = atoi (text);
525         if ( ! text) return FALSE;
526         if ( var_is_alpha (pv))
527             var_set_width (pv, width);
528         else
529           {
530             bool for_input
531               = var_store->format_type == PSPPIRE_VAR_STORE_INPUT_FORMATS;
532             struct fmt_spec fmt ;
533             fmt = *var_get_write_format (pv);
534             if ( width < fmt_min_width (fmt.type, for_input)
535                  ||
536                  width > fmt_max_width (fmt.type, for_input))
537               return FALSE;
538
539             fmt.w = width;
540             fmt.d = MIN (fmt_max_decimals (fmt.type, width, for_input), fmt.d);
541
542             var_set_both_formats (pv, &fmt);
543           }
544
545         return TRUE;
546       }
547       break;
548     case PSPPIRE_VAR_STORE_COL_DECIMALS:
549       {
550         bool for_input
551           = var_store->format_type == PSPPIRE_VAR_STORE_INPUT_FORMATS;
552         int decimals;
553         struct fmt_spec fmt;
554         if ( ! text) return FALSE;
555         decimals = atoi (text);
556         fmt = *var_get_write_format (pv);
557         if ( decimals >
558              fmt_max_decimals (fmt.type,
559                                fmt.w,
560                                for_input
561                                ))
562           return FALSE;
563
564         fmt.d = decimals;
565         var_set_both_formats (pv, &fmt);
566         return TRUE;
567       }
568       break;
569     case PSPPIRE_VAR_STORE_COL_LABEL:
570       var_set_label (pv, text);
571       return TRUE;
572       break;
573     case PSPPIRE_VAR_STORE_COL_TYPE:
574     case PSPPIRE_VAR_STORE_COL_VALUES:
575     case PSPPIRE_VAR_STORE_COL_MISSING:
576     case PSPPIRE_VAR_STORE_COL_ALIGN:
577     case PSPPIRE_VAR_STORE_COL_MEASURE:
578       /* These can be modified only by their respective dialog boxes */
579       return FALSE;
580       break;
581     default:
582       g_assert_not_reached ();
583       return FALSE;
584     }
585
586   return TRUE;
587 }
588
589
590 const static gchar none[] = N_("None");
591
592 static  gchar *
593 text_for_column (const struct variable *pv, gint c, GError **err)
594 {
595   static const gchar *const type_label[] =
596     {
597       N_("Numeric"),
598       N_("Comma"),
599       N_("Dot"),
600       N_("Scientific"),
601       N_("Date"),
602       N_("Dollar"),
603       N_("Custom"),
604       N_("String")
605     };
606   enum {VT_NUMERIC, VT_COMMA, VT_DOT, VT_SCIENTIFIC, VT_DATE, VT_DOLLAR,
607         VT_CUSTOM, VT_STRING};
608
609   const struct fmt_spec *write_spec = var_get_write_format (pv);
610
611   switch (c)
612     {
613     case PSPPIRE_VAR_STORE_COL_NAME:
614       return pspp_locale_to_utf8 ( var_get_name (pv), -1, err);
615       break;
616     case PSPPIRE_VAR_STORE_COL_TYPE:
617       {
618         switch ( write_spec->type )
619           {
620           case FMT_F:
621             return g_locale_to_utf8 (gettext (type_label[VT_NUMERIC]), -1, 0, 0, err);
622             break;
623           case FMT_COMMA:
624             return g_locale_to_utf8 (gettext (type_label[VT_COMMA]), -1, 0, 0, err);
625             break;
626           case FMT_DOT:
627             return g_locale_to_utf8 (gettext (type_label[VT_DOT]), -1, 0, 0, err);
628             break;
629           case FMT_E:
630             return g_locale_to_utf8 (gettext (type_label[VT_SCIENTIFIC]), -1, 0, 0, err);
631             break;
632           case FMT_DATE:
633           case FMT_EDATE:
634           case FMT_SDATE:
635           case FMT_ADATE:
636           case FMT_JDATE:
637           case FMT_QYR:
638           case FMT_MOYR:
639           case FMT_WKYR:
640           case FMT_DATETIME:
641           case FMT_TIME:
642           case FMT_DTIME:
643           case FMT_WKDAY:
644           case FMT_MONTH:
645             return g_locale_to_utf8 (type_label[VT_DATE], -1, 0, 0, err);
646             break;
647           case FMT_DOLLAR:
648             return g_locale_to_utf8 (type_label[VT_DOLLAR], -1, 0, 0, err);
649             break;
650           case FMT_CCA:
651           case FMT_CCB:
652           case FMT_CCC:
653           case FMT_CCD:
654           case FMT_CCE:
655             return g_locale_to_utf8 (gettext (type_label[VT_CUSTOM]), -1, 0, 0, err);
656             break;
657           case FMT_A:
658             return g_locale_to_utf8 (gettext (type_label[VT_STRING]), -1, 0, 0, err);
659             break;
660           default:
661             {
662               char str[FMT_STRING_LEN_MAX + 1];
663               g_warning ("Unknown format: \"%s\"\n",
664                         fmt_to_string (write_spec, str));
665             }
666             break;
667           }
668       }
669       break;
670     case PSPPIRE_VAR_STORE_COL_WIDTH:
671       {
672         gchar *s;
673         GString *gstr = g_string_sized_new (10);
674         g_string_printf (gstr, _("%d"), write_spec->w);
675         s = g_locale_to_utf8 (gstr->str, gstr->len, 0, 0, err);
676         g_string_free (gstr, TRUE);
677         return s;
678       }
679       break;
680     case PSPPIRE_VAR_STORE_COL_DECIMALS:
681       {
682         gchar *s;
683         GString *gstr = g_string_sized_new (10);
684         g_string_printf (gstr, _("%d"), write_spec->d);
685         s = g_locale_to_utf8 (gstr->str, gstr->len, 0, 0, err);
686         g_string_free (gstr, TRUE);
687         return s;
688       }
689       break;
690     case PSPPIRE_VAR_STORE_COL_COLUMNS:
691       {
692         gchar *s;
693         GString *gstr = g_string_sized_new (10);
694         g_string_printf (gstr, _("%d"), var_get_display_width (pv));
695         s = g_locale_to_utf8 (gstr->str, gstr->len, 0, 0, err);
696         g_string_free (gstr, TRUE);
697         return s;
698       }
699       break;
700     case PSPPIRE_VAR_STORE_COL_LABEL:
701       return pspp_locale_to_utf8 (var_get_label (pv), -1, err);
702       break;
703
704     case PSPPIRE_VAR_STORE_COL_MISSING:
705       {
706         return missing_values_to_string (pv, err);
707       }
708       break;
709     case PSPPIRE_VAR_STORE_COL_VALUES:
710       {
711         if ( ! var_has_value_labels (pv))
712           return g_locale_to_utf8 (gettext (none), -1, 0, 0, err);
713         else
714           {
715             gchar *ss;
716             GString *gstr = g_string_sized_new (10);
717             const struct val_labs *vls = var_get_value_labels (pv);
718             struct val_labs_iterator *ip = 0;
719             struct val_lab *vl = val_labs_first_sorted (vls, &ip);
720
721             g_assert (vl);
722
723             {
724               gchar *const vstr = value_to_text (vl->value, *write_spec);
725
726               g_string_printf (gstr, "{%s,\"%s\"}_", vstr, vl->label);
727               g_free (vstr);
728             }
729
730             val_labs_done (&ip);
731
732             ss = pspp_locale_to_utf8 (gstr->str, gstr->len, err);
733             g_string_free (gstr, TRUE);
734             return ss;
735           }
736       }
737       break;
738     case PSPPIRE_VAR_STORE_COL_ALIGN:
739       {
740         const gint align = var_get_alignment (pv);
741
742         g_assert (align < n_ALIGNMENTS);
743         return g_locale_to_utf8 (gettext (alignments[align]), -1, 0, 0, err);
744       }
745       break;
746     case PSPPIRE_VAR_STORE_COL_MEASURE:
747       {
748         return measure_to_string (pv, err);
749       }
750       break;
751     }
752   return 0;
753 }
754
755
756
757 /* Return the number of variables */
758 gint
759 psppire_var_store_get_var_cnt (PsppireVarStore  *store)
760 {
761   return psppire_dict_get_var_cnt (store->dict);
762 }
763
764
765 void
766 psppire_var_store_set_font (PsppireVarStore *store, const PangoFontDescription *fd)
767 {
768   g_return_if_fail (store);
769   g_return_if_fail (PSPPIRE_IS_VAR_STORE (store));
770
771   store->font_desc = fd;
772
773   g_sheet_model_range_changed (G_SHEET_MODEL (store), -1, -1, -1, -1);
774 }
775
776
777 static glong
778 psppire_var_store_get_row_count (const GSheetModel * model)
779 {
780   gint rows = 0;
781   PsppireVarStore *vs = PSPPIRE_VAR_STORE (model);
782
783   if (vs->dict)
784     rows =  psppire_dict_get_var_cnt (vs->dict);
785
786   return rows ;
787 }
788
789 static glong
790 psppire_var_store_get_column_count (const GSheetModel * model)
791 {
792   return PSPPIRE_VAR_STORE_n_COLS ;
793 }
794
795
796 /* Row related funcs */
797
798 static glong
799 geometry_get_row_count (const GSheetRow *geom)
800 {
801   gint rows = 0;
802   PsppireVarStore *vs = PSPPIRE_VAR_STORE (geom);
803
804   if (vs->dict)
805     rows =  psppire_dict_get_var_cnt (vs->dict);
806
807   return rows + vs->trailing_rows;
808 }
809
810
811 static gint
812 geometry_get_height (const GSheetRow *geom, glong row)
813 {
814   return 25;
815 }
816
817
818 static gboolean
819 geometry_is_sensitive (const GSheetRow *geom, glong row)
820 {
821   PsppireVarStore *vs = PSPPIRE_VAR_STORE (geom);
822
823   if ( ! vs->dict)
824     return FALSE;
825
826   return  row < psppire_dict_get_var_cnt (vs->dict);
827 }
828
829 static
830 gboolean always_true ()
831 {
832   return TRUE;
833 }
834
835
836 static gchar *
837 geometry_get_button_label (const GSheetRow *geom, glong unit)
838 {
839   gchar *label = g_strdup_printf (_("%ld"), unit + 1);
840
841   return label;
842 }
843
844 static void
845 psppire_var_store_sheet_row_init (GSheetRowIface *iface)
846 {
847   iface->get_row_count =     geometry_get_row_count;
848   iface->get_height =        geometry_get_height;
849   iface->set_height =        0;
850   iface->get_visibility =    always_true;
851   iface->get_sensitivity =   geometry_is_sensitive;
852
853   iface->get_button_label = geometry_get_button_label;
854 }
855
856
857