From 422dcc73035463644b3a5e746808dc7bbbbbc45f Mon Sep 17 00:00:00 2001 From: John Darrington Date: Fri, 1 Jul 2011 18:39:55 +0200 Subject: [PATCH] Implement dialog box for the non-parametric 2-related-samples tests --- src/ui/gui/automake.mk | 4 + src/ui/gui/data-editor.ui | 7 + src/ui/gui/npar-two-sample-related.c | 170 ++++++++++++++++++++++++ src/ui/gui/npar-two-sample-related.h | 26 ++++ src/ui/gui/paired-dialog.c | 188 +++++++++++++++++++++++++++ src/ui/gui/paired-dialog.h | 31 +++++ src/ui/gui/paired-samples.ui | 176 +++++++++++++------------ src/ui/gui/psppire-data-window.c | 2 + src/ui/gui/t-test-paired-samples.c | 2 + 9 files changed, 524 insertions(+), 82 deletions(-) create mode 100644 src/ui/gui/npar-two-sample-related.c create mode 100644 src/ui/gui/npar-two-sample-related.h create mode 100644 src/ui/gui/paired-dialog.c create mode 100644 src/ui/gui/paired-dialog.h diff --git a/src/ui/gui/automake.mk b/src/ui/gui/automake.mk index b5a588e5..f02f85bd 100644 --- a/src/ui/gui/automake.mk +++ b/src/ui/gui/automake.mk @@ -172,6 +172,8 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/missing-val-dialog.h \ src/ui/gui/oneway-anova-dialog.c \ src/ui/gui/oneway-anova-dialog.h \ + src/ui/gui/paired-dialog.c \ + src/ui/gui/paired-dialog.h \ src/ui/gui/psppire.c \ src/ui/gui/psppire.h \ src/ui/gui/psppire-acr.h \ @@ -243,6 +245,8 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/t-test-options.h \ src/ui/gui/t-test-paired-samples.c \ src/ui/gui/t-test-paired-samples.h \ + src/ui/gui/npar-two-sample-related.c \ + src/ui/gui/npar-two-sample-related.h \ src/ui/gui/val-labs-dialog.c \ src/ui/gui/val-labs-dialog.h \ src/ui/gui/var-display.c \ diff --git a/src/ui/gui/data-editor.ui b/src/ui/gui/data-editor.ui index 670b4b86..83241ce5 100644 --- a/src/ui/gui/data-editor.ui +++ b/src/ui/gui/data-editor.ui @@ -433,6 +433,12 @@ _Binomial... + + + "two-related-samples"> + 2 _Related Samples... + + "k-related-samples"> @@ -571,6 +577,7 @@ + diff --git a/src/ui/gui/npar-two-sample-related.c b/src/ui/gui/npar-two-sample-related.c new file mode 100644 index 00000000..ac3bcd54 --- /dev/null +++ b/src/ui/gui/npar-two-sample-related.c @@ -0,0 +1,170 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2011 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-data-window.h" +#include "psppire-selector.h" +#include "psppire-var-view.h" + +#include "psppire-dict.h" +#include "psppire-var-store.h" + +#include "dialog-common.h" +#include "psppire-dialog.h" + +#include "executor.h" + +#include "helper.h" + +#include "psppire-var-ptr.h" + +#include "paired-dialog.h" +#include "npar-two-sample-related.h" + +#include +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + +enum test + { + NT_WILCOXON, + NT_SIGN, + NT_MCNEMAR, + n_Tests + }; + +struct ts_test +{ + GtkWidget *button; + char syntax[16]; +}; + + +static void +refresh (void *aux) +{ + int i; + struct ts_test *tst = aux; + + for (i = 0 ; i < n_Tests; ++i) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tst[i].button), FALSE); + } +} + + +static gboolean +valid (void *aux) +{ + int i; + struct ts_test *tst = aux; + + for (i = 0 ; i < n_Tests; ++i) + { + if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (tst[i].button))) + return TRUE; + } + + return FALSE; +} + + + +static gchar * +generate_syntax (struct paired_samples_dialog *psd, const struct ts_test *test) +{ + int i; + gchar *text = NULL; + GString *str = g_string_new ("NPAR TEST"); + + for (i = 0 ; i < n_Tests; ++i) + { + if (! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (test[i].button))) + continue; + + g_string_append (str, "\n\t"); + g_string_append (str, test[i].syntax); + + psppire_var_view_append_names (PSPPIRE_VAR_VIEW (psd->pairs_treeview), 0, str); + + g_string_append (str, " WITH "); + + psppire_var_view_append_names (PSPPIRE_VAR_VIEW (psd->pairs_treeview), 1, str); + + g_string_append (str, " (PAIRED)"); + } + + g_string_append (str, ".\n"); + + text = str->str; + g_string_free (str, FALSE); + + return text; +} + +/* Pops up the dialog box */ +void +two_related_dialog (PsppireDataWindow *de) +{ + gint response; + struct ts_test nts[n_Tests]; + struct paired_samples_dialog *tt_d = two_sample_dialog_create (de); + + GtkWidget *frame = gtk_frame_new (_("Test Type")); + GtkWidget *bb = gtk_vbutton_box_new (); + + strcpy (nts[NT_WILCOXON].syntax, "/WILCOXON"); + strcpy (nts[NT_SIGN].syntax, "/SIGN"); + strcpy (nts[NT_MCNEMAR].syntax, "/MCNEMAR"); + + nts[NT_WILCOXON].button = gtk_check_button_new_with_mnemonic (_("_Wilcoxon")); + nts[NT_SIGN].button = gtk_check_button_new_with_mnemonic (_("_Sign")); + nts[NT_MCNEMAR].button = gtk_check_button_new_with_mnemonic (_("_McNemar")); + + gtk_box_pack_start (GTK_BOX (bb), nts[NT_WILCOXON].button, FALSE, FALSE, 5); + gtk_box_pack_start (GTK_BOX (bb), nts[NT_SIGN].button, FALSE, FALSE, 5); + gtk_box_pack_start (GTK_BOX (bb), nts[NT_MCNEMAR].button, FALSE, FALSE, 5); + + gtk_container_add (GTK_CONTAINER (frame), bb); + + gtk_widget_show_all (frame); + two_sample_dialog_add_widget (tt_d, frame); + + tt_d->refresh = refresh; + tt_d->valid = valid; + tt_d->aux = nts; + + gtk_window_set_title (GTK_WINDOW (tt_d->dialog), _("Two-Related-Samples Tests")); + + response = psppire_dialog_run (PSPPIRE_DIALOG (tt_d->dialog)); + + switch (response) + { + case GTK_RESPONSE_OK: + g_free (execute_syntax_string (de, generate_syntax (tt_d, nts))); + break; + case PSPPIRE_RESPONSE_PASTE: + g_free (paste_syntax_to_window (generate_syntax (tt_d, nts))); + break; + default: + break; + } + + two_sample_dialog_destroy (tt_d); +} diff --git a/src/ui/gui/npar-two-sample-related.h b/src/ui/gui/npar-two-sample-related.h new file mode 100644 index 00000000..de3a8607 --- /dev/null +++ b/src/ui/gui/npar-two-sample-related.h @@ -0,0 +1,26 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2011 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 NPAR_PAIRED_H +#define NPAR_PAIRED_H 1 + +#include "psppire-data-window.h" + +/* Pops up the dialog box */ +void two_related_dialog (PsppireDataWindow *de); + +#endif diff --git a/src/ui/gui/paired-dialog.c b/src/ui/gui/paired-dialog.c new file mode 100644 index 00000000..70f6c34b --- /dev/null +++ b/src/ui/gui/paired-dialog.c @@ -0,0 +1,188 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2011 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 "paired-dialog.h" + +#include "psppire-data-window.h" +#include "psppire-selector.h" +#include "psppire-var-view.h" + +#include "psppire-dict.h" +#include "psppire-var-store.h" + +#include "dialog-common.h" +#include "psppire-dialog.h" + +#include "psppire-var-ptr.h" + + +#include "helper.h" + + + +static void +refresh (struct paired_samples_dialog *tt_d) +{ + gtk_list_store_clear (GTK_LIST_STORE (tt_d->list_store)); + + if (tt_d->refresh) + tt_d->refresh (tt_d->aux); +} + +static gboolean +dialog_state_valid (gpointer data) +{ + struct variable *v = NULL; + struct paired_samples_dialog *tt_d = data; + GtkTreeIter dest_iter; + + gint n_rows = gtk_tree_model_iter_n_children (tt_d->list_store, NULL); + + if ( n_rows == 0 ) + return FALSE; + + /* Get the last row */ + gtk_tree_model_iter_nth_child (tt_d->list_store, &dest_iter, + NULL, n_rows - 1); + + /* Get the last (2nd) column */ + gtk_tree_model_get (tt_d->list_store, &dest_iter, 1, &v, -1); + + + if (v == NULL) + return FALSE; + + if ( NULL == tt_d->valid) + return TRUE; + + return tt_d->valid (tt_d->aux); +} + + + +static void +select_as_pair_member (GtkTreeIter source_iter, + GtkWidget *dest, + GtkTreeModel *source_model, + gpointer data) +{ + struct variable *v; + struct variable *v1; + gint n_rows; + GtkTreeIter dest_iter; + struct paired_samples_dialog *tt_d = data; + + + gtk_tree_model_get (source_model, &source_iter, + DICT_TVM_COL_VAR, &v, -1); + + n_rows = gtk_tree_model_iter_n_children (tt_d->list_store, NULL); + + if ( n_rows > 0 ) + { + + gtk_tree_model_iter_nth_child (tt_d->list_store, + &dest_iter, NULL, n_rows - 1); + + gtk_tree_model_get (tt_d->list_store, &dest_iter, 1, &v1, -1); + } + else + v1 = NULL; + + if ( n_rows == 0 || v1 != NULL) + { + gtk_list_store_append (GTK_LIST_STORE (tt_d->list_store), &dest_iter); + + gtk_list_store_set (GTK_LIST_STORE (tt_d->list_store), &dest_iter, + 0, v, + 1, NULL, + -1); + } + else + { + gtk_list_store_set (GTK_LIST_STORE (tt_d->list_store), &dest_iter, + 1, v, + -1); + + } +} + +void +two_sample_dialog_add_widget (struct paired_samples_dialog *psd, GtkWidget *w) +{ + GtkWidget *box = get_widget_assert (psd->xml, "vbox3"); + gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 5); +} + +void +two_sample_dialog_destroy (struct paired_samples_dialog *psd) +{ + g_object_unref (psd->xml); + free (psd); +} + +struct paired_samples_dialog * +two_sample_dialog_create (PsppireDataWindow *de) +{ + struct paired_samples_dialog *tt_d = g_malloc (sizeof *tt_d); + + PsppireVarStore *vs = NULL; + + tt_d->xml = builder_new ("paired-samples.ui"); + + GtkWidget *dict_view = + get_widget_assert (tt_d->xml, "paired-samples-t-test-treeview1"); + + GtkWidget *options_button = get_widget_assert (tt_d->xml, "paired-samples-t-test-options-button"); + + GtkWidget *selector = get_widget_assert (tt_d->xml, "psppire-selector3"); + + tt_d->dialog = get_widget_assert (tt_d->xml, "t-test-paired-samples-dialog"); + + g_object_get (de->data_editor, "var-store", &vs, NULL); + + g_object_get (vs, "dictionary", &tt_d->dict, NULL); + tt_d->pairs_treeview = + get_widget_assert (tt_d->xml, "paired-samples-t-test-treeview2"); + + gtk_window_set_transient_for (GTK_WINDOW (tt_d->dialog), GTK_WINDOW (de)); + + + g_object_set (dict_view, "model", tt_d->dict, + "predicate", + var_is_numeric, NULL); + + + tt_d->list_store = gtk_tree_view_get_model (GTK_TREE_VIEW (tt_d->pairs_treeview)); + + psppire_selector_set_select_func (PSPPIRE_SELECTOR (selector), + select_as_pair_member, + tt_d); + + g_signal_connect_swapped (tt_d->dialog, "refresh", + G_CALLBACK (refresh), tt_d); + + psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (tt_d->dialog), + dialog_state_valid, tt_d); + + return tt_d; +} diff --git a/src/ui/gui/paired-dialog.h b/src/ui/gui/paired-dialog.h new file mode 100644 index 00000000..c370f77c --- /dev/null +++ b/src/ui/gui/paired-dialog.h @@ -0,0 +1,31 @@ +#ifndef PAIRED_DIALOG_H +#define PAIRED_DIALOG_H 1 + +#include "psppire-data-window.h" +#include "psppire-dict.h" + +#include + +typedef void refresh_f (void *aux); +typedef gboolean valid_f (void *aux); + +struct paired_samples_dialog +{ + PsppireDict *dict; + GtkWidget *pairs_treeview; + GtkTreeModel *list_store; + GtkWidget *dialog; + GtkBuilder *xml; + + refresh_f *refresh; + valid_f *valid; + void *aux; +}; + + +struct paired_samples_dialog *two_sample_dialog_create (PsppireDataWindow *de); +void two_sample_dialog_destroy (struct paired_samples_dialog *psd); +void two_sample_dialog_add_widget (struct paired_samples_dialog *psd, GtkWidget *w); + + +#endif diff --git a/src/ui/gui/paired-samples.ui b/src/ui/gui/paired-samples.ui index 1e6f8b55..59332928 100644 --- a/src/ui/gui/paired-samples.ui +++ b/src/ui/gui/paired-samples.ui @@ -5,7 +5,6 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Paired Samples T Test True @@ -13,135 +12,148 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 2 - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 5 + 5 - + True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - never - automatic - etched-in - + True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False + never + automatic + etched-in + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + False + + + + 0 + - - - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0.059999998658895493 - 0 - + True - True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - 5 - paired-samples-t-test-treeview1 - paired-samples-t-test-treeview2 + 0.059999998658895493 + 0 + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + 5 + paired-samples-t-test-treeview1 + paired-samples-t-test-treeview2 + + + + False + False + 1 + - - - False - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - vertical - 5 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none + vertical + 5 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 + 0 + none - + True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - automatic - etched-in + 12 - + True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - 2 + automatic + etched-in + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + False + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Test _Pair(s): + True + True + paired-samples-t-test-treeview2 + + + + 0 + - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Test Variable(s): - True - - - - - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - vertical - - Options... + True - True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + vertical + + + Options... + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + False + 0 + + False False - 0 + end + 1 - False - False - 1 + 2 - - 2 - diff --git a/src/ui/gui/psppire-data-window.c b/src/ui/gui/psppire-data-window.c index 21626fe2..86c81853 100644 --- a/src/ui/gui/psppire-data-window.c +++ b/src/ui/gui/psppire-data-window.c @@ -43,6 +43,7 @@ #include "ui/gui/help-menu.h" #include "ui/gui/helper.h" #include "ui/gui/k-related-dialog.h" +#include "ui/gui/npar-two-sample-related.h" #include "ui/gui/oneway-anova-dialog.h" #include "ui/gui/psppire-data-window.h" #include "ui/gui/psppire-syntax-window.h" @@ -1116,6 +1117,7 @@ psppire_data_window_finish_init (PsppireDataWindow *de, connect_action (de, "binomial", G_CALLBACK (binomial_dialog)); connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog)); + connect_action (de, "two-related-samples", G_CALLBACK (two_related_dialog)); { diff --git a/src/ui/gui/t-test-paired-samples.c b/src/ui/gui/t-test-paired-samples.c index 7e50c8b1..5f2d6f22 100644 --- a/src/ui/gui/t-test-paired-samples.c +++ b/src/ui/gui/t-test-paired-samples.c @@ -204,6 +204,8 @@ t_test_paired_samples_dialog (PsppireDataWindow *de) psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog), dialog_state_valid, &tt_d); + gtk_window_set_title (GTK_WINDOW (dialog), _("Paired Samples T Test")); + response = psppire_dialog_run (PSPPIRE_DIALOG (dialog)); switch (response) -- 2.30.2