1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2015 Free Software Foundation
3
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.
8
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.
13
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/>. */
16
17
18 #include <config.h>
19
20 #include "psppire-dialog-action-descriptives.h"
21
22 #include "psppire-checkbox-treeview.h"
23
24 #include "psppire-var-view.h"
25 #include "psppire-dict.h"
26 #include "psppire-dialog.h"
27 #include "builder-wrapper.h"
28
29 #include "gettext.h"
30 #define _(msgid) gettext (msgid)
31 #define N_(msgid) msgid
32
33 static void psppire_dialog_action_descriptives_class_init (PsppireDialogActionDescriptivesClass *class);
34
35 G_DEFINE_TYPE (PsppireDialogActionDescriptives, psppire_dialog_action_descriptives, PSPPIRE_TYPE_DIALOG_ACTION);
36
37
38 #define DESCRIPTIVE_STATS \
39 DS (MEAN, N_("Mean"), NULL) \
40 DS (STDDEV, N_("Standard deviation"), NULL) \
41 DS (MINIMUM, N_("Minimum"), N_("Minimum value")) \
42 DS (MAXIMUM, N_("Maximum"), N_("Maximum value")) \
43 DS (RANGE, N_("Range"), NULL) \
44 DS (SUM, N_("Sum"), NULL) \
45 DS (SEMEAN, N_("Standard error"), N_("Standard error of mean")) \
46 DS (VARIANCE, N_("Variance"), NULL) \
47 DS (KURTOSIS, N_("Kurtosis"), N_("Kurtosis and standard error of kurtosis")) \
48 DS (SKEWNESS, N_("Skewness"), N_("Skewness and standard error of skewness"))
49
50 enum
51 {
52 #define DS(NAME, LABEL, TOOLTIP) DS_##NAME,
53 DESCRIPTIVE_STATS
54 #undef DS
55 N_DESCRIPTIVE_STATS
56 };
57
58 enum
59 {
60 #define DS(NAME, LABEL, TOOLTIP) B_DS_##NAME = 1u << DS_##NAME,
61 DESCRIPTIVE_STATS
62 #undef DS
63 B_DS_ALL = (1u << N_DESCRIPTIVE_STATS) - 1,
64 B_DS_DEFAULT = B_DS_MEAN | B_DS_STDDEV | B_DS_MINIMUM | B_DS_MAXIMUM
65 };
66
67
68 static const struct checkbox_entry_item stats[] =
69 {
70 #define DS(NAME, LABEL, TOOLTIP) {#NAME, LABEL, TOOLTIP},
71 DESCRIPTIVE_STATS
72 #undef DS
73 };
74
75
76 static char *
generate_syntax(const PsppireDialogAction * act)77 generate_syntax (const PsppireDialogAction *act)
78 {
79 PsppireDialogActionDescriptives *scd = PSPPIRE_DIALOG_ACTION_DESCRIPTIVES (act);
80 gchar *text;
81 GString *string;
82 GtkTreeIter iter;
83 unsigned int selected;
84 size_t i;
85 bool listwise, include;
86 bool ok;
87
88 string = g_string_new ("DESCRIPTIVES");
89 g_string_append (string, "\n /VARIABLES=");
90 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (scd->stat_vars), 0, string);
91
92 listwise = gtk_toggle_button_get_active (scd->exclude_missing_listwise);
93 include = gtk_toggle_button_get_active (scd->include_user_missing);
94 if (listwise || include)
95 {
96 g_string_append (string, "\n /MISSING=");
97 if (listwise)
98 {
99 g_string_append (string, "LISTWISE");
100 if (include)
101 g_string_append (string, " ");
102 }
103 if (include)
104 g_string_append (string, "INCLUDE");
105 }
106
107 selected = 0;
108 for (i = 0, ok = gtk_tree_model_get_iter_first (scd->stats, &iter); ok;
109 i++, ok = gtk_tree_model_iter_next (scd->stats, &iter))
110 {
111 gboolean toggled;
112 gtk_tree_model_get (scd->stats, &iter,
113 CHECKBOX_COLUMN_SELECTED, &toggled, -1);
114 if (toggled)
115 selected |= 1u << i;
116 }
117
118 if (selected != B_DS_DEFAULT)
119 {
120 g_string_append (string, "\n /STATISTICS=");
121 if (selected == B_DS_ALL)
122 g_string_append (string, "ALL");
123 else if (selected == 0)
124 g_string_append (string, "NONE");
125 else
126 {
127 int n = 0;
128 if ((selected & B_DS_DEFAULT) == B_DS_DEFAULT)
129 {
130 g_string_append (string, "DEFAULT");
131 selected &= ~B_DS_DEFAULT;
132 n++;
133 }
134 for (i = 0; i < N_DESCRIPTIVE_STATS; i++)
135 if (selected & (1u << i))
136 {
137 if (n++)
138 g_string_append (string, " ");
139 g_string_append (string, stats[i].name);
140 }
141 }
142 }
143
144 if (gtk_toggle_button_get_active (scd->save_z_scores))
145 g_string_append (string, "\n /SAVE");
146
147 g_string_append (string, ".");
148
149 if (gtk_toggle_button_get_active (scd->save_z_scores))
150 g_string_append (string, "\nEXECUTE.");
151
152 text = string->str;
153
154 g_string_free (string, FALSE);
155
156 return text;
157 }
158
159 static gboolean
dialog_state_valid(gpointer data)160 dialog_state_valid (gpointer data)
161 {
162 PsppireDialogActionDescriptives *dd = data;
163
164 GtkTreeModel *vars = gtk_tree_view_get_model (dd->stat_vars);
165
166 GtkTreeIter notused;
167
168 return gtk_tree_model_get_iter_first (vars, ¬used);
169 }
170
171 static void
dialog_refresh(PsppireDialogAction * scd_)172 dialog_refresh (PsppireDialogAction *scd_)
173 {
174 PsppireDialogActionDescriptives *scd
175 = PSPPIRE_DIALOG_ACTION_DESCRIPTIVES (scd_);
176 GtkTreeModel *liststore;
177 GtkTreeIter iter;
178 size_t i;
179 bool ok;
180
181 liststore = gtk_tree_view_get_model (scd->stat_vars);
182 gtk_list_store_clear (GTK_LIST_STORE (liststore));
183
184 for (i = 0, ok = gtk_tree_model_get_iter_first (scd->stats, &iter); ok;
185 i++, ok = gtk_tree_model_iter_next (scd->stats, &iter))
186 gtk_list_store_set (GTK_LIST_STORE (scd->stats), &iter,
187 CHECKBOX_COLUMN_SELECTED,
188 (B_DS_DEFAULT & (1u << i)) ? true : false, -1);
189
190 gtk_toggle_button_set_active (scd->exclude_missing_listwise, false);
191 gtk_toggle_button_set_active (scd->include_user_missing, false);
192 gtk_toggle_button_set_active (scd->save_z_scores, false);
193 }
194
195
196 static GtkBuilder *
psppire_dialog_action_descriptives_activate(PsppireDialogAction * a,GVariant * param)197 psppire_dialog_action_descriptives_activate (PsppireDialogAction *a, GVariant *param)
198 {
199 PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
200 PsppireDialogActionDescriptives *act = PSPPIRE_DIALOG_ACTION_DESCRIPTIVES (a);
201
202 GtkBuilder *xml = builder_new ("descriptives.ui");
203
204 GtkWidget *stats_treeview = get_widget_assert (xml, "statistics");
205 psppire_checkbox_treeview_populate (PSPPIRE_CHECKBOX_TREEVIEW (stats_treeview),
206 B_DS_DEFAULT,
207 N_DESCRIPTIVE_STATS, stats);
208 act->stats = gtk_tree_view_get_model (GTK_TREE_VIEW (stats_treeview));
209
210 pda->dialog = get_widget_assert (xml, "descriptives-dialog");
211 pda->source = get_widget_assert (xml, "all-variables");
212 act->variables = get_widget_assert (xml, "stat-variables");
213
214 g_object_set (pda->source,
215 "predicate", var_is_numeric, NULL);
216
217 act->stat_vars = GTK_TREE_VIEW (act->variables);
218
219 act->include_user_missing =
220 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "include_user_missing"));
221 act->exclude_missing_listwise =
222 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "exclude_missing_listwise"));
223 act->save_z_scores =
224 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "save_z_scores"));
225
226 psppire_dialog_action_set_valid_predicate (pda, dialog_state_valid);
227 psppire_dialog_action_set_refresh (pda, dialog_refresh);
228
229 return xml;
230 }
231
232 static void
psppire_dialog_action_descriptives_class_init(PsppireDialogActionDescriptivesClass * class)233 psppire_dialog_action_descriptives_class_init (PsppireDialogActionDescriptivesClass *class)
234 {
235 PSPPIRE_DIALOG_ACTION_CLASS (class)->initial_activate = psppire_dialog_action_descriptives_activate;
236
237 PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
238 }
239
240 static void
psppire_dialog_action_descriptives_init(PsppireDialogActionDescriptives * act)241 psppire_dialog_action_descriptives_init (PsppireDialogActionDescriptives *act)
242 {
243 }
244