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-barchart.h"
21 #include "psppire-value-entry.h"
22 
23 #include "dialog-common.h"
24 #include <ui/syntax-gen.h>
25 #include "psppire-var-view.h"
26 
27 #include "psppire-dialog.h"
28 #include "builder-wrapper.h"
29 
30 #include "psppire-dict.h"
31 #include "libpspp/str.h"
32 
33 #include "language/stats/chart-category.h"
34 
35 static void
36 psppire_dialog_action_barchart_class_init (PsppireDialogActionBarchartClass *class);
37 
38 G_DEFINE_TYPE (PsppireDialogActionBarchart, psppire_dialog_action_barchart, PSPPIRE_TYPE_DIALOG_ACTION);
39 
40 static gboolean
dialog_state_valid(gpointer rd_)41 dialog_state_valid (gpointer rd_)
42 {
43   PsppireDialogActionBarchart *rd = PSPPIRE_DIALOG_ACTION_BARCHART (rd_);
44 
45   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->button_summary_func)))
46     {
47       if (0 == g_strcmp0 ("", gtk_entry_get_text (GTK_ENTRY (rd->var))))
48 	return FALSE;
49     }
50 
51   if (0 == g_strcmp0 ("", gtk_entry_get_text (GTK_ENTRY (rd->variable_xaxis))))
52     return FALSE;
53 
54   return TRUE;
55 }
56 
57 static void
refresh(PsppireDialogAction * rd_)58 refresh (PsppireDialogAction *rd_)
59 {
60   PsppireDialogActionBarchart *rd = PSPPIRE_DIALOG_ACTION_BARCHART (rd_);
61 
62   gtk_entry_set_text (GTK_ENTRY (rd->var), "");
63   gtk_entry_set_text (GTK_ENTRY (rd->variable_xaxis), "");
64   gtk_entry_set_text (GTK_ENTRY (rd->variable_cluster), "");
65 
66   /* Set summary_func to true, then let it get unset again.
67      This ensures that the signal handler gets called.   */
68   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->button_summary_func), TRUE);
69   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->button_freq_func[0]), TRUE);
70 
71   gtk_widget_set_sensitive (rd->combobox, FALSE);
72 
73   gtk_combo_box_set_active (GTK_COMBO_BOX (rd->combobox), 0);
74 }
75 
76 static void
on_summary_toggle(PsppireDialogActionBarchart * act)77 on_summary_toggle (PsppireDialogActionBarchart *act)
78 {
79   gboolean status = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->button_summary_func));
80 
81   gtk_widget_set_sensitive (act->summary_variables, status);
82   gtk_widget_set_sensitive (act->combobox, status);
83 }
84 
85 static void
populate_combo_model(GtkComboBox * cb)86 populate_combo_model (GtkComboBox *cb)
87 {
88   int i;
89   GtkListStore *list =  gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
90   GtkTreeIter iter;
91   GtkCellRenderer *renderer ;
92 
93   for (i = 0; i < N_AG_FUNCS;  ++i)
94     {
95       const struct ag_func *af = ag_func + i;
96 
97       if (af->arity == 0)
98 	continue;
99 
100       gtk_list_store_append (list, &iter);
101       gtk_list_store_set (list, &iter,
102                           0, af->description,
103 			  1, af->name,
104                           -1);
105     }
106 
107   renderer = gtk_cell_renderer_text_new ();
108   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), renderer, FALSE);
109 
110   gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (cb), renderer, "text", 0);
111 
112   gtk_combo_box_set_model (GTK_COMBO_BOX (cb), GTK_TREE_MODEL (list));
113   g_object_unref (list);
114 }
115 
116 
117 static GtkBuilder *
psppire_dialog_action_barchart_activate(PsppireDialogAction * a,GVariant * param)118 psppire_dialog_action_barchart_activate (PsppireDialogAction *a, GVariant *param)
119 {
120   PsppireDialogActionBarchart *act = PSPPIRE_DIALOG_ACTION_BARCHART (a);
121   PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
122 
123   GtkBuilder *xml = builder_new ("barchart.ui");
124 
125   pda->dialog = get_widget_assert (xml, "barchart-dialog");
126   pda->source = get_widget_assert (xml, "dict-view");
127 
128   act->variable_xaxis = get_widget_assert (xml, "entry1");
129   act->variable_cluster = get_widget_assert (xml, "entry3");
130   act->var = get_widget_assert (xml, "entry2");
131   act->button_freq_func[0] = get_widget_assert (xml, "radiobutton-count");
132   act->button_freq_func[1] = get_widget_assert (xml, "radiobutton-percent");
133   act->button_freq_func[2] = get_widget_assert (xml, "radiobutton-cum-count");
134   act->button_freq_func[3] = get_widget_assert (xml, "radiobutton-cum-percent");
135 
136   act->button_summary_func = get_widget_assert (xml, "radiobutton3");
137   act->summary_variables = get_widget_assert (xml, "hbox1");
138   act->combobox = get_widget_assert (xml, "combobox1");
139 
140   populate_combo_model (GTK_COMBO_BOX(act->combobox));
141 
142   g_signal_connect_swapped (act->button_summary_func, "toggled",
143 			    G_CALLBACK (on_summary_toggle), act);
144 
145   psppire_dialog_action_set_refresh (pda, refresh);
146 
147   psppire_dialog_action_set_valid_predicate (pda,
148 					     dialog_state_valid);
149 
150   return xml;
151 }
152 
153 static char *
generate_syntax(const PsppireDialogAction * a)154 generate_syntax (const PsppireDialogAction *a)
155 {
156   PsppireDialogActionBarchart *rd = PSPPIRE_DIALOG_ACTION_BARCHART (a);
157   gchar *text;
158   const gchar *var_name_xaxis = gtk_entry_get_text (GTK_ENTRY (rd->variable_xaxis));
159   const gchar *var_name_cluster = gtk_entry_get_text (GTK_ENTRY (rd->variable_cluster));
160 
161   GString *string = g_string_new ("GRAPH /BAR = ");
162 
163   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->button_summary_func)))
164     {
165       GtkTreeIter iter;
166       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (rd->combobox), &iter))
167 	{
168 	  GValue value = {0};
169 	  GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (rd->combobox));
170 	  gtk_tree_model_get_value (model, &iter, 1, &value);
171 	  g_string_append (string, g_value_get_string (&value));
172 	  g_value_unset (&value);
173 	}
174       g_string_append (string, " (");
175       g_string_append (string, gtk_entry_get_text (GTK_ENTRY (rd->var)));
176       g_string_append (string, ")");
177     }
178   else
179     {
180       int b;
181       for (b = 0; b < 4; ++b)
182 	{
183 	  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->button_freq_func[b])))
184 	    break;
185 	}
186       switch (b)
187 	{
188 	case 0:
189 	  g_string_append (string, "COUNT");
190 	  break;
191 	case 1:
192 	  g_string_append (string, "PCT");
193 	  break;
194 	case 2:
195 	  g_string_append (string, "CUFREQ");
196 	  break;
197 	case 3:
198 	  g_string_append (string, "CUPCT");
199 	  break;
200 	default:
201 	  g_assert_not_reached ();
202 	  break;
203 	}
204     }
205 
206   g_string_append (string, " BY ");
207   g_string_append (string, var_name_xaxis);
208 
209   if (g_strcmp0 (var_name_cluster, ""))
210   {
211     g_string_append (string, " BY ");
212     g_string_append (string, var_name_cluster);
213   }
214 
215   g_string_append (string, ".\n");
216 
217   text = string->str;
218 
219   g_string_free (string, FALSE);
220 
221   return text;
222 }
223 
224 static void
psppire_dialog_action_barchart_class_init(PsppireDialogActionBarchartClass * class)225 psppire_dialog_action_barchart_class_init (PsppireDialogActionBarchartClass *class)
226 {
227   PSPPIRE_DIALOG_ACTION_CLASS (class)->initial_activate = psppire_dialog_action_barchart_activate;
228 
229   PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
230 }
231 
232 
233 static void
psppire_dialog_action_barchart_init(PsppireDialogActionBarchart * act)234 psppire_dialog_action_barchart_init (PsppireDialogActionBarchart *act)
235 {
236 }
237