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