Select Cases Dialog: Convert to PsppireDialogAction
authorJohn Darrington <john@darrington.wattle.id.au>
Thu, 31 Dec 2015 13:59:49 +0000 (14:59 +0100)
committerJohn Darrington <john@darrington.wattle.id.au>
Thu, 31 Dec 2015 14:00:20 +0000 (15:00 +0100)
src/ui/gui/automake.mk
src/ui/gui/data-editor.ui
src/ui/gui/psppire-data-window.c
src/ui/gui/psppire-dialog-action-select.c [new file with mode: 0644]
src/ui/gui/psppire-dialog-action-select.h [new file with mode: 0644]
src/ui/gui/select-cases-dialog.c [deleted file]
src/ui/gui/select-cases-dialog.h [deleted file]
src/ui/gui/widgets.c

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