84e4bda76bc5d14b2bfa16133a0499eef093b5ec
[pspp] / src / ui / gui / psppire-dialog-action-count.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2011, 2012, 2013  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-count.h"
21
22 #include "psppire-var-view.h"
23
24 #include "psppire-dialog.h"
25 #include "psppire-selector.h"
26 #include "builder-wrapper.h"
27 #include "psppire-acr.h"
28 #include "dialog-common.h"
29
30 #include <ui/syntax-gen.h>
31
32 #include "psppire-val-chooser.h"
33 #include "helper.h"
34
35
36 static void values_dialog (PsppireDialogActionCount *cd);
37
38
39 static void psppire_dialog_action_count_init            (PsppireDialogActionCount      *act);
40 static void psppire_dialog_action_count_class_init      (PsppireDialogActionCountClass *class);
41
42 G_DEFINE_TYPE (PsppireDialogActionCount, psppire_dialog_action_count, PSPPIRE_TYPE_DIALOG_ACTION);
43
44
45 static char *
46 generate_syntax (PsppireDialogAction *act)
47 {
48   PsppireDialogActionCount *cnt = PSPPIRE_DIALOG_ACTION_COUNT (act);
49   gchar *text = NULL;
50   const gchar *s = NULL;
51   gboolean ok;
52   GtkTreeIter iter;
53   struct string dds;
54   
55   ds_init_empty (&dds);
56
57   ds_put_cstr (&dds, "\nCOUNT ");
58
59   ds_put_cstr (&dds, gtk_entry_get_text (GTK_ENTRY (cnt->target)));
60
61   ds_put_cstr (&dds, " =");
62
63   psppire_var_view_append_names_str (PSPPIRE_VAR_VIEW (cnt->variable_treeview), 0, &dds);
64
65   ds_put_cstr (&dds, "(");
66   for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cnt->value_list),
67                                            &iter);
68        ok;
69        ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (cnt->value_list), &iter))
70     {
71       GValue a_value = {0};
72       struct old_value *ov;
73
74       gtk_tree_model_get_value (GTK_TREE_MODEL (cnt->value_list), &iter,
75                                 0, &a_value);
76
77       ov = g_value_get_boxed (&a_value);
78
79       ds_put_cstr (&dds, " ");
80       old_value_append_syntax (&dds, ov);
81     }
82   ds_put_cstr (&dds, ").");
83
84
85   s = gtk_entry_get_text (GTK_ENTRY (cnt->label));
86   if (0 != strcmp (s, ""))
87   {
88     ds_put_cstr (&dds, "\nVARIABLE LABELS ");
89
90     ds_put_cstr (&dds, gtk_entry_get_text (GTK_ENTRY (cnt->target)));
91
92     ds_put_cstr (&dds, " ");
93
94     syntax_gen_string (&dds, ss_cstr (s));
95
96     ds_put_cstr (&dds, ".");
97   }
98
99   ds_put_cstr (&dds, "\nEXECUTE.\n");
100
101   text = ds_steal_cstr (&dds);
102
103   ds_destroy (&dds);
104
105   return text;
106 }
107
108
109 static gboolean
110 dialog_state_valid (gpointer data)
111 {
112   PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (data);
113   PsppireDialogActionCount *cnt = PSPPIRE_DIALOG_ACTION_COUNT (pda);
114
115   GtkTreeIter iter;
116
117   if (! cnt->value_list)
118     return FALSE;
119
120   if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cnt->value_list), &iter) )
121     return FALSE;
122
123   if (!gtk_tree_model_get_iter_first (gtk_tree_view_get_model (GTK_TREE_VIEW (cnt->variable_treeview)), &iter))
124     return FALSE;
125
126   if (0 == strcmp ("", gtk_entry_get_text (GTK_ENTRY (cnt->target))))
127     return FALSE;
128
129   return TRUE;
130 }
131
132 static void
133 refresh (PsppireDialogAction *rd_)
134 {
135   PsppireDialogActionCount *cnt = PSPPIRE_DIALOG_ACTION_COUNT (rd_);
136
137   GtkTreeModel *vars =
138     gtk_tree_view_get_model (GTK_TREE_VIEW (cnt->variable_treeview));
139
140   gtk_list_store_clear (GTK_LIST_STORE (vars));
141
142   gtk_entry_set_text (GTK_ENTRY (cnt->target), "");
143   gtk_entry_set_text (GTK_ENTRY (cnt->label), "");
144   gtk_list_store_clear (GTK_LIST_STORE (cnt->value_list));
145 }
146
147 static void
148 psppire_dialog_action_count_activate (GtkAction *a)
149 {
150   PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
151   PsppireDialogActionCount *act = PSPPIRE_DIALOG_ACTION_COUNT (a);
152
153   GHashTable *thing = psppire_dialog_action_get_hash_table (pda);
154   GtkBuilder *xml = g_hash_table_lookup (thing, a);
155   if (!xml)
156     {
157       xml = builder_new ("count.ui");
158       g_hash_table_insert (thing, a, xml);
159     }
160
161   GtkWidget *selector = get_widget_assert (xml, "count-selector1");
162   GtkWidget *button = get_widget_assert (xml, "button1");
163
164   pda->dialog = get_widget_assert   (xml, "count-dialog");
165   pda->source = get_widget_assert   (xml, "dict-view");
166
167
168   act->target = get_widget_assert (xml, "entry1");
169   act->label = get_widget_assert (xml, "entry2");
170   act->variable_treeview = get_widget_assert (xml, "treeview2");
171
172   act->value_list = gtk_list_store_new (1, old_value_get_type ());
173
174   psppire_selector_set_allow (PSPPIRE_SELECTOR (selector),  numeric_only);
175
176   g_signal_connect_swapped (button, "clicked", G_CALLBACK (values_dialog), act);
177
178   psppire_dialog_action_set_valid_predicate (pda, dialog_state_valid);
179   psppire_dialog_action_set_refresh (pda, refresh);
180
181   if (PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_count_parent_class)->activate)
182     PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_count_parent_class)->activate (pda);
183 }
184
185 static void
186 psppire_dialog_action_count_class_init (PsppireDialogActionCountClass *class)
187 {
188   psppire_dialog_action_set_activation (class,psppire_dialog_action_count_activate);
189   PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
190 }
191
192
193 static void
194 psppire_dialog_action_count_init (PsppireDialogActionCount *act)
195 {
196 }
197
198
199
200 \f
201
202
203 /* Callback which gets called when a new row is selected
204    in the acr's variable treeview.
205    We use if to set the togglebuttons and entries to correspond to the
206    selected row.
207 */
208 static void
209 on_acr_selection_change (GtkTreeSelection *selection, gpointer data)
210 {
211   GtkTreeIter iter;
212   struct old_value *ov = NULL;
213   GtkTreeModel *model = NULL;
214   PsppireDialogActionCount *cnt = PSPPIRE_DIALOG_ACTION_COUNT (data);
215   GValue ov_value = {0};
216
217   if ( ! gtk_tree_selection_get_selected (selection, &model, &iter) )
218     return;
219
220   gtk_tree_model_get_value (GTK_TREE_MODEL (model), &iter,
221                             0, &ov_value);
222
223   ov = g_value_get_boxed (&ov_value);
224   psppire_val_chooser_set_status (PSPPIRE_VAL_CHOOSER (cnt->chooser), ov);
225 }
226
227
228 /* A function to set a value in a column in the ACR */
229 static gboolean
230 set_value (gint col, GValue  *val, gpointer data)
231 {
232   PsppireDialogActionCount *cnt = PSPPIRE_DIALOG_ACTION_COUNT (data);
233   PsppireValChooser *vc = PSPPIRE_VAL_CHOOSER (cnt->chooser);
234   struct old_value ov;
235         
236   g_assert (col == 0);
237
238   psppire_val_chooser_get_status (vc, &ov);
239
240   g_value_init (val, old_value_get_type ());
241   g_value_set_boxed (val, &ov);
242
243   return TRUE;
244 }
245
246
247 static void
248 values_dialog (PsppireDialogActionCount *cd)
249 {
250   PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (cd);
251   gint response;
252   GtkListStore *local_store = clone_list_store (cd->value_list);
253   GtkBuilder *builder = builder_new ("count.ui");
254
255   GtkWidget *dialog = get_widget_assert (builder, "values-dialog");
256
257   GtkWidget *acr = get_widget_assert (builder, "acr");
258   cd->chooser = get_widget_assert (builder, "value-chooser");
259
260   psppire_acr_set_enabled (PSPPIRE_ACR (acr), TRUE);
261
262   psppire_acr_set_model (PSPPIRE_ACR (acr), local_store);
263   psppire_acr_set_get_value_func (PSPPIRE_ACR (acr), set_value, cd);
264
265   {
266     GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (PSPPIRE_ACR(acr)->tv));
267     g_signal_connect (sel, "changed",
268                     G_CALLBACK (on_acr_selection_change), cd);
269   }
270
271   response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
272
273   if ( response == PSPPIRE_RESPONSE_CONTINUE )
274     {
275       g_object_unref (cd->value_list);
276       cd->value_list = local_store;
277     }
278   else
279     {
280       g_object_unref (local_store);
281     }
282
283   psppire_dialog_notify_change (PSPPIRE_DIALOG (pda->dialog));
284
285   g_object_unref (builder);
286 }
287
288