1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2012 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-frequencies.h"
21 #include "psppire-value-entry.h"
23 #include "dialog-common.h"
25 #include <ui/syntax-gen.h>
26 #include "psppire-var-view.h"
28 #include "psppire-dialog.h"
29 #include "builder-wrapper.h"
30 #include "psppire-checkbox-treeview.h"
31 #include "psppire-dict.h"
32 #include "libpspp/str.h"
35 #define _(msgid) gettext (msgid)
36 #define N_(msgid) msgid
39 #define FREQUENCY_STATS \
40 FS (MEAN, N_("Mean")) \
41 FS (STDDEV, N_("Standard deviation")) \
42 FS (MINIMUM, N_("Minimum")) \
43 FS (MAXIMUM, N_("Maximum")) \
44 FS (SEMEAN, N_("Standard error of the mean")) \
45 FS (VARIANCE, N_("Variance")) \
46 FS (SKEWNESS, N_("Skewness")) \
47 FS (SESKEW, N_("Standard error of the skewness")) \
48 FS (RANGE, N_("Range")) \
49 FS (MODE, N_("Mode")) \
50 FS (KURTOSIS, N_("Kurtosis")) \
51 FS (SEKURT, N_("Standard error of the kurtosis")) \
52 FS (MEDIAN, N_("Median")) \
59 #define FS(NAME, LABEL) FS_##NAME,
67 #define FS(NAME, LABEL) B_FS_##NAME = 1u << FS_##NAME,
70 B_FS_ALL = (1u << N_FREQUENCY_STATS) - 1,
71 B_FS_DEFAULT = B_FS_MEAN | B_FS_STDDEV | B_FS_MINIMUM | B_FS_MAXIMUM
75 static const struct checkbox_entry_item stats[] = {
76 #define FS(NAME, LABEL) {#NAME, LABEL},
83 on_tables_clicked (PsppireDialogActionFrequencies * fd)
87 switch (fd->tables_opts_order)
90 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->avalue), TRUE);
93 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->dvalue), TRUE);
96 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->afreq), TRUE);
99 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->dfreq), TRUE);
103 switch (fd->tables_opts_table)
106 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->always), TRUE);
109 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->never), TRUE);
112 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->limit), TRUE);
116 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->limit_spinbutton),
117 fd->tables_opts_limit);
119 g_signal_emit_by_name (fd->limit, "toggled");
121 ret = psppire_dialog_run (PSPPIRE_DIALOG (fd->tables_dialog));
123 if (ret == PSPPIRE_RESPONSE_CONTINUE)
125 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->avalue)))
126 fd->tables_opts_order = FRQ_AVALUE;
127 else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->dvalue)))
128 fd->tables_opts_order = FRQ_DVALUE;
129 else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->afreq)))
130 fd->tables_opts_order = FRQ_ACOUNT;
131 else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->dfreq)))
132 fd->tables_opts_order = FRQ_DCOUNT;
134 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->always)))
135 fd->tables_opts_table = FRQ_TABLE;
136 else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->never)))
137 fd->tables_opts_table = FRQ_NOTABLE;
139 fd->tables_opts_table = FRQ_LIMIT;
142 fd->tables_opts_limit =
143 gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->limit_spinbutton));
149 on_charts_clicked (PsppireDialogActionFrequencies *fd)
153 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->min), fd->charts_opts_use_min);
154 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->min_spin), fd->charts_opts_min);
155 g_signal_emit_by_name (fd->min, "toggled");
157 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->max), fd->charts_opts_use_max);
158 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->max_spin), fd->charts_opts_max);
159 g_signal_emit_by_name (fd->max, "toggled");
161 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->hist), fd->charts_opts_draw_hist);
162 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->normal), fd->charts_opts_draw_normal);
163 g_signal_emit_by_name (fd->hist, "toggled");
165 switch (fd->charts_opts_scale)
168 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->freqs), TRUE);
171 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->percents), TRUE);
175 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->pie), fd->charts_opts_draw_pie);
176 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->pie_include_missing),
177 fd->charts_opts_pie_include_missing);
179 g_signal_emit_by_name (fd->pie, "toggled");
182 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->bar), fd->charts_opts_draw_bar);
183 g_signal_emit_by_name (fd->bar, "toggled");
185 ret = psppire_dialog_run (PSPPIRE_DIALOG (fd->charts_dialog));
187 if ( ret == PSPPIRE_RESPONSE_CONTINUE )
189 fd->charts_opts_use_min = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->min));
190 fd->charts_opts_min = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->min_spin));
192 fd->charts_opts_use_max = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->max));
193 fd->charts_opts_max = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->max_spin));
195 fd->charts_opts_draw_hist = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->hist));
196 fd->charts_opts_draw_normal = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->normal));
197 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->freqs)))
198 fd->charts_opts_scale = FRQ_FREQ;
199 else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->percents)))
200 fd->charts_opts_scale = FRQ_PERCENT;
202 fd->charts_opts_draw_pie = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->pie));
203 fd->charts_opts_pie_include_missing
204 = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->pie_include_missing));
207 fd->charts_opts_draw_bar = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->bar));
213 psppire_dialog_action_frequencies_class_init
214 (PsppireDialogActionFrequenciesClass * class);
216 G_DEFINE_TYPE (PsppireDialogActionFrequencies,
217 psppire_dialog_action_frequencies, PSPPIRE_TYPE_DIALOG_ACTION);
220 dialog_state_valid (gpointer data)
222 PsppireDialogActionFrequencies *fd =
223 PSPPIRE_DIALOG_ACTION_FREQUENCIES (data);
226 gtk_tree_view_get_model (GTK_TREE_VIEW (fd->stat_vars));
230 return gtk_tree_model_get_iter_first (vars, ¬used);
234 refresh (PsppireDialogAction * fdx)
236 PsppireDialogActionFrequencies *fd =
237 PSPPIRE_DIALOG_ACTION_FREQUENCIES (fdx);
243 GtkTreeModel *liststore =
244 gtk_tree_view_get_model (GTK_TREE_VIEW (fd->stat_vars));
245 gtk_list_store_clear (GTK_LIST_STORE (liststore));
247 for (i = 0, ok = gtk_tree_model_get_iter_first (fd->stats, &iter); ok;
248 i++, ok = gtk_tree_model_iter_next (fd->stats, &iter))
249 gtk_list_store_set (GTK_LIST_STORE (fd->stats), &iter,
250 CHECKBOX_COLUMN_SELECTED,
251 (B_FS_DEFAULT & (1u << i)) ? true : false, -1);
257 psppire_dialog_action_frequencies_activate (GtkAction * a)
259 PsppireDialogActionFrequencies *act = PSPPIRE_DIALOG_ACTION_FREQUENCIES (a);
260 PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
262 GtkBuilder *xml = builder_new ("frequencies.ui");
264 GtkWidget *stats_treeview = get_widget_assert (xml, "stats-treeview");
265 GtkWidget *tables_button = get_widget_assert (xml, "tables-button");
266 GtkWidget *charts_button = get_widget_assert (xml, "charts-button");
268 pda->dialog = get_widget_assert (xml, "frequencies-dialog");
269 pda->source = get_widget_assert (xml, "dict-treeview");
271 act->stat_vars = get_widget_assert (xml, "var-treeview");
273 psppire_checkbox_treeview_populate (PSPPIRE_CHECKBOX_TREEVIEW (stats_treeview),
274 B_FS_DEFAULT, N_FREQUENCY_STATS, stats);
276 act->stats = gtk_tree_view_get_model (GTK_TREE_VIEW (stats_treeview));
278 act->include_missing = get_widget_assert (xml, "include_missing");
281 act->tables_dialog = get_widget_assert (xml, "tables-dialog");
282 act->charts_dialog = get_widget_assert (xml, "charts-dialog");
283 act->always = get_widget_assert (xml, "always");
284 act->never = get_widget_assert (xml, "never");
285 act->limit = get_widget_assert (xml, "limit");
286 act->limit_spinbutton = get_widget_assert (xml, "limit-spin");
288 g_signal_connect (act->limit, "toggled",
289 G_CALLBACK (set_sensitivity_from_toggle),
290 act->limit_spinbutton);
292 act->avalue = get_widget_assert (xml, "avalue");
293 act->dvalue = get_widget_assert (xml, "dvalue");
294 act->afreq = get_widget_assert (xml, "afreq");
295 act->dfreq = get_widget_assert (xml, "dfreq");
297 act->charts_opts_use_min = false;
298 act->charts_opts_min = 0;
299 act->charts_opts_use_max = false;
300 act->charts_opts_max = 100;
301 act->charts_opts_draw_hist = false;
302 act->charts_opts_draw_normal = false;
303 act->charts_opts_scale = FRQ_FREQ;
304 act->charts_opts_draw_pie = false;
305 act->charts_opts_draw_bar = false;
306 act->charts_opts_pie_include_missing = false;
308 act->freqs = get_widget_assert (xml, "freqs");
309 act->percents = get_widget_assert (xml, "percents");
311 act->min = get_widget_assert (xml, "min");
312 act->min_spin = get_widget_assert (xml, "min-spin");
313 g_signal_connect (act->min, "toggled",
314 G_CALLBACK (set_sensitivity_from_toggle), act->min_spin);
315 act->max = get_widget_assert (xml, "max");
316 act->max_spin = get_widget_assert (xml, "max-spin");
317 g_signal_connect (act->max, "toggled",
318 G_CALLBACK (set_sensitivity_from_toggle), act->max_spin);
320 act->hist = get_widget_assert (xml, "hist");
321 act->normal = get_widget_assert (xml, "normal");
322 g_signal_connect (act->hist, "toggled",
323 G_CALLBACK (set_sensitivity_from_toggle), act->normal);
325 act->pie = (get_widget_assert (xml, "pie"));
326 act->pie_include_missing = get_widget_assert (xml, "pie-include-missing");
328 act->bar = (get_widget_assert (xml, "bar"));
331 g_object_unref (xml);
334 act->tables_opts_order = FRQ_AVALUE;
335 act->tables_opts_table = FRQ_TABLE;
336 act->tables_opts_limit = 50;
338 g_signal_connect_swapped (tables_button, "clicked",
339 G_CALLBACK (on_tables_clicked), act);
341 g_signal_connect_swapped (charts_button, "clicked",
342 G_CALLBACK (on_charts_clicked), act);
344 psppire_dialog_action_set_refresh (pda, refresh);
346 psppire_dialog_action_set_valid_predicate (pda, dialog_state_valid);
348 if (PSPPIRE_DIALOG_ACTION_CLASS
349 (psppire_dialog_action_frequencies_parent_class)->activate)
350 PSPPIRE_DIALOG_ACTION_CLASS
351 (psppire_dialog_action_frequencies_parent_class)->activate (pda);
355 generate_syntax (PsppireDialogAction * a)
357 PsppireDialogActionFrequencies *fd = PSPPIRE_DIALOG_ACTION_FREQUENCIES (a);
365 ds_init_cstr (&str, "FREQUENCIES");
367 ds_put_cstr (&str, "\n\t/VARIABLES=");
368 psppire_var_view_append_names_str (PSPPIRE_VAR_VIEW (fd->stat_vars), 0, &str);
370 ds_put_cstr (&str, "\n\t/FORMAT=");
372 switch (fd->tables_opts_order)
375 ds_put_cstr (&str, "AVALUE");
378 ds_put_cstr (&str, "DVALUE");
381 ds_put_cstr (&str, "AFREQ");
384 ds_put_cstr (&str, "DFREQ");
387 g_assert_not_reached ();
390 ds_put_cstr (&str, " ");
392 switch (fd->tables_opts_table)
395 ds_put_cstr (&str, "TABLE");
398 ds_put_cstr (&str, "NOTABLE");
401 ds_put_c_format (&str, "LIMIT (%d)", fd->tables_opts_limit);
406 for (i = 0, ok = gtk_tree_model_get_iter_first (fd->stats, &iter); ok;
407 i++, ok = gtk_tree_model_iter_next (fd->stats, &iter))
410 gtk_tree_model_get (fd->stats, &iter,
411 CHECKBOX_COLUMN_SELECTED, &toggled, -1);
416 if (selected != B_FS_DEFAULT)
418 ds_put_cstr (&str, "\n\t/STATISTICS=");
419 if (selected == B_FS_ALL)
420 ds_put_cstr (&str, "ALL");
421 else if (selected == 0)
422 ds_put_cstr (&str, "NONE");
426 if ((selected & B_FS_DEFAULT) == B_FS_DEFAULT)
428 ds_put_cstr (&str, "DEFAULT");
429 selected &= ~B_FS_DEFAULT;
432 for (i = 0; i < N_FREQUENCY_STATS; i++)
433 if (selected & (1u << i))
436 ds_put_cstr (&str, " ");
437 ds_put_cstr (&str, stats[i].name);
442 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->include_missing)))
443 ds_put_cstr (&str, "\n\t/MISSING=INCLUDE");
446 if (fd->charts_opts_draw_hist)
448 ds_put_cstr (&str, "\n\t/HISTOGRAM=");
450 fd->charts_opts_draw_normal ? "NORMAL" : "NONORMAL");
452 if (fd->charts_opts_scale == FRQ_PERCENT)
453 ds_put_cstr (&str, " PERCENT");
455 if (fd->charts_opts_use_min)
456 ds_put_c_format (&str, " MIN(%.15g)", fd->charts_opts_min);
457 if (fd->charts_opts_use_max)
458 ds_put_c_format (&str, " MAX(%.15g)", fd->charts_opts_max);
461 if (fd->charts_opts_draw_pie)
463 ds_put_cstr (&str, "\n\t/PIECHART=");
465 if (fd->charts_opts_pie_include_missing)
466 ds_put_cstr (&str, " MISSING");
468 if (fd->charts_opts_use_min)
469 ds_put_c_format (&str, " MIN(%.15g)", fd->charts_opts_min);
470 if (fd->charts_opts_use_max)
471 ds_put_c_format (&str, " MAX(%.15g)", fd->charts_opts_max);
475 if (fd->charts_opts_draw_bar)
477 ds_put_cstr (&str, "\n\t/BARCHART=");
479 if (fd->charts_opts_scale == FRQ_PERCENT)
480 ds_put_cstr (&str, " PERCENT");
482 if (fd->charts_opts_use_min)
483 ds_put_c_format (&str, " MIN(%.15g)", fd->charts_opts_min);
484 if (fd->charts_opts_use_max)
485 ds_put_c_format (&str, " MAX(%.15g)", fd->charts_opts_max);
489 ds_put_cstr (&str, ".\n");
491 text = ds_steal_cstr (&str);
499 psppire_dialog_action_frequencies_class_init (PsppireDialogActionFrequenciesClass *class)
501 psppire_dialog_action_set_activation (class, psppire_dialog_action_frequencies_activate);
502 PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
507 psppire_dialog_action_frequencies_init (PsppireDialogActionFrequencies * act)