1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2007, 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/>. */
19 #include "select-cases-dialog.h"
22 #include "psppire-dialog.h"
23 #include "psppire-data-window.h"
24 #include "dialog-common.h"
25 #include "dict-display.h"
26 #include "widget-io.h"
27 #include <language/syntax-string-source.h>
32 #define _(msgid) gettext (msgid)
33 #define N_(msgid) msgid
37 /* FIXME: These shouldn't be here */
38 #include "psppire-data-store.h"
41 struct select_cases_dialog
43 /* The XML that created the dialog */
46 GtkWidget *spinbutton ;
47 GtkWidget *spinbutton1 ;
48 GtkWidget *spinbutton2 ;
53 PsppireDataStore *data_store;
56 static gchar * generate_syntax (const struct select_cases_dialog *scd);
60 set_sensitivity_from_toggle (GtkToggleButton *togglebutton, gpointer data)
63 gboolean active = gtk_toggle_button_get_active (togglebutton);
65 gtk_widget_set_sensitive (w, active);
69 set_sensitivity_from_toggle_invert (GtkToggleButton *togglebutton,
73 gboolean active = gtk_toggle_button_get_active (togglebutton);
75 gtk_widget_set_sensitive (w, !active);
80 static const gchar label1[]=N_("Approximately %3d%% of all cases.");
81 static const gchar label2[]=N_("Exactly %3d cases from the first %3d cases.");
85 sample_subdialog (GtkButton *b, gpointer data)
88 struct select_cases_dialog *scd = data;
90 gint case_count = psppire_data_store_get_case_count (scd->data_store);
92 GtkWidget *parent_dialog = get_widget_assert (scd->xml,
93 "select-cases-dialog");
94 GtkWidget *dialog = get_widget_assert (scd->xml,
95 "select-cases-random-sample-dialog");
96 GtkWidget *percent = get_widget_assert (scd->xml,
97 "radiobutton-sample-percent");
98 GtkWidget *sample_n_cases = get_widget_assert (scd->xml,
99 "radiobutton-sample-n-cases");
100 GtkWidget *table = get_widget_assert (scd->xml,
101 "select-cases-random-sample-table");
105 scd->hbox1 = widget_scanf (gettext (label1), &scd->spinbutton);
107 gtk_widget_show (scd->hbox1);
109 gtk_table_attach_defaults (GTK_TABLE (table),
110 scd->hbox1, 1, 2, 0, 1);
112 g_signal_connect (G_OBJECT (percent), "toggled",
113 G_CALLBACK (set_sensitivity_from_toggle), scd->hbox1);
115 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (percent), TRUE);
122 widget_scanf (gettext (label2), &scd->spinbutton1, &scd->spinbutton2);
124 gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton1),
127 gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton2),
130 gtk_widget_show (scd->hbox2);
131 gtk_widget_set_sensitive (scd->hbox2, FALSE);
133 gtk_table_attach_defaults (GTK_TABLE (table),
134 scd->hbox2, 1, 2, 1, 2);
136 g_signal_connect (G_OBJECT (sample_n_cases), "toggled",
137 G_CALLBACK (set_sensitivity_from_toggle), scd->hbox2);
139 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_n_cases), FALSE);
143 gtk_window_set_transient_for (GTK_WINDOW (dialog),
144 GTK_WINDOW (parent_dialog));
146 response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
148 if ( response != PSPPIRE_RESPONSE_CONTINUE)
150 g_signal_handlers_disconnect_by_func
152 G_CALLBACK (set_sensitivity_from_toggle),
155 g_signal_handlers_disconnect_by_func
156 (G_OBJECT (sample_n_cases),
157 G_CALLBACK (set_sensitivity_from_toggle),
160 gtk_widget_destroy(scd->hbox1);
161 gtk_widget_destroy(scd->hbox2);
162 scd->hbox1 = scd->hbox2 = NULL;
167 GtkWidget *l0 = get_widget_assert (scd->xml, "random-sample-label");
169 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (percent)))
171 text = widget_printf (gettext(label1), scd->spinbutton);
172 gtk_label_set_text (GTK_LABEL (l0), text);
177 widget_printf (gettext(label2), scd->spinbutton1, scd->spinbutton2);
178 gtk_label_set_text (GTK_LABEL (l0), text);
187 range_subdialog (GtkButton *b, gpointer data)
190 struct select_cases_dialog *scd = data;
192 gint n_cases = psppire_data_store_get_case_count (scd->data_store);
194 GtkWidget *parent_dialog = get_widget_assert (scd->xml,
195 "select-cases-dialog");
197 GtkWidget *dialog = get_widget_assert (scd->xml,
198 "select-cases-range-dialog");
200 GtkWidget *first = get_widget_assert (scd->xml,
201 "range-dialog-first");
203 GtkWidget *last = get_widget_assert (scd->xml,
204 "range-dialog-last");
207 gtk_spin_button_set_range (GTK_SPIN_BUTTON (last), 1, n_cases);
209 gtk_spin_button_set_range (GTK_SPIN_BUTTON (first), 1, n_cases);
211 gtk_window_set_transient_for (GTK_WINDOW (dialog),
212 GTK_WINDOW (parent_dialog));
215 response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
216 if ( response == PSPPIRE_RESPONSE_CONTINUE)
218 GtkWidget *first = get_widget_assert (scd->xml, "range-dialog-first");
219 GtkWidget *last = get_widget_assert (scd->xml, "range-dialog-last");
220 GtkWidget *l1 = get_widget_assert (scd->xml, "range-sample-label");
221 gchar *text = widget_printf (_("%d thru %d"), first, last);
223 gtk_label_set_text (GTK_LABEL (l1), text);
230 set_radiobutton (GtkWidget *button, gpointer data)
232 GtkToggleButton *toggle = data;
233 gtk_toggle_button_set_active (toggle, TRUE);
236 /* Pops up the Select Cases dialog box */
238 select_cases_dialog (GObject *o, gpointer data)
241 struct select_cases_dialog scd = {0,0,0,0,0,0};
243 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
244 GtkWidget *entry = NULL;
245 GtkWidget *selector ;
246 GtkWidget *button_range;
247 GtkWidget *button_sample;
249 scd.xml = builder_new ("psppire.ui");
251 g_object_get (de->data_editor, "data-store", &scd.data_store, NULL);
253 button_range = get_widget_assert (scd.xml, "button-range");
254 button_sample = get_widget_assert (scd.xml, "button-sample");
255 entry = get_widget_assert (scd.xml, "filter-variable-entry");
256 selector = get_widget_assert (scd.xml, "psppire-selector-filter");
259 GtkWidget *button_if =
260 get_widget_assert (scd.xml, "button-if");
262 GtkWidget *radiobutton_if =
263 get_widget_assert (scd.xml, "radiobutton-if");
265 GtkWidget *radiobutton_all =
266 get_widget_assert (scd.xml, "radiobutton-all");
268 GtkWidget *radiobutton_sample =
269 get_widget_assert (scd.xml, "radiobutton-sample");
271 GtkWidget *radiobutton_range =
272 get_widget_assert (scd.xml, "radiobutton-range");
274 GtkWidget *radiobutton_filter =
275 get_widget_assert (scd.xml, "radiobutton-filter-variable");
277 GtkWidget *range_label =
278 get_widget_assert (scd.xml, "range-sample-label");
280 GtkWidget *sample_label =
281 get_widget_assert (scd.xml, "random-sample-label");
283 g_signal_connect (radiobutton_all, "toggled",
284 G_CALLBACK (set_sensitivity_from_toggle_invert),
285 get_widget_assert (scd.xml, "filter-delete-button-box")
288 g_signal_connect (button_if, "clicked",
289 G_CALLBACK (set_radiobutton), radiobutton_if);
291 g_signal_connect (button_sample, "clicked",
292 G_CALLBACK (set_radiobutton), radiobutton_sample);
294 g_signal_connect (button_range, "clicked",
295 G_CALLBACK (set_radiobutton), radiobutton_range);
297 g_signal_connect (selector, "clicked",
298 G_CALLBACK (set_radiobutton), radiobutton_filter);
300 g_signal_connect (selector, "selected",
301 G_CALLBACK (set_radiobutton), radiobutton_filter);
303 g_signal_connect (radiobutton_range, "toggled",
304 G_CALLBACK (set_sensitivity_from_toggle),
308 g_signal_connect (radiobutton_sample, "toggled",
309 G_CALLBACK (set_sensitivity_from_toggle),
313 g_signal_connect (radiobutton_filter, "toggled",
314 G_CALLBACK (set_sensitivity_from_toggle),
321 dialog = get_widget_assert (scd.xml, "select-cases-dialog");
322 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de));
325 GtkWidget *source = get_widget_assert (scd.xml, "select-cases-treeview");
327 attach_dictionary_to_treeview (GTK_TREE_VIEW (source),
328 scd.data_store->dict,
329 GTK_SELECTION_SINGLE, NULL);
331 psppire_selector_set_subjects (PSPPIRE_SELECTOR (selector),
334 insert_source_row_into_entry,
335 is_currently_in_entry,
341 g_signal_connect (button_range,
342 "clicked", G_CALLBACK (range_subdialog), &scd);
345 g_signal_connect (button_sample,
346 "clicked", G_CALLBACK (sample_subdialog), &scd);
349 response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
353 case GTK_RESPONSE_OK:
355 gchar *syntax = generate_syntax (&scd);
357 struct getl_interface *sss = create_syntax_string_source (syntax);
358 execute_syntax (sss);
363 case PSPPIRE_RESPONSE_PASTE:
365 gchar *syntax = generate_syntax (&scd);
366 paste_syntax_in_new_window (syntax);
375 g_object_unref (scd.xml);
380 generate_syntax (const struct select_cases_dialog *scd)
383 GString *string = NULL;
385 if ( gtk_toggle_button_get_active
386 (GTK_TOGGLE_BUTTON (get_widget_assert (scd->xml,
387 "radiobutton-all"))))
389 return strdup ("\n");
392 string = g_string_new ("");
394 if ( gtk_toggle_button_get_active
395 (GTK_TOGGLE_BUTTON (get_widget_assert (scd->xml,
396 "radiobutton-sample"))))
398 GtkWidget *random_sample =
399 get_widget_assert (scd->xml,
400 "radiobutton-sample-percent");
402 g_string_append (string, "SAMPLE ");
404 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (random_sample)))
406 const double percentage =
407 gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton));
408 g_string_append_printf (string, "%g.", percentage / 100.0);
413 gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton1));
414 const gint from_n_cases =
415 gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton2));
417 g_string_append_printf (string, "%d FROM %d .", n_cases, from_n_cases);
421 else if ( gtk_toggle_button_get_active
422 (GTK_TOGGLE_BUTTON (get_widget_assert (scd->xml,
423 "radiobutton-range"))))
425 GtkSpinButton *first =
426 GTK_SPIN_BUTTON (get_widget_assert (scd->xml,
427 "range-dialog-first"));
429 GtkSpinButton *last =
430 GTK_SPIN_BUTTON (get_widget_assert (scd->xml,
431 "range-dialog-last"));
433 g_string_append_printf (string,
434 "COMPUTE filter_$ = ($CASENUM >= %ld "
435 "AND $CASENUM <= %ld).\n",
436 (long) gtk_spin_button_get_value (first),
437 (long) gtk_spin_button_get_value (last)
439 g_string_append (string, "EXECUTE.\n");
440 g_string_append_printf (string, "SELECT IF filter_$.\n");
443 else if ( gtk_toggle_button_get_active
445 (get_widget_assert (scd->xml,
446 "radiobutton-filter-variable"))))
449 GTK_ENTRY (get_widget_assert (scd->xml,
450 "filter-variable-entry"));
452 g_string_append_printf (string, "SELECT IF (%s <> 0).",
453 gtk_entry_get_text (entry));
457 g_string_append (string, "\n");
460 /* Are we filtering or deleting ? */
461 if ( gtk_toggle_button_get_active
462 (GTK_TOGGLE_BUTTON (get_widget_assert (scd->xml,
463 "radiobutton-delete"))))
465 g_string_append (string, "EXECUTE.\n");
467 if ( gtk_toggle_button_get_active
468 (GTK_TOGGLE_BUTTON (get_widget_assert (scd->xml,
469 "radiobutton-range"))))
471 g_string_append (string, "DELETE VARIABLES filter_$.\n");
477 g_string_free (string, FALSE);