1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2007, 2009, 2010, 2011, 2012, 2016 Free Software Foundation
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "psppire-dialog-action-indep-samps.h"
21 #include "psppire-value-entry.h"
23 #include "dialog-common.h"
24 #include <ui/syntax-gen.h>
25 #include "psppire-var-view.h"
27 #include "t-test-options.h"
29 #include "psppire-dialog.h"
30 #include "builder-wrapper.h"
32 #include "psppire-dict.h"
33 #include "libpspp/str.h"
36 psppire_dialog_action_indep_samps_class_init (PsppireDialogActionIndepSampsClass
*class);
38 G_DEFINE_TYPE (PsppireDialogActionIndepSamps
, psppire_dialog_action_indep_samps
, PSPPIRE_TYPE_DIALOG_ACTION
);
41 dialog_state_valid (gpointer data
)
43 PsppireDialogActionIndepSamps
*act
= PSPPIRE_DIALOG_ACTION_INDEP_SAMPS (data
);
45 GtkTreeModel
*vars
= gtk_tree_view_get_model (GTK_TREE_VIEW (act
->test_vars_tv
));
49 if (NULL
== act
->grp_var
)
52 if (0 == gtk_tree_model_get_iter_first (vars
, ¬used
))
55 if (act
->group_defn
== GROUPS_UNDEF
)
63 refresh (PsppireDialogAction
*da
)
65 PsppireDialogActionIndepSamps
*act
= PSPPIRE_DIALOG_ACTION_INDEP_SAMPS (da
);
67 GtkTreeModel
*model
= gtk_tree_view_get_model (GTK_TREE_VIEW (act
->test_vars_tv
));
69 act
->group_defn
= GROUPS_UNDEF
;
73 const int width
= act
->grp_var_width
;
74 value_destroy (&act
->cut_point
, width
);
75 value_destroy (&act
->grp_val
[0], width
);
76 value_destroy (&act
->grp_val
[1], width
);
77 var_unref (act
->grp_var
);
79 act
->grp_var_width
= -1;
82 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act
->dg_grp_entry
[0]), NULL
);
83 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act
->dg_grp_entry
[1]), NULL
);
84 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act
->dg_cut_point_entry
), NULL
);
86 gtk_entry_set_text (GTK_ENTRY (act
->group_var_entry
), "");
88 gtk_list_store_clear (GTK_LIST_STORE (model
));
90 gtk_widget_set_sensitive (act
->define_groups_button
, FALSE
);
93 /* Return TRUE if VE contains a text which is not valid for VAR or if it
94 contains the SYSMIS value */
96 value_entry_contains_invalid (PsppireValueEntry
*ve
, const struct variable
*var
)
98 gboolean result
= FALSE
;
103 const int width
= var_get_width (var
);
104 value_init (&val
, width
);
106 if (psppire_value_entry_get_value (ve
, &val
, width
))
108 if (var_is_value_missing (var
, &val
) == MV_SYSTEM
)
116 value_destroy (&val
, width
);
122 /* Returns TRUE iff the define groups subdialog has a
123 state which defines a valid group criterion */
125 define_groups_state_valid (gpointer data
)
127 PsppireDialogActionIndepSamps
*act
= data
;
129 if (act
->grp_var
== NULL
)
132 if (gtk_toggle_button_get_active
133 (GTK_TOGGLE_BUTTON (act
->dg_values_toggle_button
)))
135 if (value_entry_contains_invalid (PSPPIRE_VALUE_ENTRY (act
->dg_grp_entry
[0]),
139 if (value_entry_contains_invalid (PSPPIRE_VALUE_ENTRY (act
->dg_grp_entry
[1]),
145 if (value_entry_contains_invalid (PSPPIRE_VALUE_ENTRY (act
->dg_cut_point_entry
),
155 run_define_groups (PsppireDialogActionIndepSamps
*act
)
158 PsppireDialogAction
*da
= PSPPIRE_DIALOG_ACTION (act
);
159 GtkWidget
*parent1
= gtk_widget_get_parent (act
->dg_table1
);
160 GtkWidget
*parent2
= gtk_widget_get_parent (act
->dg_table2
);
162 g_return_if_fail (act
->grp_var
);
165 gtk_container_remove (GTK_CONTAINER (parent1
), act
->dg_table1
);
168 gtk_container_remove (GTK_CONTAINER (parent2
), act
->dg_table2
);
170 if (var_is_numeric (act
->grp_var
))
172 gtk_grid_attach (GTK_GRID (act
->dg_table1
), act
->dg_table2
,
175 gtk_container_add (GTK_CONTAINER (act
->dg_box
), act
->dg_table1
);
179 gtk_container_add (GTK_CONTAINER (act
->dg_box
), act
->dg_table2
);
180 act
->group_defn
= GROUPS_VALUES
;
184 psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (act
->dg_dialog
),
185 define_groups_state_valid
, act
);
187 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act
->dg_grp_entry
[0]), act
->grp_var
);
188 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act
->dg_grp_entry
[1]), act
->grp_var
);
189 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act
->dg_cut_point_entry
), act
->grp_var
);
191 if (act
->group_defn
!= GROUPS_CUT_POINT
)
193 gtk_toggle_button_set_active
194 (GTK_TOGGLE_BUTTON (act
->dg_cut_point_toggle_button
), TRUE
);
196 gtk_toggle_button_set_active
197 (GTK_TOGGLE_BUTTON (act
->dg_values_toggle_button
), TRUE
);
201 gtk_toggle_button_set_active
202 (GTK_TOGGLE_BUTTON (act
->dg_values_toggle_button
), TRUE
);
204 gtk_toggle_button_set_active
205 (GTK_TOGGLE_BUTTON (act
->dg_cut_point_toggle_button
), TRUE
);
208 g_signal_emit_by_name (act
->dg_grp_entry
[0], "changed");
209 g_signal_emit_by_name (act
->dg_grp_entry
[1], "changed");
210 g_signal_emit_by_name (act
->dg_cut_point_entry
, "changed");
212 response
= psppire_dialog_run (PSPPIRE_DIALOG (act
->def_grps_dialog
));
214 if (response
== PSPPIRE_RESPONSE_CONTINUE
)
216 const int width
= var_get_width (act
->grp_var
);
218 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act
->dg_values_toggle_button
)))
220 act
->group_defn
= GROUPS_VALUES
;
222 psppire_value_entry_get_value (PSPPIRE_VALUE_ENTRY (act
->dg_grp_entry
[0]),
223 &act
->grp_val
[0], width
);
225 psppire_value_entry_get_value (PSPPIRE_VALUE_ENTRY (act
->dg_grp_entry
[1]),
226 &act
->grp_val
[1], width
);
230 act
->group_defn
= GROUPS_CUT_POINT
;
232 psppire_value_entry_get_value (PSPPIRE_VALUE_ENTRY (act
->dg_cut_point_entry
),
233 &act
->cut_point
, width
);
236 psppire_dialog_notify_change (PSPPIRE_DIALOG (da
->dialog
));
240 /* Called whenever the group variable entry widget's contents change */
242 on_grp_var_change (GtkEntry
*entry
, PsppireDialogActionIndepSamps
*act
)
244 PsppireDialogAction
*da
= PSPPIRE_DIALOG_ACTION (act
);
245 const gchar
*text
= gtk_entry_get_text (entry
);
247 struct variable
*v
= da
->dict
? psppire_dict_lookup_var (da
->dict
, text
) : NULL
;
249 gtk_widget_set_sensitive (act
->define_groups_button
, v
!= NULL
);
253 const int width
= act
->grp_var_width
;
254 value_destroy (&act
->cut_point
, width
);
255 value_destroy (&act
->grp_val
[0], width
);
256 value_destroy (&act
->grp_val
[1], width
);
261 const int width
= var_get_width (v
);
262 value_init (&act
->cut_point
, width
);
263 value_init (&act
->grp_val
[0], width
);
264 value_init (&act
->grp_val
[1], width
);
268 act
->cut_point
.f
= SYSMIS
;
269 act
->grp_val
[0].f
= SYSMIS
;
270 act
->grp_val
[1].f
= SYSMIS
;
274 act
->cut_point
.s
[0] = '\0';
275 act
->grp_val
[0].s
[0] = '\0';
276 act
->grp_val
[1].s
[0] = '\0';
280 struct variable
*old_grp_var
= act
->grp_var
;
282 act
->grp_var
= var_ref (v
);
284 var_unref (old_grp_var
);
285 act
->grp_var_width
= v
? var_get_width (v
) : -1;
289 set_group_criterion_type (GtkToggleButton
*button
,
290 PsppireDialogActionIndepSamps
*act
)
292 gboolean by_values
= gtk_toggle_button_get_active (button
);
294 gtk_widget_set_sensitive (act
->dg_label
, by_values
);
295 gtk_widget_set_sensitive (act
->dg_table2
, by_values
);
297 gtk_widget_set_sensitive (act
->dg_hbox1
, !by_values
);
302 psppire_dialog_action_indep_samps_activate (PsppireDialogAction
*a
, GVariant
*param
)
304 PsppireDialogActionIndepSamps
*act
= PSPPIRE_DIALOG_ACTION_INDEP_SAMPS (a
);
305 PsppireDialogAction
*pda
= PSPPIRE_DIALOG_ACTION (a
);
307 GtkBuilder
*xml
= builder_new ("indep-samples.ui");
309 pda
->dialog
= get_widget_assert (xml
,"independent-samples-dialog");
310 pda
->source
= get_widget_assert (xml
, "indep-samples-treeview1");
311 act
->define_groups_button
= get_widget_assert (xml
, "define-groups-button");
312 act
->options_button
= get_widget_assert (xml
, "indep-samples-options-button");
314 act
->def_grps_dialog
= get_widget_assert (xml
, "define-groups-dialog");
315 act
->group_var_entry
= get_widget_assert (xml
, "indep-samples-entry");
316 act
->test_vars_tv
= get_widget_assert (xml
, "indep-samples-treeview2");
318 act
->dg_dialog
= get_widget_assert (xml
, "define-groups-dialog");
319 act
->dg_grp_entry
[0] = get_widget_assert (xml
, "group1-entry");
320 act
->dg_grp_entry
[1] = get_widget_assert (xml
, "group2-entry");
321 act
->dg_cut_point_entry
= get_widget_assert (xml
, "cut-point-entry");
322 act
->dg_box
= get_widget_assert (xml
, "dialog-hbox2");
324 act
->dg_table1
= get_widget_assert (xml
, "table1");
325 act
->dg_table2
= get_widget_assert (xml
, "table2");
326 act
->dg_label
= get_widget_assert (xml
, "label4");
327 act
->dg_hbox1
= get_widget_assert (xml
, "hbox1");
328 act
->dg_values_toggle_button
= get_widget_assert (xml
, "radiobutton3");
329 act
->dg_cut_point_toggle_button
= get_widget_assert (xml
, "radiobutton4");
331 act
->opts
= tt_options_dialog_create (GTK_WINDOW (pda
->toplevel
));
333 g_object_ref (act
->dg_table1
);
334 g_object_ref (act
->dg_table2
);
336 g_signal_connect (act
->dg_values_toggle_button
, "toggled",
337 G_CALLBACK (set_group_criterion_type
), act
);
339 psppire_dialog_action_set_refresh (pda
, refresh
);
341 psppire_dialog_action_set_valid_predicate (pda
,
344 g_signal_connect_swapped (act
->define_groups_button
, "clicked",
345 G_CALLBACK (run_define_groups
), act
);
347 g_signal_connect_swapped (act
->options_button
, "clicked",
348 G_CALLBACK (tt_options_dialog_run
), act
->opts
);
351 g_signal_connect (act
->group_var_entry
, "changed",
352 G_CALLBACK (on_grp_var_change
), act
);
354 on_grp_var_change (GTK_ENTRY (act
->group_var_entry
), act
);
362 generate_syntax (const PsppireDialogAction
*a
)
364 PsppireDialogActionIndepSamps
*act
= PSPPIRE_DIALOG_ACTION_INDEP_SAMPS (a
);
367 GString
*str
= g_string_new ("T-TEST /VARIABLES=");
369 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (act
->test_vars_tv
), 0, str
);
371 g_string_append (str
, "\n\t/GROUPS=");
373 g_string_append (str
, var_get_name (act
->grp_var
));
375 if (act
->group_defn
!= GROUPS_UNDEF
)
377 g_string_append (str
, "(");
380 const union value
*val
=
381 (act
->group_defn
== GROUPS_VALUES
) ?
386 ds_init_empty (&strx
);
387 syntax_gen_value (&strx
, val
, var_get_width (act
->grp_var
),
388 var_get_print_format (act
->grp_var
));
390 g_string_append (str
, ds_cstr (&strx
));
394 if (act
->group_defn
== GROUPS_VALUES
)
396 g_string_append (str
, ",");
400 ds_init_empty (&strx
);
402 syntax_gen_value (&strx
, &act
->grp_val
[1], var_get_width (act
->grp_var
),
403 var_get_print_format (act
->grp_var
));
405 g_string_append (str
, ds_cstr (&strx
));
410 g_string_append (str
, ")");
413 tt_options_dialog_append_syntax (act
->opts
, str
);
415 g_string_append (str
, ".\n");
419 g_string_free (str
, FALSE
);
425 psppire_dialog_action_indep_samps_class_init (PsppireDialogActionIndepSampsClass
*class)
427 PSPPIRE_DIALOG_ACTION_CLASS (class)->initial_activate
= psppire_dialog_action_indep_samps_activate
;
429 PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax
= generate_syntax
;
434 psppire_dialog_action_indep_samps_init (PsppireDialogActionIndepSamps
*act
)
437 act
->grp_var_width
= -1;
438 act
->group_defn
= GROUPS_UNDEF
;