Change license from GPLv2+ to GPLv3+.
[pspp-builds.git] / src / ui / gui / dict-display.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
18 #include <config.h>
19 #include <gettext.h>
20 #include <gtk/gtk.h>
21
22 #include "dict-display.h"
23
24 #include "psppire-dict.h"
25 #include "helper.h"
26 #include <data/variable.h>
27
28 #define _(msgid) gettext (msgid)
29 #define N_(msgid) msgid
30
31
32 /* A GtkTreeModelFilterVisibleFunc to filter lines in the treeview */
33 static gboolean
34 filter_variables (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
35 {
36   var_predicate_func *predicate = data;
37   struct variable *var;
38   PsppireDict *dict = PSPPIRE_DICT (model);
39
40   GtkTreePath *path = gtk_tree_model_get_path (model, iter);
41
42   gint *idx = gtk_tree_path_get_indices (path);
43
44   var =  psppire_dict_get_variable (dict, *idx);
45
46   gtk_tree_path_free (path);
47
48   return predicate (var);
49 }
50
51 /* A GtkTreeCellDataFunc which sets the icon appropriate to the type
52    of variable */
53 static void
54 var_icon_cell_data_func (GtkTreeViewColumn *col,
55                        GtkCellRenderer *cell,
56                        GtkTreeModel *model,
57                        GtkTreeIter *iter,
58                        gpointer data)
59 {
60   struct variable *var;
61   gtk_tree_model_get (model, iter, DICT_TVM_COL_VAR, &var, -1);
62
63   if ( var_is_alpha (var))
64     {
65       g_object_set (cell, "stock-id", "var-string", NULL);
66     }
67   else
68     {
69       const struct fmt_spec *fs = var_get_write_format (var);
70       int cat = fmt_get_category (fs->type);
71       switch ( var_get_measure (var))
72         {
73         case MEASURE_NOMINAL:
74           g_object_set (cell, "stock-id", "var-nominal", NULL);
75           break;
76         case MEASURE_ORDINAL:
77           g_object_set (cell, "stock-id", "var-ordinal", NULL);
78           break;
79         case MEASURE_SCALE:
80           if ( ( FMT_CAT_DATE | FMT_CAT_TIME ) & cat )
81             g_object_set (cell, "stock-id", "var-date-scale", NULL);
82           else
83             g_object_set (cell, "stock-id", "var-scale", NULL);
84           break;
85         default:
86           g_assert_not_reached ();
87         };
88     }
89 }
90
91
92 void
93 get_base_model (GtkTreeModel *top_model, GtkTreeIter *top_iter,
94                 GtkTreeModel **model, GtkTreeIter *iter
95                 )
96 {
97   *model = top_model;
98   *iter = *top_iter;
99   while (GTK_IS_TREE_MODEL_FILTER (*model))
100     {
101       GtkTreeIter parent_iter = *iter;
102       GtkTreeModelFilter *parent_model = GTK_TREE_MODEL_FILTER (*model);
103
104       *model = gtk_tree_model_filter_get_model (parent_model);
105
106       gtk_tree_model_filter_convert_iter_to_child_iter (parent_model,
107                                                         iter,
108                                                         &parent_iter);
109     }
110
111   g_assert (PSPPIRE_IS_DICT (*model));
112 }
113
114 /* A GtkTreeCellDataFunc which renders the name and/or label of the
115    variable */
116 static void
117 var_description_cell_data_func (GtkTreeViewColumn *col,
118                                 GtkCellRenderer *cell,
119                                 GtkTreeModel *top_model,
120                                 GtkTreeIter *top_iter,
121                                 gpointer data)
122 {
123   struct variable *var;
124   GtkTreeIter iter;
125   GtkTreeModel *model;
126
127
128   get_base_model (top_model, top_iter, &model, &iter);
129
130   g_assert (PSPPIRE_IS_DICT (model));
131
132
133   gtk_tree_model_get (model,
134                       &iter, DICT_TVM_COL_VAR, &var, -1);
135
136   if ( var_has_label (var))
137     {
138       gchar *text = g_strdup_printf (
139                                      "<span stretch=\"condensed\">%s</span>"
140                                      " (<span weight=\"bold\">%s</span>)",
141                                      var_get_label (var),
142                                      var_get_name (var));
143
144       char *utf8 = pspp_locale_to_utf8 (text, -1, NULL);
145
146       g_free (text);
147       g_object_set (cell, "markup", utf8, NULL);
148       g_free (utf8);
149     }
150   else
151     {
152       g_object_set (cell, "text", var_get_name (var), NULL);
153     }
154 }
155
156    /* Sets up TREEVIEW to display the variables of DICT.
157    MODE is the selection mode for TREEVIEW.
158    PREDICATE determines which variables should be visible, or NULL if
159    all are to be visible.
160  */
161 void
162 attach_dictionary_to_treeview (GtkTreeView *treeview, PsppireDict *dict,
163                                GtkSelectionMode mode,
164                                var_predicate_func *predicate
165                                )
166 {
167   GtkTreeViewColumn *col;
168
169   GtkTreeSelection *selection =
170     gtk_tree_view_get_selection (treeview);
171
172   GtkCellRenderer *renderer;
173
174   GtkTreeModel *model ;
175
176   if ( predicate )
177     {
178       model = gtk_tree_model_filter_new (GTK_TREE_MODEL (dict),
179                                           NULL);
180
181       gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model),
182                                               filter_variables,
183                                               predicate,
184                                               NULL);
185     }
186   else
187     {
188       model = GTK_TREE_MODEL (dict);
189     }
190
191   gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), model);
192
193
194   col = gtk_tree_view_column_new ();
195   gtk_tree_view_column_set_title (col, _("Variable"));
196
197   renderer = gtk_cell_renderer_pixbuf_new ();
198   gtk_tree_view_column_pack_start (col, renderer, FALSE);
199
200   gtk_tree_view_column_set_cell_data_func (col, renderer,
201                                            var_icon_cell_data_func,
202                                            NULL, NULL);
203
204
205   renderer = gtk_cell_renderer_text_new ();
206   gtk_tree_view_column_pack_start (col, renderer, TRUE);
207   gtk_tree_view_column_set_cell_data_func (col, renderer,
208                                            var_description_cell_data_func,
209                                            NULL, NULL);
210
211   g_object_set (renderer, "ellipsize-set", TRUE, NULL);
212   g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL);
213
214   gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
215
216   /* FIXME: make this a value in terms of character widths */
217   gtk_tree_view_column_set_min_width (col, 150);
218
219   gtk_tree_view_append_column (treeview, col);
220
221   gtk_tree_selection_set_mode (selection, mode);
222 }
223
224
225 void
226 insert_source_row_into_entry (GtkTreeIter iter,
227                               GtkWidget *dest,
228                               GtkTreeModel *model
229                               )
230 {
231   GtkTreePath *path;
232   GtkTreeModel *dict;
233   gint *idx;
234   struct variable *var;
235   GtkTreeIter dict_iter;
236   gchar *name;
237
238   g_return_if_fail (GTK_IS_ENTRY(dest));
239
240   get_base_model (model, &iter, &dict, &dict_iter);
241
242   path = gtk_tree_model_get_path (GTK_TREE_MODEL (dict), &dict_iter);
243
244   idx = gtk_tree_path_get_indices (path);
245
246   var =  psppire_dict_get_variable (PSPPIRE_DICT (dict), *idx);
247
248   gtk_tree_path_free (path);
249
250   name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
251   gtk_entry_set_text (GTK_ENTRY (dest),  name);
252   g_free (name);
253 }
254
255
256
257 void
258 insert_source_row_into_tree_view (GtkTreeIter iter,
259                                   GtkWidget *dest,
260                                   GtkTreeModel *model
261                                   )
262 {
263   GtkTreePath *path;
264   GtkTreeIter dest_iter;
265   GtkTreeIter dict_iter;
266   gint *row ;
267   GtkTreeModel *destmodel = gtk_tree_view_get_model ( GTK_TREE_VIEW (dest));
268
269   GtkTreeModel *dict;
270
271
272   get_base_model (model, &iter, &dict, &dict_iter);
273
274   path = gtk_tree_model_get_path (dict, &dict_iter);
275
276   row = gtk_tree_path_get_indices (path);
277
278   gtk_list_store_append (GTK_LIST_STORE (destmodel),  &dest_iter);
279   gtk_list_store_set (GTK_LIST_STORE (destmodel), &dest_iter, 0, *row, -1);
280
281   gtk_tree_path_free (path);
282 }
283
284
285 gboolean
286 is_currently_in_entry (GtkTreeModel *model, GtkTreeIter *iter,
287                        PsppireSelector *selector)
288 {
289   gboolean result;
290   gchar *name;
291   GtkTreeIter dict_iter;
292   GtkTreeModel *dict;
293   struct variable *var;
294   gint dict_index;
295   gint *indeces;
296   GtkTreePath *path;
297   const gchar *text =   gtk_entry_get_text (GTK_ENTRY (selector->dest));
298
299   get_base_model (model, iter, &dict, &dict_iter);
300
301   path = gtk_tree_model_get_path (dict, &dict_iter);
302
303   indeces = gtk_tree_path_get_indices (path);
304
305   dict_index = indeces [0];
306
307   var = psppire_dict_get_variable (PSPPIRE_DICT (dict), dict_index);
308
309   gtk_tree_path_free (path);
310
311   name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
312   result = ( 0 == strcmp (text, name));
313   g_free (name);
314
315   return result;
316 }
317
318