psppire: add "Plots" subdialog for examine (Explore)
authorFriedrich Beckmann <friedrich.beckmann@gmx.de>
Sun, 13 Sep 2020 21:55:00 +0000 (23:55 +0200)
committerFriedrich Beckmann <friedrich.beckmann@gmx.de>
Sun, 13 Sep 2020 22:10:40 +0000 (00:10 +0200)
Closes: https://savannah.gnu.org/bugs/?49674
NEWS
src/ui/gui/examine.ui
src/ui/gui/psppire-dialog-action-examine.c
src/ui/gui/psppire-dialog-action-examine.h

diff --git a/NEWS b/NEWS
index bb2901a428bd50a5fae4e22848f637897f50656f..9a70ca95fb291ceb07c6e3aa8818af9150365877 100644 (file)
--- 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:
 
index 23d57e973d81c2c6c0e37f04d11ed375e057e3a4..723b11451cb94578ac404ab56ae0ce92886eb5c4 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- PSPP - a program for statistical analysis. -->
-<!-- Copyright (C) 2017 Free Software Foundation, Inc. -->
+<!-- Copyright (C) 2017, 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 -->
                 <property name="position">0</property>
               </packing>
             </child>
+           <child>
+             <object class="GtkFrame" id="display-frame">
+               <property name="visible">True</property>
+               <child>
+                 <object class="GtkBox" id="display-hbox">
+                   <property name="visible">True</property>
+                   <property name="orientation">horizontal</property>
+                   <child>
+                     <object class="GtkRadioButton" id="display-both-button">
+                       <property name="label" translatable="yes">Both</property>
+                       <property name="visible">True</property>
+                     </object>
+                   </child>
+                   <child>
+                     <object class="GtkRadioButton" id="display-stats-button">
+                       <property name="label" translatable="yes">Statistics</property>
+                       <property name="visible">True</property>
+                       <property name="group">display-both-button</property>
+                     </object>
+                   </child>
+                   <child>
+                     <object class="GtkRadioButton" id="display-plots-button">
+                       <property name="label" translatable="yes">Plots</property>
+                       <property name="visible">True</property>
+                       <property name="group">display-both-button</property>
+                     </object>
+                   </child>
+                 </object>
+               </child>
+               <child type="label">
+                 <object class="GtkLabel" id="display-label">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Display</property>
+                    <property name="use_markup">True</property>
+                 </object>
+               </child>
+              </object>
+             <packing>
+                <property name="position">1</property>
+              </packing>
+           </child>
             <child>
               <object class="GtkButtonBox" id="hbuttonbox1">
                 <property name="visible">True</property>
                     <property name="position">1</property>
                   </packing>
                 </child>
+                <child>
+                  <object class="GtkButton" id="plots-button">
+                    <property name="label" translatable="yes">Plot...</property>
+                   <property name="visible">True</property>
+                  </object>
+                </child>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">False</property>
                 <property name="padding">5</property>
-                <property name="position">1</property>
+                <property name="position">2</property>
               </packing>
             </child>
           </object>
       </object>
     </child>
   </object>
