X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Foneway-anova-dialog.c;fp=src%2Fui%2Fgui%2Foneway-anova-dialog.c;h=f94756ec23808eda5f1187430c33c5cc14db5d0d;hb=7751519f5ca0b6106fe3d611010a70804677ab86;hp=0000000000000000000000000000000000000000;hpb=3bdb0f0b14fc7b1a417257e6a384956afa16ab14;p=pspp-builds.git diff --git a/src/ui/gui/oneway-anova-dialog.c b/src/ui/gui/oneway-anova-dialog.c new file mode 100644 index 00000000..f94756ec --- /dev/null +++ b/src/ui/gui/oneway-anova-dialog.c @@ -0,0 +1,484 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2007 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 +#include "oneway-anova-dialog.h" +#include "psppire-dict.h" +#include "psppire-var-store.h" +#include "helper.h" +#include +#include "data-editor.h" +#include "psppire-dialog.h" +#include "dialog-common.h" +#include "dict-display.h" +#include "psppire-acr.h" + + +#include +#include "syntax-editor.h" + + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + + +struct contrasts_subdialog; +struct oneway_anova_dialog; + + +static void run_contrasts_dialog (struct oneway_anova_dialog *); +static void push_new_store (GArray *, struct contrasts_subdialog *); + +static void next (GtkWidget *, gpointer); +static void prev (GtkWidget *, gpointer); + + +struct contrasts_subdialog +{ + /* Contrasts Dialog widgets */ + GtkWidget *contrasts_dialog; + GtkWidget *stack_label; + PsppireAcr *acr; + + + /* Gets copied into contrasts when "Continue" + is clicked */ + GArray *temp_contrasts; + + /* Index into the temp_contrasts */ + guint c; + + GtkWidget *prev; + GtkWidget *next; + + GtkWidget *ctotal; +}; + + +struct oneway_anova_dialog +{ + PsppireDict *dict; + + GtkWidget *factor_entry; + GtkWidget *vars_treeview; + GtkWindow *dialog; + GArray *contrasts_array; + + GtkToggleButton *descriptives; + GtkToggleButton *homogeneity; + + struct contrasts_subdialog contrasts; +}; + +static gboolean +dialog_state_valid (gpointer data) +{ + struct oneway_anova_dialog *ow = data; + + GtkTreeModel *vars = + gtk_tree_view_get_model (GTK_TREE_VIEW (ow->vars_treeview)); + + GtkTreeIter notused; + + if ( !gtk_tree_model_get_iter_first (vars, ¬used) ) + return FALSE; + + if ( 0 == strcmp ("", gtk_entry_get_text (GTK_ENTRY (ow->factor_entry)))) + return FALSE; + + return TRUE; +} + +static gchar * generate_syntax (const struct oneway_anova_dialog *); + + +static void +refresh (struct oneway_anova_dialog *ow) +{ + GtkTreeModel *model = + gtk_tree_view_get_model (GTK_TREE_VIEW (ow->vars_treeview)); + + gtk_entry_set_text (GTK_ENTRY (ow->factor_entry), ""); + + gtk_list_store_clear (GTK_LIST_STORE (model)); +} + + +/* Pops up the dialog box */ +void +oneway_anova_dialog (GObject *o, gpointer data) +{ + gint response; + struct data_editor *de = data; + + PsppireVarStore *vs; + + GladeXML *xml = XML_NEW ("oneway.glade"); + + struct oneway_anova_dialog ow; + + GtkSheet *var_sheet = + GTK_SHEET (get_widget_assert (de->xml, "variable_sheet")); + + GtkWidget *dict_view = + get_widget_assert (xml, "oneway-anova-treeview1"); + + GtkWidget *selector2 = + get_widget_assert (xml, "oneway-anova-selector2"); + + GtkWidget *selector1 = + get_widget_assert (xml, "oneway-anova-selector1"); + + GtkWidget *contrasts_button = + get_widget_assert (xml, "contrasts-button"); + + + g_signal_connect_swapped (contrasts_button, "clicked", + G_CALLBACK (run_contrasts_dialog), &ow); + + + ow.factor_entry = get_widget_assert (xml, "oneway-anova-entry"); + ow.vars_treeview = + get_widget_assert (xml, "oneway-anova-treeview2"); + + ow.descriptives = + GTK_TOGGLE_BUTTON (get_widget_assert (xml, "checkbutton1")); + + ow.homogeneity = + GTK_TOGGLE_BUTTON (get_widget_assert (xml, "checkbutton2")); + + vs = PSPPIRE_VAR_STORE (gtk_sheet_get_model (var_sheet)); + + ow.dict = vs->dict; + + ow.dialog = + GTK_WINDOW (get_widget_assert (xml, "oneway-anova-dialog")); + + gtk_window_set_transient_for (ow.dialog, de->parent.window); + + attach_dictionary_to_treeview (GTK_TREE_VIEW (dict_view), + vs->dict, + GTK_SELECTION_MULTIPLE, NULL); + + set_dest_model (GTK_TREE_VIEW (ow.vars_treeview), vs->dict); + + + psppire_selector_set_subjects (PSPPIRE_SELECTOR (selector1), + dict_view, ow.vars_treeview, + insert_source_row_into_tree_view, + NULL); + + + psppire_selector_set_subjects (PSPPIRE_SELECTOR (selector2), + dict_view, ow.factor_entry, + insert_source_row_into_entry, + is_currently_in_entry); + + + + g_signal_connect_swapped (ow.dialog, "refresh", G_CALLBACK (refresh), &ow); + + + + psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (ow.dialog), + dialog_state_valid, &ow); + + + { + struct contrasts_subdialog *cd = &ow.contrasts; + GtkEntry *entry = GTK_ENTRY (get_widget_assert (xml, "entry1")); + + cd->acr = PSPPIRE_ACR (get_widget_assert (xml, "psppire-acr1")); + cd->contrasts_dialog = get_widget_assert (xml, "contrasts-dialog"); + + cd->next = get_widget_assert (xml, "next-button"); + cd->prev = get_widget_assert (xml, "prev-button"); + cd->ctotal = get_widget_assert (xml, "entry2"); + + cd->stack_label = get_widget_assert (xml, "contrast-stack-label"); + + /* Contrasts */ + ow.contrasts_array = g_array_new (FALSE, FALSE, sizeof (GtkListStore *)); + + g_signal_connect (cd->next, "clicked", G_CALLBACK (next), cd); + g_signal_connect (cd->prev, "clicked", G_CALLBACK (prev), cd); + + psppire_acr_set_entry (cd->acr, entry); + + gtk_window_set_transient_for (GTK_WINDOW (cd->contrasts_dialog), + de->parent.window); + } + + response = psppire_dialog_run (PSPPIRE_DIALOG (ow.dialog)); + + switch (response) + { + case GTK_RESPONSE_OK: + { + gchar *syntax = generate_syntax (&ow); + struct getl_interface *sss = create_syntax_string_source (syntax); + execute_syntax (sss); + + g_free (syntax); + } + break; + case PSPPIRE_RESPONSE_PASTE: + { + gchar *syntax = generate_syntax (&ow); + + struct syntax_editor *se = + (struct syntax_editor *) window_create (WINDOW_SYNTAX, NULL); + + gtk_text_buffer_insert_at_cursor (se->buffer, syntax, -1); + + g_free (syntax); + } + break; + default: + break; + } + + g_array_free (ow.contrasts_array, FALSE); + + g_object_unref (xml); +} + + +static gchar * generate_syntax (const struct oneway_anova_dialog *ow) +{ + gchar *text; + gint i; + gboolean descriptives = gtk_toggle_button_get_active (ow->descriptives); + gboolean homogeneity = gtk_toggle_button_get_active (ow->homogeneity); + + GString *str = g_string_new ("ONEWAY /VARIABLES="); + + append_variable_names (str, ow->dict, GTK_TREE_VIEW (ow->vars_treeview)); + + g_string_append (str, " BY "); + + g_string_append (str, gtk_entry_get_text (GTK_ENTRY (ow->factor_entry))); + + if (descriptives || homogeneity ) + { + g_string_append (str, "\n\t/STATISTICS="); + if (descriptives) + g_string_append (str, "DESCRIPTIVES "); + if (homogeneity) + g_string_append (str, "HOMOGENEITY "); + } + + for (i = 0 ; i < ow->contrasts_array->len ; ++i ) + { + GtkListStore *ls = g_array_index (ow->contrasts_array, GtkListStore*, i); + GtkTreeIter iter; + gboolean ok; + + g_string_append (str, "\n\t/CONTRAST="); + + for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(ls), + &iter); + ok; + ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (ls), &iter)) + { + gdouble v; + + gtk_tree_model_get (GTK_TREE_MODEL (ls), &iter, 0, &v, -1); + + g_string_append_printf (str, " %g", v); + } + } + + g_string_append (str, ".\n"); + + text = str->str; + g_string_free (str, FALSE); + + return text; +} + + + +/* Contrasts stuff */ + + + + +/* Callback for when the list store currently associated with the + treeview has changed. It sets the widgets of the subdialog + to reflect the store's new state. +*/ +static void +list_store_changed (struct contrasts_subdialog *csd) +{ + gboolean ok; + gdouble total = 0.0; + GtkTreeIter iter; + GtkTreeModel *ls = NULL; + gchar *text = + g_strdup_printf (_("Contrast %d of %d"), + csd->c, csd->temp_contrasts->len); + + gtk_label_set_label (GTK_LABEL (csd->stack_label), text); + + g_free (text); + + gtk_widget_set_sensitive (csd->prev, csd->c > 1); + + if ( csd->c > 0 ) + ls = g_array_index (csd->temp_contrasts, GtkTreeModel*, csd->c - 1); + + psppire_acr_set_model (csd->acr, GTK_LIST_STORE (ls)); + + /* Sensitive iff the liststore has two items or more */ + gtk_widget_set_sensitive (csd->next, + gtk_tree_model_iter_nth_child + (ls, &iter, NULL, 1)); + + for (ok = gtk_tree_model_get_iter_first (ls, &iter); + ok; + ok = gtk_tree_model_iter_next (ls, &iter) + ) + { + gdouble v; + gtk_tree_model_get (ls, &iter, 0, &v, -1); + total += v; + } + + text = g_strdup_printf ("%g", total); + + gtk_entry_set_text (GTK_ENTRY (csd->ctotal), text); + + g_free (text); +} + + +/* Copy the contrasts array into the local array */ +static GArray * +clone_contrasts_array (GArray *src_array) +{ + gint i; + + GArray *dest_array = + g_array_sized_new (FALSE, FALSE, sizeof (GtkListStore *), + src_array->len); + + for (i = 0 ; i < src_array->len ; ++i ) + { + gboolean ok; + GtkTreeIter src_iter; + GtkListStore *src = g_array_index (src_array, GtkListStore*, i); + GtkListStore *dest; + + /* Refuse to copy empty stores */ + if (! gtk_tree_model_get_iter_first (GTK_TREE_MODEL (src), + &src_iter)) + continue; + + dest = gtk_list_store_new (1, G_TYPE_DOUBLE); + + for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(src), + &src_iter); + ok; + ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (src), &src_iter)) + { + gdouble v; + GtkTreeIter dest_iter; + + gtk_tree_model_get (GTK_TREE_MODEL (src), &src_iter, 0, &v, -1); + + gtk_list_store_append (dest, &dest_iter); + gtk_list_store_set (dest, &dest_iter, 0, v, -1); + } + + g_array_append_val (dest_array, dest); + } + + return dest_array; +} + + +static void +run_contrasts_dialog (struct oneway_anova_dialog *ow) +{ + struct contrasts_subdialog *csd = &ow->contrasts; + gint response; + + csd->temp_contrasts = clone_contrasts_array (ow->contrasts_array); + + csd->c = 1; + + push_new_store (csd->temp_contrasts, csd); + + response = psppire_dialog_run (PSPPIRE_DIALOG (csd->contrasts_dialog)); + + if ( response == PSPPIRE_RESPONSE_CONTINUE ) + { + ow->contrasts_array = clone_contrasts_array (csd->temp_contrasts); + } + + /* Destroy the temp contrasts here */ + +} + + +static void +push_new_store (GArray *contrast_stack, struct contrasts_subdialog *csd) +{ + GtkListStore *ls = gtk_list_store_new (1, G_TYPE_DOUBLE); + + g_array_append_val (contrast_stack, ls); + + g_signal_connect_swapped (ls, "row-deleted", + G_CALLBACK (list_store_changed), csd); + + g_signal_connect_swapped (ls, "row-changed", + G_CALLBACK (list_store_changed), csd); + + list_store_changed (csd); +} + +static void +next (GtkWidget *widget, gpointer data) +{ + struct contrasts_subdialog *csd = data; + + if (csd->c >= csd->temp_contrasts->len) + push_new_store (csd->temp_contrasts, csd); + + csd->c++; + + list_store_changed (csd); +} + + +static void +prev (GtkWidget *widget, gpointer data) +{ + struct contrasts_subdialog *csd = data; + + if ( csd->c > 0 ) + --csd->c; + + list_store_changed (csd); +} + +