Adapt to new sheet
[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, 2013  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 #include <data/datasheet.h>
25 #include <data/data-out.h>
26 #include <data/variable.h>
27
28 #include <ui/gui/psppire-marshal.h>
29
30 #include <pango/pango-context.h>
31
32 #include "psppire-data-store.h"
33 #include <libpspp/i18n.h>
34 #include "helper.h"
35
36 #include <data/dictionary.h>
37 #include <data/missing-values.h>
38 #include <data/value-labels.h>
39 #include <data/data-in.h>
40 #include <data/format.h>
41
42 #include <math/sort.h>
43
44 #include "xalloc.h"
45 #include "xmalloca.h"
46
47
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     BACKEND_CHANGED,
71     CASES_DELETED,
72     CASE_INSERTED,
73     CASE_CHANGED,
74     n_SIGNALS
75   };
76
77 static guint signals [n_SIGNALS];
78
79 static gint
80 __tree_model_iter_n_children (GtkTreeModel *tree_model,
81                              GtkTreeIter *iter)
82 {
83   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
84
85   gint n =  datasheet_get_n_rows (store->datasheet);
86
87   return n;
88 }
89
90
91 static gint
92 __tree_model_get_n_columns (GtkTreeModel *tree_model)
93 {
94   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
95
96   return psppire_dict_get_value_cnt (store->dict);
97 }
98
99
100 static gboolean
101 __iter_nth_child (GtkTreeModel *tree_model,
102                   GtkTreeIter *iter,
103                   GtkTreeIter *parent,
104                   gint n)
105 {
106   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
107   
108   g_assert (parent == NULL);
109
110   g_return_val_if_fail (store, FALSE);
111   g_return_val_if_fail (store->datasheet, FALSE);
112
113   if (n >= datasheet_get_n_rows (store->datasheet))
114     {
115       iter->stamp = -1;
116       iter->user_data = NULL;
117       return FALSE;
118     }
119   
120   iter->user_data = n;
121   return TRUE;
122 }
123
124
125
126 static void
127 __get_value (GtkTreeModel *tree_model,
128              GtkTreeIter *iter,
129              gint column,
130              GValue *value)
131 {
132   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
133
134   g_value_init (value, G_TYPE_DOUBLE);
135
136   gint row = GPOINTER_TO_INT (iter->user_data);
137
138   struct ccase *cc = datasheet_get_row (store->datasheet, row);
139   
140   g_value_set_double (value, case_data_idx (cc, column)->f);
141   case_unref (cc);
142 }
143
144
145 static void
146 __tree_model_init (GtkTreeModelIface *iface)
147 {
148   iface->get_flags       = NULL; 
149   iface->get_n_columns   = __tree_model_get_n_columns ;
150   iface->get_column_type = NULL; 
151   iface->get_iter        = NULL; 
152   iface->iter_next       = NULL; 
153   iface->get_path        = NULL; 
154   iface->get_value       = __get_value;
155
156   iface->iter_children   = NULL; 
157   iface->iter_has_child  = NULL; 
158   iface->iter_n_children = __tree_model_iter_n_children;
159   iface->iter_nth_child  = __iter_nth_child;
160   iface->iter_parent     = NULL; 
161 }
162
163
164 GType
165 psppire_data_store_get_type (void)
166 {
167   static GType data_store_type = 0;
168
169   if (!data_store_type)
170     {
171       static const GTypeInfo data_store_info =
172       {
173         sizeof (PsppireDataStoreClass),
174         NULL,           /* base_init */
175         NULL,           /* base_finalize */
176         (GClassInitFunc) psppire_data_store_class_init,
177         NULL,           /* class_finalize */
178         NULL,           /* class_data */
179         sizeof (PsppireDataStore),
180         0,
181         (GInstanceInitFunc) psppire_data_store_init,
182       };
183
184       static const GInterfaceInfo tree_model_info = {
185         (GInterfaceInitFunc) __tree_model_init,
186         NULL,
187         NULL
188       };
189
190       data_store_type = g_type_register_static (G_TYPE_OBJECT,
191                                                 "PsppireDataStore",
192                                                 &data_store_info, 0);
193
194       g_type_add_interface_static (data_store_type, GTK_TYPE_TREE_MODEL,
195                                    &tree_model_info);
196     }
197
198   return data_store_type;
199 }
200
201
202 static void
203 psppire_data_store_class_init (PsppireDataStoreClass *class)
204 {
205   GObjectClass *object_class;
206
207   parent_class = g_type_class_peek_parent (class);
208   object_class = (GObjectClass*) class;
209
210   object_class->finalize = psppire_data_store_finalize;
211   object_class->dispose = psppire_data_store_dispose;
212
213   signals [BACKEND_CHANGED] =
214     g_signal_new ("backend-changed",
215                   G_TYPE_FROM_CLASS (class),
216                   G_SIGNAL_RUN_FIRST,
217                   0,
218                   NULL, NULL,
219                   g_cclosure_marshal_VOID__VOID,
220                   G_TYPE_NONE,
221                   0);
222
223   signals [CASE_INSERTED] =
224     g_signal_new ("case-inserted",
225                   G_TYPE_FROM_CLASS (class),
226                   G_SIGNAL_RUN_FIRST,
227                   0,
228                   NULL, NULL,
229                   g_cclosure_marshal_VOID__INT,
230                   G_TYPE_NONE,
231                   1,
232                   G_TYPE_INT);
233
234
235   signals [CASE_CHANGED] =
236     g_signal_new ("case-changed",
237                   G_TYPE_FROM_CLASS (class),
238                   G_SIGNAL_RUN_FIRST,
239                   0,
240                   NULL, NULL,
241                   g_cclosure_marshal_VOID__INT,
242                   G_TYPE_NONE,
243                   1,
244                   G_TYPE_INT);
245
246   signals [CASES_DELETED] =
247     g_signal_new ("cases-deleted",
248                   G_TYPE_FROM_CLASS (class),
249                   G_SIGNAL_RUN_FIRST,
250                   0,
251                   NULL, NULL,
252                   psppire_marshal_VOID__INT_INT,
253                   G_TYPE_NONE,
254                   2,
255                   G_TYPE_INT,
256                   G_TYPE_INT);
257 }
258
259
260
261 static gboolean
262 psppire_data_store_insert_value (PsppireDataStore *ds,
263                                   gint width, gint where);
264
265 casenumber
266 psppire_data_store_get_case_count (const PsppireDataStore *store)
267 {
268   return datasheet_get_n_rows (store->datasheet);
269 }
270
271 size_t
272 psppire_data_store_get_value_count (const PsppireDataStore *store)
273 {
274   return psppire_dict_get_value_cnt (store->dict);
275 }
276
277 const struct caseproto *
278 psppire_data_store_get_proto (const PsppireDataStore *store)
279 {
280   return psppire_dict_get_proto (store->dict);
281 }
282
283 static void
284 psppire_data_store_init (PsppireDataStore *data_store)
285 {
286   data_store->dict = NULL;
287   data_store->datasheet = NULL;
288   data_store->dispose_has_run = FALSE;
289 }
290
291 /*
292    A callback which occurs after a variable has been deleted.
293  */
294 static void
295 delete_variable_callback (GObject *obj, const struct variable *var UNUSED,
296                           gint dict_index, gint case_index,
297                           gpointer data)
298 {
299   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
300
301   g_return_if_fail (store->datasheet);
302
303   datasheet_delete_columns (store->datasheet, case_index, 1);
304   datasheet_insert_column (store->datasheet, NULL, -1, case_index);
305 }
306
307 struct resize_datum_aux
308   {
309     const struct dictionary *dict;
310     const struct variable *new_variable;
311     const struct variable *old_variable;
312   };
313
314 static void
315 resize_datum (const union value *old, union value *new, const void *aux_)
316 {
317   const struct resize_datum_aux *aux = aux_;
318   int new_width = var_get_width (aux->new_variable);
319   const char *enc = dict_get_encoding (aux->dict);
320   const struct fmt_spec *newfmt = var_get_print_format (aux->new_variable);
321   char *s = data_out (old, enc, var_get_print_format (aux->old_variable));
322   enum fmt_type type = (fmt_usable_for_input (newfmt->type)
323                         ? newfmt->type
324                         : FMT_DOLLAR);
325   free (data_in (ss_cstr (s), enc, type, new, new_width, enc));
326   free (s);
327 }
328
329 static void
330 variable_changed_callback (GObject *obj, gint var_num, guint what, const struct variable *oldvar,
331                            gpointer data)
332 {
333   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
334   struct variable *variable = psppire_dict_get_variable (store->dict, var_num);
335
336   if (what & VAR_TRAIT_WIDTH)
337     {
338       int posn = var_get_case_index (variable);
339       struct resize_datum_aux aux;
340       aux.old_variable = oldvar;
341       aux.new_variable = variable;
342       aux.dict = store->dict->dict;
343       datasheet_resize_column (store->datasheet, posn, var_get_width (variable),
344                                resize_datum, &aux);
345     }
346 }
347
348 static void
349 insert_variable_callback (GObject *obj, gint var_num, gpointer data)
350 {
351   struct variable *variable;
352   PsppireDataStore *store;
353   gint posn;
354
355   g_return_if_fail (data);
356
357   store  = PSPPIRE_DATA_STORE (data);
358
359   variable = psppire_dict_get_variable (store->dict, var_num);
360   posn = var_get_case_index (variable);
361   psppire_data_store_insert_value (store, var_get_width (variable), posn);
362 }
363
364 /**
365  * psppire_data_store_new:
366  * @dict: The dictionary for this data_store.
367  *
368  *
369  * Return value: a new #PsppireDataStore
370  **/
371 PsppireDataStore *
372 psppire_data_store_new (PsppireDict *dict)
373 {
374   PsppireDataStore *retval;
375
376   retval = g_object_new (PSPPIRE_TYPE_DATA_STORE, NULL);
377
378   psppire_data_store_set_dictionary (retval, dict);
379
380   return retval;
381 }
382
383 void
384 psppire_data_store_set_reader (PsppireDataStore *ds,
385                                struct casereader *reader)
386 {
387   gint i;
388
389   if ( ds->datasheet)
390     datasheet_destroy (ds->datasheet);
391
392   ds->datasheet = datasheet_create (reader);
393
394   g_signal_emit_by_name (ds, "notify", 0, 0);
395   g_print ("Datasheet row count %d\n", datasheet_get_n_rows (ds->datasheet));
396
397   if ( ds->dict )
398     for (i = 0 ; i < n_dict_signals; ++i )
399       {
400         if ( ds->dict_handler_id [i] > 0)
401           {
402             g_signal_handler_unblock (ds->dict,
403                                       ds->dict_handler_id[i]);
404           }
405       }
406
407   g_signal_emit (ds, signals[BACKEND_CHANGED], 0);
408 }
409
410
411 /**
412  * psppire_data_store_replace_set_dictionary:
413  * @data_store: The variable store
414  * @dict: The dictionary to set
415  *
416  * If a dictionary is already associated with the data-store, then it will be
417  * destroyed.
418  **/
419 void
420 psppire_data_store_set_dictionary (PsppireDataStore *data_store, PsppireDict *dict)
421 {
422   int i;
423
424   /* Disconnect any existing handlers */
425   if ( data_store->dict )
426     for (i = 0 ; i < n_dict_signals; ++i )
427       {
428         g_signal_handler_disconnect (data_store->dict,
429                                      data_store->dict_handler_id[i]);
430       }
431
432   data_store->dict = dict;
433
434   if ( dict != NULL)
435     {
436
437       data_store->dict_handler_id [VARIABLE_INSERTED] =
438         g_signal_connect (dict, "variable-inserted",
439                           G_CALLBACK (insert_variable_callback),
440                           data_store);
441
442       data_store->dict_handler_id [VARIABLE_DELETED] =
443         g_signal_connect (dict, "variable-deleted",
444                           G_CALLBACK (delete_variable_callback),
445                           data_store);
446
447       data_store->dict_handler_id [VARIABLE_CHANGED] =
448         g_signal_connect (dict, "variable-changed",
449                           G_CALLBACK (variable_changed_callback),
450                           data_store);
451     }
452
453
454
455   /* The entire model has changed */
456
457   if ( data_store->dict )
458     for (i = 0 ; i < n_dict_signals; ++i )
459       {
460         if ( data_store->dict_handler_id [i] > 0)
461           {
462             g_signal_handler_block (data_store->dict,
463                                     data_store->dict_handler_id[i]);
464           }
465       }
466 }
467
468 static void
469 psppire_data_store_finalize (GObject *object)
470 {
471   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
472
473   if (ds->datasheet)
474     {
475       datasheet_destroy (ds->datasheet);
476       ds->datasheet = NULL;
477     }
478
479   /* must chain up */
480   (* parent_class->finalize) (object);
481 }
482
483
484 static void
485 psppire_data_store_dispose (GObject *object)
486 {
487   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
488
489   if (ds->dispose_has_run)
490     return;
491
492   psppire_data_store_set_dictionary (ds, NULL);
493
494   /* must chain up */
495   (* parent_class->dispose) (object);
496
497   ds->dispose_has_run = TRUE;
498 }
499
500
501
502 /* Insert a blank case before POSN */
503 gboolean
504 psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
505 {
506   gboolean result;
507   const struct caseproto *proto;
508   struct ccase *cc;
509   g_return_val_if_fail (ds, FALSE);
510
511   proto = datasheet_get_proto (ds->datasheet);
512   g_return_val_if_fail (caseproto_get_n_widths (proto) > 0, FALSE);
513   g_return_val_if_fail (posn <= psppire_data_store_get_case_count (ds), FALSE);
514
515   cc = case_create (proto);
516   case_set_missing (cc);
517
518   result = psppire_data_store_insert_case (ds, cc, posn);
519
520   case_unref (cc);
521
522   return result;
523 }
524
525 gchar *
526 psppire_data_store_get_string (PsppireDataStore *store,
527                                glong row, const struct variable *var,
528                                bool use_value_label)
529 {
530   gchar *string;
531   union value v;
532   int width;
533
534   g_return_val_if_fail (store != NULL, NULL);
535   g_return_val_if_fail (store->datasheet != NULL, NULL);
536   g_return_val_if_fail (var != NULL, NULL);
537
538   if (row < 0 || row >= datasheet_get_n_rows (store->datasheet))
539     return NULL;
540
541   width = var_get_width (var);
542   value_init (&v, width);
543   datasheet_get_value (store->datasheet, row, var_get_case_index (var), &v);
544
545   string = NULL;
546   if (use_value_label)
547     {
548       const char *label = var_lookup_value_label (var, &v);
549       if (label != NULL)
550         string = g_strdup (label);
551     }
552   if (string == NULL)
553     string = value_to_text (v, var);
554
555   value_destroy (&v, width);
556
557   return string;
558 }
559
560
561 /* Attempts to update that part of the variable store which corresponds to VAR
562    within ROW with the value TEXT.
563
564    If USE_VALUE_LABEL is true, and TEXT is a value label for the column's
565    variable, then stores the value from that value label instead of the literal
566    TEXT.
567
568    Returns true if anything was updated, false otherwise.  */
569 gboolean
570 psppire_data_store_set_string (PsppireDataStore *store,
571                                const gchar *text,
572                                glong row, const struct variable *var,
573                                gboolean use_value_label)
574 {
575   gint case_index;
576   glong n_cases;
577   gboolean ok;
578
579   n_cases = psppire_data_store_get_case_count (store);
580   if (row > n_cases)
581     return FALSE;
582   if (row == n_cases)
583     psppire_data_store_insert_new_case (store, row);
584
585   case_index = var_get_case_index (var);
586   if (use_value_label)
587     {
588       const struct val_labs *vls = var_get_value_labels (var);
589       const union value *value = vls ? val_labs_find_value (vls, text) : NULL;
590       if (value)
591         ok = datasheet_put_value (store->datasheet, row, case_index, value);
592       else
593         ok = FALSE;
594     }
595   else
596     ok = psppire_data_store_data_in (store, row, case_index, ss_cstr (text),
597                                      var_get_print_format (var));
598
599   if (ok)
600     g_signal_emit (store, signals [CASE_CHANGED], 0, row);
601   return ok;
602 }
603
604
605
606 void
607 psppire_data_store_clear (PsppireDataStore *ds)
608 {
609   datasheet_destroy (ds->datasheet);
610   ds->datasheet = NULL;
611
612   psppire_dict_clear (ds->dict);
613
614   g_signal_emit (ds, signals [CASES_DELETED], 0, 0, -1);
615 }
616
617
618
619 /* Return a casereader made from this datastore */
620 struct casereader *
621 psppire_data_store_get_reader (PsppireDataStore *ds)
622 {
623   int i;
624   struct casereader *reader ;
625
626   if ( ds->dict )
627     for (i = 0 ; i < n_dict_signals; ++i )
628       {
629         g_signal_handler_block (ds->dict,
630                                 ds->dict_handler_id[i]);
631       }
632
633   reader = datasheet_make_reader (ds->datasheet);
634
635   /* We must not reference this again */
636   ds->datasheet = NULL;
637
638   return reader;
639 }
640
641
642
643 /* Column related funcs */
644
645
646 static const gchar null_var_name[]=N_("var");
647
648
649 \f
650
651
652 /* Returns the CASENUMth case, or a null pointer on failure.
653  */
654 struct ccase *
655 psppire_data_store_get_case (const PsppireDataStore *ds,
656                              casenumber casenum)
657 {
658   g_return_val_if_fail (ds, FALSE);
659   g_return_val_if_fail (ds->datasheet, FALSE);
660
661   return datasheet_get_row (ds->datasheet, casenum);
662 }
663
664
665 gboolean
666 psppire_data_store_delete_cases (PsppireDataStore *ds, casenumber first,
667                                  casenumber n_cases)
668 {
669   g_return_val_if_fail (ds, FALSE);
670   g_return_val_if_fail (ds->datasheet, FALSE);
671
672   g_return_val_if_fail (first + n_cases <=
673                         psppire_data_store_get_case_count (ds), FALSE);
674
675
676   datasheet_delete_rows (ds->datasheet, first, n_cases);
677
678   g_signal_emit (ds, signals [CASES_DELETED], 0, first, n_cases);
679
680   return TRUE;
681 }
682
683
684
685 /* Insert case CC into the case file before POSN */
686 static gboolean
687 psppire_data_store_insert_case (PsppireDataStore *ds,
688                                 struct ccase *cc,
689                                 casenumber posn)
690 {
691   bool result ;
692
693   g_return_val_if_fail (ds, FALSE);
694   g_return_val_if_fail (ds->datasheet, FALSE);
695
696   cc = case_ref (cc);
697   result = datasheet_insert_rows (ds->datasheet, posn, &cc, 1);
698
699   if ( result )
700     g_signal_emit (ds, signals [CASE_INSERTED], 0, posn);
701   else
702     g_warning ("Cannot insert case at position %ld\n", posn);
703
704   return result;
705 }
706
707
708 /* Set the value of VAR in case CASENUM to V.
709    V must be the correct width for IDX.
710    Returns true if successful, false on I/O error. */
711 gboolean
712 psppire_data_store_set_value (PsppireDataStore *ds, casenumber casenum,
713                               const struct variable *var, const union value *v)
714 {
715   glong n_cases;
716   bool ok;
717
718   g_return_val_if_fail (ds, FALSE);
719   g_return_val_if_fail (ds->datasheet, FALSE);
720
721   n_cases = psppire_data_store_get_case_count (ds);
722   if ( casenum > n_cases)
723     return FALSE;
724
725   if (casenum == n_cases)
726     psppire_data_store_insert_new_case (ds, casenum);
727
728   ok = datasheet_put_value (ds->datasheet, casenum, var_get_case_index (var),
729                             v);
730   if (ok)
731     g_signal_emit (ds, signals [CASE_CHANGED], 0, casenum);
732
733   return ok;
734 }
735
736
737
738
739 /* Set the IDXth value of case C using D_IN */
740 static gboolean
741 psppire_data_store_data_in (PsppireDataStore *ds, casenumber casenum, gint idx,
742                             struct substring input, const struct fmt_spec *fmt)
743 {
744   union value value;
745   int width;
746   bool ok;
747
748   PsppireDict *dict;
749
750   g_return_val_if_fail (ds, FALSE);
751   g_return_val_if_fail (ds->datasheet, FALSE);
752
753   g_return_val_if_fail (idx < datasheet_get_n_columns (ds->datasheet), FALSE);
754
755   dict = ds->dict;
756
757   width = fmt_var_width (fmt);
758   g_return_val_if_fail (caseproto_get_width (
759                           datasheet_get_proto (ds->datasheet), idx) == width,
760                         FALSE);
761   value_init (&value, width);
762   ok = (datasheet_get_value (ds->datasheet, casenum, idx, &value)
763         && data_in_msg (input, UTF8, fmt->type, &value, width,
764                         dict_get_encoding (dict->dict))
765         && datasheet_put_value (ds->datasheet, casenum, idx, &value));
766   value_destroy (&value, width);
767
768   return ok;
769 }
770
771 /* Resize the cases in the casefile, by inserting a value of the
772    given WIDTH into every one of them at the position immediately
773    preceding WHERE.
774 */
775 static gboolean
776 psppire_data_store_insert_value (PsppireDataStore *ds,
777                                  gint width, gint where)
778 {
779   union value value;
780
781   g_return_val_if_fail (ds, FALSE);
782
783   g_assert (width >= 0);
784
785   if ( ! ds->datasheet )
786     ds->datasheet = datasheet_create (NULL);
787
788   value_init (&value, width);
789   value_set_missing (&value, width);
790
791   datasheet_insert_column (ds->datasheet, &value, width, where);
792   value_destroy (&value, width);
793
794   return TRUE;
795 }
796
797 gboolean
798 psppire_data_store_filtered (PsppireDataStore *ds,
799                              glong row)
800 {
801   union value val;
802
803   const struct dictionary *dict;
804   const struct variable *filter;
805
806   if ( row < 0 || row >= datasheet_get_n_rows (ds->datasheet))
807     return FALSE;
808
809   dict = ds->dict->dict;
810   g_return_val_if_fail (dict, FALSE);
811   filter = dict_get_filter (dict);
812   if ( ! filter)
813     return FALSE;
814
815   g_return_val_if_fail (var_is_numeric (filter), FALSE);
816   value_init (&val, 0);
817   if ( ! datasheet_get_value (ds->datasheet, row,
818                               var_get_case_index (filter),
819                               &val) )
820     return FALSE;
821
822   return (val.f == 0.0);
823 }