723a65e4a3bf5751b0923961db90bdf36000e989
[pspp-builds.git] / src / ui / gui / dialog-common.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2007  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 #include "dialog-common.h"
19
20 #include "helper.h"
21
22
23 /* Append the names of selected variables to STRING.
24    TREEVIEW is the treeview containing the variables.
25    DICT is the dictionary for those variables.
26 */
27 gint
28 append_variable_names (GString *string,
29                        PsppireDict *dict, GtkTreeView *treeview)
30 {
31   gint n_vars = 0;
32   GtkTreeIter iter;
33
34   GtkTreeModel *list_store =
35     gtk_tree_view_get_model (treeview);
36
37   if ( gtk_tree_model_get_iter_first (list_store, &iter) )
38     {
39       do
40         {
41           GValue value = {0};
42           struct variable *var;
43           GtkTreePath *path = gtk_tree_model_get_path (list_store, &iter);
44
45           gtk_tree_model_get_value (list_store, &iter, 0, &value);
46
47           var = psppire_dict_get_variable (dict, g_value_get_int (&value));
48           g_value_unset (&value);
49
50           g_string_append (string, " ");
51           g_string_append (string, var_get_name (var));
52
53           gtk_tree_path_free (path);
54           n_vars++;
55         }
56       while (gtk_tree_model_iter_next (list_store, &iter));
57     }
58
59   return n_vars;
60 }
61
62
63
64 struct variable *
65 get_selected_variable (GtkTreeModel *treemodel,
66                        GtkTreeIter *iter,
67                        PsppireDict *dict)
68 {
69   struct variable *var;
70   GValue value = {0};
71
72   GtkTreePath *path = gtk_tree_model_get_path (treemodel, iter);
73
74   gtk_tree_model_get_value (treemodel, iter, 0, &value);
75
76   gtk_tree_path_free (path);
77
78   var =  psppire_dict_get_variable (dict, g_value_get_int (&value));
79
80   g_value_unset (&value);
81
82   return var;
83 }
84
85
86
87
88 /* A (*GtkTreeCellDataFunc) function.
89    This function expects TREEMODEL to hold G_TYPE_INT.  The ints it holds
90    are the indices of the variables in the dictionary, which DATA points to.
91    It renders the name of the variable into CELL.
92 */
93 void
94 cell_var_name (GtkTreeViewColumn *tree_column,
95                GtkCellRenderer *cell,
96                GtkTreeModel *tree_model,
97                GtkTreeIter *iter,
98                gpointer data)
99 {
100   PsppireDict *dict = data;
101   struct variable *var;
102   gchar *name;
103
104   var = get_selected_variable (tree_model, iter, dict);
105
106   name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
107   g_object_set (cell, "text", name, NULL);
108   g_free (name);
109 }
110
111
112
113 /* Set a model for DEST, which is an GtkListStore of g_int's
114    whose values are the indices into DICT */
115 void
116 set_dest_model (GtkTreeView *dest, PsppireDict *dict)
117 {
118   GtkTreeViewColumn *col;
119   GtkListStore *dest_list = gtk_list_store_new (1, G_TYPE_INT);
120   GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
121
122   gtk_tree_view_set_model (GTK_TREE_VIEW (dest), GTK_TREE_MODEL (dest_list));
123
124   col = gtk_tree_view_column_new_with_attributes ("Var",
125                                                   renderer,
126                                                   "text",
127                                                   0,
128                                                   NULL);
129
130   gtk_tree_view_column_set_cell_data_func (col, renderer,
131                                            cell_var_name,
132                                            dict, 0);
133
134   /* FIXME: make this a value in terms of character widths */
135   g_object_set (col, "min-width",  100, NULL);
136
137   gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
138
139   gtk_tree_view_append_column (GTK_TREE_VIEW (dest), col);
140 }
141
142
143
144 /* Returns FALSE if the variables represented by the union of the rows
145    currently selected by SOURCE widget, and contents of the DEST
146    widget, are of different types.
147
148    In other words, this function when passed as the argument to
149    psppire_selector_set_allow, ensures that the selector selects only
150    string  variables, or only numeric variables, not a mixture.
151 */
152 gboolean
153 homogeneous_types (GtkWidget *source, GtkWidget *dest)
154 {
155   gboolean ok;
156   GtkTreeIter iter;
157   gboolean retval = TRUE;
158
159   GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (source));
160
161   PsppireDict *dict;
162   GtkTreeSelection *selection;
163   enum val_type type = -1;
164   GList *list, *l;
165
166   while (GTK_IS_TREE_MODEL_FILTER (model))
167     {
168       model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
169     }
170
171   dict = PSPPIRE_DICT (model);
172
173   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (source));
174
175   list = gtk_tree_selection_get_selected_rows (selection, &model);
176
177   /* Iterate through the selection of the source treeview */
178   for (l = list; l ; l = l->next)
179     {
180       GtkTreePath *path = l->data;
181       GtkTreePath *fpath;
182       gint *idx;
183
184       const struct variable *v;
185
186       fpath = gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (model), path);
187
188       idx = gtk_tree_path_get_indices (fpath);
189
190       v = psppire_dict_get_variable (dict, idx[0]);
191
192       if ( type != -1 )
193         {
194           if ( var_get_type (v) != type )
195             {
196               retval = FALSE;
197               break;
198             }
199         }
200
201       type = var_get_type (v);
202     }
203
204   g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
205   g_list_free (list);
206
207   if ( retval == FALSE )
208     return FALSE;
209
210   /* now deal with the dest widget */
211   model = gtk_tree_view_get_model (GTK_TREE_VIEW (dest));
212
213   for (ok = gtk_tree_model_get_iter_first (model, &iter);
214        ok;
215        ok = gtk_tree_model_iter_next (model, &iter))
216     {
217       gint idx;
218       const struct variable *v;
219       gtk_tree_model_get (model, &iter, 0, &idx, -1);
220
221       v = psppire_dict_get_variable (dict, idx);
222
223       if ( type != -1 )
224         {
225           if ( var_get_type (v) != type )
226             {
227               retval = FALSE;
228               break;
229             }
230         }
231
232       type = var_get_type (v);
233     }
234
235
236   return retval;
237 }
238