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