From: John Darrington Date: Sat, 24 Nov 2012 15:29:39 +0000 (+0100) Subject: Frequencies dialog: Convert to new system X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=39a8ab70a29700e1b0c943c5e8a6856b18f0b951;p=pspp Frequencies dialog: Convert to new system --- diff --git a/src/ui/gui/automake.mk b/src/ui/gui/automake.mk index 2c6427a255..d9ed78e875 100644 --- a/src/ui/gui/automake.mk +++ b/src/ui/gui/automake.mk @@ -190,8 +190,6 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/executor.h \ src/ui/gui/find-dialog.c \ src/ui/gui/find-dialog.h \ - src/ui/gui/frequencies-dialog.c \ - src/ui/gui/frequencies-dialog.h \ src/ui/gui/goto-case-dialog.c \ src/ui/gui/goto-case-dialog.h \ src/ui/gui/helper.c \ @@ -234,6 +232,8 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/psppire-dialog-action-examine.h \ src/ui/gui/psppire-dialog-action-factor.c \ src/ui/gui/psppire-dialog-action-factor.h \ + src/ui/gui/psppire-dialog-action-frequencies.c \ + src/ui/gui/psppire-dialog-action-frequencies.h \ src/ui/gui/psppire-dialog-action-indep-samps.c \ src/ui/gui/psppire-dialog-action-indep-samps.h \ src/ui/gui/psppire-dialog-action-kmeans.c \ diff --git a/src/ui/gui/data-editor.ui b/src/ui/gui/data-editor.ui index 3408036357..8d948a5b6e 100644 --- a/src/ui/gui/data-editor.ui +++ b/src/ui/gui/data-editor.ui @@ -346,8 +346,9 @@ - - analyze_frequencies + + uimanager1 + frequencies _Frequencies... @@ -624,7 +625,7 @@ - + diff --git a/src/ui/gui/dialog-common.c b/src/ui/gui/dialog-common.c index 416be46f44..9e97923e3f 100644 --- a/src/ui/gui/dialog-common.c +++ b/src/ui/gui/dialog-common.c @@ -176,6 +176,8 @@ set_sensitivity_from_toggle (GtkToggleButton *togglebutton, GtkWidget *w) gboolean active = gtk_toggle_button_get_active (togglebutton); gtk_widget_set_sensitive (w, active); + if (active) + gtk_widget_grab_focus (w); } /* */ diff --git a/src/ui/gui/frequencies-dialog.c b/src/ui/gui/frequencies-dialog.c deleted file mode 100644 index 8db8ddc88b..0000000000 --- a/src/ui/gui/frequencies-dialog.c +++ /dev/null @@ -1,583 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2007, 2010, 2011, 2012 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 "checkbox-treeview.h" -#include "frequencies-dialog.h" -#include "psppire-var-view.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "executor.h" -#include "helper.h" - -#include "gettext.h" -#define _(msgid) gettext (msgid) -#define N_(msgid) msgid - - -#define FREQUENCY_STATS \ - FS (MEAN, N_("Mean")) \ - FS (STDDEV, N_("Standard deviation")) \ - FS (MINIMUM, N_("Minimum")) \ - FS (MAXIMUM, N_("Maximum")) \ - FS (SEMEAN, N_("Standard error of the mean")) \ - FS (VARIANCE, N_("Variance")) \ - FS (SKEWNESS, N_("Skewness")) \ - FS (SESKEW, N_("Standard error of the skewness")) \ - FS (RANGE, N_("Range")) \ - FS (MODE, N_("Mode")) \ - FS (KURTOSIS, N_("Kurtosis")) \ - FS (SEKURT, N_("Standard error of the kurtosis")) \ - FS (MEDIAN, N_("Median")) \ - FS (SUM, N_("Sum")) - -enum - { -#define FS(NAME, LABEL) FS_##NAME, - FREQUENCY_STATS -#undef FS - N_FREQUENCY_STATS - }; - -enum - { -#define FS(NAME, LABEL) B_FS_##NAME = 1u << FS_##NAME, - FREQUENCY_STATS -#undef FS - B_FS_ALL = (1u << N_FREQUENCY_STATS) - 1, - B_FS_DEFAULT = B_FS_MEAN | B_FS_STDDEV | B_FS_MINIMUM | B_FS_MAXIMUM - }; - - -static const struct checkbox_entry_item stats[] = - { -#define FS(NAME, LABEL) {#NAME, LABEL}, - FREQUENCY_STATS -#undef FS - }; - - - -enum frq_order - { - FRQ_AVALUE, - FRQ_DVALUE, - FRQ_ACOUNT, - FRQ_DCOUNT - }; - -enum frq_table - { - FRQ_TABLE, - FRQ_NOTABLE, - FRQ_LIMIT - }; - -struct tables_options -{ - enum frq_order order; - enum frq_table table; - int limit; -}; - -enum frq_scale - { - FRQ_FREQ, - FRQ_PERCENT - }; - -struct charts_options - { - bool use_min; - double min; - bool use_max; - double max; - bool draw_hist; - bool draw_normal; - enum frq_scale scale; - bool draw_pie; - bool pie_include_missing; - }; - -struct frequencies_dialog -{ - /* Main dialog. */ - GtkTreeView *stat_vars; - PsppireDict *dict; - - GtkWidget *tables_button; - GtkWidget *charts_button; - - GtkToggleButton *include_missing; - - GtkTreeModel *stats; - - /* Frequency Tables dialog. */ - GtkWidget *tables_dialog; - struct tables_options tables_opts; - - GtkToggleButton *always; - GtkToggleButton *never; - GtkToggleButton *limit; - GtkSpinButton *limit_spinbutton; - - GtkToggleButton *avalue; - GtkToggleButton *dvalue; - GtkToggleButton *afreq; - GtkToggleButton *dfreq; - - /* Charts dialog. */ - GtkWidget *charts_dialog; - struct charts_options charts_opts; - - GtkToggleButton *freqs; - GtkToggleButton *percents; - - GtkToggleButton *min; - GtkSpinButton *min_spin; - GtkToggleButton *max; - GtkSpinButton *max_spin; - - GtkToggleButton *hist; - GtkToggleButton *normal; - - GtkToggleButton *pie; - GtkToggleButton *pie_include_missing; -}; - -static void -refresh (PsppireDialog *dialog, struct frequencies_dialog *fd) -{ - GtkTreeIter iter; - size_t i; - bool ok; - - GtkTreeModel *liststore = gtk_tree_view_get_model (fd->stat_vars); - gtk_list_store_clear (GTK_LIST_STORE (liststore)); - - for (i = 0, ok = gtk_tree_model_get_iter_first (fd->stats, &iter); ok; - i++, ok = gtk_tree_model_iter_next (fd->stats, &iter)) - gtk_list_store_set (GTK_LIST_STORE (fd->stats), &iter, - CHECKBOX_COLUMN_SELECTED, - (B_FS_DEFAULT & (1u << i)) ? true : false, -1); -} - -static char * -generate_syntax (const struct frequencies_dialog *fd) -{ - GtkTreeIter iter; - gboolean ok; - gint i; - guint selected = 0; - - gchar *text; - GString *string = g_string_new ("FREQUENCIES"); - - g_string_append (string, "\n\t/VARIABLES="); - psppire_var_view_append_names (PSPPIRE_VAR_VIEW (fd->stat_vars), 0, string); - - g_string_append (string, "\n\t/FORMAT="); - - switch (fd->tables_opts.order) - { - case FRQ_AVALUE: - g_string_append (string, "AVALUE"); - break; - case FRQ_DVALUE: - g_string_append (string, "DVALUE"); - break; - case FRQ_ACOUNT: - g_string_append (string, "AFREQ"); - break; - case FRQ_DCOUNT: - g_string_append (string, "DFREQ"); - break; - default: - g_assert_not_reached(); - } - - g_string_append (string, " "); - - switch (fd->tables_opts.table) - { - case FRQ_TABLE: - g_string_append (string, "TABLE"); - break; - case FRQ_NOTABLE: - g_string_append (string, "NOTABLE"); - break; - case FRQ_LIMIT: - g_string_append_printf (string, "LIMIT (%d)", fd->tables_opts.limit); - break; - } - - - for (i = 0, ok = gtk_tree_model_get_iter_first (fd->stats, &iter); ok; - i++, ok = gtk_tree_model_iter_next (fd->stats, &iter)) - { - gboolean toggled; - gtk_tree_model_get (fd->stats, &iter, - CHECKBOX_COLUMN_SELECTED, &toggled, -1); - if (toggled) - selected |= 1u << i; - } - - if (selected != B_FS_DEFAULT) - { - g_string_append (string, "\n\t/STATISTICS="); - if (selected == B_FS_ALL) - g_string_append (string, "ALL"); - else if (selected == 0) - g_string_append (string, "NONE"); - else - { - int n = 0; - if ((selected & B_FS_DEFAULT) == B_FS_DEFAULT) - { - g_string_append (string, "DEFAULT"); - selected &= ~B_FS_DEFAULT; - n++; - } - for (i = 0; i < N_FREQUENCY_STATS; i++) - if (selected & (1u << i)) - { - if (n++) - g_string_append (string, " "); - g_string_append (string, stats[i].name); - } - } - } - - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->include_missing))) - g_string_append (string, "\n\t/MISSING=INCLUDE"); - - if (fd->charts_opts.draw_hist) - { - g_string_append (string, "\n\t/HISTOGRAM="); - g_string_append (string, - fd->charts_opts.draw_normal ? "NORMAL" : "NONORMAL"); - - if (fd->charts_opts.scale == FRQ_PERCENT) - g_string_append (string, " PERCENT"); - - if (fd->charts_opts.use_min) - g_string_append_printf (string, " MIN(%.15g)", fd->charts_opts.min); - if (fd->charts_opts.use_max) - g_string_append_printf (string, " MAX(%.15g)", fd->charts_opts.max); - } - - if (fd->charts_opts.draw_pie) - { - g_string_append (string, "\n\t/PIECHART="); - - if (fd->charts_opts.pie_include_missing) - g_string_append (string, " MISSING"); - - if (fd->charts_opts.use_min) - g_string_append_printf (string, " MIN(%.15g)", fd->charts_opts.min); - if (fd->charts_opts.use_max) - g_string_append_printf (string, " MAX(%.15g)", fd->charts_opts.max); - } - - g_string_append (string, ".\n"); - - text = string->str; - - g_string_free (string, FALSE); - - return text; -} - -/* Dialog is valid iff at least one variable has been selected */ -static gboolean -dialog_state_valid (gpointer data) -{ - struct frequencies_dialog *fd = data; - - GtkTreeModel *vars = gtk_tree_view_get_model (fd->stat_vars); - - GtkTreeIter notused; - - return gtk_tree_model_get_iter_first (vars, ¬used); -} - - -static void -on_tables_clicked (struct frequencies_dialog *fd) -{ - int ret; - - switch (fd->tables_opts.order) - { - case FRQ_AVALUE: - gtk_toggle_button_set_active (fd->avalue, TRUE); - break; - case FRQ_DVALUE: - gtk_toggle_button_set_active (fd->dvalue, TRUE); - break; - case FRQ_ACOUNT: - gtk_toggle_button_set_active (fd->afreq, TRUE); - break; - case FRQ_DCOUNT: - gtk_toggle_button_set_active (fd->dfreq, TRUE); - break; - }; - - switch (fd->tables_opts.table) - { - case FRQ_TABLE: - gtk_toggle_button_set_active (fd->always, TRUE); - break; - case FRQ_NOTABLE: - gtk_toggle_button_set_active (fd->never, TRUE); - break; - case FRQ_LIMIT: - gtk_toggle_button_set_active (fd->limit, TRUE); - break; - } - gtk_spin_button_set_value (fd->limit_spinbutton, - fd->tables_opts.limit); - g_signal_emit_by_name (fd->limit, "toggled"); - - ret = psppire_dialog_run (PSPPIRE_DIALOG (fd->tables_dialog)); - - if ( ret == PSPPIRE_RESPONSE_CONTINUE ) - { - if (gtk_toggle_button_get_active (fd->avalue)) - fd->tables_opts.order = FRQ_AVALUE; - else if (gtk_toggle_button_get_active (fd->dvalue)) - fd->tables_opts.order = FRQ_DVALUE; - else if (gtk_toggle_button_get_active (fd->afreq)) - fd->tables_opts.order = FRQ_ACOUNT; - else if (gtk_toggle_button_get_active (fd->dfreq)) - fd->tables_opts.order = FRQ_DCOUNT; - - if (gtk_toggle_button_get_active (fd->always)) - fd->tables_opts.table = FRQ_TABLE; - else if (gtk_toggle_button_get_active (fd->never)) - fd->tables_opts.table = FRQ_NOTABLE; - else - fd->tables_opts.table = FRQ_LIMIT; - - fd->tables_opts.limit = gtk_spin_button_get_value (fd->limit_spinbutton); - } -} - -static void -on_charts_clicked (struct frequencies_dialog *fd) -{ - int ret; - - gtk_toggle_button_set_active (fd->min, fd->charts_opts.use_min); - gtk_spin_button_set_value (fd->min_spin, fd->charts_opts.min); - g_signal_emit_by_name (fd->min, "toggled"); - - gtk_toggle_button_set_active (fd->max, fd->charts_opts.use_max); - gtk_spin_button_set_value (fd->max_spin, fd->charts_opts.max); - g_signal_emit_by_name (fd->max, "toggled"); - - gtk_toggle_button_set_active (fd->hist, fd->charts_opts.draw_hist); - gtk_toggle_button_set_active (fd->normal, fd->charts_opts.draw_normal); - g_signal_emit_by_name (fd->hist, "toggled"); - - switch (fd->charts_opts.scale) - { - case FRQ_FREQ: - gtk_toggle_button_set_active (fd->freqs, TRUE); - break; - case FRQ_DVALUE: - gtk_toggle_button_set_active (fd->percents, TRUE); - break; - }; - - - gtk_toggle_button_set_active (fd->pie, fd->charts_opts.draw_pie); - gtk_toggle_button_set_active (fd->pie_include_missing, - fd->charts_opts.pie_include_missing); - g_signal_emit_by_name (fd->pie, "toggled"); - - ret = psppire_dialog_run (PSPPIRE_DIALOG (fd->charts_dialog)); - - if ( ret == PSPPIRE_RESPONSE_CONTINUE ) - { - fd->charts_opts.use_min = gtk_toggle_button_get_active (fd->min); - fd->charts_opts.min = gtk_spin_button_get_value (fd->min_spin); - - fd->charts_opts.use_max = gtk_toggle_button_get_active (fd->max); - fd->charts_opts.max = gtk_spin_button_get_value (fd->max_spin); - - fd->charts_opts.draw_hist = gtk_toggle_button_get_active (fd->hist); - fd->charts_opts.draw_normal = gtk_toggle_button_get_active (fd->normal); - if (gtk_toggle_button_get_active (fd->freqs)) - fd->charts_opts.scale = FRQ_FREQ; - else if (gtk_toggle_button_get_active (fd->percents)) - fd->charts_opts.scale = FRQ_PERCENT; - - fd->charts_opts.draw_pie = gtk_toggle_button_get_active (fd->pie); - fd->charts_opts.pie_include_missing - = gtk_toggle_button_get_active (fd->pie_include_missing); - } -} - - -/* Makes widget W's sensitivity follow the active state of TOGGLE */ -static void -sensitive_if_active (GtkToggleButton *toggle, GtkWidget *w) -{ - gboolean active = gtk_toggle_button_get_active (toggle); - - gtk_widget_set_sensitive (w, active); -} - -/* Pops up the Frequencies dialog box */ -void -frequencies_dialog (PsppireDataWindow *de) -{ - gint response; - - struct frequencies_dialog fd; - - GtkBuilder *xml = builder_new ("frequencies.ui"); - - GtkWidget *dialog = get_widget_assert (xml, "frequencies-dialog"); - GtkWidget *source = get_widget_assert (xml, "dict-treeview"); - GtkWidget *dest = get_widget_assert (xml, "var-treeview"); - GtkWidget *tables_button = get_widget_assert (xml, "tables-button"); - GtkWidget *charts_button = get_widget_assert (xml, "charts-button"); - GtkWidget *stats_treeview = get_widget_assert (xml, "stats-treeview"); - - PsppireVarStore *vs = NULL; - - g_object_get (de->data_editor, "var-store", &vs, NULL); - - put_checkbox_items_in_treeview (GTK_TREE_VIEW(stats_treeview), - B_FS_DEFAULT, - N_FREQUENCY_STATS, - stats - ); - - - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de)); - - g_object_get (vs, "dictionary", &fd.dict, NULL); - g_object_set (source, "model", fd.dict, NULL); - - fd.stat_vars = GTK_TREE_VIEW (dest); - fd.tables_button = get_widget_assert (xml, "tables-button"); - fd.charts_button = get_widget_assert (xml, "charts-button"); - - fd.include_missing = GTK_TOGGLE_BUTTON ( - get_widget_assert (xml, "include_missing")); - - fd.stats = gtk_tree_view_get_model (GTK_TREE_VIEW (stats_treeview)); - - /* Frequency Tables dialog. */ - fd.tables_dialog = get_widget_assert (xml, "tables-dialog"); - fd.tables_opts.order = FRQ_AVALUE; - fd.tables_opts.table = FRQ_TABLE; - fd.tables_opts.limit = 50; - - fd.always = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "always")); - fd.never = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "never")); - fd.limit = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "limit")); - fd.limit_spinbutton = - GTK_SPIN_BUTTON (get_widget_assert (xml, "limit-spin")); - g_signal_connect (fd.limit, "toggled", - G_CALLBACK (sensitive_if_active), fd.limit_spinbutton); - - fd.avalue = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "avalue")); - fd.dvalue = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "dvalue")); - fd.afreq = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "afreq")); - fd.dfreq = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "dfreq")); - - gtk_window_set_transient_for (GTK_WINDOW (fd.tables_dialog), - GTK_WINDOW (de)); - - /* Charts dialog. */ - fd.charts_dialog = get_widget_assert (xml, "charts-dialog"); - fd.charts_opts.use_min = false; - fd.charts_opts.min = 0; - fd.charts_opts.use_max = false; - fd.charts_opts.max = 100; - fd.charts_opts.draw_hist = false; - fd.charts_opts.draw_normal = false; - fd.charts_opts.scale = FRQ_FREQ; - fd.charts_opts.draw_pie = false; - fd.charts_opts.pie_include_missing = false; - - fd.freqs = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "freqs")); - fd.percents = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "percents")); - - fd.min = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "min")); - fd.min_spin = GTK_SPIN_BUTTON (get_widget_assert (xml, "min-spin")); - g_signal_connect (fd.min, "toggled", - G_CALLBACK (sensitive_if_active), fd.min_spin); - fd.max = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "max")); - fd.max_spin = GTK_SPIN_BUTTON (get_widget_assert (xml, "max-spin")); - g_signal_connect (fd.max, "toggled", - G_CALLBACK (sensitive_if_active), fd.max_spin); - - fd.hist = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "hist")); - fd.normal = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "normal")); - g_signal_connect (fd.hist, "toggled", - G_CALLBACK (sensitive_if_active), fd.normal); - - fd.pie = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "pie")); - fd.pie_include_missing = GTK_TOGGLE_BUTTON ( - get_widget_assert (xml, "pie-include-missing")); - g_signal_connect (fd.pie, "toggled", - G_CALLBACK (sensitive_if_active), fd.pie_include_missing); - - gtk_window_set_transient_for (GTK_WINDOW (fd.charts_dialog), - GTK_WINDOW (de)); - - /* Main dialog. */ - g_signal_connect (dialog, "refresh", G_CALLBACK (refresh), &fd); - - psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog), - dialog_state_valid, &fd); - - g_signal_connect_swapped (tables_button, "clicked", - G_CALLBACK (on_tables_clicked), &fd); - g_signal_connect_swapped (charts_button, "clicked", - G_CALLBACK (on_charts_clicked), &fd); - - response = psppire_dialog_run (PSPPIRE_DIALOG (dialog)); - - - switch (response) - { - case GTK_RESPONSE_OK: - g_free (execute_syntax_string (de, generate_syntax (&fd))); - break; - case PSPPIRE_RESPONSE_PASTE: - g_free (paste_syntax_to_window (generate_syntax (&fd))); - break; - default: - break; - } - - g_object_unref (xml); -} diff --git a/src/ui/gui/frequencies-dialog.h b/src/ui/gui/frequencies-dialog.h deleted file mode 100644 index 5632ab5e77..0000000000 --- a/src/ui/gui/frequencies-dialog.h +++ /dev/null @@ -1,24 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2007, 2010 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 . */ - -#ifndef __FREQUENCIES_DIALOG_H -#define __FREQUENCIES_DIALOG_H - -#include "psppire-data-window.h" - -void frequencies_dialog (PsppireDataWindow * data); - -#endif diff --git a/src/ui/gui/psppire-data-window.c b/src/ui/gui/psppire-data-window.c index ea3ec43d1f..a2cfcbbffc 100644 --- a/src/ui/gui/psppire-data-window.c +++ b/src/ui/gui/psppire-data-window.c @@ -35,7 +35,6 @@ #include "ui/gui/entry-dialog.h" #include "ui/gui/executor.h" #include "ui/gui/find-dialog.h" -#include "ui/gui/frequencies-dialog.h" #include "ui/gui/goto-case-dialog.h" #include "ui/gui/help-menu.h" #include "ui/gui/helper.h" @@ -1071,7 +1070,6 @@ psppire_data_window_finish_init (PsppireDataWindow *de, connect_action (de, "transform_count", G_CALLBACK (count_dialog)); connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog)); connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog)); - connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog)); connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog)); connect_action (de, "univariate", G_CALLBACK (univariate_dialog)); connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog)); diff --git a/src/ui/gui/psppire-dialog-action-frequencies.c b/src/ui/gui/psppire-dialog-action-frequencies.c new file mode 100644 index 0000000000..b2ddd196a3 --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-frequencies.c @@ -0,0 +1,486 @@ +/* PSPPIRE - a graphical user interface for PSPP. +Copyright (C) 2012 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 "psppire-dialog-action-frequencies.h" +#include "psppire-value-entry.h" + +#include "dialog-common.h" +#include "helper.h" +#include +#include "psppire-var-view.h" + +#include "psppire-dialog.h" +#include "builder-wrapper.h" +#include "checkbox-treeview.h" +#include "psppire-dict.h" +#include "libpspp/str.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + + +#define FREQUENCY_STATS \ + FS (MEAN, N_("Mean")) \ + FS (STDDEV, N_("Standard deviation")) \ + FS (MINIMUM, N_("Minimum")) \ + FS (MAXIMUM, N_("Maximum")) \ + FS (SEMEAN, N_("Standard error of the mean")) \ + FS (VARIANCE, N_("Variance")) \ + FS (SKEWNESS, N_("Skewness")) \ + FS (SESKEW, N_("Standard error of the skewness")) \ + FS (RANGE, N_("Range")) \ + FS (MODE, N_("Mode")) \ + FS (KURTOSIS, N_("Kurtosis")) \ + FS (SEKURT, N_("Standard error of the kurtosis")) \ + FS (MEDIAN, N_("Median")) \ + FS (SUM, N_("Sum")) + + + +enum +{ +#define FS(NAME, LABEL) FS_##NAME, + FREQUENCY_STATS +#undef FS + N_FREQUENCY_STATS +}; + +enum +{ +#define FS(NAME, LABEL) B_FS_##NAME = 1u << FS_##NAME, + FREQUENCY_STATS +#undef FS + B_FS_ALL = (1u << N_FREQUENCY_STATS) - 1, + B_FS_DEFAULT = B_FS_MEAN | B_FS_STDDEV | B_FS_MINIMUM | B_FS_MAXIMUM +}; + + +static const struct checkbox_entry_item stats[] = { +#define FS(NAME, LABEL) {#NAME, LABEL}, + FREQUENCY_STATS +#undef FS +}; + + +static void +on_tables_clicked (PsppireDialogActionFrequencies * fd) +{ + int ret; + + switch (fd->tables_opts_order) + { + case FRQ_AVALUE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->avalue), TRUE); + break; + case FRQ_DVALUE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->dvalue), TRUE); + break; + case FRQ_ACOUNT: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->afreq), TRUE); + break; + case FRQ_DCOUNT: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->dfreq), TRUE); + break; + }; + + switch (fd->tables_opts_table) + { + case FRQ_TABLE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->always), TRUE); + break; + case FRQ_NOTABLE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->never), TRUE); + break; + case FRQ_LIMIT: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->limit), TRUE); + break; + } + + gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->limit_spinbutton), + fd->tables_opts_limit); + + g_signal_emit_by_name (fd->limit, "toggled"); + + ret = psppire_dialog_run (PSPPIRE_DIALOG (fd->tables_dialog)); + + if (ret == PSPPIRE_RESPONSE_CONTINUE) + { + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->avalue))) + fd->tables_opts_order = FRQ_AVALUE; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->dvalue))) + fd->tables_opts_order = FRQ_DVALUE; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->afreq))) + fd->tables_opts_order = FRQ_ACOUNT; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->dfreq))) + fd->tables_opts_order = FRQ_DCOUNT; + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->always))) + fd->tables_opts_table = FRQ_TABLE; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->never))) + fd->tables_opts_table = FRQ_NOTABLE; + else + fd->tables_opts_table = FRQ_LIMIT; + + + fd->tables_opts_limit = + gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->limit_spinbutton)); + } +} + + +static void +on_charts_clicked (PsppireDialogActionFrequencies *fd) +{ + int ret; + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->min), fd->charts_opts_use_min); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->min_spin), fd->charts_opts_min); + g_signal_emit_by_name (fd->min, "toggled"); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->max), fd->charts_opts_use_max); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->max_spin), fd->charts_opts_max); + g_signal_emit_by_name (fd->max, "toggled"); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->hist), fd->charts_opts_draw_hist); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->normal), fd->charts_opts_draw_normal); + g_signal_emit_by_name (fd->hist, "toggled"); + + switch (fd->charts_opts_scale) + { + case FRQ_FREQ: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->freqs), TRUE); + break; + case FRQ_DVALUE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->percents), TRUE); + break; + }; + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->pie), fd->charts_opts_draw_pie); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->pie_include_missing), + fd->charts_opts_pie_include_missing); + + g_signal_emit_by_name (fd->pie, "toggled"); + + ret = psppire_dialog_run (PSPPIRE_DIALOG (fd->charts_dialog)); + + if ( ret == PSPPIRE_RESPONSE_CONTINUE ) + { + fd->charts_opts_use_min = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->min)); + fd->charts_opts_min = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->min_spin)); + + fd->charts_opts_use_max = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->max)); + fd->charts_opts_max = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->max_spin)); + + fd->charts_opts_draw_hist = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->hist)); + fd->charts_opts_draw_normal = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->normal)); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->freqs))) + fd->charts_opts_scale = FRQ_FREQ; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->percents))) + fd->charts_opts_scale = FRQ_PERCENT; + + fd->charts_opts_draw_pie = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->pie)); + fd->charts_opts_pie_include_missing + = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->pie_include_missing)); + } +} + + +static void +psppire_dialog_action_frequencies_class_init +(PsppireDialogActionFrequenciesClass * class); + +G_DEFINE_TYPE (PsppireDialogActionFrequencies, + psppire_dialog_action_frequencies, PSPPIRE_TYPE_DIALOG_ACTION); + +static gboolean +dialog_state_valid (gpointer data) +{ + PsppireDialogActionFrequencies *fd = + PSPPIRE_DIALOG_ACTION_FREQUENCIES (data); + + GtkTreeModel *vars = + gtk_tree_view_get_model (GTK_TREE_VIEW (fd->stat_vars)); + + GtkTreeIter notused; + + return gtk_tree_model_get_iter_first (vars, ¬used); +} + +static void +refresh (PsppireDialogAction * fdx) +{ + PsppireDialogActionFrequencies *fd = + PSPPIRE_DIALOG_ACTION_FREQUENCIES (fdx); + + GtkTreeIter iter; + size_t i; + bool ok; + + GtkTreeModel *liststore = + gtk_tree_view_get_model (GTK_TREE_VIEW (fd->stat_vars)); + gtk_list_store_clear (GTK_LIST_STORE (liststore)); + + for (i = 0, ok = gtk_tree_model_get_iter_first (fd->stats, &iter); ok; + i++, ok = gtk_tree_model_iter_next (fd->stats, &iter)) + gtk_list_store_set (GTK_LIST_STORE (fd->stats), &iter, + CHECKBOX_COLUMN_SELECTED, + (B_FS_DEFAULT & (1u << i)) ? true : false, -1); +} + + + +static void +psppire_dialog_action_frequencies_activate (GtkAction * a) +{ + PsppireDialogActionFrequencies *act = PSPPIRE_DIALOG_ACTION_FREQUENCIES (a); + PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a); + + GtkBuilder *xml = builder_new ("frequencies.ui"); + + GtkWidget *stats_treeview = get_widget_assert (xml, "stats-treeview"); + GtkWidget *tables_button = get_widget_assert (xml, "tables-button"); + GtkWidget *charts_button = get_widget_assert (xml, "charts-button"); + + pda->dialog = get_widget_assert (xml, "frequencies-dialog"); + pda->source = get_widget_assert (xml, "dict-treeview"); + + act->stat_vars = get_widget_assert (xml, "var-treeview"); + + put_checkbox_items_in_treeview (GTK_TREE_VIEW (stats_treeview), + B_FS_DEFAULT, N_FREQUENCY_STATS, stats); + + act->stats = gtk_tree_view_get_model (GTK_TREE_VIEW (stats_treeview)); + + act->include_missing = get_widget_assert (xml, "include_missing"); + + + act->tables_dialog = get_widget_assert (xml, "tables-dialog"); + act->charts_dialog = get_widget_assert (xml, "charts-dialog"); + act->always = get_widget_assert (xml, "always"); + act->never = get_widget_assert (xml, "never"); + act->limit = get_widget_assert (xml, "limit"); + act->limit_spinbutton = get_widget_assert (xml, "limit-spin"); + + g_signal_connect (act->limit, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), + act->limit_spinbutton); + + act->avalue = get_widget_assert (xml, "avalue"); + act->dvalue = get_widget_assert (xml, "dvalue"); + act->afreq = get_widget_assert (xml, "afreq"); + act->dfreq = get_widget_assert (xml, "dfreq"); + + act->charts_opts_use_min = false; + act->charts_opts_min = 0; + act->charts_opts_use_max = false; + act->charts_opts_max = 100; + act->charts_opts_draw_hist = false; + act->charts_opts_draw_normal = false; + act->charts_opts_scale = FRQ_FREQ; + act->charts_opts_draw_pie = false; + act->charts_opts_pie_include_missing = false; + + act->freqs = get_widget_assert (xml, "freqs"); + act->percents = get_widget_assert (xml, "percents"); + + act->min = get_widget_assert (xml, "min"); + act->min_spin = get_widget_assert (xml, "min-spin"); + g_signal_connect (act->min, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), act->min_spin); + act->max = get_widget_assert (xml, "max"); + act->max_spin = get_widget_assert (xml, "max-spin"); + g_signal_connect (act->max, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), act->max_spin); + + act->hist = get_widget_assert (xml, "hist"); + act->normal = get_widget_assert (xml, "normal"); + g_signal_connect (act->hist, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), act->normal); + + act->pie = (get_widget_assert (xml, "pie")); + act->pie_include_missing = get_widget_assert (xml, "pie-include-missing"); + + + g_object_unref (xml); + + + act->tables_opts_order = FRQ_AVALUE; + act->tables_opts_table = FRQ_TABLE; + act->tables_opts_limit = 50; + + g_signal_connect_swapped (tables_button, "clicked", + G_CALLBACK (on_tables_clicked), act); + + g_signal_connect_swapped (charts_button, "clicked", + G_CALLBACK (on_charts_clicked), 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_frequencies_parent_class)->activate) + PSPPIRE_DIALOG_ACTION_CLASS + (psppire_dialog_action_frequencies_parent_class)->activate (pda); +} + +static char * +generate_syntax (PsppireDialogAction * a) +{ + PsppireDialogActionFrequencies *fd = PSPPIRE_DIALOG_ACTION_FREQUENCIES (a); + gchar *text = NULL; + gint i; + gboolean ok; + GtkTreeIter iter; + guint selected = 0; + + GString *string = g_string_new ("FREQUENCIES"); + + g_string_append (string, "\n\t/VARIABLES="); + psppire_var_view_append_names (PSPPIRE_VAR_VIEW (fd->stat_vars), 0, string); + + g_string_append (string, "\n\t/FORMAT="); + + switch (fd->tables_opts_order) + { + case FRQ_AVALUE: + g_string_append (string, "AVALUE"); + break; + case FRQ_DVALUE: + g_string_append (string, "DVALUE"); + break; + case FRQ_ACOUNT: + g_string_append (string, "AFREQ"); + break; + case FRQ_DCOUNT: + g_string_append (string, "DFREQ"); + break; + default: + g_assert_not_reached (); + } + + g_string_append (string, " "); + + switch (fd->tables_opts_table) + { + case FRQ_TABLE: + g_string_append (string, "TABLE"); + break; + case FRQ_NOTABLE: + g_string_append (string, "NOTABLE"); + break; + case FRQ_LIMIT: + g_string_append_printf (string, "LIMIT (%d)", fd->tables_opts_limit); + break; + } + + + for (i = 0, ok = gtk_tree_model_get_iter_first (fd->stats, &iter); ok; + i++, ok = gtk_tree_model_iter_next (fd->stats, &iter)) + { + gboolean toggled; + gtk_tree_model_get (fd->stats, &iter, + CHECKBOX_COLUMN_SELECTED, &toggled, -1); + if (toggled) + selected |= 1u << i; + } + + if (selected != B_FS_DEFAULT) + { + g_string_append (string, "\n\t/STATISTICS="); + if (selected == B_FS_ALL) + g_string_append (string, "ALL"); + else if (selected == 0) + g_string_append (string, "NONE"); + else + { + int n = 0; + if ((selected & B_FS_DEFAULT) == B_FS_DEFAULT) + { + g_string_append (string, "DEFAULT"); + selected &= ~B_FS_DEFAULT; + n++; + } + for (i = 0; i < N_FREQUENCY_STATS; i++) + if (selected & (1u << i)) + { + if (n++) + g_string_append (string, " "); + g_string_append (string, stats[i].name); + } + } + } + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->include_missing))) + g_string_append (string, "\n\t/MISSING=INCLUDE"); + + + if (fd->charts_opts_draw_hist) + { + g_string_append (string, "\n\t/HISTOGRAM="); + g_string_append (string, + fd->charts_opts_draw_normal ? "NORMAL" : "NONORMAL"); + + if (fd->charts_opts_scale == FRQ_PERCENT) + g_string_append (string, " PERCENT"); + + if (fd->charts_opts_use_min) + g_string_append_printf (string, " MIN(%.15g)", fd->charts_opts_min); + if (fd->charts_opts_use_max) + g_string_append_printf (string, " MAX(%.15g)", fd->charts_opts_max); + } + + if (fd->charts_opts_draw_pie) + { + g_string_append (string, "\n\t/PIECHART="); + + if (fd->charts_opts_pie_include_missing) + g_string_append (string, " MISSING"); + + if (fd->charts_opts_use_min) + g_string_append_printf (string, " MIN(%.15g)", fd->charts_opts_min); + if (fd->charts_opts_use_max) + g_string_append_printf (string, " MAX(%.15g)", fd->charts_opts_max); + } + + g_string_append (string, ".\n"); + + text = string->str; + + g_string_free (string, FALSE); + + return text; +} + +static void +psppire_dialog_action_frequencies_class_init (PsppireDialogActionFrequenciesClass *class) +{ + GtkActionClass *action_class = GTK_ACTION_CLASS (class); + + action_class->activate = psppire_dialog_action_frequencies_activate; + + PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax; +} + + +static void +psppire_dialog_action_frequencies_init (PsppireDialogActionFrequencies * act) +{ +} diff --git a/src/ui/gui/psppire-dialog-action-frequencies.h b/src/ui/gui/psppire-dialog-action-frequencies.h new file mode 100644 index 0000000000..ea801581ad --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-frequencies.h @@ -0,0 +1,151 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2012 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_FREQUENCIES_H__ +#define __PSPPIRE_DIALOG_ACTION_FREQUENCIES_H__ + +G_BEGIN_DECLS + + +#define PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES (psppire_dialog_action_frequencies_get_type ()) + +#define PSPPIRE_DIALOG_ACTION_FREQUENCIES(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES, \ + PsppireDialogActionFrequencies)) + +#define PSPPIRE_DIALOG_ACTION_FREQUENCIES_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES, \ + PsppireDialogActionFrequenciesClass)) + + +#define PSPPIRE_IS_DIALOG_ACTION_FREQUENCIES(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES)) + +#define PSPPIRE_IS_DIALOG_ACTION_FREQUENCIES_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES)) + + +#define PSPPIRE_DIALOG_ACTION_FREQUENCIES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES, \ + PsppireDialogActionFrequenciesClass)) + +typedef struct _PsppireDialogActionFrequencies PsppireDialogActionFrequencies; +typedef struct _PsppireDialogActionFrequenciesClass PsppireDialogActionFrequenciesClass; + + +enum frq_scale + { + FRQ_FREQ, + FRQ_PERCENT + }; + +enum frq_order + { + FRQ_AVALUE, + FRQ_DVALUE, + FRQ_ACOUNT, + FRQ_DCOUNT + }; + +enum frq_table + { + FRQ_TABLE, + FRQ_NOTABLE, + FRQ_LIMIT + }; + + +struct _PsppireDialogActionFrequencies +{ + PsppireDialogAction parent; + + /*< private >*/ + gboolean dispose_has_run ; + + GtkWidget *stat_vars; + GtkTreeModel *stats; + + GtkWidget *include_missing; + + enum frq_order tables_opts_order; + enum frq_table tables_opts_table; + gint tables_opts_limit; + + GtkWidget * always; + GtkWidget * never; + GtkWidget * limit; + GtkWidget * limit_spinbutton; + + GtkWidget * avalue; + GtkWidget * dvalue; + GtkWidget * afreq; + GtkWidget * dfreq; + + GtkWidget *tables_dialog; + + /* Charts dialog */ + + GtkWidget *min; + GtkWidget *min_spin; + GtkWidget *max; + GtkWidget *max_spin; + + GtkWidget *hist; + GtkWidget *normal; + + gboolean charts_opts_use_min; + gdouble charts_opts_min; + + gboolean charts_opts_use_max; + gdouble charts_opts_max; + + gboolean charts_opts_draw_hist; + gboolean charts_opts_draw_normal; + + gboolean charts_opts_draw_pie; + gboolean charts_opts_pie_include_missing; + + + enum frq_scale charts_opts_scale; + + GtkWidget *freqs; + GtkWidget *percents; + GtkWidget *pie; + GtkWidget *pie_include_missing; + + GtkWidget *charts_dialog; +}; + + +struct _PsppireDialogActionFrequenciesClass +{ + PsppireDialogActionClass parent_class; +}; + + +GType psppire_dialog_action_frequencies_get_type (void) ; + +G_END_DECLS + +#endif /* __PSPPIRE_DIALOG_ACTION_FREQUENCIES_H__ */ diff --git a/src/ui/gui/widgets.c b/src/ui/gui/widgets.c index 1230d5d6c3..433ab4f36b 100644 --- a/src/ui/gui/widgets.c +++ b/src/ui/gui/widgets.c @@ -20,6 +20,7 @@ #include "psppire-dialog-action-descriptives.h" #include "psppire-dialog-action-examine.h" #include "psppire-dialog-action-factor.h" +#include "psppire-dialog-action-frequencies.h" #include "psppire-dialog-action-indep-samps.h" #include "psppire-dialog-action-kmeans.h" #include "psppire-dialog-action-logistic.h" @@ -57,6 +58,7 @@ preregister_widgets (void) psppire_dialog_action_descriptives_get_type (); psppire_dialog_action_examine_get_type (); psppire_dialog_action_factor_get_type (); + psppire_dialog_action_frequencies_get_type (); psppire_dialog_action_logistic_get_type (); psppire_dialog_action_kmeans_get_type (); psppire_dialog_action_means_get_type ();