012c010fe61ad7b6a1b7b5df417a78e1e48545ec
[pspp] / src / ui / gui / psppire-data-store.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2006, 2008, 2009, 2010, 2011, 2012,
3    2013, 2016, 2017  Free Software Foundation
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
17
18 #include <config.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <gettext.h>
22 #define _(msgid) gettext (msgid)
23 #define P_(msgid) msgid
24
25 #include <data/datasheet.h>
26 #include <data/data-out.h>
27 #include <data/variable.h>
28
29 #include <ui/gui/psppire-marshal.h>
30
31 #include <pango/pango-context.h>
32
33 #include "psppire-data-store.h"
34 #include <libpspp/i18n.h>
35 #include "helper.h"
36
37 #include <data/dictionary.h>
38 #include <data/missing-values.h>
39 #include <data/value-labels.h>
40 #include <data/data-in.h>
41 #include <data/format.h>
42
43 #include <math/sort.h>
44
45 #include "xmalloca.h"
46
47 #include "value-variant.h"
48
49 static void psppire_data_store_init            (PsppireDataStore      *data_store);
50 static void psppire_data_store_class_init      (PsppireDataStoreClass *class);
51
52 static void psppire_data_store_finalize        (GObject           *object);
53 static void psppire_data_store_dispose        (GObject           *object);
54
55 static gboolean psppire_data_store_insert_case (PsppireDataStore *ds,
56                                                 struct ccase *cc,
57                                                 casenumber posn);
58
59
60 static gboolean psppire_data_store_data_in (PsppireDataStore *ds,
61                                             casenumber casenum, gint idx,
62                                             struct substring input,
63                                             const struct fmt_spec *fmt);
64
65 static GObjectClass *parent_class = NULL;
66
67
68 enum
69   {
70     ITEMS_CHANGED,
71     CASE_CHANGED,
72     n_SIGNALS
73   };
74
75 static guint signals [n_SIGNALS];
76
77 static gint
78 __tree_model_iter_n_children (GtkTreeModel *tree_model,
79                              GtkTreeIter *iter)
80 {
81   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
82
83   if (store->datasheet == NULL)
84     return 0;
85
86   gint n =  datasheet_get_n_rows (store->datasheet);
87
88   return n;
89 }
90
91 static GtkTreeModelFlags
92 __tree_model_get_flags (GtkTreeModel *model)
93 {
94   g_return_val_if_fail (PSPPIRE_IS_DATA_STORE (model), (GtkTreeModelFlags) 0);
95
96   return GTK_TREE_MODEL_LIST_ONLY;
97 }
98
99 static gint
100 __tree_model_get_n_columns (GtkTreeModel *tree_model)
101 {
102   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
103
104   return psppire_dict_get_var_cnt (store->dict);
105 }
106
107
108 static gboolean
109 __iter_nth_child (GtkTreeModel *tree_model,
110                   GtkTreeIter *iter,
111                   GtkTreeIter *parent,
112                   gint n)
113 {
114   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
115
116   g_assert (parent == NULL);
117   g_return_val_if_fail (store, FALSE);
118
119   if (!store->datasheet || n >= datasheet_get_n_rows (store->datasheet))
120     {
121       iter->stamp = -1;
122       iter->user_data = NULL;
123       return FALSE;
124     }
125
126   iter->user_data = GINT_TO_POINTER (n);
127   iter->stamp = store->stamp;
128
129   return TRUE;
130 }
131
132 /* Set the contents of OUT to reflect the information provided by IN, COL, and
133    ROW, for MODEL.  Returns TRUE if successful. */
134 gboolean
135 psppire_data_store_string_to_value (GtkTreeModel *model, gint col, gint row,
136                                     const gchar *in, GValue *out)
137 {
138   PsppireDataStore *store = PSPPIRE_DATA_STORE (model);
139
140   while (col >= psppire_dict_get_var_cnt (store->dict))
141     {
142       const struct variable *var =
143         psppire_dict_insert_variable (store->dict,
144                                       psppire_dict_get_var_cnt (store->dict),
145                                       NULL);
146       g_return_val_if_fail (var, FALSE);
147     }
148
149   const struct variable *variable = psppire_dict_get_variable (store->dict, col);
150   g_return_val_if_fail (variable, FALSE);
151
152   const struct fmt_spec *fmt = var_get_print_format (variable);
153
154   int width = var_get_width (variable);
155
156   union value val;
157   value_init (&val, width);
158   char *xx =
159     data_in (ss_cstr (in), psppire_dict_encoding (store->dict),
160              fmt->type, &val, width, "UTF-8");
161
162   GVariant *vrnt = value_variant_new (&val, width);
163   value_destroy (&val, width);
164
165   g_value_init (out, G_TYPE_VARIANT);
166   g_value_set_variant (out, vrnt);
167   free (xx);
168   return TRUE;
169 }
170
171 static char *
172 unlabeled_value (PsppireDataStore *store, const struct variable *variable, const union value *val)
173 {
174   const struct fmt_spec *fmt = var_get_print_format (variable);
175   return data_out (val, psppire_dict_encoding (store->dict),  fmt);
176 }
177
178 gchar *
179 psppire_data_store_value_to_string (gpointer unused, PsppireDataStore *store, gint col, gint row, const GValue *v)
180 {
181   const struct variable *variable = psppire_dict_get_variable (store->dict, col);
182   g_return_val_if_fail (variable, g_strdup ("???"));
183
184   GVariant *vrnt = g_value_get_variant (v);
185   g_return_val_if_fail (vrnt, g_strdup ("???"));
186
187   union value val;
188   value_variant_get (&val, vrnt);
189
190   char *out = unlabeled_value (store, variable, &val);
191
192   value_destroy_from_variant (&val, vrnt);
193
194   return out;
195 }
196
197 gchar *
198 psppire_data_store_value_to_string_with_labels (gpointer unused, PsppireDataStore *store, gint col, gint row, const GValue *v)
199 {
200   const struct variable *variable = psppire_dict_get_variable (store->dict, col);
201   g_return_val_if_fail (variable, g_strdup ("???"));
202
203   GVariant *vrnt = g_value_get_variant (v);
204   union value val;
205   value_variant_get (&val, vrnt);
206
207   char *out = NULL;
208
209   const struct val_labs *vls = var_get_value_labels (variable);
210   struct val_lab *vl = val_labs_lookup (vls, &val);
211   if (vl != NULL)
212     out = strdup (val_lab_get_label (vl));
213   else
214     out = unlabeled_value (store, variable, &val);
215
216   value_destroy_from_variant (&val, vrnt);
217
218   return out;
219 }
220
221 static void
222 __get_value (GtkTreeModel *tree_model,
223              GtkTreeIter *iter,
224              gint column,
225              GValue *value)
226 {
227   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
228
229   g_return_if_fail (iter->stamp == store->stamp);
230
231   const struct variable *variable = psppire_dict_get_variable (store->dict, column);
232   if (NULL == variable)
233     return;
234
235   gint row = GPOINTER_TO_INT (iter->user_data);
236
237   struct ccase *cc = datasheet_get_row (store->datasheet, row);
238
239   g_return_if_fail (cc);
240
241   g_value_init (value, G_TYPE_VARIANT);
242
243   const union value *val = case_data_idx (cc, var_get_case_index (variable));
244
245   GVariant *vv = value_variant_new (val, var_get_width (variable));
246
247   g_value_set_variant (value, vv);
248
249   case_unref (cc);
250 }
251
252
253 static void
254 __tree_model_init (GtkTreeModelIface *iface)
255 {
256   iface->get_flags       = __tree_model_get_flags;
257   iface->get_n_columns   = __tree_model_get_n_columns ;
258   iface->get_column_type = NULL;
259   iface->get_iter        = NULL;
260   iface->iter_next       = NULL;
261   iface->get_path        = NULL;
262   iface->get_value       = __get_value;
263
264   iface->iter_children   = NULL;
265   iface->iter_has_child  = NULL;
266   iface->iter_n_children = __tree_model_iter_n_children;
267   iface->iter_nth_child  = __iter_nth_child;
268   iface->iter_parent     = NULL;
269 }
270
271
272 GType
273 psppire_data_store_get_type (void)
274 {
275   static GType data_store_type = 0;
276
277   if (!data_store_type)
278     {
279       static const GTypeInfo data_store_info =
280       {
281         sizeof (PsppireDataStoreClass),
282         NULL,           /* base_init */
283         NULL,           /* base_finalize */
284         (GClassInitFunc) psppire_data_store_class_init,
285         NULL,           /* class_finalize */
286         NULL,           /* class_data */
287         sizeof (PsppireDataStore),
288         0,
289         (GInstanceInitFunc) psppire_data_store_init,
290       };
291
292       static const GInterfaceInfo tree_model_info = {
293         (GInterfaceInitFunc) __tree_model_init,
294         NULL,
295         NULL
296       };
297
298       data_store_type = g_type_register_static (G_TYPE_OBJECT,
299                                                 "PsppireDataStore",
300                                                 &data_store_info, 0);
301
302       g_type_add_interface_static (data_store_type, GTK_TYPE_TREE_MODEL,
303                                    &tree_model_info);
304     }
305
306   return data_store_type;
307 }
308
309
310 static void
311 psppire_data_store_class_init (PsppireDataStoreClass *class)
312 {
313   GObjectClass *object_class;
314
315   parent_class = g_type_class_peek_parent (class);
316   object_class = (GObjectClass*) class;
317
318   object_class->finalize = psppire_data_store_finalize;
319   object_class->dispose = psppire_data_store_dispose;
320
321   signals [ITEMS_CHANGED] =
322     g_signal_new ("items-changed",
323                   G_TYPE_FROM_CLASS (class),
324                   G_SIGNAL_RUN_FIRST,
325                   0,
326                   NULL, NULL,
327                   psppire_marshal_VOID__UINT_UINT_UINT,
328                   G_TYPE_NONE,
329                   3,
330                   G_TYPE_UINT,  /* Index of the start of the change */
331                   G_TYPE_UINT,  /* The number of items deleted */
332                   G_TYPE_UINT); /* The number of items inserted */
333
334   signals [CASE_CHANGED] =
335     g_signal_new ("case-changed",
336                   G_TYPE_FROM_CLASS (class),
337                   G_SIGNAL_RUN_FIRST,
338                   0,
339                   NULL, NULL,
340                   g_cclosure_marshal_VOID__INT,
341                   G_TYPE_NONE,
342                   1,
343                   G_TYPE_INT);
344 }
345
346
347
348 casenumber
349 psppire_data_store_get_case_count (const PsppireDataStore *store)
350 {
351   return datasheet_get_n_rows (store->datasheet);
352 }
353
354 size_t
355 psppire_data_store_get_value_count (const PsppireDataStore *store)
356 {
357   return psppire_dict_get_value_cnt (store->dict);
358 }
359
360 const struct caseproto *
361 psppire_data_store_get_proto (const PsppireDataStore *store)
362 {
363   return psppire_dict_get_proto (store->dict);
364 }
365
366 static void
367 psppire_data_store_init (PsppireDataStore *data_store)
368 {
369   data_store->dict = NULL;
370   data_store->datasheet = NULL;
371   data_store->dispose_has_run = FALSE;
372   data_store->stamp = g_random_int ();
373 }
374
375
376 static void
377 psppire_data_store_delete_value (PsppireDataStore *store, gint case_index)
378 {
379   g_return_if_fail (store->datasheet);
380   g_return_if_fail (case_index < datasheet_get_n_columns (store->datasheet));
381
382   datasheet_delete_columns (store->datasheet, case_index, 1);
383   datasheet_insert_column (store->datasheet, NULL, -1, case_index);
384 }
385
386
387 /*
388    A callback which occurs after a variable has been deleted.
389  */
390 static void
391 delete_variable_callback (GObject *obj, const struct variable *var UNUSED,
392                           gint dict_index, gint case_index,
393                           gpointer data)
394 {
395   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
396
397   psppire_data_store_delete_value (store, case_index);
398 }
399
400 struct resize_datum_aux
401   {
402     const struct dictionary *dict;
403     const struct variable *new_variable;
404     const struct variable *old_variable;
405   };
406
407 static void
408 resize_datum (const union value *old, union value *new, const void *aux_)
409 {
410   const struct resize_datum_aux *aux = aux_;
411   int new_width = var_get_width (aux->new_variable);
412   const char *enc = dict_get_encoding (aux->dict);
413   const struct fmt_spec *newfmt = var_get_print_format (aux->new_variable);
414   char *s = data_out (old, enc, var_get_print_format (aux->old_variable));
415   enum fmt_type type = (fmt_usable_for_input (newfmt->type)
416                         ? newfmt->type
417                         : FMT_DOLLAR);
418   free (data_in (ss_cstr (s), enc, type, new, new_width, enc));
419   free (s);
420 }
421
422 static void
423 variable_changed_callback (GObject *obj, gint var_num, guint what, const struct variable *oldvar,
424                            gpointer data)
425 {
426   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
427   struct variable *variable = psppire_dict_get_variable (store->dict, var_num);
428
429   if (what & VAR_TRAIT_WIDTH)
430     {
431       int posn = var_get_case_index (variable);
432       struct resize_datum_aux aux;
433       aux.old_variable = oldvar;
434       aux.new_variable = variable;
435       aux.dict = store->dict->dict;
436       datasheet_resize_column (store->datasheet, posn, var_get_width (variable),
437                                resize_datum, &aux);
438     }
439 }
440
441 static void
442 insert_variable_callback (GObject *obj, gint var_num, gpointer data)
443 {
444   struct variable *variable;
445   PsppireDataStore *store;
446   gint posn;
447
448   g_return_if_fail (data);
449
450   store  = PSPPIRE_DATA_STORE (data);
451
452   variable = psppire_dict_get_variable (store->dict, var_num);
453   posn = var_get_case_index (variable);
454   psppire_data_store_insert_value (store, var_get_width (variable), posn);
455 }
456
457 /**
458  * psppire_data_store_new:
459  * @dict: The dictionary for this data_store.
460  *
461  *
462  * Return value: a new #PsppireDataStore
463  **/
464 PsppireDataStore *
465 psppire_data_store_new (PsppireDict *dict)
466 {
467   PsppireDataStore *retval;
468
469   retval = g_object_new (PSPPIRE_TYPE_DATA_STORE, NULL);
470
471   psppire_data_store_set_dictionary (retval, dict);
472
473   return retval;
474 }
475
476 void
477 psppire_data_store_set_reader (PsppireDataStore *ds,
478                                struct casereader *reader)
479 {
480   gint i;
481   gint old_n = 0;
482   if (ds->datasheet)
483     {
484       old_n = datasheet_get_n_rows (ds->datasheet);
485       datasheet_destroy (ds->datasheet);
486     }
487
488   ds->datasheet = datasheet_create (reader);
489
490   gint new_n = datasheet_get_n_rows (ds->datasheet);
491
492   if (ds->dict)
493     for (i = 0 ; i < n_dict_signals; ++i)
494       {
495         if (ds->dict_handler_id [i] > 0)
496           {
497             g_signal_handler_unblock (ds->dict,
498                                       ds->dict_handler_id[i]);
499           }
500       }
501
502   g_signal_emit (ds, signals[ITEMS_CHANGED], 0, 0, old_n, new_n);
503 }
504
505
506 /**
507  * psppire_data_store_replace_set_dictionary:
508  * @data_store: The variable store
509  * @dict: The dictionary to set
510  *
511  * If a dictionary is already associated with the data-store, then it will be
512  * destroyed.
513  **/
514 void
515 psppire_data_store_set_dictionary (PsppireDataStore *data_store, PsppireDict *dict)
516 {
517   int i;
518
519   /* Disconnect any existing handlers */
520   if (data_store->dict)
521     for (i = 0 ; i < n_dict_signals; ++i)
522       {
523         g_signal_handler_disconnect (data_store->dict,
524                                      data_store->dict_handler_id[i]);
525       }
526
527   data_store->dict = dict;
528
529   if (dict != NULL)
530     {
531
532       data_store->dict_handler_id [VARIABLE_INSERTED] =
533         g_signal_connect (dict, "variable-inserted",
534                           G_CALLBACK (insert_variable_callback),
535                           data_store);
536
537       data_store->dict_handler_id [VARIABLE_DELETED] =
538         g_signal_connect (dict, "variable-deleted",
539                           G_CALLBACK (delete_variable_callback),
540                           data_store);
541
542       data_store->dict_handler_id [VARIABLE_CHANGED] =
543         g_signal_connect (dict, "variable-changed",
544                           G_CALLBACK (variable_changed_callback),
545                           data_store);
546     }
547
548
549
550   /* The entire model has changed */
551
552   if (data_store->dict)
553     for (i = 0 ; i < n_dict_signals; ++i)
554       {
555         if (data_store->dict_handler_id [i] > 0)
556           {
557             g_signal_handler_block (data_store->dict,
558                                     data_store->dict_handler_id[i]);
559           }
560       }
561 }
562
563 static void
564 psppire_data_store_finalize (GObject *object)
565 {
566   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
567
568   if (ds->datasheet)
569     {
570       datasheet_destroy (ds->datasheet);
571       ds->datasheet = NULL;
572     }
573
574   /* must chain up */
575   (* parent_class->finalize) (object);
576 }
577
578
579 static void
580 psppire_data_store_dispose (GObject *object)
581 {
582   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
583
584   if (ds->dispose_has_run)
585     return;
586
587   psppire_data_store_set_dictionary (ds, NULL);
588
589   /* must chain up */
590   (* parent_class->dispose) (object);
591
592   ds->dispose_has_run = TRUE;
593 }
594
595
596
597 /* Insert a blank case before POSN */
598 gboolean
599 psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
600 {
601   gboolean result;
602   const struct caseproto *proto;
603   struct ccase *cc;
604   g_return_val_if_fail (ds, FALSE);
605
606   proto = datasheet_get_proto (ds->datasheet);
607   g_return_val_if_fail (caseproto_get_n_widths (proto) > 0, FALSE);
608   g_return_val_if_fail (posn <= psppire_data_store_get_case_count (ds), FALSE);
609
610   cc = case_create (proto);
611   case_set_missing (cc);
612
613   result = psppire_data_store_insert_case (ds, cc, posn);
614
615   case_unref (cc);
616
617   return result;
618 }
619
620 gboolean
621 psppire_data_store_get_value (PsppireDataStore *store,
622                               glong row, const struct variable *var,
623                               union value *val)
624 {
625   g_return_val_if_fail (store != NULL, FALSE);
626   g_return_val_if_fail (store->datasheet != NULL, FALSE);
627   g_return_val_if_fail (var != NULL, FALSE);
628
629   if (row < 0 || row >= datasheet_get_n_rows (store->datasheet))
630     return FALSE;
631
632   int width = var_get_width (var);
633   value_init (val, width);
634   datasheet_get_value (store->datasheet, row, var_get_case_index (var), val);
635
636   return TRUE;
637 }
638
639
640
641 gchar *
642 psppire_data_store_get_string (PsppireDataStore *store,
643                                glong row, const struct variable *var,
644                                bool use_value_label)
645 {
646   gchar *string;
647   union value v;
648   int width = var_get_width (var);
649   if (! psppire_data_store_get_value (store, row, var, &v))
650     return NULL;
651
652   string = NULL;
653   if (use_value_label)
654     {
655       const char *label = var_lookup_value_label (var, &v);
656       if (label != NULL)
657         string = g_strdup (label);
658     }
659   if (string == NULL)
660     string = value_to_text (v, var);
661
662   value_destroy (&v, width);
663
664   return string;
665 }
666
667
668 /* Attempts to update that part of the variable store which corresponds to VAR
669    within ROW with the value TEXT.
670
671    If USE_VALUE_LABEL is true, and TEXT is a value label for the column's
672    variable, then stores the value from that value label instead of the literal
673    TEXT.
674
675    Returns true if anything was updated, false otherwise.  */
676 gboolean
677 psppire_data_store_set_string (PsppireDataStore *store,
678                                const gchar *text,
679                                glong row, const struct variable *var,
680                                gboolean use_value_label)
681 {
682   gint case_index;
683   glong n_cases;
684   gboolean ok;
685
686   n_cases = psppire_data_store_get_case_count (store);
687   if (row > n_cases)
688     return FALSE;
689   if (row == n_cases)
690     psppire_data_store_insert_new_case (store, row);
691
692   case_index = var_get_case_index (var);
693   if (use_value_label)
694     {
695       const struct val_labs *vls = var_get_value_labels (var);
696       const union value *value = vls ? val_labs_find_value (vls, text) : NULL;
697       if (value)
698         ok = datasheet_put_value (store->datasheet, row, case_index, value);
699       else
700         ok = FALSE;
701     }
702   else
703     ok = psppire_data_store_data_in (store, row, case_index, ss_cstr (text),
704                                      var_get_print_format (var));
705
706   if (ok)
707     g_signal_emit (store, signals [CASE_CHANGED], 0, row);
708   return ok;
709 }
710
711
712
713 void
714 psppire_data_store_clear (PsppireDataStore *ds)
715 {
716   datasheet_destroy (ds->datasheet);
717   ds->datasheet = NULL;
718
719   psppire_dict_clear (ds->dict);
720
721   g_signal_emit (ds, signals [ITEMS_CHANGED], 0, 0, -1, 0);
722 }
723
724
725
726 /* Return a casereader made from this datastore */
727 struct casereader *
728 psppire_data_store_get_reader (PsppireDataStore *ds)
729 {
730   int i;
731   struct casereader *reader ;
732
733   if (ds->dict)
734     for (i = 0 ; i < n_dict_signals; ++i)
735       {
736         g_signal_handler_block (ds->dict,
737                                 ds->dict_handler_id[i]);
738       }
739
740   reader = datasheet_make_reader (ds->datasheet);
741
742   /* We must not reference this again */
743   ds->datasheet = NULL;
744
745   return reader;
746 }
747
748 /* Returns the CASENUMth case, or a null pointer on failure.
749  */
750 struct ccase *
751 psppire_data_store_get_case (const PsppireDataStore *ds,
752                              casenumber casenum)
753 {
754   g_return_val_if_fail (ds, FALSE);
755   g_return_val_if_fail (ds->datasheet, FALSE);
756
757   return datasheet_get_row (ds->datasheet, casenum);
758 }
759
760
761 gboolean
762 psppire_data_store_delete_cases (PsppireDataStore *ds, casenumber first,
763                                  casenumber n_cases)
764 {
765   g_return_val_if_fail (ds, FALSE);
766   g_return_val_if_fail (ds->datasheet, FALSE);
767
768   g_return_val_if_fail (first + n_cases <=
769                         psppire_data_store_get_case_count (ds), FALSE);
770
771
772   datasheet_delete_rows (ds->datasheet, first, n_cases);
773
774   g_signal_emit (ds, signals[ITEMS_CHANGED], 0, first, n_cases, 0);
775
776   return TRUE;
777 }
778
779
780
781 /* Insert case CC into the case file before POSN */
782 static gboolean
783 psppire_data_store_insert_case (PsppireDataStore *ds,
784                                 struct ccase *cc,
785                                 casenumber posn)
786 {
787   bool result ;
788
789   g_return_val_if_fail (ds, FALSE);
790   g_return_val_if_fail (ds->datasheet, FALSE);
791
792   cc = case_ref (cc);
793   result = datasheet_insert_rows (ds->datasheet, posn, &cc, 1);
794
795   if (result)
796     {
797       g_signal_emit (ds, signals[ITEMS_CHANGED], 0, posn, 0, 1);
798     }
799   else
800     g_warning ("Cannot insert case at position %ld\n", posn);
801
802   return result;
803 }
804
805
806 /* Set the value of VAR in case CASENUM to V.
807    V must be the correct width for IDX.
808    Returns true if successful, false on I/O error. */
809 gboolean
810 psppire_data_store_set_value (PsppireDataStore *ds, casenumber casenum,
811                               const struct variable *var, const union value *v)
812 {
813   glong n_cases;
814   bool ok;
815
816   g_return_val_if_fail (ds, FALSE);
817   g_return_val_if_fail (ds->datasheet, FALSE);
818
819   n_cases = psppire_data_store_get_case_count (ds);
820   if (casenum > n_cases)
821     return FALSE;
822
823   if (casenum == n_cases)
824     psppire_data_store_insert_new_case (ds, casenum);
825
826   ok = datasheet_put_value (ds->datasheet, casenum, var_get_case_index (var),
827                             v);
828   if (ok)
829     {
830       g_signal_emit (ds, signals [CASE_CHANGED], 0, casenum);
831       g_signal_emit (ds, signals [ITEMS_CHANGED], 0, casenum, 1, 1);
832     }
833
834   return ok;
835 }
836
837
838
839
840 /* Set the IDXth value of case C using D_IN */
841 static gboolean
842 psppire_data_store_data_in (PsppireDataStore *ds, casenumber casenum, gint idx,
843                             struct substring input, const struct fmt_spec *fmt)
844 {
845   union value value;
846   int width;
847   bool ok;
848
849   PsppireDict *dict;
850
851   g_return_val_if_fail (ds, FALSE);
852   g_return_val_if_fail (ds->datasheet, FALSE);
853
854   g_return_val_if_fail (idx < datasheet_get_n_columns (ds->datasheet), FALSE);
855
856   dict = ds->dict;
857
858   width = fmt_var_width (fmt);
859   g_return_val_if_fail (caseproto_get_width (
860                           datasheet_get_proto (ds->datasheet), idx) == width,
861                         FALSE);
862   value_init (&value, width);
863   ok = (datasheet_get_value (ds->datasheet, casenum, idx, &value)
864         && data_in_msg (input, UTF8, fmt->type, &value, width,
865                         dict_get_encoding (dict->dict))
866         && datasheet_put_value (ds->datasheet, casenum, idx, &value));
867   value_destroy (&value, width);
868
869   return ok;
870 }
871
872 /* Resize the cases in the casefile, by inserting a value of the
873    given WIDTH into every one of them at the position immediately
874    preceding WHERE.
875 */
876 gboolean
877 psppire_data_store_insert_value (PsppireDataStore *ds,
878                                  gint width, gint where)
879 {
880   union value value;
881
882   g_return_val_if_fail (ds, FALSE);
883
884   g_assert (width >= 0);
885
886   if (! ds->datasheet)
887     ds->datasheet = datasheet_create (NULL);
888
889   value_init (&value, width);
890   value_set_missing (&value, width);
891
892   datasheet_insert_column (ds->datasheet, &value, width, where);
893   value_destroy (&value, width);
894
895   return TRUE;
896 }
897
898 gboolean
899 psppire_data_store_filtered (PsppireDataStore *ds,
900                              glong row)
901 {
902   union value val;
903
904   const struct dictionary *dict;
905   const struct variable *filter;
906
907   if (row < 0 || row >= datasheet_get_n_rows (ds->datasheet))
908     return FALSE;
909
910   dict = ds->dict->dict;
911   g_return_val_if_fail (dict, FALSE);
912   filter = dict_get_filter (dict);
913   if (! filter)
914     return FALSE;
915
916   g_return_val_if_fail (var_is_numeric (filter), FALSE);
917   value_init (&val, 0);
918   if (! datasheet_get_value (ds->datasheet, row,
919                               var_get_case_index (filter),
920                               &val))
921     return FALSE;
922
923   return (val.f == 0.0);
924 }