From: John Darrington Date: Sun, 29 Apr 2012 05:56:07 +0000 (+0200) Subject: Converted Factor Dialog to PsppireDialogAction class X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=e0d88baeadd6bc1eb1176da30de771ac9658f4c9 Converted Factor Dialog to PsppireDialogAction class --- diff --git a/src/ui/gui/automake.mk b/src/ui/gui/automake.mk index 70e76a268b..96209a0199 100644 --- a/src/ui/gui/automake.mk +++ b/src/ui/gui/automake.mk @@ -187,8 +187,6 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/executor.h \ src/ui/gui/find-dialog.c \ src/ui/gui/find-dialog.h \ - src/ui/gui/factor-dialog.c \ - src/ui/gui/factor-dialog.h \ src/ui/gui/frequencies-dialog.c \ src/ui/gui/frequencies-dialog.h \ src/ui/gui/goto-case-dialog.c \ @@ -229,6 +227,8 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/psppire-dialog-action-descriptives.h \ src/ui/gui/psppire-dialog-action-examine.c \ src/ui/gui/psppire-dialog-action-examine.h \ + src/ui/gui/psppire-dialog-action-factor.c \ + src/ui/gui/psppire-dialog-action-factor.h \ src/ui/gui/psppire-dialog-action-kmeans.c \ src/ui/gui/psppire-dialog-action-kmeans.h \ src/ui/gui/psppire-dialog-action-means.c \ diff --git a/src/ui/gui/data-editor.ui b/src/ui/gui/data-editor.ui index 10c0a2c000..890d975c1f 100644 --- a/src/ui/gui/data-editor.ui +++ b/src/ui/gui/data-editor.ui @@ -430,8 +430,9 @@ - + factor-analysis + uimanager1 Factor _Analysis... diff --git a/src/ui/gui/factor-dialog.c b/src/ui/gui/factor-dialog.c deleted file mode 100644 index 3385505fc3..0000000000 --- a/src/ui/gui/factor-dialog.c +++ /dev/null @@ -1,500 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2009, 2010, 2011, 2012 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 "dialog-common.h" -#include -#include - -#include "factor-dialog.h" -#include "psppire-selector.h" -#include "psppire-dictview.h" -#include "psppire-dialog.h" - -#include "psppire-data-window.h" -#include "psppire-var-view.h" - -#include "psppire-scanf.h" - -#include "executor.h" -#include "helper.h" -#include "builder-wrapper.h" - -#include - -#include "gettext.h" -#define _(msgid) gettext (msgid) -#define N_(msgid) msgid - - -struct extraction_parameters -{ - gdouble mineigen; - gint n_factors; - gint n_iterations; - - gboolean explicit_nfactors; - gboolean covariance; - - gboolean scree; - gboolean unrotated; - - gboolean paf; -}; - -enum rotation_type { - ROT_NONE, - ROT_VARIMAX, - ROT_QUARTIMAX, - ROT_EQUIMAX -}; - -static const char *rot_method_syntax[] = - { - "NOROTATE", - "VARIMAX", - "QUARTIMAX", - "EQUAMAX" - }; - -struct rotation_parameters -{ - gboolean rotated_solution; - gint iterations; - - enum rotation_type method; -}; - - - -static const struct extraction_parameters default_extraction_parameters = {1.0, 0, 25, FALSE, TRUE, FALSE, TRUE, FALSE}; - -static const struct rotation_parameters default_rotation_parameters = {TRUE, 25, ROT_VARIMAX}; - -struct factor -{ - GtkBuilder *xml; - PsppireDict *dict; - - GtkWidget *variables; - PsppireDataWindow *de ; - - /* The Extraction subdialog */ - GtkWidget *extraction_dialog; - GtkWidget *rotation_dialog; - - GtkWidget *n_factors; - GtkWidget *mineigen; - GtkWidget *extract_iterations; - - GtkWidget *nfactors_toggle; - GtkWidget *mineigen_toggle; - - GtkWidget *covariance_toggle; - GtkWidget *correlation_toggle; - - GtkWidget *scree_button; - GtkWidget *unrotated_button; - - GtkWidget *extraction_combo; - - - /* Rotation Widgets */ - GtkWidget *rotate_iterations; - GtkWidget *display_rotated_solution; - GtkWidget *rotation_none; - GtkWidget *rotation_varimax; - GtkWidget *rotation_quartimax; - GtkWidget *rotation_equimax; - - - struct extraction_parameters extraction; - struct rotation_parameters rotation; -}; - -static void -load_rotation_parameters (struct factor *fd, const struct rotation_parameters *p) -{ - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->display_rotated_solution), - p->rotated_solution); - - gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->rotate_iterations), - p->iterations); - - switch (p->method) - { - case ROT_NONE: - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_none), TRUE); - break; - case ROT_VARIMAX: - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_varimax), TRUE); - break; - case ROT_QUARTIMAX: - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_quartimax), TRUE); - break; - case ROT_EQUIMAX: - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_equimax), TRUE); - break; - default: - g_assert_not_reached (); - break; - } -} - -static void -load_extraction_parameters (struct factor *fd, const struct extraction_parameters *p) -{ - gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->mineigen), p->mineigen); - gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->n_factors), p->n_factors); - - gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->extract_iterations), p->n_iterations); - - - if (p->explicit_nfactors) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->nfactors_toggle), TRUE); - else - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->mineigen_toggle), TRUE); - - if (p->covariance) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->covariance_toggle), TRUE); - else - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->correlation_toggle), TRUE); - - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->scree_button), p->scree); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->unrotated_button), p->unrotated); - - if ( p->paf ) - gtk_combo_box_set_active (GTK_COMBO_BOX (fd->extraction_combo), 1); - else - gtk_combo_box_set_active (GTK_COMBO_BOX (fd->extraction_combo), 0); - -} - -static void -set_rotation_parameters (const struct factor *fd, struct rotation_parameters *p) -{ - p->iterations = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->rotate_iterations)); - p->rotated_solution = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->display_rotated_solution)); - - - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->rotation_none))) - p->method = ROT_NONE; - - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->rotation_varimax))) - p->method = ROT_VARIMAX; - - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->rotation_quartimax))) - p->method = ROT_QUARTIMAX; - - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->rotation_equimax))) - p->method = ROT_EQUIMAX; -} - -static void -set_extraction_parameters (const struct factor *fd, struct extraction_parameters *p) -{ - p->mineigen = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->mineigen)); - p->n_factors = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->n_factors)); - p->n_iterations = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->extract_iterations)); - - p->explicit_nfactors = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->nfactors_toggle)); - p->covariance = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->covariance_toggle)); - - p->scree = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->scree_button)); - p->unrotated = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->unrotated_button)); - - p->paf = (gtk_combo_box_get_active (GTK_COMBO_BOX (fd->extraction_combo)) == 1); -} - -static void -run_extractions_subdialog (struct factor *fd) -{ - struct extraction_parameters *ex = &fd->extraction; - - gint response = psppire_dialog_run (PSPPIRE_DIALOG (fd->extraction_dialog)); - - if ( response == PSPPIRE_RESPONSE_CONTINUE ) - { - /* Set the parameters from their respective widgets */ - set_extraction_parameters (fd, ex); - } - else - { - /* Cancelled. Reset the widgets to their old state */ - load_extraction_parameters (fd, ex); - } -} - -static void -run_rotations_subdialog (struct factor *fd) -{ - struct rotation_parameters *rot = &fd->rotation; - - gint response = psppire_dialog_run (PSPPIRE_DIALOG (fd->rotation_dialog)); - - if ( response == PSPPIRE_RESPONSE_CONTINUE ) - { - /* Set the parameters from their respective widgets */ - set_rotation_parameters (fd, rot); - } - else - { - /* Cancelled. Reset the widgets to their old state */ - load_rotation_parameters (fd, rot); - } -} - - -static char * generate_syntax (const struct factor *rd); - - -static void -refresh (struct factor *fd) -{ - GtkTreeModel *liststore = - gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables)); - gtk_list_store_clear (GTK_LIST_STORE (liststore)); - - load_extraction_parameters (fd, &default_extraction_parameters); - load_rotation_parameters (fd, &default_rotation_parameters); -} - - -static gboolean -dialog_state_valid (gpointer data) -{ - struct factor *fd = data; - - GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables)); - - if (gtk_tree_model_iter_n_children (liststore, NULL) < 2) - return FALSE; - - return TRUE; -} - -static void -on_show (struct factor *fd, GtkWidget *dialog) -{ - GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables)); - - gint n_vars = gtk_tree_model_iter_n_children (liststore, NULL); - - gtk_spin_button_set_range (GTK_SPIN_BUTTON (fd->n_factors), 1, n_vars - 1); -} - - -static void -on_extract_toggle (GtkToggleButton *button, struct factor *f) -{ - gboolean active = gtk_toggle_button_get_active (button); - - gtk_widget_set_sensitive (GTK_WIDGET (f->n_factors), active); - gtk_widget_set_sensitive (GTK_WIDGET (f->mineigen), ! active); -} - -/* Pops up the Factor dialog box */ -void -factor_dialog (PsppireDataWindow *dw) -{ - struct factor fd; - gint response; - - PsppireVarStore *vs; - - GtkWidget *dialog ; - GtkWidget *source ; - GtkWidget *extraction_button ; - GtkWidget *rotation_button ; - - fd.xml = builder_new ("factor.ui"); - - fd.extraction = default_extraction_parameters; - fd.rotation = default_rotation_parameters; - - dialog = get_widget_assert (fd.xml, "factor-dialog"); - source = get_widget_assert (fd.xml, "dict-view"); - extraction_button = get_widget_assert (fd.xml, "button-extractions"); - rotation_button = get_widget_assert (fd.xml, "button-rotations"); - - fd.extraction_dialog = get_widget_assert (fd.xml, "extractions-dialog"); - fd.rotation_dialog = get_widget_assert (fd.xml, "rotations-dialog"); - - fd.de = dw; - - g_signal_connect_swapped (dialog, "refresh", G_CALLBACK (refresh), &fd); - - { - GtkWidget *hbox = get_widget_assert (fd.xml, "hbox6"); - GtkWidget *eigenvalue_extraction ; - - fd.mineigen_toggle = get_widget_assert (fd.xml, "mineigen-radiobutton"); - - eigenvalue_extraction = psppire_scanf_new (_("_Eigenvalues over %4.2f times the mean eigenvalue"), &fd.mineigen); - - g_object_set (eigenvalue_extraction, - "use-underline", TRUE, - "mnemonic-widget", fd.mineigen_toggle, - NULL); - - fd.nfactors_toggle = get_widget_assert (fd.xml, "nfactors-radiobutton"); - fd.n_factors = get_widget_assert (fd.xml, "spinbutton-nfactors"); - fd.extract_iterations = get_widget_assert (fd.xml, "spinbutton-extract-iterations"); - fd.covariance_toggle = get_widget_assert (fd.xml, "covariance-radiobutton"); - fd.correlation_toggle = get_widget_assert (fd.xml, "correlations-radiobutton"); - - fd.scree_button = get_widget_assert (fd.xml, "scree-button"); - fd.unrotated_button = get_widget_assert (fd.xml, "unrotated-button"); - fd.extraction_combo = get_widget_assert (fd.xml, "combobox1"); - - gtk_container_add (GTK_CONTAINER (hbox), eigenvalue_extraction); - - g_signal_connect (fd.nfactors_toggle, "toggled", G_CALLBACK (on_extract_toggle), &fd); - - gtk_widget_show_all (eigenvalue_extraction); - } - - { - fd.rotate_iterations = get_widget_assert (fd.xml, "spinbutton-rot-iterations"); - - fd.display_rotated_solution = get_widget_assert (fd.xml, "checkbutton-rotated-solution"); - - fd.rotation_none = get_widget_assert (fd.xml, "radiobutton-none"); - fd.rotation_varimax = get_widget_assert (fd.xml, "radiobutton-varimax"); - fd.rotation_quartimax = get_widget_assert (fd.xml, "radiobutton-quartimax"); - fd.rotation_equimax = get_widget_assert (fd.xml, "radiobutton-equimax"); - } - - g_signal_connect_swapped (extraction_button, "clicked", G_CALLBACK (run_extractions_subdialog), &fd); - g_signal_connect_swapped (rotation_button, "clicked", G_CALLBACK (run_rotations_subdialog), &fd); - - g_signal_connect_swapped (fd.extraction_dialog, "show", G_CALLBACK (on_show), &fd); - - fd.variables = get_widget_assert (fd.xml, "psppire-var-view1"); - - g_object_get (fd.de->data_editor, "var-store", &vs, NULL); - - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fd.de)); - gtk_window_set_transient_for (GTK_WINDOW (fd.extraction_dialog), GTK_WINDOW (fd.de)); - gtk_window_set_transient_for (GTK_WINDOW (fd.rotation_dialog), GTK_WINDOW (fd.de)); - - g_object_get (vs, "dictionary", &fd.dict, NULL); - g_object_set (source, "model", fd.dict, NULL); - - - psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog), - dialog_state_valid, &fd); - - psppire_selector_set_allow (PSPPIRE_SELECTOR (get_widget_assert (fd.xml, "dep-selector")), - numeric_only); - - response = psppire_dialog_run (PSPPIRE_DIALOG (dialog)); - - switch (response) - { - case GTK_RESPONSE_OK: - g_free (execute_syntax_string (dw, generate_syntax (&fd))); - break; - case PSPPIRE_RESPONSE_PASTE: - g_free (paste_syntax_to_window (generate_syntax (&fd))); - break; - default: - break; - } - - g_object_unref (fd.xml); -} - - - - -static char * -generate_syntax (const struct factor *rd) -{ - gchar *text; - - GString *string = g_string_new ("FACTOR "); - - g_string_append (string, "VARIABLES = "); - - psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->variables), 0, string); - - - g_string_append (string, "\n\t/CRITERIA = "); - if ( rd->extraction.explicit_nfactors ) - g_string_append_printf (string, "FACTORS (%d)", rd->extraction.n_factors); - else - g_string_append_printf (string, "MINEIGEN (%g)", rd->extraction.mineigen); - - /* - The CRITERIA = ITERATE subcommand is overloaded. - It applies to the next /ROTATION and/or EXTRACTION command whatever comes first. - */ - g_string_append_printf (string, " ITERATE (%d)", rd->extraction.n_iterations); - - - g_string_append (string, "\n\t/EXTRACTION ="); - if ( rd->extraction.paf) - g_string_append (string, "PAF"); - else - g_string_append (string, "PC"); - - - - - g_string_append (string, "\n\t/METHOD = "); - if ( rd->extraction.covariance ) - g_string_append (string, "COVARIANCE"); - else - g_string_append (string, "CORRELATION"); - - - - if ( rd->extraction.scree ) - { - g_string_append (string, "\n\t/PLOT = "); - g_string_append (string, "EIGEN"); - } - - g_string_append (string, "\n\t/PRINT = "); - g_string_append (string, "INITIAL "); - - if ( rd->extraction.unrotated ) - g_string_append (string, "EXTRACTION "); - - if ( rd->rotation.rotated_solution ) - g_string_append (string, "ROTATION"); - - - /* The CRITERIA = ITERATE subcommand is overloaded. - It applies to the next /ROTATION and/or EXTRACTION command whatever comes first. - */ - g_string_append_printf (string, "\n\t/CRITERIA = ITERATE (%d)", rd->rotation.iterations ); - - g_string_append (string, "\n\t/ROTATION = "); - g_string_append (string, rot_method_syntax[rd->rotation.method]); - - - g_string_append (string, ".\n"); - - text = string->str; - - g_string_free (string, FALSE); - - return text; -} diff --git a/src/ui/gui/factor-dialog.h b/src/ui/gui/factor-dialog.h deleted file mode 100644 index 04ecbca22e..0000000000 --- a/src/ui/gui/factor-dialog.h +++ /dev/null @@ -1,24 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2009, 2010 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 __FACTOR_DIALOG_H -#define __FACTOR_DIALOG_H - -#include "psppire-data-window.h" - -void factor_dialog (PsppireDataWindow * data); - -#endif diff --git a/src/ui/gui/psppire-data-window.c b/src/ui/gui/psppire-data-window.c index 7fa572a173..81fe567c10 100644 --- a/src/ui/gui/psppire-data-window.c +++ b/src/ui/gui/psppire-data-window.c @@ -35,7 +35,6 @@ #include "ui/gui/crosstabs-dialog.h" #include "ui/gui/entry-dialog.h" #include "ui/gui/executor.h" -#include "ui/gui/factor-dialog.h" #include "ui/gui/find-dialog.h" #include "ui/gui/frequencies-dialog.h" #include "ui/gui/goto-case-dialog.h" @@ -1058,53 +1057,31 @@ psppire_data_window_finish_init (PsppireDataWindow *de, connect_action (de, "data_transpose", G_CALLBACK (transpose_dialog)); - connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog)); - connect_action (de, "data_aggregate", G_CALLBACK (aggregate_dialog)); - connect_action (de, "transform_compute", G_CALLBACK (compute_dialog)); - connect_action (de, "transform_autorecode", G_CALLBACK (autorecode_dialog)); - connect_action (de, "edit_find", G_CALLBACK (find_dialog)); - connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog)); - connect_action (de, "data_weight-cases", G_CALLBACK (weight_cases_dialog)); - connect_action (de, "oneway-anova", G_CALLBACK (oneway_anova_dialog)); - connect_action (de, "indep-t-test", G_CALLBACK (t_test_independent_samples_dialog)); - connect_action (de, "paired-t-test", G_CALLBACK (t_test_paired_samples_dialog)); - connect_action (de, "one-sample-t-test", G_CALLBACK (t_test_one_sample_dialog)); - connect_action (de, "utilities_comments", G_CALLBACK (comments_dialog)); - connect_action (de, "transform_count", G_CALLBACK (count_dialog)); - connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog)); - connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog)); - connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog)); - connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog)); connect_action (de, "linear-regression", G_CALLBACK (regression_dialog)); - connect_action (de, "univariate", G_CALLBACK (univariate_dialog)); - - connect_action (de, "factor-analysis", G_CALLBACK (factor_dialog)); - connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog)); connect_action (de, "binomial", G_CALLBACK (binomial_dialog)); connect_action (de, "runs", G_CALLBACK (runs_dialog)); connect_action (de, "ks-one-sample", G_CALLBACK (ks_one_sample_dialog)); connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog)); connect_action (de, "two-related-samples", G_CALLBACK (two_related_dialog)); - { GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER)); diff --git a/src/ui/gui/psppire-dialog-action-factor.c b/src/ui/gui/psppire-dialog-action-factor.c new file mode 100644 index 0000000000..6b6144a6fb --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-factor.c @@ -0,0 +1,379 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2009, 2010, 2011, 2012 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 "psppire-dialog-action-factor.h" + +#include "psppire-var-view.h" +#include "dialog-common.h" +#include "psppire-selector.h" +#include "psppire-dict.h" +#include "psppire-dialog.h" +#include "builder-wrapper.h" +#include "psppire-scanf.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + +static void psppire_dialog_action_factor_class_init (PsppireDialogActionFactorClass *class); + +G_DEFINE_TYPE (PsppireDialogActionFactor, psppire_dialog_action_factor, PSPPIRE_TYPE_DIALOG_ACTION); + +static const char *rot_method_syntax[] = + { + "NOROTATE", + "VARIMAX", + "QUARTIMAX", + "EQUAMAX" + }; + +static void +on_extract_toggle (GtkToggleButton *button, PsppireDialogActionFactor *f) +{ + gboolean active = gtk_toggle_button_get_active (button); + + gtk_widget_set_sensitive (GTK_WIDGET (f->n_factors), active); + gtk_widget_set_sensitive (GTK_WIDGET (f->mineigen), ! active); +} + +static char * +generate_syntax (PsppireDialogAction *act) +{ + PsppireDialogActionFactor *rd = PSPPIRE_DIALOG_ACTION_FACTOR (act); + + gchar *text = NULL; + GString *string = g_string_new ("FACTOR "); + + g_string_append (string, "\n\t/VARIABLES="); + + psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->variables), 0, string); + + + g_string_append (string, "\n\t/CRITERIA = "); + if ( rd->extraction.explicit_nfactors ) + g_string_append_printf (string, "FACTORS (%d)", rd->extraction.n_factors); + else + g_string_append_printf (string, "MINEIGEN (%g)", rd->extraction.mineigen); + + /* + The CRITERIA = ITERATE subcommand is overloaded. + It applies to the next /ROTATION and/or EXTRACTION command whatever comes first. + */ + g_string_append_printf (string, " ITERATE (%d)", rd->extraction.n_iterations); + + + g_string_append (string, "\n\t/EXTRACTION ="); + if ( rd->extraction.paf) + g_string_append (string, "PAF"); + else + g_string_append (string, "PC"); + + + g_string_append (string, "\n\t/METHOD = "); + if ( rd->extraction.covariance ) + g_string_append (string, "COVARIANCE"); + else + g_string_append (string, "CORRELATION"); + + + + if ( rd->extraction.scree ) + { + g_string_append (string, "\n\t/PLOT = "); + g_string_append (string, "EIGEN"); + } + + g_string_append (string, "\n\t/PRINT = "); + g_string_append (string, "INITIAL "); + + if ( rd->extraction.unrotated ) + g_string_append (string, "EXTRACTION "); + + if ( rd->rotation.rotated_solution ) + g_string_append (string, "ROTATION"); + + + /* The CRITERIA = ITERATE subcommand is overloaded. + It applies to the next /ROTATION and/or EXTRACTION command whatever comes first. + */ + g_string_append_printf (string, "\n\t/CRITERIA = ITERATE (%d)", rd->rotation.iterations ); + + g_string_append (string, "\n\t/ROTATION = "); + g_string_append (string, rot_method_syntax[rd->rotation.method]); + + g_string_append (string, "."); + text = string->str; + + g_string_free (string, FALSE); + + return text; +} + +static void +load_rotation_parameters (PsppireDialogActionFactor *fd, const struct rotation_parameters *p) +{ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->display_rotated_solution), + p->rotated_solution); + + gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->rotate_iterations), + p->iterations); + + switch (p->method) + { + case ROT_NONE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_none), TRUE); + break; + case ROT_VARIMAX: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_varimax), TRUE); + break; + case ROT_QUARTIMAX: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_quartimax), TRUE); + break; + case ROT_EQUIMAX: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_equimax), TRUE); + break; + default: + g_assert_not_reached (); + break; + } +} + +static void +load_extraction_parameters (PsppireDialogActionFactor *fd, const struct extraction_parameters *p) +{ + gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->mineigen), p->mineigen); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->n_factors), p->n_factors); + + gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->extract_iterations), p->n_iterations); + + + if (p->explicit_nfactors) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->nfactors_toggle), TRUE); + else + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->mineigen_toggle), TRUE); + + if (p->covariance) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->covariance_toggle), TRUE); + else + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->correlation_toggle), TRUE); + + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->scree_button), p->scree); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->unrotated_button), p->unrotated); + + if ( p->paf ) + gtk_combo_box_set_active (GTK_COMBO_BOX (fd->extraction_combo), 1); + else + gtk_combo_box_set_active (GTK_COMBO_BOX (fd->extraction_combo), 0); + +} + +static gboolean +dialog_state_valid (PsppireDialogActionFactor *da) +{ + GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (da->variables)); + + if (gtk_tree_model_iter_n_children (liststore, NULL) < 2) + return FALSE; + + return TRUE; +} + +static const struct extraction_parameters default_extraction_parameters = + {1.0, 0, 25, FALSE, TRUE, FALSE, TRUE, FALSE}; + +static const struct rotation_parameters default_rotation_parameters = + {TRUE, 25, ROT_VARIMAX}; + +static void +dialog_refresh (PsppireDialogAction *da) +{ + PsppireDialogActionFactor *fd = PSPPIRE_DIALOG_ACTION_FACTOR (da); + GtkTreeModel *liststore = + gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables)); + gtk_list_store_clear (GTK_LIST_STORE (liststore)); + + load_extraction_parameters (fd, &default_extraction_parameters); + load_rotation_parameters (fd, &default_rotation_parameters); +} + + + +static void +set_rotation_parameters (PsppireDialogActionFactor *act, struct rotation_parameters *p) +{ + p->iterations = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->rotate_iterations)); + p->rotated_solution = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->display_rotated_solution)); + + + if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->rotation_none))) + p->method = ROT_NONE; + + if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->rotation_varimax))) + p->method = ROT_VARIMAX; + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->rotation_quartimax))) + p->method = ROT_QUARTIMAX; + + if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->rotation_equimax))) + p->method = ROT_EQUIMAX; +} + +static void +set_extraction_parameters (PsppireDialogActionFactor *act, struct extraction_parameters *p) +{ + p->mineigen = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->mineigen)); + p->n_factors = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->n_factors)); + p->n_iterations = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->extract_iterations)); + + p->explicit_nfactors = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->nfactors_toggle)); + p->covariance = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->covariance_toggle)); + + p->scree = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->scree_button)); + p->unrotated = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->unrotated_button)); + + p->paf = (gtk_combo_box_get_active (GTK_COMBO_BOX (act->extraction_combo)) == 1); +} + + +static void +run_extractions_subdialog (PsppireDialogActionFactor *act) +{ + struct extraction_parameters *ex = &act->extraction; + + gint response = psppire_dialog_run (PSPPIRE_DIALOG (act->extraction_dialog)); + + if ( response == PSPPIRE_RESPONSE_CONTINUE ) + { + /* Set the parameters from their respective widgets */ + set_extraction_parameters (act, ex); + } + else + { + /* Cancelled. Reset the widgets to their old state */ + load_extraction_parameters (act, ex); + } +} + +static void +run_rotations_subdialog (PsppireDialogActionFactor *act) +{ + struct rotation_parameters *rot = &act->rotation; + + gint response = psppire_dialog_run (PSPPIRE_DIALOG (act->rotation_dialog)); + + if ( response == PSPPIRE_RESPONSE_CONTINUE ) + { + /* Set the parameters from their respective widgets */ + set_rotation_parameters (act, rot); + } + else + { + /* Cancelled. Reset the widgets to their old state */ + load_rotation_parameters (act, rot); + } +} + +static void +psppire_dialog_action_factor_activate (GtkAction *a) +{ + PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a); + PsppireDialogActionFactor *act = PSPPIRE_DIALOG_ACTION_FACTOR (a); + GtkWidget *extraction_button ; + GtkWidget *rotation_button ; + + GtkBuilder *xml = builder_new ("factor.ui"); + + pda->dialog = get_widget_assert (xml, "factor-dialog"); + pda->source = get_widget_assert (xml, "dict-view"); + + extraction_button = get_widget_assert (xml, "button-extractions"); + rotation_button = get_widget_assert (xml, "button-rotations"); + + act->extraction_dialog = get_widget_assert (xml, "extractions-dialog"); + act->rotation_dialog = get_widget_assert (xml, "rotations-dialog"); + + act->variables = get_widget_assert (xml, "psppire-var-view1"); + + { + GtkWidget *hbox = get_widget_assert (xml, "hbox6"); + GtkWidget *eigenvalue_extraction ; + + act->mineigen_toggle = get_widget_assert (xml, "mineigen-radiobutton"); + + eigenvalue_extraction = psppire_scanf_new (_("_Eigenvalues over %4.2f times the mean eigenvalue"), &act->mineigen); + + g_object_set (eigenvalue_extraction, + "use-underline", TRUE, + "mnemonic-widget", act->mineigen_toggle, + NULL); + + act->nfactors_toggle = get_widget_assert (xml, "nfactors-radiobutton"); + act->n_factors = get_widget_assert (xml, "spinbutton-nfactors"); + act->extract_iterations = get_widget_assert (xml, "spinbutton-extract-iterations"); + act->covariance_toggle = get_widget_assert (xml, "covariance-radiobutton"); + act->correlation_toggle = get_widget_assert (xml, "correlations-radiobutton"); + + act->scree_button = get_widget_assert (xml, "scree-button"); + act->unrotated_button = get_widget_assert (xml, "unrotated-button"); + act->extraction_combo = get_widget_assert (xml, "combobox1"); + + gtk_container_add (GTK_CONTAINER (hbox), eigenvalue_extraction); + + g_signal_connect (act->nfactors_toggle, "toggled", G_CALLBACK (on_extract_toggle), act); + + gtk_widget_show_all (eigenvalue_extraction); + } + + { + act->rotate_iterations = get_widget_assert (xml, "spinbutton-rot-iterations"); + + act->display_rotated_solution = get_widget_assert (xml, "checkbutton-rotated-solution"); + + act->rotation_none = get_widget_assert (xml, "radiobutton-none"); + act->rotation_varimax = get_widget_assert (xml, "radiobutton-varimax"); + act->rotation_quartimax = get_widget_assert (xml, "radiobutton-quartimax"); + act->rotation_equimax = get_widget_assert (xml, "radiobutton-equimax"); + } + + g_signal_connect_swapped (extraction_button, "clicked", + G_CALLBACK (run_extractions_subdialog), act); + g_signal_connect_swapped (rotation_button, "clicked", G_CALLBACK (run_rotations_subdialog), act); + + + psppire_dialog_action_set_valid_predicate (pda, (void *) dialog_state_valid); + psppire_dialog_action_set_refresh (pda, dialog_refresh); + + PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_factor_parent_class)->activate (pda); + + g_object_unref (xml); +} + +static void +psppire_dialog_action_factor_class_init (PsppireDialogActionFactorClass *class) +{ + GTK_ACTION_CLASS (class)->activate = psppire_dialog_action_factor_activate; + + PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax; +} + +static void +psppire_dialog_action_factor_init (PsppireDialogActionFactor *act) +{ +} diff --git a/src/ui/gui/psppire-dialog-action-factor.h b/src/ui/gui/psppire-dialog-action-factor.h new file mode 100644 index 0000000000..432a717863 --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-factor.h @@ -0,0 +1,138 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2012 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 __PSPPIRE_DIALOG_ACTION_FACTOR_H__ +#define __PSPPIRE_DIALOG_ACTION_FACTOR_H__ + +#include +#include + +#include "psppire-dialog-action.h" + +G_BEGIN_DECLS + + +#define PSPPIRE_TYPE_DIALOG_ACTION_FACTOR (psppire_dialog_action_factor_get_type ()) + +#define PSPPIRE_DIALOG_ACTION_FACTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_FACTOR, PsppireDialogActionFactor)) + +#define PSPPIRE_DIALOG_ACTION_FACTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + PSPPIRE_TYPE_DIALOG_ACTION_FACTOR, \ + PsppireDialogActionFactorClass)) + + +#define PSPPIRE_IS_DIALOG_ACTION_FACTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_FACTOR)) + +#define PSPPIRE_IS_DIALOG_ACTION_FACTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_FACTOR)) + + +#define PSPPIRE_DIALOG_ACTION_FACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_FACTOR, \ + PsppireDialogActionFactorClass)) + +typedef struct _PsppireDialogActionFactor PsppireDialogActionFactor; +typedef struct _PsppireDialogActionFactorClass PsppireDialogActionFactorClass; + + +enum rotation_type { + ROT_NONE, + ROT_VARIMAX, + ROT_QUARTIMAX, + ROT_EQUIMAX +}; + +struct rotation_parameters +{ + gboolean rotated_solution; + gint iterations; + + enum rotation_type method; +}; + +struct extraction_parameters +{ + gdouble mineigen; + gint n_factors; + gint n_iterations; + + gboolean explicit_nfactors; + gboolean covariance; + + gboolean scree; + gboolean unrotated; + + gboolean paf; +}; + + +struct _PsppireDialogActionFactor +{ + PsppireDialogAction parent; + + /*< private >*/ + GtkWidget *variables ; + + /* The Extraction subdialog */ + GtkWidget *extraction_dialog; + GtkWidget *rotation_dialog; + + GtkWidget *n_factors; + GtkWidget *mineigen; + GtkWidget *extract_iterations; + + GtkWidget *nfactors_toggle; + GtkWidget *mineigen_toggle; + + GtkWidget *covariance_toggle; + GtkWidget *correlation_toggle; + + GtkWidget *scree_button; + GtkWidget *unrotated_button; + + GtkWidget *extraction_combo; + + + /* Rotation Widgets */ + GtkWidget *rotate_iterations; + GtkWidget *display_rotated_solution; + GtkWidget *rotation_none; + GtkWidget *rotation_varimax; + GtkWidget *rotation_quartimax; + GtkWidget *rotation_equimax; + + + struct extraction_parameters extraction; + struct rotation_parameters rotation; +}; + + +struct _PsppireDialogActionFactorClass +{ + PsppireDialogActionClass parent_class; +}; + + +GType psppire_dialog_action_factor_get_type (void) ; + +G_END_DECLS + +#endif /* __PSPPIRE_DIALOG_ACTION_FACTOR_H__ */ diff --git a/src/ui/gui/widgets.c b/src/ui/gui/widgets.c index 2a0cc21bb4..9ef2ae8833 100644 --- a/src/ui/gui/widgets.c +++ b/src/ui/gui/widgets.c @@ -16,6 +16,7 @@ #include "psppire-dialog-action-correlation.h" #include "psppire-dialog-action-descriptives.h" #include "psppire-dialog-action-examine.h" +#include "psppire-dialog-action-factor.h" #include "psppire-dialog-action-kmeans.h" #include "psppire-dialog-action-means.h" #include "psppire-means-layer.h" @@ -47,6 +48,7 @@ preregister_widgets (void) psppire_dialog_action_correlation_get_type (); psppire_dialog_action_descriptives_get_type (); psppire_dialog_action_examine_get_type (); + psppire_dialog_action_factor_get_type (); psppire_dialog_action_kmeans_get_type (); psppire_dialog_action_means_get_type (); psppire_means_layer_get_type ();