1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2007, 2014 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 #include <config.h>
18
19 #include <libpspp/i18n.h>
20 #include "dialog-common.h"
21 #include "dict-display.h"
22
23 #include "psppire-var-ptr.h"
24
25 #include "helper.h"
26
27 /*
28 If m is not a base TreeModel type (ie, is a filter or sorter) then
29 convert OP to a TreePath for the base and return it.
30 The return value must be freed by the caller.
31 */
32 static GtkTreePath *
get_base_tree_path(GtkTreeModel * m,GtkTreePath * op)33 get_base_tree_path (GtkTreeModel *m, GtkTreePath *op)
34 {
35 GtkTreePath *p = gtk_tree_path_copy (op);
36 while (! PSPPIRE_IS_DICT (m))
37 {
38 GtkTreePath *oldp = p;
39
40 if (GTK_IS_TREE_MODEL_FILTER (m))
41 {
42 p = gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (m), oldp);
43 m = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (m));
44 }
45 else if (GTK_IS_TREE_MODEL_SORT (m))
46 {
47 p = gtk_tree_model_sort_convert_path_to_child_path (GTK_TREE_MODEL_SORT (m), oldp);
48 m = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (m));
49 }
50 else
51 {
52 g_error ("Unexpected model type: %s", G_OBJECT_TYPE_NAME (m));
53 }
54
55 gtk_tree_path_free (oldp);
56 }
57
58 return p;
59 }
60
61
62 /* Returns FALSE if the variables represented by the union of the rows
63 currently selected by SOURCE widget, and contents of the DEST
64 widget, are of different types.
65
66 In other words, this function when passed as the argument to
67 psppire_selector_set_allow, ensures that the selector selects only
68 string variables, or only numeric variables, not a mixture.
69 */
70 gboolean
homogeneous_types(GtkWidget * source,GtkWidget * dest)71 homogeneous_types (GtkWidget *source, GtkWidget *dest)
72 {
73 gboolean ok;
74 GtkTreeIter iter;
75 gboolean retval = TRUE;
76
77 GtkTreeModel *top_model = gtk_tree_view_get_model (GTK_TREE_VIEW (source));
78 GtkTreeModel *model;
79
80 PsppireDict *dict;
81 GtkTreeSelection *selection;
82 enum val_type type;
83 GList *list, *l;
84 bool have_type;
85
86
87 get_base_model (top_model, NULL, &model, NULL);
88
89 dict = PSPPIRE_DICT (model);
90
91 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (source));
92
93 list = gtk_tree_selection_get_selected_rows (selection, &model);
94
95 /* Iterate through the selection of the source treeview */
96 have_type = false;
97 for (l = list; l ; l = l->next)
98 {
99 GtkTreePath *p = get_base_tree_path (top_model, l->data);
100 gint *idx = gtk_tree_path_get_indices (p);
101 const struct variable *v = psppire_dict_get_variable (dict, idx[0]);
102
103 gtk_tree_path_free (p);
104
105 if (have_type && var_get_type (v) != type)
106 {
107 retval = FALSE;
108 break;
109 }
110
111 type = var_get_type (v);
112 have_type = true;
113 }
114
115 g_list_foreach (list, GFUNC_COMPAT_CAST (gtk_tree_path_free), NULL);
116 g_list_free (list);
117
118 if (retval == FALSE)
119 return FALSE;
120
121 /* now deal with the dest widget */
122 model = gtk_tree_view_get_model (GTK_TREE_VIEW (dest));
123
124 for (ok = gtk_tree_model_get_iter_first (model, &iter);
125 ok;
126 ok = gtk_tree_model_iter_next (model, &iter))
127 {
128 const struct variable *v;
129 gtk_tree_model_get (model, &iter, 0, &v, -1);
130
131 if (have_type && var_get_type (v) != type)
132 {
133 retval = FALSE;
134 break;
135 }
136
137 type = var_get_type (v);
138 have_type = true;
139 }
140
141 return retval;
142 }
143
144
145
146 /* Returns true iff the variable selected by SOURCE is numeric */
147 gboolean
numeric_only(GtkWidget * source,GtkWidget * dest)148 numeric_only (GtkWidget *source, GtkWidget *dest)
149 {
150 gboolean retval = TRUE;
151
152 GtkTreeModel *top_model = gtk_tree_view_get_model (GTK_TREE_VIEW (source));
153 GtkTreeModel *model = NULL;
154
155 PsppireDict *dict;
156 GtkTreeSelection *selection;
157 GList *list, *l;
158
159 get_base_model (top_model, NULL, &model, NULL);
160
161 dict = PSPPIRE_DICT (model);
162
163 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (source));
164
165 list = gtk_tree_selection_get_selected_rows (selection, &top_model);
166
167 /* Iterate through the selection of the source treeview */
168 for (l = list; l ; l = l->next)
169 {
170 GtkTreePath *p = get_base_tree_path (top_model, l->data);
171 gint *idx = gtk_tree_path_get_indices (p);
172 const struct variable *v = psppire_dict_get_variable (dict, idx[0]);
173 gtk_tree_path_free (p);
174
175 if (var_is_alpha (v))
176 {
177 retval = FALSE;
178 break;
179 }
180 }
181
182 g_list_foreach (list, GFUNC_COMPAT_CAST (gtk_tree_path_free), NULL);
183 g_list_free (list);
184
185 return retval;
186 }
187
188 /*
189 A pair of functions intended to be used as callbacks for the "toggled" signal
190 of a GtkToggleButton widget. They make the sensitivity of W follow the status
191 of the togglebutton.
192 */
193 void
set_sensitivity_from_toggle(GtkToggleButton * togglebutton,GtkWidget * w)194 set_sensitivity_from_toggle (GtkToggleButton *togglebutton, GtkWidget *w)
195 {
196 gboolean active = gtk_toggle_button_get_active (togglebutton);
197
198 gtk_widget_set_sensitive (w, active);
199 if (active)
200 gtk_widget_grab_focus (w);
201 }
202
203 /* */
204 void
set_sensitivity_from_toggle_invert(GtkToggleButton * togglebutton,GtkWidget * w)205 set_sensitivity_from_toggle_invert (GtkToggleButton *togglebutton,
206 GtkWidget *w)
207 {
208 gboolean active = gtk_toggle_button_get_active (togglebutton);
209
210 gtk_widget_set_sensitive (w, !active);
211 }
212
213
214
215