1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2007, 2008, 2009 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 "psppire-selector.h"
25 #include "dict-display.h"
26 #include "dialog-common.h"
27 #include "widget-io.h"
28 #include <language/syntax-string-source.h>
34 #define _(msgid) gettext (msgid)
35 #define N_(msgid) msgid
39 /* FIXME: These shouldn't be here */
40 #include "psppire-data-store.h"
43 struct select_cases_dialog
45 /* The XML that created the dialog */
48 GtkWidget *spinbutton ;
49 GtkWidget *spinbutton1 ;
50 GtkWidget *spinbutton2 ;
55 PsppireDataStore *data_store;
58 static gchar * generate_syntax (const struct select_cases_dialog *scd);
62 set_sensitivity_from_toggle (GtkToggleButton *togglebutton, gpointer data)
65 gboolean active = gtk_toggle_button_get_active (togglebutton);
67 gtk_widget_set_sensitive (w, active);
71 set_sensitivity_from_toggle_invert (GtkToggleButton *togglebutton,
75 gboolean active = gtk_toggle_button_get_active (togglebutton);
77 gtk_widget_set_sensitive (w, !active);
82 static const gchar label1[]=N_("Approximately %3d%% of all cases.");
83 static const gchar label2[]=N_("Exactly %3d cases from the first %3d cases.");
87 sample_subdialog (GtkButton *b, gpointer data)
90 struct select_cases_dialog *scd = data;
92 gint case_count = psppire_data_store_get_case_count (scd->data_store);
94 GtkWidget *parent_dialog = get_widget_assert (scd->xml,
95 "select-cases-dialog");
96 GtkWidget *dialog = get_widget_assert (scd->xml,
97 "select-cases-random-sample-dialog");
98 GtkWidget *percent = get_widget_assert (scd->xml,
99 "radiobutton-sample-percent");
100 GtkWidget *sample_n_cases = get_widget_assert (scd->xml,
101 "radiobutton-sample-n-cases");
102 GtkWidget *table = get_widget_assert (scd->xml,
103 "select-cases-random-sample-table");
107 scd->hbox1 = widget_scanf (gettext (label1), &scd->spinbutton);
109 gtk_widget_show (scd->hbox1);
111 gtk_table_attach_defaults (GTK_TABLE (table),
112 scd->hbox1, 1, 2, 0, 1);
114 g_signal_connect (percent, "toggled",
115 G_CALLBACK (set_sensitivity_from_toggle), scd->hbox1);
117 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (percent), TRUE);
124 widget_scanf (gettext (label2), &scd->spinbutton1, &scd->spinbutton2);
126 gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton1),
129 gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton2),
132 gtk_widget_show (scd->hbox2);
133 gtk_widget_set_sensitive (scd->hbox2, FALSE);
135 gtk_table_attach_defaults (GTK_TABLE (table),
136 scd->hbox2, 1, 2, 1, 2);
138 g_signal_connect (sample_n_cases, "toggled",
139 G_CALLBACK (set_sensitivity_from_toggle), scd->hbox2);
141 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_n_cases), FALSE);
145 gtk_window_set_transient_for (GTK_WINDOW (dialog),
146 GTK_WINDOW (parent_dialog));
148 response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
150 if ( response != PSPPIRE_RESPONSE_CONTINUE)
152 g_signal_handlers_disconnect_by_func
154 G_CALLBACK (set_sensitivity_from_toggle),
157 g_signal_handlers_disconnect_by_func
158 (G_OBJECT (sample_n_cases),
159 G_CALLBACK (set_sensitivity_from_toggle),
162 gtk_widget_destroy(scd->hbox1);
163 gtk_widget_destroy(scd->hbox2);
164 scd->hbox1 = scd->hbox2 = NULL;
169 GtkWidget *l0 = get_widget_assert (scd->xml, "random-sample-label");
171 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (percent)))
173 text = widget_printf (gettext(label1), scd->spinbutton);
174 gtk_label_set_text (GTK_LABEL (l0), text);
179 widget_printf (gettext(label2), scd->spinbutton1, scd->spinbutton2);
180 gtk_label_set_text (GTK_LABEL (l0), text);
189 range_subdialog (GtkButton *b, gpointer data)
192 struct select_cases_dialog *scd = data;
194 gint n_cases = psppire_data_store_get_case_count (scd->data_store);
196 GtkWidget *parent_dialog = get_widget_assert (scd->xml,
197 "select-cases-dialog");
199 GtkWidget *dialog = get_widget_assert (scd->xml,
200 "select-cases-range-dialog");
202 GtkWidget *first = get_widget_assert (scd->xml,
203 "range-dialog-first");
205 GtkWidget *last = get_widget_assert (scd->xml,
206 "range-dialog-last");
209 gtk_spin_button_set_range (GTK_SPIN_BUTTON (last), 1, n_cases);
211 gtk_spin_button_set_range (GTK_SPIN_BUTTON (first), 1, n_cases);
213 gtk_window_set_transient_for (GTK_WINDOW (dialog),
214 GTK_WINDOW (parent_dialog));
217 response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
218 if ( response == PSPPIRE_RESPONSE_CONTINUE)
220 GtkWidget *first = get_widget_assert (scd->xml, "range-dialog-first");
221 GtkWidget *last = get_widget_assert (scd->xml, "range-dialog-last");
222 GtkWidget *l1 = get_widget_assert (scd->xml, "range-sample-label");
223 gchar *text = widget_printf (_("%d thru %d"), first, last);
225 gtk_label_set_text (GTK_LABEL (l1), text);
232 set_radiobutton (GtkWidget *button, gpointer data)
234 GtkToggleButton *toggle = data;
235 gtk_toggle_button_set_active (toggle, TRUE);
238 /* Pops up the Select Cases dialog box */
240 select_cases_dialog (PsppireDataWindow *de)
243 struct select_cases_dialog scd = {0,0,0,0,0,0};
245 GtkWidget *entry = NULL;
246 GtkWidget *selector ;
247 GtkWidget *button_range;
248 GtkWidget *button_sample;
250 scd.xml = builder_new ("select-cases.ui");
252 g_object_get (de->data_editor, "data-store", &scd.data_store, NULL);
254 button_range = get_widget_assert (scd.xml, "button-range");
255 button_sample = get_widget_assert (scd.xml, "button-sample");
256 entry = get_widget_assert (scd.xml, "filter-variable-entry");
257 selector = get_widget_assert (scd.xml, "psppire-selector-filter");
260 GtkWidget *button_if =
261 get_widget_assert (scd.xml, "button-if");
263 GtkWidget *radiobutton_if =
264 get_widget_assert (scd.xml, "radiobutton-if");
266 GtkWidget *radiobutton_all =
267 get_widget_assert (scd.xml, "radiobutton-all");
269 GtkWidget *radiobutton_sample =
270 get_widget_assert (scd.xml, "radiobutton-sample");
272 GtkWidget *radiobutton_range =
273 get_widget_assert (scd.xml, "radiobutton-range");
275 GtkWidget *radiobutton_filter =
276 get_widget_assert (scd.xml, "radiobutton-filter-variable");
278 GtkWidget *range_label =
279 get_widget_assert (scd.xml, "range-sample-label");
281 GtkWidget *sample_label =
282 get_widget_assert (scd.xml, "random-sample-label");
284 g_signal_connect (radiobutton_all, "toggled",
285 G_CALLBACK (set_sensitivity_from_toggle_invert),
286 get_widget_assert (scd.xml, "filter-delete-button-box")
289 g_signal_connect (button_if, "clicked",
290 G_CALLBACK (set_radiobutton), radiobutton_if);
292 g_signal_connect (button_sample, "clicked",
293 G_CALLBACK (set_radiobutton), radiobutton_sample);
295 g_signal_connect (button_range, "clicked",
296 G_CALLBACK (set_radiobutton), radiobutton_range);
298 g_signal_connect (selector, "clicked",
299 G_CALLBACK (set_radiobutton), radiobutton_filter);
301 g_signal_connect (selector, "selected",
302 G_CALLBACK (set_radiobutton), radiobutton_filter);
304 g_signal_connect (radiobutton_range, "toggled",
305 G_CALLBACK (set_sensitivity_from_toggle),
309 g_signal_connect (radiobutton_sample, "toggled",
310 G_CALLBACK (set_sensitivity_from_toggle),
314 g_signal_connect (radiobutton_filter, "toggled",
315 G_CALLBACK (set_sensitivity_from_toggle),
322 dialog = get_widget_assert (scd.xml, "select-cases-dialog");
323 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de));
326 GtkWidget *source = get_widget_assert (scd.xml, "select-cases-treeview");
328 g_object_set (source, "model",
329 scd.data_store->dict,
331 GTK_SELECTION_SINGLE, NULL);
333 psppire_selector_set_filter_func (PSPPIRE_SELECTOR (selector),
334 is_currently_in_entry);
339 g_signal_connect (button_range,
340 "clicked", G_CALLBACK (range_subdialog), &scd);
343 g_signal_connect (button_sample,
344 "clicked", G_CALLBACK (sample_subdialog), &scd);
347 response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
351 case GTK_RESPONSE_OK:
353 gchar *syntax = generate_syntax (&scd);
355 struct getl_interface *sss = create_syntax_string_source (syntax);
356 execute_syntax (sss);
361 case PSPPIRE_RESPONSE_PASTE:
363 gchar *syntax = generate_syntax (&scd);
364 paste_syntax_to_window (syntax);
373 g_object_unref (scd.xml);
378 generate_syntax (const struct select_cases_dialog *scd)
381 GString *string = NULL;
383 if ( gtk_toggle_button_get_active
384 (GTK_TOGGLE_BUTTON (get_widget_assert (scd->xml,
385 "radiobutton-all"))))
387 return xstrdup ("\n");
390 string = g_string_new ("");
392 if ( gtk_toggle_button_get_active
393 (GTK_TOGGLE_BUTTON (get_widget_assert (scd->xml,
394 "radiobutton-sample"))))
396 GtkWidget *random_sample =
397 get_widget_assert (scd->xml,
398 "radiobutton-sample-percent");
400 g_string_append (string, "SAMPLE ");
402 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (random_sample)))
404 const double percentage =
405 gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton));
406 g_string_append_printf (string, "%g.", percentage / 100.0);
411 gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton1));
412 const gint from_n_cases =
413 gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton2));
415 g_string_append_printf (string, "%d FROM %d .", n_cases, from_n_cases);
419 else if ( gtk_toggle_button_get_active
420 (GTK_TOGGLE_BUTTON (get_widget_assert (scd->xml,
421 "radiobutton-range"))))
423 GtkSpinButton *first =
424 GTK_SPIN_BUTTON (get_widget_assert (scd->xml,
425 "range-dialog-first"));
427 GtkSpinButton *last =
428 GTK_SPIN_BUTTON (get_widget_assert (scd->xml,
429 "range-dialog-last"));
431 g_string_append_printf (string,
432 "COMPUTE filter_$ = ($CASENUM >= %ld "
433 "AND $CASENUM <= %ld).\n",
434 (long) gtk_spin_button_get_value (first),
435 (long) gtk_spin_button_get_value (last)
437 g_string_append (string, "EXECUTE.\n");
438 g_string_append_printf (string, "SELECT IF filter_$.\n");
441 else if ( gtk_toggle_button_get_active
443 (get_widget_assert (scd->xml,
444 "radiobutton-filter-variable"))))
447 GTK_ENTRY (get_widget_assert (scd->xml,
448 "filter-variable-entry"));
450 g_string_append_printf (string, "SELECT IF (%s <> 0).",
451 gtk_entry_get_text (entry));
455 g_string_append (string, "\n");
458 /* Are we filtering or deleting ? */
459 if ( gtk_toggle_button_get_active
460 (GTK_TOGGLE_BUTTON (get_widget_assert (scd->xml,
461 "radiobutton-delete"))))
463 g_string_append (string, "EXECUTE.\n");
465 if ( gtk_toggle_button_get_active
466 (GTK_TOGGLE_BUTTON (get_widget_assert (scd->xml,
467 "radiobutton-range"))))
469 g_string_append (string, "DELETE VARIABLES filter_$.\n");
475 g_string_free (string, FALSE);