Merge 'master' into 'psppsheet'.
[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   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
393
394   if (ds->datasheet)
395     {
396       datasheet_destroy (ds->datasheet);
397       ds->datasheet = NULL;
398     }
399
400   /* must chain up */
401   (* parent_class->finalize) (object);
402 }
403
404
405 static void
406 psppire_data_store_dispose (GObject *object)
407 {
408   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
409
410   if (ds->dispose_has_run)
411     return;
412
413
414   /* must chain up */
415   (* parent_class->dispose) (object);
416
417   ds->dispose_has_run = TRUE;
418 }
419
420
421
422 /* Insert a blank case before POSN */
423 gboolean
424 psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
425 {
426   gboolean result;
427   const struct caseproto *proto;
428   struct ccase *cc;
429   g_return_val_if_fail (ds, FALSE);
430
431   proto = datasheet_get_proto (ds->datasheet);
432   g_return_val_if_fail (caseproto_get_n_widths (proto) > 0, FALSE);
433   g_return_val_if_fail (posn <= psppire_data_store_get_case_count (ds), FALSE);
434
435   cc = case_create (proto);
436   case_set_missing (cc);
437
438   result = psppire_data_store_insert_case (ds, cc, posn);
439
440   case_unref (cc);
441
442   return result;
443 }
444
445 gchar *
446 psppire_data_store_get_string (PsppireDataStore *store,
447                                glong row, const struct variable *var,
448                                bool use_value_label)
449 {
450   gchar *string;
451   union value v;
452   int width;
453
454   g_return_val_if_fail (store != NULL, NULL);
455   g_return_val_if_fail (var != NULL, NULL);
456
457   if (row < 0 || row >= datasheet_get_n_rows (store->datasheet))
458     return NULL;
459
460   width = var_get_width (var);
461   value_init (&v, width);
462   datasheet_get_value (store->datasheet, row, var_get_case_index (var), &v);
463
464   string = NULL;
465   if (use_value_label)
466     {
467       const char *label = var_lookup_value_label (var, &v);
468       if (label != NULL)
469         string = g_strdup (label);
470     }
471   if (string == NULL)
472     string = value_to_text (v, var);
473
474   value_destroy (&v, width);
475
476   return string;
477 }
478
479
480 /* Attempts to update that part of the variable store which corresponds to VAR
481    within ROW with the value TEXT.
482
483    If USE_VALUE_LABEL is true, and TEXT is a value label for the column's
484    variable, then stores the value from that value label instead of the literal
485    TEXT.
486
487    Returns true if anything was updated, false otherwise.  */
488 gboolean
489 psppire_data_store_set_string (PsppireDataStore *store,
490                                const gchar *text,
491                                glong row, const struct variable *var,
492                                gboolean use_value_label)
493 {
494   gint case_index;
495   glong n_cases;
496   gboolean ok;
497
498   n_cases = psppire_data_store_get_case_count (store);
499   if (row > n_cases)
500     return FALSE;
501   if (row == n_cases)
502     psppire_data_store_insert_new_case (store, row);
503
504   case_index = var_get_case_index (var);
505   if (use_value_label)
506     {
507       const struct val_labs *vls = var_get_value_labels (var);
508       const union value *value = vls ? val_labs_find_value (vls, text) : NULL;
509       if (value)
510         ok = datasheet_put_value (store->datasheet, row, case_index, value);
511       else
512         ok = FALSE;
513     }
514   else
515     ok = psppire_data_store_data_in (store, row, case_index, ss_cstr (text),
516                                      var_get_print_format (var));
517
518   if (ok)
519     g_signal_emit (store, signals [CASE_CHANGED], 0, row);
520   return ok;
521 }
522
523
524
525 void
526 psppire_data_store_clear (PsppireDataStore *ds)
527 {
528   datasheet_destroy (ds->datasheet);
529   ds->datasheet = NULL;
530
531   psppire_dict_clear (ds->dict);
532
533   g_signal_emit (ds, signals [CASES_DELETED], 0, 0, -1);
534 }
535
536
537
538 /* Return a casereader made from this datastore */
539 struct casereader *
540 psppire_data_store_get_reader (PsppireDataStore *ds)
541 {
542   int i;
543   struct casereader *reader ;
544
545   if ( ds->dict )
546     for (i = 0 ; i < n_dict_signals; ++i )
547       {
548         g_signal_handler_block (ds->dict,
549                                 ds->dict_handler_id[i]);
550       }
551
552   reader = datasheet_make_reader (ds->datasheet);
553
554   /* We must not reference this again */
555   ds->datasheet = NULL;
556
557   return reader;
558 }
559
560
561
562 /* Column related funcs */
563
564
565 static const gchar null_var_name[]=N_("var");
566
567
568 \f
569
570
571 /* Returns the CASENUMth case, or a null pointer on failure.
572  */
573 struct ccase *
574 psppire_data_store_get_case (const PsppireDataStore *ds,
575                              casenumber casenum)
576 {
577   g_return_val_if_fail (ds, FALSE);
578   g_return_val_if_fail (ds->datasheet, FALSE);
579
580   return datasheet_get_row (ds->datasheet, casenum);
581 }
582
583
584 gboolean
585 psppire_data_store_delete_cases (PsppireDataStore *ds, casenumber first,
586                                  casenumber n_cases)
587 {
588   g_return_val_if_fail (ds, FALSE);
589   g_return_val_if_fail (ds->datasheet, FALSE);
590
591   g_return_val_if_fail (first + n_cases <=
592                         psppire_data_store_get_case_count (ds), FALSE);
593
594
595   datasheet_delete_rows (ds->datasheet, first, n_cases);
596
597   g_signal_emit (ds, signals [CASES_DELETED], 0, first, n_cases);
598
599   return TRUE;
600 }
601
602
603
604 /* Insert case CC into the case file before POSN */
605 static gboolean
606 psppire_data_store_insert_case (PsppireDataStore *ds,
607                                 struct ccase *cc,
608                                 casenumber posn)
609 {
610   bool result ;
611
612   g_return_val_if_fail (ds, FALSE);
613   g_return_val_if_fail (ds->datasheet, FALSE);
614
615   cc = case_ref (cc);
616   result = datasheet_insert_rows (ds->datasheet, posn, &cc, 1);
617
618   if ( result )
619     g_signal_emit (ds, signals [CASE_INSERTED], 0, posn);
620   else
621     g_warning ("Cannot insert case at position %ld\n", posn);
622
623   return result;
624 }
625
626
627 /* Set the value of VAR in case CASENUM to V.
628    V must be the correct width for IDX.
629    Returns true if successful, false on I/O error. */
630 gboolean
631 psppire_data_store_set_value (PsppireDataStore *ds, casenumber casenum,
632                               const struct variable *var, const union value *v)
633 {
634   glong n_cases;
635   bool ok;
636
637   g_return_val_if_fail (ds, FALSE);
638   g_return_val_if_fail (ds->datasheet, FALSE);
639
640   n_cases = psppire_data_store_get_case_count (ds);
641   if ( casenum > n_cases)
642     return FALSE;
643
644   if (casenum == n_cases)
645     psppire_data_store_insert_new_case (ds, casenum);
646
647   ok = datasheet_put_value (ds->datasheet, casenum, var_get_case_index (var),
648                             v);
649   if (ok)
650     g_signal_emit (ds, signals [CASE_CHANGED], 0, casenum);
651
652   return ok;
653 }
654
655
656
657
658 /* Set the IDXth value of case C using D_IN */
659 static gboolean
660 psppire_data_store_data_in (PsppireDataStore *ds, casenumber casenum, gint idx,
661                             struct substring input, const struct fmt_spec *fmt)
662 {
663   union value value;
664   int width;
665   bool ok;
666
667   PsppireDict *dict;
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 (idx < datasheet_get_n_columns (ds->datasheet), FALSE);
673
674   dict = ds->dict;
675
676   width = fmt_var_width (fmt);
677   g_return_val_if_fail (caseproto_get_width (
678                           datasheet_get_proto (ds->datasheet), idx) == width,
679                         FALSE);
680   value_init (&value, width);
681   ok = (datasheet_get_value (ds->datasheet, casenum, idx, &value)
682         && data_in_msg (input, UTF8, fmt->type, &value, width,
683                         dict_get_encoding (dict->dict))
684         && datasheet_put_value (ds->datasheet, casenum, idx, &value));
685   value_destroy (&value, width);
686
687   return ok;
688 }
689
690 /* Resize the cases in the casefile, by inserting a value of the
691    given WIDTH into every one of them at the position immediately
692    preceding WHERE.
693 */
694 static gboolean
695 psppire_data_store_insert_value (PsppireDataStore *ds,
696                                  gint width, gint where)
697 {
698   union value value;
699
700   g_return_val_if_fail (ds, FALSE);
701
702   g_assert (width >= 0);
703
704   if ( ! ds->datasheet )
705     ds->datasheet = datasheet_create (NULL);
706
707   value_init (&value, width);
708   value_set_missing (&value, width);
709
710   datasheet_insert_column (ds->datasheet, &value, width, where);
711   value_destroy (&value, width);
712
713   return TRUE;
714 }
715
716 gboolean
717 psppire_data_store_filtered (PsppireDataStore *ds,
718                              glong row)
719 {
720   union value val;
721
722   const struct dictionary *dict;
723   const struct variable *filter;
724
725   if ( row < 0 || row >= datasheet_get_n_rows (ds->datasheet))
726     return FALSE;
727
728   dict = ds->dict->dict;
729   g_return_val_if_fail (dict, FALSE);
730   filter = dict_get_filter (dict);
731   if ( ! filter)
732     return FALSE;
733
734   g_return_val_if_fail (var_is_numeric (filter), FALSE);
735   value_init (&val, 0);
736   if ( ! datasheet_get_value (ds->datasheet, row,
737                               var_get_case_index (filter),
738                               &val) )
739     return FALSE;
740
741   return (val.f == 0.0);
742 }