1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2005, 2006, 2009 Free Software Foundation
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/>. */
17 /* This module describes the behaviour of the Missing Values dialog box,
18 used for input of the missing values in the variable sheet */
22 #define _(msgid) gettext (msgid)
23 #define N_(msgid) msgid
27 #include <data/format.h>
28 #include "missing-val-dialog.h"
29 #include <data/missing-values.h>
30 #include <data/variable.h>
31 #include <data/data-in.h>
39 /* A simple (sub) dialog box for displaying user input errors */
41 err_dialog (const gchar *msg, GtkWindow *window)
44 GtkWidget *label = gtk_label_new (msg);
47 gtk_dialog_new_with_buttons ("PSPP",
50 GTK_DIALOG_DESTROY_WITH_PARENT |
51 GTK_DIALOG_NO_SEPARATOR,
57 GtkWidget *icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR,
58 GTK_ICON_SIZE_DIALOG);
60 g_signal_connect_swapped (dialog,
62 G_CALLBACK (gtk_widget_destroy),
65 hbox = gtk_hbox_new (FALSE, 10);
67 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
70 gtk_box_pack_start (GTK_BOX (hbox), icon, TRUE, FALSE, 10);
71 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 10);
73 gtk_widget_show_all (dialog);
77 /* Callback which occurs when the OK button is clicked */
79 missing_val_dialog_accept (GtkWidget *w, gpointer data)
81 struct missing_val_dialog *dialog = data;
83 if ( gtk_toggle_button_get_active (dialog->button_discrete))
88 mv_clear(&dialog->mvl);
89 for(i = 0 ; i < 3 ; ++i )
92 g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->mv[i])));
95 if ( !text || strlen (g_strstrip (text)) == 0 )
101 if ( text_to_value (text, dialog->dict, dialog->pv, &v))
104 mv_add_value (&dialog->mvl, &v);
109 value_destroy (&v, var_get_width (dialog->pv));
111 if ( nvals == 0 || badvals > 0 )
113 err_dialog (_("Incorrect value for variable type"),
114 GTK_WINDOW (dialog->window));
119 if (gtk_toggle_button_get_active (dialog->button_range))
121 gchar *discrete_text ;
123 union value low_val ;
124 union value high_val;
125 const gchar *low_text = gtk_entry_get_text (GTK_ENTRY (dialog->low));
126 const gchar *high_text = gtk_entry_get_text (GTK_ENTRY (dialog->high));
128 if ( text_to_value (low_text, dialog->dict, dialog->pv, &low_val)
130 text_to_value (high_text, dialog->dict, dialog->pv, &high_val))
132 if ( low_val.f > high_val.f )
134 err_dialog (_("Incorrect range specification"),
135 GTK_WINDOW (dialog->window));
136 value_destroy (&low_val, var_get_width (dialog->pv));
137 value_destroy (&high_val, var_get_width (dialog->pv));
143 err_dialog (_("Incorrect range specification"),
144 GTK_WINDOW (dialog->window));
145 value_destroy (&low_val, var_get_width (dialog->pv));
146 value_destroy (&high_val, var_get_width (dialog->pv));
151 g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->discrete)));
153 mv_clear (&dialog->mvl);
154 mv_add_range (&dialog->mvl, low_val.f, high_val.f);
156 value_destroy (&low_val, var_get_width (dialog->pv));
157 value_destroy (&high_val, var_get_width (dialog->pv));
159 if ( discrete_text && strlen (g_strstrip (discrete_text)) > 0 )
161 union value discrete_val;
162 if ( !text_to_value (discrete_text,
167 err_dialog (_("Incorrect value for variable type"),
168 GTK_WINDOW (dialog->window) );
169 g_free (discrete_text);
170 value_destroy (&discrete_val, var_get_width (dialog->pv));
173 mv_add_value (&dialog->mvl, &discrete_val);
174 value_destroy (&discrete_val, var_get_width (dialog->pv));
176 g_free (discrete_text);
180 if (gtk_toggle_button_get_active (dialog->button_none))
181 mv_clear (&dialog->mvl);
183 var_set_missing_values (dialog->pv, &dialog->mvl);
185 gtk_widget_hide (dialog->window);
189 /* Callback which occurs when the 'discrete' radiobutton is toggled */
191 discrete (GtkToggleButton *button, gpointer data)
194 struct missing_val_dialog *dialog = data;
196 for (i = 0 ; i < 3 ; ++i )
198 gtk_widget_set_sensitive (dialog->mv[i],
199 gtk_toggle_button_get_active (button));
203 /* Callback which occurs when the 'range' radiobutton is toggled */
205 range (GtkToggleButton *button, gpointer data)
207 struct missing_val_dialog *dialog = data;
209 const gboolean active = gtk_toggle_button_get_active (button);
211 gtk_widget_set_sensitive (dialog->low, active);
212 gtk_widget_set_sensitive (dialog->high, active);
213 gtk_widget_set_sensitive (dialog->discrete, active);
218 /* Callback for when the Missing Value dialog is closed using
219 the window delete button.*/
221 on_delete (GtkWidget *w, GdkEvent *e, gpointer data)
223 struct missing_val_dialog *dialog = data;
225 gtk_widget_hide (dialog->window);
231 /* Creates the dialog structure */
232 struct missing_val_dialog *
233 missing_val_dialog_create (GtkWindow *toplevel)
235 GtkBuilder *xml = builder_new ("var-sheet-dialogs.ui");
237 struct missing_val_dialog *dialog = g_malloc (sizeof (*dialog));
239 dialog->window = get_widget_assert (xml, "missing_values_dialog");
241 gtk_window_set_transient_for
242 (GTK_WINDOW (dialog->window), toplevel);
244 g_signal_connect_swapped (get_widget_assert (xml, "missing_val_cancel"),
245 "clicked", G_CALLBACK (gtk_widget_hide), dialog->window);
247 g_signal_connect (get_widget_assert (xml, "missing_val_ok"),
248 "clicked", G_CALLBACK (missing_val_dialog_accept), dialog);
250 g_signal_connect (dialog->window, "delete-event",
251 G_CALLBACK (on_delete), dialog);
253 dialog->mv[0] = get_widget_assert (xml, "mv0");
254 dialog->mv[1] = get_widget_assert (xml, "mv1");
255 dialog->mv[2] = get_widget_assert (xml, "mv2");
257 dialog->low = get_widget_assert (xml, "mv-low");
258 dialog->high = get_widget_assert (xml, "mv-high");
259 dialog->discrete = get_widget_assert (xml, "mv-discrete");
262 dialog->button_none =
263 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "no_missing"));
265 dialog->button_discrete =
266 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "discrete_missing"));
268 dialog->button_range =
269 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "range_missing"));
272 g_signal_connect (dialog->button_discrete, "toggled",
273 G_CALLBACK (discrete), dialog);
275 g_signal_connect (dialog->button_range, "toggled",
276 G_CALLBACK (range), dialog);
278 g_object_unref (xml);
283 /* Shows the dialog box and sets default values */
285 missing_val_dialog_show (struct missing_val_dialog *dialog)
287 const struct fmt_spec *write_spec ;
290 g_return_if_fail (dialog);
291 g_return_if_fail (dialog->pv);
293 mv_copy (&dialog->mvl, var_get_missing_values (dialog->pv));
295 write_spec = var_get_write_format (dialog->pv);
297 /* Blank all entry boxes and make them insensitive */
298 gtk_entry_set_text (GTK_ENTRY (dialog->low), "");
299 gtk_entry_set_text (GTK_ENTRY (dialog->high), "");
300 gtk_entry_set_text (GTK_ENTRY (dialog->discrete), "");
301 gtk_widget_set_sensitive (dialog->low, FALSE);
302 gtk_widget_set_sensitive (dialog->high, FALSE);
303 gtk_widget_set_sensitive (dialog->discrete, FALSE);
305 gtk_widget_set_sensitive (GTK_WIDGET (dialog->button_range),
306 var_is_numeric (dialog->pv));
309 for (i = 0 ; i < 3 ; ++i )
311 gtk_entry_set_text (GTK_ENTRY (dialog->mv[i]), "");
312 gtk_widget_set_sensitive (dialog->mv[i], FALSE);
315 if ( mv_has_range (&dialog->mvl))
317 union value low, high;
320 mv_get_range (&dialog->mvl, &low.f, &high.f);
323 low_text = value_to_text (low, dialog->dict, *write_spec);
324 high_text = value_to_text (high, dialog->dict, *write_spec);
326 gtk_entry_set_text (GTK_ENTRY (dialog->low), low_text);
327 gtk_entry_set_text (GTK_ENTRY (dialog->high), high_text);
331 if ( mv_has_value (&dialog->mvl))
334 text = value_to_text (*mv_get_value (&dialog->mvl, 0), dialog->dict, *write_spec);
335 gtk_entry_set_text (GTK_ENTRY (dialog->discrete), text);
339 gtk_toggle_button_set_active (dialog->button_range, TRUE);
340 gtk_widget_set_sensitive (dialog->low, TRUE);
341 gtk_widget_set_sensitive (dialog->high, TRUE);
342 gtk_widget_set_sensitive (dialog->discrete, TRUE);
345 else if ( mv_has_value (&dialog->mvl))
347 const int n = mv_n_values (&dialog->mvl);
349 for (i = 0 ; i < 3 ; ++i )
355 text = value_to_text (*mv_get_value (&dialog->mvl, i), dialog->dict,
357 gtk_entry_set_text (GTK_ENTRY (dialog->mv[i]), text);
360 gtk_widget_set_sensitive (dialog->mv[i], TRUE);
362 gtk_toggle_button_set_active (dialog->button_discrete, TRUE);
364 else if ( mv_is_empty (&dialog->mvl))
366 gtk_toggle_button_set_active (dialog->button_none, TRUE);
369 gtk_widget_show (dialog->window);