X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fpsppire-dialog-action-select.c;h=5ee493a45f7fa79190c1daba34f975bcece675a4;hb=65d602ed236d685ffec00ad1552a193cf47b2e4d;hp=d3eee6570dcf242ff19516122ce52d9c597c0956;hpb=469b69a6df92b30f18a4a5c7262d9290601a0a88;p=pspp diff --git a/src/ui/gui/psppire-dialog-action-select.c b/src/ui/gui/psppire-dialog-action-select.c index d3eee6570d..5ee493a45f 100644 --- a/src/ui/gui/psppire-dialog-action-select.c +++ b/src/ui/gui/psppire-dialog-action-select.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2007, 2008, 2009, 2010, 2011, 2014, 2015 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2009, 2010, 2011, 2014, 2015, 2020 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 @@ -47,6 +47,18 @@ G_DEFINE_TYPE (PsppireDialogActionSelect, psppire_dialog_action_select, PSPPIRE_ static gboolean dialog_state_valid (gpointer data) { + PsppireDialogActionSelect *act = PSPPIRE_DIALOG_ACTION_SELECT (data); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->radiobutton_all))) + { + return TRUE; + } + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->radiobutton_filter_variable))) + { + const gchar *text = gtk_entry_get_text (GTK_ENTRY (act->entry)); + if (!psppire_dict_lookup_var (PSPPIRE_DIALOG_ACTION (act)->dict, text)) + return FALSE; + } + return TRUE; } @@ -77,6 +89,23 @@ static const gchar label1[] = N_("Approximately %3d%% of all cases."); static const gchar label2[] = N_("Exactly %3d cases from the first %3d cases."); +/* Ensure that the range "first" and "last" spinbuttons are self consistent */ +static void +sample_consistent (GtkSpinButton *spin, PsppireDialogActionSelect *act) +{ + gdouble size = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->spin_sample_size)); + gdouble limit = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->spin_sample_limit)); + + if (limit < size) + { + if (spin == GTK_SPIN_BUTTON (act->spin_sample_size)) + gtk_spin_button_set_value (GTK_SPIN_BUTTON (act->spin_sample_limit), size); + if (spin == GTK_SPIN_BUTTON (act->spin_sample_limit)) + gtk_spin_button_set_value (GTK_SPIN_BUTTON (act->spin_sample_size), limit); + } +} + + static void sample_subdialog (GtkButton *b, gpointer data) { @@ -112,14 +141,18 @@ sample_subdialog (GtkButton *b, gpointer data) if (!scd->hbox2) { scd->hbox2 = - psppire_scanf_new (gettext (label2), &scd->spinbutton1, &scd->spinbutton2); + psppire_scanf_new (gettext (label2), &scd->spin_sample_size, &scd->spin_sample_limit); - gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton1), + gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spin_sample_size), 1, case_count); - gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton2), + gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spin_sample_limit), 1, case_count); + g_signal_connect (scd->spin_sample_size, "value-changed", G_CALLBACK (sample_consistent), scd); + g_signal_connect (scd->spin_sample_limit, "value-changed", G_CALLBACK (sample_consistent), scd); + + gtk_widget_show (scd->hbox2); gtk_widget_set_sensitive (scd->hbox2, FALSE); @@ -139,7 +172,7 @@ sample_subdialog (GtkButton *b, gpointer data) response = psppire_dialog_run (PSPPIRE_DIALOG (scd->rsample_dialog)); - if ( response != PSPPIRE_RESPONSE_CONTINUE) + if (response != PSPPIRE_RESPONSE_CONTINUE) { g_signal_handlers_disconnect_by_func (G_OBJECT (scd->percent), @@ -159,7 +192,7 @@ sample_subdialog (GtkButton *b, gpointer data) { gchar *text; - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->percent))) + 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); @@ -167,7 +200,7 @@ sample_subdialog (GtkButton *b, gpointer data) else { text = - widget_printf (gettext(label2), scd->spinbutton1, scd->spinbutton2); + widget_printf (gettext(label2), scd->spin_sample_size, scd->spin_sample_limit); gtk_label_set_text (GTK_LABEL (scd->l0), text); } @@ -198,7 +231,7 @@ range_subdialog (GtkButton *b, gpointer data) GTK_WINDOW (pda->dialog)); response = psppire_dialog_run (PSPPIRE_DIALOG (scd->range_subdialog)); - if ( response == PSPPIRE_RESPONSE_CONTINUE) + 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); @@ -206,116 +239,140 @@ range_subdialog (GtkButton *b, gpointer data) } } - +/* Ensure that the range "first" and "last" spinbuttons are self consistent */ static void -psppire_dialog_action_select_activate (PsppireDialogAction *a) +consistency (GtkSpinButton *spin, PsppireDialogActionSelect *act) +{ + gdouble first = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->first)); + gdouble last = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->last)); + + if (last < first) + { + if (spin == GTK_SPIN_BUTTON (act->first)) + gtk_spin_button_set_value (GTK_SPIN_BUTTON (act->last), first); + if (spin == GTK_SPIN_BUTTON (act->last)) + gtk_spin_button_set_value (GTK_SPIN_BUTTON (act->first), last); + } +} + + +/* When the all cases label button is clicked, set the corresponding button + to active. This is a convenience thing, since the button itself has + a very small area and is hard to find with the mouse pointer. */ +static gboolean +on_button_release (GtkWidget *w, GdkEvent *e, gpointer a) +{ + PsppireDialogActionSelect *act = PSPPIRE_DIALOG_ACTION_SELECT (a); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (act->radiobutton_all), TRUE); + + return FALSE; +} + +static GtkBuilder * +psppire_dialog_action_select_activate (PsppireDialogAction *a, GVariant *param) { 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); + GtkBuilder *xml = builder_new ("select-cases.ui"); + pda->dialog = get_widget_assert (xml, "select-cases-dialog"); + pda->source = get_widget_assert (xml, "select-cases-treeview"); - 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); - g_object_set (pda->source, - "selection-mode", GTK_SELECTION_SINGLE, - NULL); - - act->entry = get_widget_assert (xml, "filter-variable-entry"); + 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); + 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->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->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->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->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"); + g_signal_connect (act->first, "value-changed", G_CALLBACK (consistency), act); + g_signal_connect (act->last, "value-changed", G_CALLBACK (consistency), act); - act->radiobutton_all = get_widget_assert (xml, "radiobutton-all"); - act->radiobutton_filter_variable = get_widget_assert (xml, "radiobutton-filter-variable"); + act->l1 = get_widget_assert (xml, "range-sample-label"); + act->radiobutton_sample = get_widget_assert (xml, "radiobutton-sample"); - act->radiobutton_filter = get_widget_assert (xml, "radiobutton-filter"); - act->radiobutton_delete = get_widget_assert (xml, "radiobutton-delete"); + 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 *all_cases_event = get_widget_assert (xml, "all-cases-event"); + g_signal_connect (all_cases_event, "button-release-event", G_CALLBACK (on_button_release), act); - GtkWidget *button_if =get_widget_assert (xml, "button-if"); + GtkWidget *button_range = get_widget_assert (xml, "button-range"); + GtkWidget *button_sample = get_widget_assert (xml, "button-sample"); - GtkWidget *radiobutton_if = get_widget_assert (xml, "radiobutton-if"); + GtkWidget *button_if =get_widget_assert (xml, "button-if"); - GtkWidget *sample_label = get_widget_assert (xml, "random-sample-label"); + GtkWidget *radiobutton_if = get_widget_assert (xml, "radiobutton-if"); - g_signal_connect (act->radiobutton_all, "toggled", - G_CALLBACK (set_sensitivity_from_toggle_invert), - get_widget_assert (xml, "filter-delete-button-box")); + GtkWidget *sample_label = get_widget_assert (xml, "random-sample-label"); - g_signal_connect (button_if, "clicked", - G_CALLBACK (set_radiobutton), radiobutton_if); + 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_sample, "clicked", - G_CALLBACK (set_radiobutton), act->radiobutton_sample); + g_signal_connect (button_if, "clicked", + G_CALLBACK (set_radiobutton), radiobutton_if); - g_signal_connect (button_range, "clicked", - G_CALLBACK (set_radiobutton), act->radiobutton_range); + g_signal_connect (button_sample, "clicked", + G_CALLBACK (set_radiobutton), act->radiobutton_sample); - g_signal_connect (selector, "clicked", - G_CALLBACK (set_radiobutton), act->radiobutton_filter_variable); + g_signal_connect (button_range, "clicked", + G_CALLBACK (set_radiobutton), act->radiobutton_range); - g_signal_connect (selector, "selected", - G_CALLBACK (set_radiobutton), act->radiobutton_filter_variable); + g_signal_connect (selector, "clicked", + 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 (selector, "selected", + G_CALLBACK (set_radiobutton), act->radiobutton_filter_variable); - g_signal_connect (act->radiobutton_sample, "toggled", - G_CALLBACK (set_sensitivity_from_toggle), - sample_label); + g_signal_connect (act->radiobutton_range, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), + act->l1); - g_signal_connect (act->radiobutton_filter_variable, "toggled", - G_CALLBACK (set_sensitivity_from_toggle), - act->entry); + g_signal_connect (act->radiobutton_sample, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), + sample_label); - g_signal_connect (button_range, - "clicked", G_CALLBACK (range_subdialog), act); + g_signal_connect (act->radiobutton_filter_variable, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), + act->entry); - g_signal_connect (button_sample, - "clicked", G_CALLBACK (sample_subdialog), act); - } + 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); + dialog_state_valid); + return xml; } static char * -generate_syntax_filter (PsppireDialogAction *a) +generate_syntax_filter (const PsppireDialogAction *a) { PsppireDialogActionSelect *scd = PSPPIRE_DIALOG_ACTION_SELECT (a); @@ -338,10 +395,10 @@ generate_syntax_filter (PsppireDialogAction *a) ds_put_cstr (&dss, "EXECUTE.\n"); } - else if ( gtk_toggle_button_get_active + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->radiobutton_sample))) { - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->percent))) + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->percent))) { const double percentage = gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton)); @@ -349,14 +406,14 @@ generate_syntax_filter (PsppireDialogAction *a) ds_put_c_format (&dss, "COMPUTE %s = RV.UNIFORM (0,1) < %.*g.\n", filter, - DBL_DIG + 1, percentage / 100.0 ); + DBL_DIG + 1, percentage / 100.0); } else { const gint n_cases = - gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton1)); + gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spin_sample_size)); const gint from_n_cases = - gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton2)); + gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spin_sample_limit)); const gchar ranvar[]="rv_$"; @@ -373,27 +430,27 @@ generate_syntax_filter (PsppireDialogAction *a) ranvar); ds_put_c_format (&dss, - "SORT BY %s, %s.\n", + "SORT CASES BY %s, %s.\n", filter, ranvar); ds_put_cstr (&dss, "EXECUTE.\n"); - + ds_put_c_format (&dss, "COMPUTE %s = $CASENUM.\n", - filter ); + filter); ds_put_c_format (&dss, "COMPUTE %s = %s <= %d\n", filter, filter, - n_cases ); + n_cases); ds_put_cstr (&dss, "EXECUTE.\n"); ds_put_c_format (&dss, - "SORT BY %s.\n", + "SORT CASES BY %s.\n", key); ds_put_c_format (&dss, @@ -419,13 +476,13 @@ generate_syntax_filter (PsppireDialogAction *a) static gchar * -generate_syntax_delete (PsppireDialogAction *a) +generate_syntax_delete (const PsppireDialogAction *a) { PsppireDialogActionSelect *scd = PSPPIRE_DIALOG_ACTION_SELECT (a); gchar *text = NULL; struct string dss; - if ( gtk_toggle_button_get_active + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->radiobutton_all))) { return xstrdup ("\n"); @@ -433,12 +490,12 @@ generate_syntax_delete (PsppireDialogAction *a) ds_init_empty (&dss); - if ( gtk_toggle_button_get_active + 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))) + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->percent))) { const double percentage = gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton)); @@ -447,15 +504,15 @@ generate_syntax_delete (PsppireDialogAction *a) else { const gint n_cases = - gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton1)); + gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spin_sample_size)); const gint from_n_cases = - gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton2)); - + gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spin_sample_limit)); + ds_put_c_format (&dss, "%d FROM %d .", n_cases, from_n_cases); } - + } - else if ( gtk_toggle_button_get_active + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->radiobutton_range))) { ds_put_c_format (&dss, @@ -486,18 +543,18 @@ generate_syntax_delete (PsppireDialogAction *a) static gchar * -generate_syntax (PsppireDialogAction *a) +generate_syntax (const 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))) + 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))) + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->radiobutton_delete))) { return generate_syntax_delete (a); } @@ -511,7 +568,7 @@ generate_syntax (PsppireDialogAction *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)->initial_activate = psppire_dialog_action_select_activate; PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax; }