From: Friedrich Beckmann Date: Sun, 13 Sep 2020 21:55:00 +0000 (+0200) Subject: psppire: add "Plots" subdialog for examine (Explore) X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=45ca175f33ff07d6f9214698a776097075d07045;p=pspp psppire: add "Plots" subdialog for examine (Explore) Closes: https://savannah.gnu.org/bugs/?49674 --- diff --git a/NEWS b/NEWS index bb2901a428..9a70ca95fb 100644 --- a/NEWS +++ b/NEWS @@ -6,7 +6,10 @@ Please send PSPP bug reports to bug-gnu-pspp@gnu.org. Changes from 1.4.1 to 1.4.2: - * Added Drag-N-Drop in output view + * Added Drag-N-Drop in output view. + + * The Explore GUI dialog supports the "Plots" subdialog. Boxplots, Q-Q Plots + and Spreadlevel plots are now also available via the GUI. Changes from 1.4.0 to 1.4.1: diff --git a/src/ui/gui/examine.ui b/src/ui/gui/examine.ui index 23d57e973d..723b11451c 100644 --- a/src/ui/gui/examine.ui +++ b/src/ui/gui/examine.ui @@ -1,6 +1,6 @@ - + @@ -256,6 +256,47 @@ 0 + + + True + + + True + horizontal + + + Both + True + + + + + Statistics + True + display-both-button + + + + + Plots + True + display-both-button + + + + + + + True + Display + True + + + + + 1 + + True @@ -292,12 +333,18 @@ 1 + + + Plot... + True + + False False 5 - 1 + 2 @@ -541,4 +588,155 @@ + + False + Explore: Plots + True + EXAMINE + + + True + vertical + + + True + horizontal + + + True + + + True + vertical + + + Factor levels together + True + + + + + Dependents together + True + boxplot-factors-button + + + + + None + True + boxplot-factors-button + + + + + + + True + Boxplots + True + + + + + + + True + + + Histogram + True + + + + + True + Descriptive + True + + + + + + + + + Normality plots with tests + True + + + + + True + + + True + vertical + + + None + True + + + + + Power estimation + True + spread-none-button + + + + + True + horizontal + + + Transformed Power: + True + spread-none-button + + + + + True + + Natural Log + Cube + Square + Square Root + Rec. Root + Reciprocal + + + + + + + + Untransformed + True + spread-none-button + + + + + + + True + Spread vs Level with Levene Test + True + + + + + + + horizontal + True + PSPPIRE_BUTTON_CONTINUE_MASK | PSPPIRE_BUTTON_CANCEL_MASK | PSPPIRE_BUTTON_HELP_MASK + + + + + diff --git a/src/ui/gui/psppire-dialog-action-examine.c b/src/ui/gui/psppire-dialog-action-examine.c index 12627bd7a5..d8742703dd 100644 --- a/src/ui/gui/psppire-dialog-action-examine.c +++ b/src/ui/gui/psppire-dialog-action-examine.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2012 Free Software Foundation + Copyright (C) 2012, 2020 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 @@ -103,8 +103,108 @@ run_opts_dialog (PsppireDialogActionExamine *ed) } } +static void +run_plots_dialog (PsppireDialogActionExamine *ed) +{ + gint response; + switch (ed->boxplots) + { + case BOXPLOT_FACTORS: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->boxplot_factors_button), TRUE); + break; + case BOXPLOT_DEPENDENTS: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->boxplot_dependents_button), TRUE); + break; + case BOXPLOT_NONE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->boxplot_none_button), TRUE); + break; + default: + g_assert_not_reached (); + break; + }; + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->histogram_button), ed->histogram); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->npplots_button), ed->npplots); + + switch (ed->spreadlevel) + { + case SPREAD_NONE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->spread_none_button), TRUE); + break; + case SPREAD_POWER: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->spread_power_button), TRUE); + break; + case SPREAD_TRANS: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->spread_trans_button), TRUE); + break; + case SPREAD_UNTRANS: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->spread_untrans_button), TRUE); + break; + default: + g_assert_not_reached (); + break; + } + + switch (ed->spreadpower) + { + case SPREADPOWER_NATLOG: + gtk_combo_box_set_active_id (GTK_COMBO_BOX (ed->spread_power_combo), "natlog"); + break; + case SPREADPOWER_CUBE: + gtk_combo_box_set_active_id (GTK_COMBO_BOX (ed->spread_power_combo), "cube"); + break; + case SPREADPOWER_SQUARE: + gtk_combo_box_set_active_id (GTK_COMBO_BOX (ed->spread_power_combo), "square"); + break; + case SPREADPOWER_SQUAREROOT: + gtk_combo_box_set_active_id (GTK_COMBO_BOX (ed->spread_power_combo), "squareroot"); + break; + case SPREADPOWER_RECROOT: + gtk_combo_box_set_active_id (GTK_COMBO_BOX (ed->spread_power_combo), "recroot"); + break; + case SPREADPOWER_RECIPROCAL: + gtk_combo_box_set_active_id (GTK_COMBO_BOX (ed->spread_power_combo), "reciprocal"); + break; + } + + response = psppire_dialog_run (PSPPIRE_DIALOG (ed->plots_dialog)); + + if (response == PSPPIRE_RESPONSE_CONTINUE) + { + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->boxplot_factors_button))) + ed->boxplots = BOXPLOT_FACTORS; + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->boxplot_dependents_button))) + ed->boxplots = BOXPLOT_DEPENDENTS; + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->boxplot_none_button))) + ed->boxplots = BOXPLOT_NONE; + + ed->histogram = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->histogram_button)); + ed->npplots = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->npplots_button)); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->spread_none_button))) + ed->spreadlevel = SPREAD_NONE; + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->spread_power_button))) + ed->spreadlevel = SPREAD_POWER; + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->spread_trans_button))) + ed->spreadlevel = SPREAD_TRANS; + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->spread_untrans_button))) + ed->spreadlevel = SPREAD_UNTRANS; + + if (0 == strcmp (gtk_combo_box_get_active_id (GTK_COMBO_BOX (ed->spread_power_combo)), "natlog")) + ed->spreadpower = SPREADPOWER_NATLOG; + else if (0 == strcmp (gtk_combo_box_get_active_id (GTK_COMBO_BOX (ed->spread_power_combo)), "cube")) + ed->spreadpower = SPREADPOWER_CUBE; + else if (0 == strcmp (gtk_combo_box_get_active_id (GTK_COMBO_BOX (ed->spread_power_combo)), "square")) + ed->spreadpower = SPREADPOWER_SQUARE; + else if (0 == strcmp (gtk_combo_box_get_active_id (GTK_COMBO_BOX (ed->spread_power_combo)), "squareroot")) + ed->spreadpower = SPREADPOWER_SQUAREROOT; + else if (0 == strcmp (gtk_combo_box_get_active_id (GTK_COMBO_BOX (ed->spread_power_combo)), "recroot")) + ed->spreadpower = SPREADPOWER_RECROOT; + else if (0 == strcmp (gtk_combo_box_get_active_id (GTK_COMBO_BOX (ed->spread_power_combo)), "reciprocal")) + ed->spreadpower = SPREADPOWER_RECIPROCAL; + } +} static char * generate_syntax (const PsppireDialogAction *act) @@ -114,6 +214,14 @@ generate_syntax (const PsppireDialogAction *act) const char *label; gchar *text = NULL; GString *str = g_string_new ("EXAMINE "); + bool show_stats = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->display_stats_button)); + bool show_plots = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->display_plots_button)); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->display_both_button))) + { + show_stats = true; + show_plots = true; + } g_string_append (str, "\n\t/VARIABLES="); psppire_var_view_append_names (PSPPIRE_VAR_VIEW (ed->variables), 0, str); @@ -132,20 +240,78 @@ generate_syntax (const PsppireDialogAction *act) g_string_append (str, label); } - if (ed->stats & (STAT_DESCRIPTIVES | STAT_EXTREMES)) + if (show_stats) { - g_string_append (str, "\n\t/STATISTICS ="); + if (ed->stats & (STAT_DESCRIPTIVES | STAT_EXTREMES)) + { + g_string_append (str, "\n\t/STATISTICS ="); - if (ed->stats & STAT_DESCRIPTIVES) - g_string_append (str, " DESCRIPTIVES"); + if (ed->stats & STAT_DESCRIPTIVES) + g_string_append (str, " DESCRIPTIVES"); - if (ed->stats & STAT_EXTREMES) - g_string_append (str, " EXTREME"); - } + if (ed->stats & STAT_EXTREMES) + g_string_append (str, " EXTREME"); + } - if (ed->stats & STAT_PERCENTILES) - g_string_append (str, "\n\t/PERCENTILES"); + if (ed->stats & STAT_PERCENTILES) + g_string_append (str, "\n\t/PERCENTILES"); + } + if (show_plots && + ((ed->boxplots != BOXPLOT_NONE) || + ed->histogram || + ed->npplots || + (ed->spreadlevel != SPREAD_NONE))) + { + g_string_append (str, "\n\t/PLOT ="); + + if (ed->boxplots != BOXPLOT_NONE) + g_string_append (str, " BOXPLOT"); + if (ed->histogram) + g_string_append (str, " HISTOGRAM"); + if (ed->npplots) + g_string_append (str, " NPPLOT"); + if (ed->spreadlevel != SPREAD_NONE) + { + g_string_append (str, " SPREADLEVEL"); + if (ed->spreadlevel != SPREAD_POWER) + { + gchar *power = NULL; + if (ed->spreadlevel == SPREAD_TRANS) + switch (ed->spreadpower) + { + case SPREADPOWER_NATLOG: + power = "0"; + break; + case SPREADPOWER_CUBE: + power = "3"; + break; + case SPREADPOWER_SQUARE: + power = "2"; + break; + case SPREADPOWER_SQUAREROOT: + power = "0.5"; + break; + case SPREADPOWER_RECROOT: + power = "-0.5"; + break; + case SPREADPOWER_RECIPROCAL: + power = "-1"; + break; + default: + g_assert_not_reached (); + break; + } + else + power = "1"; + g_string_append_printf(str, " (%s)",power); + } + } + if (ed->boxplots == BOXPLOT_FACTORS) + g_string_append (str, "\n\t/COMPARE = GROUPS"); + if (ed->boxplots == BOXPLOT_DEPENDENTS) + g_string_append (str, "\n\t/COMPARE = VARIABLES"); + } g_string_append (str, "\n\t/MISSING="); switch (ed->opts) @@ -193,8 +359,15 @@ dialog_refresh (PsppireDialogAction *da) gtk_list_store_clear (GTK_LIST_STORE (liststore)); gtk_entry_set_text (GTK_ENTRY (dae->id_var), ""); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dae->display_both_button), TRUE); + dae->stats = 0x00; dae->opts = OPT_LISTWISE; + dae->boxplots = BOXPLOT_FACTORS; + dae->histogram = TRUE; + dae->npplots = FALSE; + dae->spreadlevel = SPREAD_NONE; + dae->spreadpower = SPREADPOWER_NATLOG; } static GtkBuilder * @@ -207,12 +380,15 @@ psppire_dialog_action_examine_activate (PsppireDialogAction *a, GVariant *param) GtkWidget *stats_button = get_widget_assert (xml, "stats-button"); GtkWidget *opts_button = get_widget_assert (xml, "opts-button"); + GtkWidget *plots_button = get_widget_assert (xml, "plots-button"); g_signal_connect_swapped (stats_button, "clicked", G_CALLBACK (run_stats_dialog), act); g_signal_connect_swapped (opts_button, "clicked", G_CALLBACK (run_opts_dialog), act); + g_signal_connect_swapped (plots_button, "clicked", + G_CALLBACK (run_plots_dialog), act); GtkWidget *dep_sel = get_widget_assert (xml, "psppire-selector1"); GtkWidget *dep_sel2 = get_widget_assert (xml, "psppire-selector2"); @@ -224,6 +400,9 @@ psppire_dialog_action_examine_activate (PsppireDialogAction *a, GVariant *param) act->variables = get_widget_assert (xml, "treeview2"); act->factors = get_widget_assert (xml, "treeview3"); act->id_var = get_widget_assert (xml, "entry1"); + act->display_both_button = get_widget_assert (xml, "display-both-button"); + act->display_stats_button = get_widget_assert (xml, "display-stats-button"); + act->display_plots_button = get_widget_assert (xml, "display-plots-button"); /* Setting the focus chain like this is a pain. But the default focus order seems to be somewhat odd. */ @@ -249,6 +428,18 @@ psppire_dialog_action_examine_activate (PsppireDialogAction *a, GVariant *param) act->pairwise = get_widget_assert (xml, "radiobutton2"); act->report = get_widget_assert (xml, "radiobutton3"); + act->plots_dialog = get_widget_assert (xml, "plots-dialog"); + act->boxplot_factors_button = get_widget_assert (xml, "boxplot-factors-button"); + act->boxplot_dependents_button = get_widget_assert (xml, "boxplot-dependents-button"); + act->boxplot_none_button = get_widget_assert (xml, "boxplot-none-button"); + act->histogram_button = get_widget_assert (xml, "histogram-button"); + act->npplots_button = get_widget_assert (xml, "npplots-button"); + act->spread_none_button = get_widget_assert (xml, "spread-none-button"); + act->spread_power_button = get_widget_assert (xml, "spread-power-button"); + act->spread_trans_button = get_widget_assert (xml, "spread-trans-button"); + act->spread_untrans_button = get_widget_assert (xml, "spread-untrans-button"); + act->spread_power_combo = get_widget_assert (xml, "spread-power-combo"); + psppire_selector_set_allow (PSPPIRE_SELECTOR (dep_sel), numeric_only); psppire_dialog_action_set_valid_predicate (pda, (void *) dialog_state_valid); diff --git a/src/ui/gui/psppire-dialog-action-examine.h b/src/ui/gui/psppire-dialog-action-examine.h index 0780064ebf..81e290e35c 100644 --- a/src/ui/gui/psppire-dialog-action-examine.h +++ b/src/ui/gui/psppire-dialog-action-examine.h @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2012 Free Software Foundation + Copyright (C) 2012, 2020 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 @@ -60,6 +60,31 @@ enum PsppireDialogActionExamineOpts OPT_REPORT }; +enum PsppireDialogActionExaminePlotsBoxplots + { + BOXPLOT_FACTORS, + BOXPLOT_DEPENDENTS, + BOXPLOT_NONE + }; + +enum PsppireDialogActionExaminePlotsSpreadlevel + { + SPREAD_NONE, + SPREAD_POWER, + SPREAD_TRANS, + SPREAD_UNTRANS + }; + +enum PsppireDialogActionExaminePlotsSpreadpower + { + SPREADPOWER_NATLOG, + SPREADPOWER_CUBE, + SPREADPOWER_SQUARE, + SPREADPOWER_SQUAREROOT, + SPREADPOWER_RECROOT, + SPREADPOWER_RECIPROCAL + }; + struct _PsppireDialogActionExamine { PsppireDialogAction parent; @@ -69,6 +94,10 @@ struct _PsppireDialogActionExamine GtkWidget *factors; GtkWidget *id_var; + GtkWidget *display_both_button; + GtkWidget *display_stats_button; + GtkWidget *display_plots_button; + /* The stats dialog */ GtkWidget *stats_dialog; GtkWidget *descriptives_button; @@ -82,6 +111,25 @@ struct _PsppireDialogActionExamine GtkWidget *pairwise; GtkWidget *report; enum PsppireDialogActionExamineOpts opts; + + /* The plots dialog */ + GtkWidget *plots_dialog; + GtkWidget *boxplot_factors_button; + GtkWidget *boxplot_dependents_button; + GtkWidget *boxplot_none_button; + enum PsppireDialogActionExaminePlotsBoxplots boxplots; + GtkWidget *histogram_button; + bool histogram; + GtkWidget *npplots_button; + bool npplots; + GtkWidget *spread_none_button; + GtkWidget *spread_power_button; + GtkWidget *spread_trans_button; + GtkWidget *spread_untrans_button; + enum PsppireDialogActionExaminePlotsSpreadlevel spreadlevel; + GtkWidget *spread_power_combo; + enum PsppireDialogActionExaminePlotsSpreadpower spreadpower; + };