1c2858d65cc8c0a8904e4ccd72938c5f4805b4d8
[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                               gpointer data
230                               )
231 {
232   GtkTreePath *path;
233   GtkTreeModel *dict;
234   gint *idx;
235   struct variable *var;
236   GtkTreeIter dict_iter;
237   gchar *name;
238
239   g_return_if_fail (GTK_IS_ENTRY(dest));
240
241   get_base_model (model, &iter, &dict, &dict_iter);
242
243   path = gtk_tree_model_get_path (GTK_TREE_MODEL (dict), &dict_iter);
244
245   idx = gtk_tree_path_get_indices (path);
246
247   var =  psppire_dict_get_variable (PSPPIRE_DICT (dict), *idx);
248
249   gtk_tree_path_free (path);
250
251   name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
252   gtk_entry_set_text (GTK_ENTRY (dest),  name);
253   g_free (name);
254 }
255
256
257
258 void
259 insert_source_row_into_tree_view (GtkTreeIter iter,
260                                   GtkWidget *dest,
261                                   GtkTreeModel *model,
262                                   gpointer data
263                                   )
264 {
265   GtkTreePath *path;
266   GtkTreeIter dest_iter;
267   GtkTreeIter dict_iter;
268   gint *row ;
269   GtkTreeModel *destmodel = gtk_tree_view_get_model ( GTK_TREE_VIEW (dest));
270
271   GtkTreeModel *dict;
272
273
274   get_base_model (model, &iter, &dict, &dict_iter);
275
276   path = gtk_tree_model_get_path (dict, &dict_iter);
277
278   row = gtk_tree_path_get_indices (path);
279
280   gtk_list_store_append (GTK_LIST_STORE (destmodel),  &dest_iter);
281   gtk_list_store_set (GTK_LIST_STORE (destmodel), &dest_iter, 0, *row, -1);
282
283   gtk_tree_path_free (path);
284 }
285
286
287 gboolean
288 is_currently_in_entry (GtkTreeModel *model, GtkTreeIter *iter,
289                        PsppireSelector *selector)
290 {
291   gboolean result;
292   gchar *name;
293   GtkTreeIter dict_iter;
294   GtkTreeModel *dict;
295   struct variable *var;
296   gint dict_index;
297   gint *indeces;
298   GtkTreePath *path;
299   const gchar *text =   gtk_entry_get_text (GTK_ENTRY (selector->dest));
300
301   get_base_model (model, iter, &dict, &dict_iter);
302
303   path = gtk_tree_model_get_path (dict, &dict_iter);
304
305   indeces = gtk_tree_path_get_indices (path);
306
307   dict_index = indeces [0];
308
309   var = psppire_dict_get_variable (PSPPIRE_DICT (dict), dict_index);
310
311   gtk_tree_path_free (path);
312
313   name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
314   result = ( 0 == strcmp (text, name));
315   g_free (name);
316
317   return result;
318 }
319
320