Convert variable name to utf8 before displaying in tooltips
[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 #include <data/format.h>
28
29 #define _(msgid) gettext (msgid)
30 #define N_(msgid) msgid
31
32
33 /* A GtkTreeModelFilterVisibleFunc to filter lines in the treeview */
34 static gboolean
35 filter_variables (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
36 {
37   var_predicate_func *predicate = data;
38   struct variable *var;
39   PsppireDict *dict = PSPPIRE_DICT (model);
40
41   GtkTreePath *path = gtk_tree_model_get_path (model, iter);
42
43   gint *idx = gtk_tree_path_get_indices (path);
44
45   var =  psppire_dict_get_variable (dict, *idx);
46
47   gtk_tree_path_free (path);
48
49   return predicate (var);
50 }
51
52 /* A GtkTreeCellDataFunc which sets the icon appropriate to the type
53    of variable */
54 static void
55 var_icon_cell_data_func (GtkTreeViewColumn *col,
56                        GtkCellRenderer *cell,
57                        GtkTreeModel *model,
58                        GtkTreeIter *iter,
59                        gpointer data)
60 {
61   struct variable *var;
62   gtk_tree_model_get (model, iter, DICT_TVM_COL_VAR, &var, -1);
63
64   if ( var_is_alpha (var))
65     {
66       g_object_set (cell, "stock-id", "var-string", NULL);
67     }
68   else
69     {
70       const struct fmt_spec *fs = var_get_write_format (var);
71       int cat = fmt_get_category (fs->type);
72       switch ( var_get_measure (var))
73         {
74         case MEASURE_NOMINAL:
75           g_object_set (cell, "stock-id", "var-nominal", NULL);
76           break;
77         case MEASURE_ORDINAL:
78           g_object_set (cell, "stock-id", "var-ordinal", NULL);
79           break;
80         case MEASURE_SCALE:
81           if ( ( FMT_CAT_DATE | FMT_CAT_TIME ) & cat )
82             g_object_set (cell, "stock-id", "var-date-scale", NULL);
83           else
84             g_object_set (cell, "stock-id", "var-scale", NULL);
85           break;
86         default:
87           g_assert_not_reached ();
88         };
89     }
90 }
91
92
93 void
94 get_base_model (GtkTreeModel *top_model, GtkTreeIter *top_iter,
95                 GtkTreeModel **model, GtkTreeIter *iter
96                 )
97 {
98   *model = top_model;
99   *iter = *top_iter;
100   while (GTK_IS_TREE_MODEL_FILTER (*model))
101     {
102       GtkTreeIter parent_iter = *iter;
103       GtkTreeModelFilter *parent_model = GTK_TREE_MODEL_FILTER (*model);
104
105       *model = gtk_tree_model_filter_get_model (parent_model);
106
107       gtk_tree_model_filter_convert_iter_to_child_iter (parent_model,
108                                                         iter,
109                                                         &parent_iter);
110     }
111
112   g_assert (PSPPIRE_IS_DICT (*model));
113 }
114
115 /* A GtkTreeCellDataFunc which renders the name and/or label of the
116    variable */
117 static void
118 var_description_cell_data_func (GtkTreeViewColumn *col,
119                                 GtkCellRenderer *cell,
120                                 GtkTreeModel *top_model,
121                                 GtkTreeIter *top_iter,
122                                 gpointer data)
123 {
124   struct variable *var;
125   GtkTreeIter iter;
126   GtkTreeModel *model;
127
128
129   get_base_model (top_model, top_iter, &model, &iter);
130
131   g_assert (PSPPIRE_IS_DICT (model));
132
133
134   gtk_tree_model_get (model,
135                       &iter, DICT_TVM_COL_VAR, &var, -1);
136
137   if ( var_has_label (var))
138     {
139       gchar *text = g_strdup_printf (
140                                      "<span stretch=\"condensed\">%s</span>",
141                                      var_get_label (var));
142
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
157 #if GTK_CHECK_VERSION (2, 12, 0)
158 /* Sets the tooltip to be the name of the variable under the cursor */
159 static gboolean
160 set_tooltip_for_variable (GtkTreeView  *treeview,
161                           gint        x,
162                           gint        y,
163                           gboolean    keyboard_mode,
164                           GtkTooltip *tooltip,
165                           gpointer    user_data)
166
167 {
168   gint bx, by;
169   GtkTreeIter iter;
170   GtkTreePath *path;
171   GtkTreeModel *tree_model;
172   struct variable *var = NULL;
173   gboolean ok;
174
175
176   gtk_tree_view_convert_widget_to_bin_window_coords (treeview,
177                                                      x, y, &bx, &by);
178
179   if (!gtk_tree_view_get_path_at_pos (treeview, bx, by,
180                                       &path, NULL, NULL, NULL))
181     return FALSE;
182
183   tree_model = gtk_tree_view_get_model (treeview);
184
185
186   gtk_tree_view_set_tooltip_row (treeview, tooltip, path);
187
188   ok = gtk_tree_model_get_iter (tree_model, &iter, path);
189
190   gtk_tree_path_free (path);
191   if (!ok)
192     return FALSE;
193
194
195   gtk_tree_model_get (tree_model, &iter, DICT_TVM_COL_VAR,  &var, -1);
196
197   if ( ! var_has_label (var))
198     return FALSE;
199
200   {
201     char *name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
202
203     gtk_tooltip_set_text (tooltip, name);
204
205     g_free (name);
206   }
207
208   return TRUE;
209 }
210 #endif
211
212    /* Sets up TREEVIEW to display the variables of DICT.
213    MODE is the selection mode for TREEVIEW.
214    PREDICATE determines which variables should be visible, or NULL if
215    all are to be visible.
216  */
217 void
218 attach_dictionary_to_treeview (GtkTreeView *treeview, PsppireDict *dict,
219                                GtkSelectionMode mode,
220                                var_predicate_func *predicate
221                                )
222 {
223   GtkTreeViewColumn *col;
224
225   GtkTreeSelection *selection =
226     gtk_tree_view_get_selection (treeview);
227
228   GtkCellRenderer *renderer;
229
230   GtkTreeModel *model ;
231
232   if ( predicate )
233     {
234       model = gtk_tree_model_filter_new (GTK_TREE_MODEL (dict),
235                                           NULL);
236
237       gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model),
238                                               filter_variables,
239                                               predicate,
240                                               NULL);
241     }
242   else
243     {
244       model = GTK_TREE_MODEL (dict);
245     }
246
247   gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), model);
248
249
250   col = gtk_tree_view_column_new ();
251   gtk_tree_view_column_set_title (col, _("Variable"));
252
253   renderer = gtk_cell_renderer_pixbuf_new ();
254   gtk_tree_view_column_pack_start (col, renderer, FALSE);
255
256   gtk_tree_view_column_set_cell_data_func (col, renderer,
257                                            var_icon_cell_data_func,
258                                            NULL, NULL);
259
260
261   renderer = gtk_cell_renderer_text_new ();
262   gtk_tree_view_column_pack_start (col, renderer, TRUE);
263   gtk_tree_view_column_set_cell_data_func (col, renderer,
264                                            var_description_cell_data_func,
265                                            NULL, NULL);
266
267   g_object_set (renderer, "ellipsize-set", TRUE, NULL);
268   g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL);
269
270   gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
271
272   /* FIXME: make this a value in terms of character widths */
273   gtk_tree_view_column_set_min_width (col, 150);
274
275   gtk_tree_view_append_column (treeview, col);
276
277   gtk_tree_selection_set_mode (selection, mode);
278
279   g_object_set (treeview, "has-tooltip", TRUE, NULL);
280
281 #if GTK_CHECK_VERSION (2, 12, 0)
282   g_signal_connect (treeview, "query-tooltip", G_CALLBACK (set_tooltip_for_variable), NULL);
283 #endif
284 }
285
286
287 void
288 insert_source_row_into_entry (GtkTreeIter iter,
289                               GtkWidget *dest,
290                               GtkTreeModel *model,
291                               gpointer data
292                               )
293 {
294   GtkTreePath *path;
295   GtkTreeModel *dict;
296   gint *idx;
297   struct variable *var;
298   GtkTreeIter dict_iter;
299   gchar *name;
300
301   g_return_if_fail (GTK_IS_ENTRY(dest));
302
303   get_base_model (model, &iter, &dict, &dict_iter);
304
305   path = gtk_tree_model_get_path (GTK_TREE_MODEL (dict), &dict_iter);
306
307   idx = gtk_tree_path_get_indices (path);
308
309   var =  psppire_dict_get_variable (PSPPIRE_DICT (dict), *idx);
310
311   gtk_tree_path_free (path);
312
313   name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
314   gtk_entry_set_text (GTK_ENTRY (dest),  name);
315   g_free (name);
316 }
317
318
319
320 void
321 insert_source_row_into_tree_view (GtkTreeIter iter,
322                                   GtkWidget *dest,
323                                   GtkTreeModel *model,
324                                   gpointer data
325                                   )
326 {
327   GtkTreePath *path;
328   GtkTreeIter dest_iter;
329   GtkTreeIter dict_iter;
330   gint *row ;
331   GtkTreeModel *destmodel = gtk_tree_view_get_model ( GTK_TREE_VIEW (dest));
332
333   GtkTreeModel *dict;
334
335
336   get_base_model (model, &iter, &dict, &dict_iter);
337
338   path = gtk_tree_model_get_path (dict, &dict_iter);
339
340   row = gtk_tree_path_get_indices (path);
341
342   gtk_list_store_append (GTK_LIST_STORE (destmodel),  &dest_iter);
343   gtk_list_store_set (GTK_LIST_STORE (destmodel), &dest_iter, 0, *row, -1);
344
345   gtk_tree_path_free (path);
346 }
347
348
349 gboolean
350 is_currently_in_entry (GtkTreeModel *model, GtkTreeIter *iter,
351                        PsppireSelector *selector)
352 {
353   gboolean result;
354   gchar *name;
355   GtkTreeIter dict_iter;
356   GtkTreeModel *dict;
357   struct variable *var;
358   gint dict_index;
359   gint *indeces;
360   GtkTreePath *path;
361   const gchar *text =   gtk_entry_get_text (GTK_ENTRY (selector->dest));
362
363   get_base_model (model, iter, &dict, &dict_iter);
364
365   path = gtk_tree_model_get_path (dict, &dict_iter);
366
367   indeces = gtk_tree_path_get_indices (path);
368
369   dict_index = indeces [0];
370
371   var = psppire_dict_get_variable (PSPPIRE_DICT (dict), dict_index);
372
373   gtk_tree_path_free (path);
374
375   name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
376   result = ( 0 == strcmp (text, name));
377   g_free (name);
378
379   return result;
380 }
381
382