1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2008 Free Software Foundation, Inc.
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.
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.
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/>. */
18 #include "psppire-var-sheet.h"
20 #include <glade/glade.h>
22 #include <gtksheet/gsheet-hetero-column.h>
23 #include "customentry.h"
24 #include <data/variable.h>
25 #include "psppire-var-store.h"
28 #define _(msgid) gettext (msgid)
29 #define N_(msgid) msgid
32 static void psppire_var_sheet_class_init (PsppireVarSheetClass *klass);
33 static void psppire_var_sheet_init (PsppireVarSheet *vs);
37 PSPPIRE_VAR_SHEET_MAY_CREATE_VARS = 1
41 psppire_var_sheet_get_type (void)
43 static GType vs_type = 0;
47 static const GTypeInfo vs_info =
49 sizeof (PsppireVarSheetClass),
51 NULL, /* base_finalize */
52 (GClassInitFunc) psppire_var_sheet_class_init,
53 NULL, /* class_finalize */
54 NULL, /* class_data */
55 sizeof (PsppireVarSheet),
57 (GInstanceInitFunc) psppire_var_sheet_init,
60 vs_type = g_type_register_static (GTK_TYPE_SHEET, "PsppireVarSheet",
67 static GObjectClass * parent_class = NULL;
70 psppire_var_sheet_dispose (GObject *obj)
72 PsppireVarSheet *vs = (PsppireVarSheet *)obj;
74 if (vs->dispose_has_run)
77 /* Make sure dispose does not run twice. */
78 vs->dispose_has_run = TRUE;
80 /* Chain up to the parent class */
81 G_OBJECT_CLASS (parent_class)->dispose (obj);
85 psppire_var_sheet_finalize (GObject *obj)
87 /* Chain up to the parent class */
88 G_OBJECT_CLASS (parent_class)->finalize (obj);
92 struct column_parameters
98 static const struct column_parameters column_def[] = {
102 { N_("Decimals"),91},
104 { N_("Values"), 103},
105 { N_("Missing"), 95},
106 { N_("Columns"), 80},
108 { N_("Measure"), 99},
112 #define n_ALIGNMENTS 3
114 const gchar *const alignments[n_ALIGNMENTS + 1]={
121 const gchar *const measures[n_MEASURES + 1]={
130 /* Create a list store from an array of strings */
131 static GtkListStore *
132 create_label_list (const gchar *const *labels)
138 GtkListStore *list_store;
139 list_store = gtk_list_store_new (1, G_TYPE_STRING);
142 while ( (s = labels[i++]))
144 gtk_list_store_append (list_store, &iter);
145 gtk_list_store_set (list_store, &iter,
155 psppire_var_sheet_set_property (GObject *object,
160 PsppireVarSheet *self = (PsppireVarSheet *) object;
164 case PSPPIRE_VAR_SHEET_MAY_CREATE_VARS:
165 self->may_create_vars = g_value_get_boolean (value);
169 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
175 psppire_var_sheet_get_property (GObject *object,
180 PsppireVarSheet *self = (PsppireVarSheet *) object;
184 case PSPPIRE_VAR_SHEET_MAY_CREATE_VARS:
185 g_value_set_boolean (value, self->may_create_vars);
189 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
197 psppire_var_sheet_class_init (PsppireVarSheetClass *klass)
199 GObjectClass *object_class = G_OBJECT_CLASS (klass);
202 parent_class = g_type_class_peek_parent (klass);
204 object_class->dispose = psppire_var_sheet_dispose;
205 object_class->finalize = psppire_var_sheet_finalize;
206 object_class->set_property = psppire_var_sheet_set_property;
207 object_class->get_property = psppire_var_sheet_get_property;
209 pspec = g_param_spec_boolean ("may-create-vars",
210 "May create variables",
211 "Whether the user may create more variables",
214 g_object_class_install_property (object_class,
215 PSPPIRE_VAR_SHEET_MAY_CREATE_VARS,
218 klass->measure_list = create_label_list (measures);
219 klass->alignment_list = create_label_list (alignments);
224 /* Callback for when the alignment combo box
227 change_alignment (GtkComboBox *cb,
228 struct variable *var)
230 gint active_item = gtk_combo_box_get_active (cb);
232 if ( active_item < 0 ) return ;
234 var_set_alignment (var, active_item);
239 /* Callback for when the measure combo box
242 change_measure (GtkComboBox *cb,
243 struct variable *var)
245 gint active_item = gtk_combo_box_get_active (cb);
247 if ( active_item < 0 ) return ;
249 var_set_measure (var, active_item);
253 /* Moves the focus to a new cell.
254 Returns TRUE iff the move should be disallowed */
256 traverse_cell_callback (GtkSheet *sheet,
257 gint row, gint column,
258 gint *new_row, gint *new_column)
260 PsppireVarSheet *var_sheet = PSPPIRE_VAR_SHEET (sheet);
261 PsppireVarStore *var_store = PSPPIRE_VAR_STORE (gtk_sheet_get_model (sheet));
263 gint n_vars = psppire_var_store_get_var_cnt (var_store);
265 if (*new_row >= n_vars && !var_sheet->may_create_vars)
269 if ( row == n_vars && *new_row >= n_vars)
271 GtkEntry *entry = GTK_ENTRY (gtk_sheet_get_entry (sheet));
273 const gchar *name = gtk_entry_get_text (entry);
275 if (! psppire_dict_check_name (var_store->dict, name, TRUE))
278 psppire_dict_insert_variable (var_store->dict, row, name);
284 /* If the destination cell is outside the current variables, then
285 automatically create variables for the new rows.
287 if ( ((*new_row > n_vars) ||
288 (*new_row == n_vars && *new_column != PSPPIRE_VAR_STORE_COL_NAME)) )
291 for ( i = n_vars ; i <= *new_row; ++i )
292 psppire_dict_insert_variable (var_store->dict, i, NULL);
304 Callback whenever the active cell changes on the var sheet.
307 var_sheet_change_active_cell (PsppireVarSheet *vs,
308 gint row, gint column,
309 gint oldrow, gint oldcolumn,
312 GtkSheetCellAttr attributes;
313 PsppireVarStore *var_store;
314 PsppireVarSheetClass *vs_class =
315 PSPPIRE_VAR_SHEET_CLASS(G_OBJECT_GET_CLASS (vs));
317 struct variable *var ;
318 GtkSheet *sheet = GTK_SHEET (vs);
320 g_return_if_fail (sheet != NULL);
322 var_store = PSPPIRE_VAR_STORE (gtk_sheet_get_model (sheet));
324 g_assert (var_store);
326 g_return_if_fail (oldcolumn == PSPPIRE_VAR_STORE_COL_NAME ||
327 row < psppire_var_store_get_var_cnt (var_store));
329 gtk_sheet_get_attributes (sheet, row, column, &attributes);
331 var = psppire_var_store_get_var (var_store, row);
335 case PSPPIRE_VAR_STORE_COL_ALIGN:
337 static GtkListStore *list_store = NULL;
338 GtkComboBoxEntry *cbe;
339 gtk_sheet_change_entry (sheet, GTK_TYPE_COMBO_BOX_ENTRY);
341 GTK_COMBO_BOX_ENTRY (gtk_sheet_get_entry (sheet)->parent);
344 if ( ! list_store) list_store = create_label_list (alignments);
346 gtk_combo_box_set_model (GTK_COMBO_BOX (cbe),
347 GTK_TREE_MODEL (vs_class->alignment_list));
349 gtk_combo_box_entry_set_text_column (cbe, 0);
351 g_signal_connect (G_OBJECT (cbe),"changed",
352 G_CALLBACK (change_alignment), var);
356 case PSPPIRE_VAR_STORE_COL_MEASURE:
358 GtkComboBoxEntry *cbe;
359 gtk_sheet_change_entry (sheet, GTK_TYPE_COMBO_BOX_ENTRY);
361 GTK_COMBO_BOX_ENTRY (gtk_sheet_get_entry (sheet)->parent);
365 gtk_combo_box_set_model (GTK_COMBO_BOX (cbe),
366 GTK_TREE_MODEL (vs_class->measure_list));
368 gtk_combo_box_entry_set_text_column (cbe, 0);
370 g_signal_connect (G_OBJECT (cbe),"changed",
371 G_CALLBACK (change_measure), var);
375 case PSPPIRE_VAR_STORE_COL_VALUES:
377 PsppireCustomEntry *customEntry;
379 gtk_sheet_change_entry (sheet, PSPPIRE_CUSTOM_ENTRY_TYPE);
382 PSPPIRE_CUSTOM_ENTRY (gtk_sheet_get_entry (sheet));
384 if ( var_is_long_string (var))
385 g_object_set (customEntry,
389 val_labs_dialog_set_target_variable (vs->val_labs_dialog, var);
391 g_signal_connect_swapped (customEntry,
393 G_CALLBACK (val_labs_dialog_show),
394 vs->val_labs_dialog);
398 case PSPPIRE_VAR_STORE_COL_MISSING:
400 PsppireCustomEntry *customEntry;
402 gtk_sheet_change_entry (sheet, PSPPIRE_CUSTOM_ENTRY_TYPE);
405 PSPPIRE_CUSTOM_ENTRY (gtk_sheet_get_entry (sheet));
407 if ( var_is_long_string (var))
408 g_object_set (customEntry,
413 vs->missing_val_dialog->pv =
414 psppire_var_store_get_var (var_store, row);
416 g_signal_connect_swapped (customEntry,
418 G_CALLBACK (missing_val_dialog_show),
419 vs->missing_val_dialog);
423 case PSPPIRE_VAR_STORE_COL_TYPE:
425 PsppireCustomEntry *customEntry;
427 gtk_sheet_change_entry (sheet, PSPPIRE_CUSTOM_ENTRY_TYPE);
430 PSPPIRE_CUSTOM_ENTRY (gtk_sheet_get_entry (sheet));
433 /* Popup the Variable Type dialog box */
434 vs->var_type_dialog->pv = var;
436 g_signal_connect_swapped (customEntry,
438 G_CALLBACK (var_type_dialog_show),
439 vs->var_type_dialog);
443 case PSPPIRE_VAR_STORE_COL_WIDTH:
444 case PSPPIRE_VAR_STORE_COL_DECIMALS:
445 case PSPPIRE_VAR_STORE_COL_COLUMNS:
447 if ( attributes.is_editable)
451 const gchar *s = gtk_sheet_cell_get_text (sheet, row, column);
455 GtkSpinButton *spinButton ;
456 const gint current_value = g_strtod (s, NULL);
459 const struct fmt_spec *fmt = var_get_write_format (var);
462 case PSPPIRE_VAR_STORE_COL_WIDTH:
463 r_min = MAX (fmt->d + 1, fmt_min_output_width (fmt->type));
464 r_max = fmt_max_output_width (fmt->type);
466 case PSPPIRE_VAR_STORE_COL_DECIMALS:
468 r_max = fmt_max_output_decimals (fmt->type, fmt->w);
470 case PSPPIRE_VAR_STORE_COL_COLUMNS:
472 r_max = 255 ; /* Is this a sensible value ? */
475 g_assert_not_reached ();
478 adj = gtk_adjustment_new (current_value,
480 1.0, 1.0, 1.0 /* steps */
483 gtk_sheet_change_entry (sheet, GTK_TYPE_SPIN_BUTTON);
486 GTK_SPIN_BUTTON (gtk_sheet_get_entry (sheet));
488 gtk_spin_button_set_adjustment (spinButton, GTK_ADJUSTMENT (adj));
489 gtk_spin_button_set_digits (spinButton, 0);
496 gtk_sheet_change_entry (sheet, GTK_TYPE_ENTRY);
505 psppire_var_sheet_init (PsppireVarSheet *vs)
508 GObject *geo = g_sheet_hetero_column_new (75, PSPPIRE_VAR_STORE_n_COLS);
509 GladeXML *xml = XML_NEW ("data-editor.glade");
511 vs->val_labs_dialog = val_labs_dialog_create (xml);
512 vs->missing_val_dialog = missing_val_dialog_create (xml);
513 vs->var_type_dialog = var_type_dialog_create (xml);
515 g_object_unref (xml);
517 vs->dispose_has_run = FALSE;
518 vs->may_create_vars = TRUE;
520 for (i = 0 ; i < PSPPIRE_VAR_STORE_n_COLS ; ++i )
522 g_sheet_hetero_column_set_button_label (G_SHEET_HETERO_COLUMN (geo), i,
523 gettext (column_def[i].label));
525 g_sheet_hetero_column_set_width (G_SHEET_HETERO_COLUMN (geo), i,
526 column_def[i].width);
529 g_object_set (vs, "column-geometry", geo, NULL);
531 g_signal_connect (vs, "activate",
532 G_CALLBACK (var_sheet_change_active_cell),
535 g_signal_connect (vs, "traverse",
536 G_CALLBACK (traverse_cell_callback), NULL);
541 psppire_var_sheet_new (void)
543 return GTK_WIDGET (g_object_new (psppire_var_sheet_get_type (), NULL));