+  <object class="PsppireDialog" id="plots-dialog">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Explore: Plots</property>
+    <property name="modal">True</property>
+    <property name="help-page">EXAMINE</property>
+    <child>
+      <object class="GtkBox" id="dialog-plot-vboxtop">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <child>
+         <object class="GtkBox" id="dialog-plot-hboxplots">
+            <property name="visible">True</property>
+            <property name="orientation">horizontal</property>
+           <child>
+             <object class="GtkFrame" id="boxplot-frame">
+               <property name="visible">True</property>
+               <child>
+                 <object class="GtkBox" id="dialog-plot-vbox-boxplots">
+                   <property name="visible">True</property>
+                   <property name="orientation">vertical</property>
+                   <child>
+                     <object class="GtkRadioButton" id="boxplot-factors-button">
+                       <property name="label" translatable="yes">Factor levels together</property>
+                       <property name="visible">True</property>
+                     </object>
+                   </child>
+                   <child>
+                     <object class="GtkRadioButton" id="boxplot-dependents-button">
+                       <property name="label" translatable="yes">Dependents together</property>
+                       <property name="visible">True</property>
+                       <property name="group">boxplot-factors-button</property>
+                     </object>
+                   </child>
+                   <child>
+                     <object class="GtkRadioButton" id="boxplot-none-button">
+                       <property name="label" translatable="yes">None</property>
+                       <property name="visible">True</property>
+                       <property name="group">boxplot-factors-button</property>
+                     </object>
+                   </child>
+                 </object>
+               </child>
+               <child type="label">
+                 <object class="GtkLabel" id="boxplot-label">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Boxplots</property>
+                    <property name="use_markup">True</property>
+                 </object>
+               </child>
+              </object>
+           </child>
+           <child>
+             <object class="GtkFrame" id="descriptive-frame">
+               <property name="visible">True</property>
+               <child>
+                 <object class="GtkCheckButton" id="histogram-button">
+                    <property name="label" translatable="yes">Histogram</property>
+                    <property name="visible">True</property>
+                 </object>
+               </child>
+               <child type="label">
+                 <object class="GtkLabel" id="descriptive-label">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Descriptive</property>
+                    <property name="use_markup">True</property>
+                 </object>
+               </child>
+             </object>
+           </child>
+         </object>
+        </child>
+       <child>
+         <object class="GtkCheckButton" id="npplots-button">
+            <property name="label" translatable="yes">Normality plots with tests</property>
+            <property name="visible">True</property>
+         </object>
+       </child>
+       <child>
+         <object class="GtkFrame" id="spread-frame">
+           <property name="visible">True</property>
+           <child>
+             <object class="GtkBox" id="dialog-plot-vbox-spread">
+               <property name="visible">True</property>
+               <property name="orientation">vertical</property>
+               <child>
+                 <object class="GtkRadioButton" id="spread-none-button">
+                   <property name="label" translatable="yes">None</property>
+                   <property name="visible">True</property>
+                 </object>
+               </child>
+               <child>
+                 <object class="GtkRadioButton" id="spread-power-button">
+                   <property name="label" translatable="yes">Power estimation</property>
+                   <property name="visible">True</property>
+                   <property name="group">spread-none-button</property>
+                 </object>
+               </child>
+               <child>
+                 <object class="GtkBox" id="dialog-plot-hbox-spreadtrans">
+                   <property name="visible">True</property>
+                   <property name="orientation">horizontal</property>
+                   <child>
+                     <object class="GtkRadioButton" id="spread-trans-button">
+                       <property name="label" translatable="yes">Transformed Power:</property>
+                       <property name="visible">True</property>
+                       <property name="group">spread-none-button</property>
+                     </object>
+                   </child>
+                   <child>
+                     <object class="GtkComboBoxText" id="spread-power-combo">
+                       <property name="visible">True</property>
+                       <items>
+                         <item translatable="yes" id="natlog"    >Natural Log</item>
+                         <item translatable="yes" id="cube"      >Cube</item>
+                         <item translatable="yes" id="square"    >Square</item>
+                         <item translatable="yes" id="squareroot">Square Root</item>
+                         <item translatable="yes" id="recroot"   >Rec. Root</item>
+                         <item translatable="yes" id="reciprocal">Reciprocal</item>
+                       </items>
+                     </object>
+                   </child>
+                 </object>
+               </child>
+               <child>
+                 <object class="GtkRadioButton" id="spread-untrans-button">
+                   <property name="label" translatable="yes">Untransformed</property>
+                   <property name="visible">True</property>
+                   <property name="group">spread-none-button</property>
+                 </object>
+               </child>
+             </object>
+           </child>
+           <child type="label">
+             <object class="GtkLabel" id="spread-label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Spread vs Level with Levene Test</property>
+                <property name="use_markup">True</property>
+             </object>
+           </child>
+         </object>
+       </child>
+        <child>
+          <object class="PsppireButtonBox" id="psppire-plotbuttonbox">
+           <property name="orientation">horizontal</property>
+           <property name="visible">True</property>
+           <property name="buttons">PSPPIRE_BUTTON_CONTINUE_MASK | PSPPIRE_BUTTON_CANCEL_MASK | PSPPIRE_BUTTON_HELP_MASK</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
 </interface>
index 12627bd7a5f76b7a72972b3c1e4d9a09a891958b..d8742703dd0ddcf3fe873933dbeb5c10be701a1c 100644 (file)
@@ -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);
index 0780064ebfcf848038b03d036c53a8c21ab17654..81e290e35c609069bd92291067f6ea10f2fe769d 100644 (file)
@@ -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;
+
 };