From: John Darrington Date: Thu, 31 Dec 2015 13:59:49 +0000 (+0100) Subject: Select Cases Dialog: Convert to PsppireDialogAction X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=469b69a6df92b30f18a4a5c7262d9290601a0a88 Select Cases Dialog: Convert to PsppireDialogAction --- diff --git a/src/ui/gui/automake.mk b/src/ui/gui/automake.mk index 3e8bc25e61..10b315061a 100644 --- a/src/ui/gui/automake.mk +++ b/src/ui/gui/automake.mk @@ -251,6 +251,8 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/psppire-dialog-action-scatterplot.h \ src/ui/gui/psppire-dialog-action-sort.c \ src/ui/gui/psppire-dialog-action-sort.h \ + src/ui/gui/psppire-dialog-action-select.c \ + src/ui/gui/psppire-dialog-action-select.h \ src/ui/gui/psppire-dialog-action-split.c \ src/ui/gui/psppire-dialog-action-split.h \ src/ui/gui/psppire-dialog-action-tt1s.c \ @@ -309,8 +311,6 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/psppire-window-register.h \ src/ui/gui/recode-dialog.c \ src/ui/gui/recode-dialog.h \ - src/ui/gui/select-cases-dialog.c \ - src/ui/gui/select-cases-dialog.h \ src/ui/gui/t-test-options.c \ src/ui/gui/t-test-options.h \ src/ui/gui/val-labs-dialog.c \ diff --git a/src/ui/gui/data-editor.ui b/src/ui/gui/data-editor.ui index 882e40ea2b..ebf87c5a94 100644 --- a/src/ui/gui/data-editor.ui +++ b/src/ui/gui/data-editor.ui @@ -206,8 +206,9 @@ - + data_select-cases + uimanager1 Select _Cases... Choose a subset of cases for analysis data-select-cases diff --git a/src/ui/gui/psppire-data-window.c b/src/ui/gui/psppire-data-window.c index b020d19ecf..6cf3a8f617 100644 --- a/src/ui/gui/psppire-data-window.c +++ b/src/ui/gui/psppire-data-window.c @@ -38,7 +38,6 @@ #include "ui/gui/psppire-window.h" #include "ui/gui/psppire.h" #include "ui/gui/recode-dialog.h" -#include "ui/gui/select-cases-dialog.h" #include "ui/syntax-gen.h" #include "gl/c-strcase.h" @@ -1042,7 +1041,6 @@ psppire_data_window_finish_init (PsppireDataWindow *de, g_signal_connect_swapped (get_action_assert (de->builder, "view_value-labels"), "toggled", G_CALLBACK (toggle_value_labels), de); - connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog)); connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog)); connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog)); diff --git a/src/ui/gui/psppire-dialog-action-select.c b/src/ui/gui/psppire-dialog-action-select.c new file mode 100644 index 0000000000..d3eee6570d --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-select.c @@ -0,0 +1,524 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2007, 2008, 2009, 2010, 2011, 2014, 2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + + +#include "builder-wrapper.h" +#include "dialog-common.h" +#include "dict-display.h" +#include "libpspp/str.h" +#include "psppire-data-store.h" +#include "psppire-data-window.h" +#include "psppire-dialog-action-select.h" +#include "psppire-dialog.h" +#include "psppire-dict.h" +#include "psppire-scanf.h" +#include "psppire-value-entry.h" +#include "psppire-var-view.h" +#include "widget-io.h" + +#include + + + +#include +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + +static void psppire_dialog_action_select_class_init (PsppireDialogActionSelectClass *class); + +G_DEFINE_TYPE (PsppireDialogActionSelect, psppire_dialog_action_select, PSPPIRE_TYPE_DIALOG_ACTION); + +static gboolean +dialog_state_valid (gpointer data) +{ + return TRUE; +} + + +static void +refresh (PsppireDialogAction *pda) +{ + PsppireDialogActionSelect *act = PSPPIRE_DIALOG_ACTION_SELECT (pda); + + gtk_entry_set_text (GTK_ENTRY (act->entry), ""); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (act->radiobutton_all), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (act->radiobutton_filter), TRUE); + + gtk_label_set_text (GTK_LABEL (act->l1), ""); + gtk_label_set_text (GTK_LABEL (act->l0), ""); +} + + +static void +set_radiobutton (GtkWidget *button, gpointer data) +{ + GtkToggleButton *toggle = data; + gtk_toggle_button_set_active (toggle, TRUE); +} + + +static const gchar label1[] = N_("Approximately %3d%% of all cases."); +static const gchar label2[] = N_("Exactly %3d cases from the first %3d cases."); + + +static void +sample_subdialog (GtkButton *b, gpointer data) +{ + gint response; + PsppireDialogActionSelect *scd = PSPPIRE_DIALOG_ACTION_SELECT (data); + PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (data); + + PsppireDataStore *data_store = NULL; + g_object_get (PSPPIRE_DATA_WINDOW (pda->toplevel)->data_editor, + "data-store", &data_store, + NULL); + + gint case_count = psppire_data_store_get_case_count (data_store); + + if (!scd->hbox1) + { + scd->hbox1 = psppire_scanf_new (gettext (label1), &scd->spinbutton); + + gtk_widget_show (scd->hbox1); + + gtk_grid_attach (GTK_GRID (scd->table), + scd->hbox1, + 1, 0, + 1, 1); + + g_signal_connect (scd->percent, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), scd->hbox1); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scd->percent), TRUE); + } + + + if (!scd->hbox2) + { + scd->hbox2 = + psppire_scanf_new (gettext (label2), &scd->spinbutton1, &scd->spinbutton2); + + gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton1), + 1, case_count); + + gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton2), + 1, case_count); + + gtk_widget_show (scd->hbox2); + gtk_widget_set_sensitive (scd->hbox2, FALSE); + + gtk_grid_attach (GTK_GRID (scd->table), + scd->hbox2, + 1, 1, 1, 1); + + g_signal_connect (scd->sample_n_cases, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), scd->hbox2); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scd->sample_n_cases), FALSE); + } + + + gtk_window_set_transient_for (GTK_WINDOW (scd->rsample_dialog), + GTK_WINDOW (pda->dialog)); + + response = psppire_dialog_run (PSPPIRE_DIALOG (scd->rsample_dialog)); + + if ( response != PSPPIRE_RESPONSE_CONTINUE) + { + g_signal_handlers_disconnect_by_func + (G_OBJECT (scd->percent), + G_CALLBACK (set_sensitivity_from_toggle), + scd->hbox1); + + g_signal_handlers_disconnect_by_func + (G_OBJECT (scd->sample_n_cases), + G_CALLBACK (set_sensitivity_from_toggle), + scd->hbox2); + + gtk_widget_destroy(scd->hbox1); + gtk_widget_destroy(scd->hbox2); + scd->hbox1 = scd->hbox2 = NULL; + } + else + { + gchar *text; + + if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->percent))) + { + text = widget_printf (gettext(label1), scd->spinbutton); + gtk_label_set_text (GTK_LABEL (scd->l0), text); + } + else + { + text = + widget_printf (gettext(label2), scd->spinbutton1, scd->spinbutton2); + gtk_label_set_text (GTK_LABEL (scd->l0), text); + + } + g_free (text); + } +} + + + +static void +range_subdialog (GtkButton *b, gpointer data) +{ + gint response; + PsppireDialogActionSelect *scd = PSPPIRE_DIALOG_ACTION_SELECT (data); + PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (data); + + PsppireDataStore *data_store = NULL; + g_object_get (PSPPIRE_DATA_WINDOW (pda->toplevel)->data_editor, + "data-store", &data_store, + NULL); + + gint n_cases = psppire_data_store_get_case_count (data_store); + + gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->last), 1, n_cases); + gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->first), 1, n_cases); + + gtk_window_set_transient_for (GTK_WINDOW (scd->range_subdialog), + GTK_WINDOW (pda->dialog)); + + response = psppire_dialog_run (PSPPIRE_DIALOG (scd->range_subdialog)); + if ( response == PSPPIRE_RESPONSE_CONTINUE) + { + gchar *text = widget_printf (_("%d thru %d"), scd->first, scd->last); + gtk_label_set_text (GTK_LABEL (scd->l1), text); + g_free (text); + } +} + + +static void +psppire_dialog_action_select_activate (PsppireDialogAction *a) +{ + PsppireDialogActionSelect *act = PSPPIRE_DIALOG_ACTION_SELECT (a); + PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a); + + GHashTable *thing = psppire_dialog_action_get_hash_table (pda); + GtkBuilder *xml = g_hash_table_lookup (thing, a); + if (!xml) + { + xml = builder_new ("select-cases.ui"); + g_hash_table_insert (thing, a, xml); + + + pda->dialog = get_widget_assert (xml, "select-cases-dialog"); + pda->source = get_widget_assert (xml, "select-cases-treeview"); + + g_object_set (pda->source, + "selection-mode", GTK_SELECTION_SINGLE, + NULL); + + act->entry = get_widget_assert (xml, "filter-variable-entry"); + + GtkWidget *selector = get_widget_assert (xml, "psppire-selector-filter"); + psppire_selector_set_filter_func (PSPPIRE_SELECTOR (selector), + is_currently_in_entry); + + act->rsample_dialog = get_widget_assert (xml, "select-cases-random-sample-dialog"); + act->percent = get_widget_assert (xml, "radiobutton-sample-percent"); + act->sample_n_cases = get_widget_assert (xml, "radiobutton-sample-n-cases"); + act->table = get_widget_assert (xml, "select-cases-random-sample-table"); + + act->l0 = get_widget_assert (xml, "random-sample-label");; + + act->radiobutton_range = get_widget_assert (xml, "radiobutton-range"); + act->range_subdialog = get_widget_assert (xml, "select-cases-range-dialog"); + + act->first = get_widget_assert (xml, "range-dialog-first"); + act->last = get_widget_assert (xml, "range-dialog-last"); + + act->l1 = get_widget_assert (xml, "range-sample-label"); + act->radiobutton_sample = get_widget_assert (xml, "radiobutton-sample"); + + act->radiobutton_all = get_widget_assert (xml, "radiobutton-all"); + act->radiobutton_filter_variable = get_widget_assert (xml, "radiobutton-filter-variable"); + + act->radiobutton_filter = get_widget_assert (xml, "radiobutton-filter"); + act->radiobutton_delete = get_widget_assert (xml, "radiobutton-delete"); + + + GtkWidget *button_range = get_widget_assert (xml, "button-range"); + GtkWidget *button_sample = get_widget_assert (xml, "button-sample"); + + GtkWidget *button_if =get_widget_assert (xml, "button-if"); + + GtkWidget *radiobutton_if = get_widget_assert (xml, "radiobutton-if"); + + GtkWidget *sample_label = get_widget_assert (xml, "random-sample-label"); + + g_signal_connect (act->radiobutton_all, "toggled", + G_CALLBACK (set_sensitivity_from_toggle_invert), + get_widget_assert (xml, "filter-delete-button-box")); + + g_signal_connect (button_if, "clicked", + G_CALLBACK (set_radiobutton), radiobutton_if); + + g_signal_connect (button_sample, "clicked", + G_CALLBACK (set_radiobutton), act->radiobutton_sample); + + g_signal_connect (button_range, "clicked", + G_CALLBACK (set_radiobutton), act->radiobutton_range); + + g_signal_connect (selector, "clicked", + G_CALLBACK (set_radiobutton), act->radiobutton_filter_variable); + + g_signal_connect (selector, "selected", + G_CALLBACK (set_radiobutton), act->radiobutton_filter_variable); + + g_signal_connect (act->radiobutton_range, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), + act->l1); + + g_signal_connect (act->radiobutton_sample, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), + sample_label); + + g_signal_connect (act->radiobutton_filter_variable, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), + act->entry); + + g_signal_connect (button_range, + "clicked", G_CALLBACK (range_subdialog), act); + + g_signal_connect (button_sample, + "clicked", G_CALLBACK (sample_subdialog), act); + } + + psppire_dialog_action_set_refresh (pda, refresh); + + psppire_dialog_action_set_valid_predicate (pda, + dialog_state_valid); + + if (PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_select_parent_class)->activate) + PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_select_parent_class)->activate (pda); +} + + +static char * +generate_syntax_filter (PsppireDialogAction *a) +{ + PsppireDialogActionSelect *scd = PSPPIRE_DIALOG_ACTION_SELECT (a); + + gchar *text = NULL; + struct string dss; + + const gchar *filter = "filter_$"; + const gchar key[]="case_$"; + + ds_init_empty (&dss); + + if (gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON (scd->radiobutton_range))) + { + ds_put_c_format (&dss, + "COMPUTE filter_$ = ($CASENUM >= %ld " + "AND $CASENUM <= %ld).\n", + (long) gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->first)), + (long) gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->last))); + + ds_put_cstr (&dss, "EXECUTE.\n"); + } + else if ( gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON (scd->radiobutton_sample))) + { + if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->percent))) + { + const double percentage = + gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton)); + + ds_put_c_format (&dss, + "COMPUTE %s = RV.UNIFORM (0,1) < %.*g.\n", + filter, + DBL_DIG + 1, percentage / 100.0 ); + } + else + { + const gint n_cases = + gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton1)); + const gint from_n_cases = + gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton2)); + + + const gchar ranvar[]="rv_$"; + + ds_put_c_format (&dss, + "COMPUTE %s = $CASENUM.\n", key); + + ds_put_c_format (&dss, + "COMPUTE %s = %s > %d.\n", + filter, key, from_n_cases); + + ds_put_c_format (&dss, + "COMPUTE %s = RV.UNIFORM (0, 1).\n", + ranvar); + + ds_put_c_format (&dss, + "SORT BY %s, %s.\n", + filter, ranvar); + + ds_put_cstr (&dss, "EXECUTE.\n"); + + + ds_put_c_format (&dss, + "COMPUTE %s = $CASENUM.\n", + filter ); + + ds_put_c_format (&dss, + "COMPUTE %s = %s <= %d\n", + filter, + filter, + n_cases ); + + ds_put_cstr (&dss, "EXECUTE.\n"); + + + ds_put_c_format (&dss, + "SORT BY %s.\n", + key); + + ds_put_c_format (&dss, + "DELETE VARIABLES %s, %s.\n", + key, ranvar); + } + + ds_put_cstr (&dss, "EXECUTE.\n"); + } + else + { + filter = gtk_entry_get_text (GTK_ENTRY (scd->entry)); + } + + ds_put_c_format (&dss, "FILTER BY %s.\n", filter); + + text = ds_steal_cstr (&dss); + + ds_destroy (&dss); + + return text; +} + + +static gchar * +generate_syntax_delete (PsppireDialogAction *a) +{ + PsppireDialogActionSelect *scd = PSPPIRE_DIALOG_ACTION_SELECT (a); + gchar *text = NULL; + struct string dss; + + if ( gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON (scd->radiobutton_all))) + { + return xstrdup ("\n"); + } + + ds_init_empty (&dss); + + if ( gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON (scd->radiobutton_sample))) + { + ds_put_cstr (&dss, "SAMPLE "); + + if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->percent))) + { + const double percentage = + gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton)); + ds_put_c_format (&dss, "%g.", percentage / 100.0); + } + else + { + const gint n_cases = + gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton1)); + const gint from_n_cases = + gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton2)); + + ds_put_c_format (&dss, "%d FROM %d .", n_cases, from_n_cases); + } + + } + else if ( gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON (scd->radiobutton_range))) + { + ds_put_c_format (&dss, + "COMPUTE filter_$ = ($CASENUM >= %ld " + "AND $CASENUM <= %ld).\n", + (long) gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->first)), + (long) gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->last))); + ds_put_cstr (&dss, "EXECUTE.\n"); + ds_put_c_format (&dss, "SELECT IF filter_$.\n"); + + } + else if (gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON (scd->radiobutton_filter_variable))) + { + ds_put_c_format (&dss, "SELECT IF (%s <> 0).", + gtk_entry_get_text (GTK_ENTRY (scd->entry))); + } + + + ds_put_cstr (&dss, "\n"); + + text = ds_steal_cstr (&dss); + + ds_destroy (&dss); + + return text; +} + + +static gchar * +generate_syntax (PsppireDialogAction *a) +{ + PsppireDialogActionSelect *scd = PSPPIRE_DIALOG_ACTION_SELECT (a); + + /* In the simple case, all we need to do is cancel any existing filter */ + if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->radiobutton_all))) + { + return g_strdup ("FILTER OFF.\n"); + } + + /* Are we filtering or deleting ? */ + if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->radiobutton_delete))) + { + return generate_syntax_delete (a); + } + else + { + return generate_syntax_filter (a); + } +} + + +static void +psppire_dialog_action_select_class_init (PsppireDialogActionSelectClass *class) +{ + psppire_dialog_action_set_activation (class, psppire_dialog_action_select_activate); + + PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax; +} + + +static void +psppire_dialog_action_select_init (PsppireDialogActionSelect *act) +{ +} + diff --git a/src/ui/gui/psppire-dialog-action-select.h b/src/ui/gui/psppire-dialog-action-select.h new file mode 100644 index 0000000000..3b26593431 --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-select.h @@ -0,0 +1,98 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2015 Free Software Foundation + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include +#include + +#include "psppire-dialog-action.h" + +#ifndef __PSPPIRE_DIALOG_ACTION_SELECT_H__ +#define __PSPPIRE_DIALOG_ACTION_SELECT_H__ + +G_BEGIN_DECLS + + +#define PSPPIRE_TYPE_DIALOG_ACTION_SELECT (psppire_dialog_action_select_get_type ()) + +#define PSPPIRE_DIALOG_ACTION_SELECT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_SELECT, PsppireDialogActionSelect)) + +#define PSPPIRE_DIALOG_ACTION_SELECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + PSPPIRE_TYPE_DIALOG_ACTION_SELECT, \ + PsppireDialogActionSelectClass)) + + +#define PSPPIRE_IS_DIALOG_ACTION_SELECT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_SELECT)) + +#define PSPPIRE_IS_DIALOG_ACTION_SELECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_SELECT)) + + +#define PSPPIRE_DIALOG_ACTION_SELECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_SELECT, \ + PsppireDialogActionSelectClass)) + +typedef struct _PsppireDialogActionSelect PsppireDialogActionSelect; +typedef struct _PsppireDialogActionSelectClass PsppireDialogActionSelectClass; + + +struct _PsppireDialogActionSelect +{ + PsppireDialogAction parent; + + /*< private >*/ + GtkWidget *spinbutton ; + GtkWidget *spinbutton1 ; + GtkWidget *spinbutton2 ; + + GtkWidget *hbox1; + GtkWidget *hbox2; + + GtkWidget *rsample_dialog; + GtkWidget *percent ; + GtkWidget *sample_n_cases ; + GtkWidget *table ; + GtkWidget *l0 ; + GtkWidget *l1 ; + GtkWidget *radiobutton_range ; + GtkWidget *first ; + GtkWidget *last ; + GtkWidget *radiobutton_sample; + GtkWidget *radiobutton_all; + GtkWidget *entry; + GtkWidget *radiobutton_filter_variable; + GtkWidget *radiobutton_delete; + GtkWidget *radiobutton_filter; + GtkWidget *range_subdialog; + +}; + + +struct _PsppireDialogActionSelectClass +{ + PsppireDialogActionClass parent_class; +}; + + +GType psppire_dialog_action_select_get_type (void) ; + +G_END_DECLS + +#endif /* __PSPPIRE_DIALOG_ACTION_SELECT_H__ */ diff --git a/src/ui/gui/select-cases-dialog.c b/src/ui/gui/select-cases-dialog.c deleted file mode 100644 index ea906c2299..0000000000 --- a/src/ui/gui/select-cases-dialog.c +++ /dev/null @@ -1,515 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2007, 2008, 2009, 2010, 2011, 2014, 2015 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include "select-cases-dialog.h" -#include -#include -#include "executor.h" -#include "psppire-dialog.h" -#include "psppire-data-window.h" -#include "psppire-selector.h" -#include "dict-display.h" -#include "dialog-common.h" -#include "widget-io.h" -#include "psppire-scanf.h" -#include "builder-wrapper.h" -#include "helper.h" - -#include - - -#include -#define _(msgid) gettext (msgid) -#define N_(msgid) msgid - - - -/* FIXME: These shouldn't be here */ -#include "psppire-data-store.h" - - -struct select_cases_dialog -{ - GtkWidget *spinbutton ; - GtkWidget *spinbutton1 ; - GtkWidget *spinbutton2 ; - - GtkWidget *hbox1; - GtkWidget *hbox2; - - PsppireDataStore *data_store; - GtkWidget *parent_dialog ; - GtkWidget *dialog ; - GtkWidget *percent ; - GtkWidget *sample_n_cases ; - GtkWidget *table ; - GtkWidget *l0 ; - GtkWidget *l1 ; - GtkWidget *radiobutton_range ; - GtkWidget *first ; - GtkWidget *last ; - GtkWidget *radiobutton_sample; - GtkWidget *radiobutton_all; - GtkWidget *entry; - GtkWidget *radiobutton_filter; - GtkWidget *radiobutton_delete; - GtkWidget *range_subdialog; -}; - -static gchar * generate_syntax (const struct select_cases_dialog *scd); - - -static const gchar label1[] = N_("Approximately %3d%% of all cases."); -static const gchar label2[] = N_("Exactly %3d cases from the first %3d cases."); - - -static void -sample_subdialog (GtkButton *b, gpointer data) -{ - gint response; - struct select_cases_dialog *scd = data; - - gint case_count = psppire_data_store_get_case_count (scd->data_store); - - if ( ! scd->hbox1 ) - { - scd->hbox1 = psppire_scanf_new (gettext (label1), &scd->spinbutton); - - gtk_widget_show (scd->hbox1); - - gtk_grid_attach (GTK_GRID (scd->table), - scd->hbox1, - 1, 0, - 1, 1); - - g_signal_connect (scd->percent, "toggled", - G_CALLBACK (set_sensitivity_from_toggle), scd->hbox1); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scd->percent), TRUE); - } - - - if ( ! scd->hbox2 ) - { - scd->hbox2 = - psppire_scanf_new (gettext (label2), &scd->spinbutton1, &scd->spinbutton2); - - gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton1), - 1, case_count); - - gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton2), - 1, case_count); - - gtk_widget_show (scd->hbox2); - gtk_widget_set_sensitive (scd->hbox2, FALSE); - - gtk_grid_attach (GTK_GRID (scd->table), - scd->hbox2, - 1, 1, 1, 1); - - g_signal_connect (scd->sample_n_cases, "toggled", - G_CALLBACK (set_sensitivity_from_toggle), scd->hbox2); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scd->sample_n_cases), FALSE); - } - - - gtk_window_set_transient_for (GTK_WINDOW (scd->dialog), - GTK_WINDOW (scd->parent_dialog)); - - response = psppire_dialog_run (PSPPIRE_DIALOG (scd->dialog)); - - if ( response != PSPPIRE_RESPONSE_CONTINUE) - { - g_signal_handlers_disconnect_by_func - (G_OBJECT (scd->percent), - G_CALLBACK (set_sensitivity_from_toggle), - scd->hbox1); - - g_signal_handlers_disconnect_by_func - (G_OBJECT (scd->sample_n_cases), - G_CALLBACK (set_sensitivity_from_toggle), - scd->hbox2); - - gtk_widget_destroy(scd->hbox1); - gtk_widget_destroy(scd->hbox2); - scd->hbox1 = scd->hbox2 = NULL; - } - else - { - gchar *text; - - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->percent))) - { - text = widget_printf (gettext(label1), scd->spinbutton); - gtk_label_set_text (GTK_LABEL (scd->l0), text); - } - else - { - text = - widget_printf (gettext(label2), scd->spinbutton1, scd->spinbutton2); - gtk_label_set_text (GTK_LABEL (scd->l0), text); - - } - g_free (text); - } -} - -static void -range_subdialog (GtkButton *b, gpointer data) -{ - gint response; - struct select_cases_dialog *scd = data; - - gint n_cases = psppire_data_store_get_case_count (scd->data_store); - - gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->last), 1, n_cases); - gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->first), 1, n_cases); - - gtk_window_set_transient_for (GTK_WINDOW (scd->range_subdialog), - GTK_WINDOW (scd->parent_dialog)); - - response = psppire_dialog_run (PSPPIRE_DIALOG (scd->range_subdialog)); - if ( response == PSPPIRE_RESPONSE_CONTINUE) - { - gchar *text = widget_printf (_("%d thru %d"), scd->first, scd->last); - gtk_label_set_text (GTK_LABEL (scd->l1), text); - g_free (text); - } -} - -static void -set_radiobutton (GtkWidget *button, gpointer data) -{ - GtkToggleButton *toggle = data; - gtk_toggle_button_set_active (toggle, TRUE); -} - -/* Pops up the Select Cases dialog box */ -void -select_cases_dialog (PsppireDataWindow *de) -{ - gint response; - struct select_cases_dialog scd = {0,0,0,0,0,0}; - GtkWidget *entry = NULL; - GtkWidget *selector ; - - GtkBuilder *xml = builder_new ("select-cases.ui"); - - g_object_get (de->data_editor, "data-store", &scd.data_store, NULL); - - GtkWidget - *button_range = get_widget_assert (xml, "button-range"); - GtkWidget * - button_sample = get_widget_assert (xml, "button-sample"); - scd.entry = get_widget_assert (xml, "filter-variable-entry"); - selector = get_widget_assert (xml, "psppire-selector-filter"); - - scd.parent_dialog = get_widget_assert (xml, "select-cases-dialog"); - scd.dialog = get_widget_assert (xml, "select-cases-random-sample-dialog"); - scd.percent = get_widget_assert (xml, "radiobutton-sample-percent"); - scd.sample_n_cases = get_widget_assert (xml, "radiobutton-sample-n-cases"); - scd.table = get_widget_assert (xml, "select-cases-random-sample-table"); - - scd.l0 = get_widget_assert (xml, "random-sample-label");; - - scd.radiobutton_range = get_widget_assert (xml, "radiobutton-range"); - scd.range_subdialog = get_widget_assert (xml, "select-cases-range-dialog"); - - scd.first = get_widget_assert (xml, "range-dialog-first"); - scd.last = get_widget_assert (xml, "range-dialog-last"); - - scd.l1 = get_widget_assert (xml, "range-sample-label"); - scd.radiobutton_sample = get_widget_assert (xml, "radiobutton-sample"); - - scd.radiobutton_all = get_widget_assert (xml, "radiobutton-all"); - scd.radiobutton_filter = get_widget_assert (xml, "radiobutton-filter-variable"); - scd.radiobutton_delete = get_widget_assert (xml, "radiobutton-delete"); - - { - GtkWidget *button_if = - get_widget_assert (xml, "button-if"); - - GtkWidget *radiobutton_if = - get_widget_assert (xml, "radiobutton-if"); - - GtkWidget *sample_label = - get_widget_assert (xml, "random-sample-label"); - - g_signal_connect (scd.radiobutton_all, "toggled", - G_CALLBACK (set_sensitivity_from_toggle_invert), - get_widget_assert (xml, "filter-delete-button-box") - ); - - g_signal_connect (button_if, "clicked", - G_CALLBACK (set_radiobutton), radiobutton_if); - - g_signal_connect (button_sample, "clicked", - G_CALLBACK (set_radiobutton), scd.radiobutton_sample); - - g_signal_connect (button_range, "clicked", - G_CALLBACK (set_radiobutton), scd.radiobutton_range); - - g_signal_connect (selector, "clicked", - G_CALLBACK (set_radiobutton), scd.radiobutton_filter); - - g_signal_connect (selector, "selected", - G_CALLBACK (set_radiobutton), scd.radiobutton_filter); - - g_signal_connect (scd.radiobutton_range, "toggled", - G_CALLBACK (set_sensitivity_from_toggle), - scd.l1); - - g_signal_connect (scd.radiobutton_sample, "toggled", - G_CALLBACK (set_sensitivity_from_toggle), - sample_label); - - g_signal_connect (scd.radiobutton_filter, "toggled", - G_CALLBACK (set_sensitivity_from_toggle), - entry); - } - - - - GtkWidget *dialog = get_widget_assert (xml, "select-cases-dialog"); - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de)); - - { - GtkWidget *source = get_widget_assert (xml, "select-cases-treeview"); - - g_object_set (source, "model", - scd.data_store->dict, - "selection-mode", - GTK_SELECTION_SINGLE, NULL); - - psppire_selector_set_filter_func (PSPPIRE_SELECTOR (selector), - is_currently_in_entry); - } - - g_signal_connect (button_range, - "clicked", G_CALLBACK (range_subdialog), &scd); - - - g_signal_connect (button_sample, - "clicked", G_CALLBACK (sample_subdialog), &scd); - - - response = psppire_dialog_run (PSPPIRE_DIALOG (dialog)); - - switch (response) - { - case GTK_RESPONSE_OK: - g_free (execute_syntax_string (de, generate_syntax (&scd))); - break; - case PSPPIRE_RESPONSE_PASTE: - g_free (paste_syntax_to_window (generate_syntax (&scd))); - break; - default: - break; - } - - g_object_unref (xml); -} - - -static gchar * -generate_syntax_filter (const struct select_cases_dialog *scd) -{ - gchar *text = NULL; - struct string dss; - - const gchar *filter = "filter_$"; - const gchar key[]="case_$"; - - ds_init_empty (&dss); - - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON (scd->radiobutton_range))) - { - ds_put_c_format (&dss, - "COMPUTE filter_$ = ($CASENUM >= %ld " - "AND $CASENUM <= %ld).\n", - (long) gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->first)), - (long) gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->last))); - - ds_put_cstr (&dss, "EXECUTE.\n"); - } - else if ( gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON (scd->radiobutton_sample))) - { - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->percent))) - { - const double percentage = - gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton)); - - ds_put_c_format (&dss, - "COMPUTE %s = RV.UNIFORM (0,1) < %.*g.\n", - filter, - DBL_DIG + 1, percentage / 100.0 ); - } - else - { - const gint n_cases = - gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton1)); - const gint from_n_cases = - gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton2)); - - - const gchar ranvar[]="rv_$"; - - ds_put_c_format (&dss, - "COMPUTE %s = $CASENUM.\n", key); - - ds_put_c_format (&dss, - "COMPUTE %s = %s > %d.\n", - filter, key, from_n_cases); - - ds_put_c_format (&dss, - "COMPUTE %s = RV.UNIFORM (0, 1).\n", - ranvar); - - ds_put_c_format (&dss, - "SORT BY %s, %s.\n", - filter, ranvar); - - ds_put_cstr (&dss, "EXECUTE.\n"); - - - ds_put_c_format (&dss, - "COMPUTE %s = $CASENUM.\n", - filter ); - - ds_put_c_format (&dss, - "COMPUTE %s = %s <= %d\n", - filter, - filter, - n_cases ); - - ds_put_cstr (&dss, "EXECUTE.\n"); - - - ds_put_c_format (&dss, - "SORT BY %s.\n", - key); - - ds_put_c_format (&dss, - "DELETE VARIABLES %s, %s.\n", - key, ranvar); - } - - ds_put_cstr (&dss, "EXECUTE.\n"); - } - else - { - filter = gtk_entry_get_text (GTK_ENTRY (scd->entry)); - } - - ds_put_c_format (&dss, "FILTER BY %s.\n", filter); - - text = ds_steal_cstr (&dss); - - ds_destroy (&dss); - - return text; -} - -static gchar * -generate_syntax_delete (const struct select_cases_dialog *scd) -{ - gchar *text = NULL; - struct string dss; - - if ( gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON (scd->radiobutton_all))) - { - return xstrdup ("\n"); - } - - ds_init_empty (&dss); - - if ( gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON (scd->radiobutton_sample))) - { - ds_put_cstr (&dss, "SAMPLE "); - - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->percent))) - { - const double percentage = - gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton)); - ds_put_c_format (&dss, "%g.", percentage / 100.0); - } - else - { - const gint n_cases = - gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton1)); - const gint from_n_cases = - gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton2)); - - ds_put_c_format (&dss, "%d FROM %d .", n_cases, from_n_cases); - } - - } - else if ( gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON (scd->radiobutton_range))) - { - ds_put_c_format (&dss, - "COMPUTE filter_$ = ($CASENUM >= %ld " - "AND $CASENUM <= %ld).\n", - (long) gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->first)), - (long) gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->last))); - ds_put_cstr (&dss, "EXECUTE.\n"); - ds_put_c_format (&dss, "SELECT IF filter_$.\n"); - - } - else if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON (scd->radiobutton_filter))) - { - ds_put_c_format (&dss, "SELECT IF (%s <> 0).", - gtk_entry_get_text (GTK_ENTRY (scd->entry))); - } - - - ds_put_cstr (&dss, "\n"); - - text = ds_steal_cstr (&dss); - - ds_destroy (&dss); - - return text; -} - - -static gchar * -generate_syntax (const struct select_cases_dialog *scd) -{ - /* In the simple case, all we need to do is cancel any existing filter */ - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->radiobutton_all))) - { - return g_strdup ("FILTER OFF.\n"); - } - - /* Are we filtering or deleting ? */ - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->radiobutton_delete))) - { - return generate_syntax_delete (scd); - } - else - { - return generate_syntax_filter (scd); - } -} diff --git a/src/ui/gui/select-cases-dialog.h b/src/ui/gui/select-cases-dialog.h deleted file mode 100644 index fa21d0176d..0000000000 --- a/src/ui/gui/select-cases-dialog.h +++ /dev/null @@ -1,25 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef __SELECT_CASES_DIALOG_H -#define __SELECT_CASES_DIALOG_H - - -#include "psppire-data-window.h" - -void select_cases_dialog (PsppireDataWindow * data); - -#endif diff --git a/src/ui/gui/widgets.c b/src/ui/gui/widgets.c index 9ed9beb307..78e67382da 100644 --- a/src/ui/gui/widgets.c +++ b/src/ui/gui/widgets.c @@ -47,6 +47,7 @@ #include "psppire-dialog-action-roc.h" #include "psppire-dialog-action-runs.h" #include "psppire-dialog-action-scatterplot.h" +#include "psppire-dialog-action-select.h" #include "psppire-dialog-action-sort.h" #include "psppire-dialog-action-split.h" #include "psppire-dialog-action-tt1s.h" @@ -94,6 +95,7 @@ static const get_type_func dialog_action_types[]= psppire_dialog_action_roc_get_type, psppire_dialog_action_runs_get_type, psppire_dialog_action_scatterplot_get_type, + psppire_dialog_action_select_get_type, psppire_dialog_action_sort_get_type, psppire_dialog_action_split_get_type, psppire_dialog_action_tt1s_get_type,