2 /* PSPPIRE - a graphical user interface for PSPP.
3 Copyright (C) 2008 Free Software Foundation, Inc.
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.
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.
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/>. */
19 #include "psppire-var-sheet.h"
21 #include <glade/glade.h>
23 #include <gtksheet/gsheet-hetero-column.h>
24 #include "customentry.h"
25 #include <data/variable.h>
26 #include "psppire-var-store.h"
29 #define _(msgid) gettext (msgid)
30 #define N_(msgid) msgid
33 static void psppire_var_sheet_class_init (PsppireVarSheetClass *klass);
34 static void psppire_var_sheet_init (PsppireVarSheet *vs);
38 psppire_var_sheet_get_type (void)
40 static GType vs_type = 0;
44 static const GTypeInfo vs_info =
46 sizeof (PsppireVarSheetClass),
48 NULL, /* base_finalize */
49 (GClassInitFunc) psppire_var_sheet_class_init,
50 NULL, /* class_finalize */
51 NULL, /* class_data */
52 sizeof (PsppireVarSheet),
54 (GInstanceInitFunc) psppire_var_sheet_init,
57 vs_type = g_type_register_static (GTK_TYPE_SHEET, "PsppireVarSheet",
64 static GObjectClass * parent_class = NULL;
67 psppire_var_sheet_dispose (GObject *obj)
69 PsppireVarSheet *vs = (PsppireVarSheet *)obj;
71 if (vs->dispose_has_run)
74 /* Make sure dispose does not run twice. */
75 vs->dispose_has_run = TRUE;
77 /* Chain up to the parent class */
78 G_OBJECT_CLASS (parent_class)->dispose (obj);
82 psppire_var_sheet_finalize (GObject *obj)
84 /* Chain up to the parent class */
85 G_OBJECT_CLASS (parent_class)->finalize (obj);
89 struct column_parameters
95 static const struct column_parameters column_def[] = {
101 { N_("Values"), 103},
102 { N_("Missing"), 95},
103 { N_("Columns"), 80},
105 { N_("Measure"), 99},
109 #define n_ALIGNMENTS 3
111 const gchar *const alignments[n_ALIGNMENTS + 1]={
118 const gchar *const measures[n_MEASURES + 1]={
127 /* Create a list store from an array of strings */
128 static GtkListStore *
129 create_label_list (const gchar *const *labels)
135 GtkListStore *list_store;
136 list_store = gtk_list_store_new (1, G_TYPE_STRING);
139 while ( (s = labels[i++]))
141 gtk_list_store_append (list_store, &iter);
142 gtk_list_store_set (list_store, &iter,
154 psppire_var_sheet_class_init (PsppireVarSheetClass *klass)
156 GObjectClass *object_class = G_OBJECT_CLASS (klass);
158 parent_class = g_type_class_peek_parent (klass);
160 object_class->dispose = psppire_var_sheet_dispose;
161 object_class->finalize = psppire_var_sheet_finalize;
164 klass->measure_list = create_label_list (measures);
165 klass->alignment_list = create_label_list (alignments);
170 /* Callback for when the alignment combo box
173 change_alignment (GtkComboBox *cb,
174 struct variable *var)
176 gint active_item = gtk_combo_box_get_active (cb);
178 if ( active_item < 0 ) return ;
180 var_set_alignment (var, active_item);
185 /* Callback for when the measure combo box
188 change_measure (GtkComboBox *cb,
189 struct variable *var)
191 gint active_item = gtk_combo_box_get_active (cb);
193 if ( active_item < 0 ) return ;
195 var_set_measure (var, active_item);
201 traverse_cell_callback (GtkSheet *sheet,
202 gint row, gint column,
203 gint *new_row, gint *new_column
206 PsppireVarStore *var_store = PSPPIRE_VAR_STORE (gtk_sheet_get_model (sheet));
208 gint n_vars = psppire_var_store_get_var_cnt (var_store);
210 if ( row == n_vars && *new_row >= n_vars)
212 GtkEntry *entry = GTK_ENTRY (gtk_sheet_get_entry (sheet));
214 const gchar *name = gtk_entry_get_text (entry);
216 if (! psppire_dict_check_name (var_store->dict, name, TRUE))
219 psppire_dict_insert_variable (var_store->dict, row, name);
224 /* If the destination cell is outside the current variables, then
225 automatically create variables for the new rows.
227 if ( (*new_row > n_vars) ||
228 (*new_row == n_vars && *new_column != PSPPIRE_VAR_STORE_COL_NAME) )
231 for ( i = n_vars ; i <= *new_row; ++i )
232 psppire_dict_insert_variable (var_store->dict, i, NULL);
242 Callback whenever the pointer leaves a cell on the var sheet.
245 var_sheet_cell_entry_leave (GtkSheet * sheet, gint row, gint column,
248 gtk_sheet_change_entry (sheet, GTK_TYPE_ENTRY);
254 Callback whenever the pointer enters a cell on the var sheet.
257 var_sheet_cell_entry_enter (PsppireVarSheet *vs, gint row, gint column,
260 GtkSheetCellAttr attributes;
261 PsppireVarStore *var_store ;
262 PsppireVarSheetClass *vs_class =
263 PSPPIRE_VAR_SHEET_CLASS(G_OBJECT_GET_CLASS (vs));
265 struct variable *var ;
266 GtkSheet *sheet = GTK_SHEET (vs);
268 g_return_val_if_fail (sheet != NULL, FALSE);
270 var_store = PSPPIRE_VAR_STORE (gtk_sheet_get_model (sheet));
272 g_assert (var_store);
274 if ( row >= psppire_var_store_get_var_cnt (var_store))
277 gtk_sheet_get_attributes (sheet, row, column, &attributes);
280 var = psppire_var_store_get_var (var_store, row);
284 case PSPPIRE_VAR_STORE_COL_ALIGN:
286 static GtkListStore *list_store = NULL;
287 GtkComboBoxEntry *cbe;
288 gtk_sheet_change_entry (sheet, GTK_TYPE_COMBO_BOX_ENTRY);
290 GTK_COMBO_BOX_ENTRY (gtk_sheet_get_entry (sheet)->parent);
293 if ( ! list_store) list_store = create_label_list (alignments);
295 gtk_combo_box_set_model (GTK_COMBO_BOX (cbe),
296 GTK_TREE_MODEL (vs_class->alignment_list));
298 gtk_combo_box_entry_set_text_column (cbe, 0);
300 g_signal_connect (G_OBJECT (cbe),"changed",
301 G_CALLBACK (change_alignment), var);
305 case PSPPIRE_VAR_STORE_COL_MEASURE:
307 GtkComboBoxEntry *cbe;
308 gtk_sheet_change_entry (sheet, GTK_TYPE_COMBO_BOX_ENTRY);
310 GTK_COMBO_BOX_ENTRY (gtk_sheet_get_entry (sheet)->parent);
314 gtk_combo_box_set_model (GTK_COMBO_BOX (cbe),
315 GTK_TREE_MODEL (vs_class->measure_list));
317 gtk_combo_box_entry_set_text_column (cbe, 0);
319 g_signal_connect (G_OBJECT (cbe),"changed",
320 G_CALLBACK (change_measure), var);
324 case PSPPIRE_VAR_STORE_COL_VALUES:
326 PsppireCustomEntry *customEntry;
328 gtk_sheet_change_entry (sheet, PSPPIRE_CUSTOM_ENTRY_TYPE);
331 PSPPIRE_CUSTOM_ENTRY (gtk_sheet_get_entry (sheet));
333 if ( var_is_long_string (var))
334 g_object_set (customEntry,
338 val_labs_dialog_set_target_variable (vs->val_labs_dialog, var);
340 g_signal_connect_swapped (customEntry,
342 G_CALLBACK (val_labs_dialog_show),
343 vs->val_labs_dialog);
347 case PSPPIRE_VAR_STORE_COL_MISSING:
349 PsppireCustomEntry *customEntry;
351 gtk_sheet_change_entry (sheet, PSPPIRE_CUSTOM_ENTRY_TYPE);
354 PSPPIRE_CUSTOM_ENTRY (gtk_sheet_get_entry (sheet));
356 if ( var_is_long_string (var))
357 g_object_set (customEntry,
362 vs->missing_val_dialog->pv =
363 psppire_var_store_get_var (var_store, row);
365 g_signal_connect_swapped (customEntry,
367 G_CALLBACK (missing_val_dialog_show),
368 vs->missing_val_dialog);
372 case PSPPIRE_VAR_STORE_COL_TYPE:
374 PsppireCustomEntry *customEntry;
376 gtk_sheet_change_entry (sheet, PSPPIRE_CUSTOM_ENTRY_TYPE);
379 PSPPIRE_CUSTOM_ENTRY (gtk_sheet_get_entry (sheet));
382 /* Popup the Variable Type dialog box */
383 vs->var_type_dialog->pv = var;
385 g_signal_connect_swapped (customEntry,
387 G_CALLBACK (var_type_dialog_show),
388 vs->var_type_dialog);
392 case PSPPIRE_VAR_STORE_COL_WIDTH:
393 case PSPPIRE_VAR_STORE_COL_DECIMALS:
394 case PSPPIRE_VAR_STORE_COL_COLUMNS:
396 if ( attributes.is_editable)
400 const gchar *s = gtk_sheet_cell_get_text (sheet, row, column);
404 GtkSpinButton *spinButton ;
405 const gint current_value = g_strtod (s, NULL);
408 const struct fmt_spec *fmt = var_get_write_format (var);
411 case PSPPIRE_VAR_STORE_COL_WIDTH:
412 r_min = MAX (fmt->d + 1, fmt_min_output_width (fmt->type));
413 r_max = fmt_max_output_width (fmt->type);
415 case PSPPIRE_VAR_STORE_COL_DECIMALS:
417 r_max = fmt_max_output_decimals (fmt->type, fmt->w);
419 case PSPPIRE_VAR_STORE_COL_COLUMNS:
421 r_max = 255 ; /* Is this a sensible value ? */
424 g_assert_not_reached ();
427 adj = gtk_adjustment_new (current_value,
429 1.0, 1.0, 1.0 /* steps */
432 gtk_sheet_change_entry (sheet, GTK_TYPE_SPIN_BUTTON);
435 GTK_SPIN_BUTTON (gtk_sheet_get_entry (sheet));
437 gtk_spin_button_set_adjustment (spinButton, GTK_ADJUSTMENT (adj));
438 gtk_spin_button_set_digits (spinButton, 0);
445 gtk_sheet_change_entry (sheet, GTK_TYPE_ENTRY);
457 psppire_var_sheet_init (PsppireVarSheet *vs)
460 GObject *geo = g_sheet_hetero_column_new (75, PSPPIRE_VAR_STORE_n_COLS);
461 GladeXML *xml = XML_NEW ("data-editor.glade");
463 vs->val_labs_dialog = val_labs_dialog_create (xml);
464 vs->missing_val_dialog = missing_val_dialog_create (xml);
465 vs->var_type_dialog = var_type_dialog_create (xml);
467 g_object_unref (xml);
469 vs->dispose_has_run = FALSE;
471 for (i = 0 ; i < PSPPIRE_VAR_STORE_n_COLS ; ++i )
473 g_sheet_hetero_column_set_button_label (G_SHEET_HETERO_COLUMN (geo), i,
474 gettext (column_def[i].label));
476 g_sheet_hetero_column_set_width (G_SHEET_HETERO_COLUMN (geo), i,
477 column_def[i].width);
480 g_object_set (vs, "column-geometry", geo, NULL);
483 g_signal_connect (vs, "activate",
484 G_CALLBACK (var_sheet_cell_entry_enter),
487 g_signal_connect (vs, "deactivate",
488 G_CALLBACK (var_sheet_cell_entry_leave),
491 g_signal_connect (vs, "traverse",
492 G_CALLBACK (traverse_cell_callback), NULL);
497 psppire_var_sheet_new (void)
499 return GTK_WIDGET (g_object_new (psppire_var_sheet_get_type (), NULL));