1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2009 Free Software Foundation
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.
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.
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/>. */
19 #include <gtk/gtktreeview.h>
20 #include "psppire-dictview.h"
21 #include "psppire-dict.h"
22 #include "psppire-conf.h"
23 #include <data/format.h>
27 #define _(msgid) gettext (msgid)
28 #define N_(msgid) msgid
30 static void psppire_dict_view_base_finalize (PsppireDictViewClass *, gpointer);
31 static void psppire_dict_view_base_init (PsppireDictViewClass *class);
32 static void psppire_dict_view_class_init (PsppireDictViewClass *class);
33 static void psppire_dict_view_init (PsppireDictView *dict_view);
37 psppire_dict_view_get_type (void)
39 static GType psppire_dict_view_type = 0;
41 if (!psppire_dict_view_type)
43 static const GTypeInfo psppire_dict_view_info =
45 sizeof (PsppireDictViewClass),
46 (GBaseInitFunc) psppire_dict_view_base_init,
47 (GBaseFinalizeFunc) psppire_dict_view_base_finalize,
48 (GClassInitFunc)psppire_dict_view_class_init,
49 (GClassFinalizeFunc) NULL,
51 sizeof (PsppireDictView),
53 (GInstanceInitFunc) psppire_dict_view_init,
56 psppire_dict_view_type =
57 g_type_register_static (GTK_TYPE_TREE_VIEW, "PsppireDictView",
58 &psppire_dict_view_info, 0);
61 return psppire_dict_view_type;
66 psppire_dict_view_finalize (GObject *object)
80 /* A GtkTreeModelFilterVisibleFunc to filter lines in the treeview */
82 filter_variables (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
84 var_predicate_func *predicate = data;
86 PsppireDict *dict = PSPPIRE_DICT (model);
88 GtkTreePath *path = gtk_tree_model_get_path (model, iter);
90 gint *idx = gtk_tree_path_get_indices (path);
92 var = psppire_dict_get_variable (dict, *idx);
94 gtk_tree_path_free (path);
96 return predicate (var);
100 set_model (PsppireDictView *dict_view)
102 GtkTreeModel *model ;
104 if ( dict_view->predicate )
106 model = gtk_tree_model_filter_new (GTK_TREE_MODEL (dict_view->dict),
109 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model),
111 dict_view->predicate,
116 model = GTK_TREE_MODEL (dict_view->dict);
119 gtk_tree_view_set_model (GTK_TREE_VIEW (dict_view), model);
123 psppire_dict_view_set_property (GObject *object,
128 PsppireDictView *dict_view = PSPPIRE_DICT_VIEW (object);
133 dict_view->dict = g_value_get_object (value);
136 dict_view->predicate = g_value_get_pointer (value);
138 case PROP_SELECTION_MODE:
140 GtkTreeSelection *selection =
141 gtk_tree_view_get_selection (GTK_TREE_VIEW (dict_view));
143 GtkSelectionMode mode = g_value_get_enum (value);
145 gtk_tree_selection_set_mode (selection, mode);
149 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
154 set_model (dict_view);
159 psppire_dict_view_get_property (GObject *object,
164 PsppireDictView *dict_view = PSPPIRE_DICT_VIEW (object);
169 g_value_set_object (value, dict_view->dict);
172 g_value_set_pointer (value, dict_view->predicate);
174 case PROP_SELECTION_MODE:
176 GtkTreeSelection *selection =
177 gtk_tree_view_get_selection (GTK_TREE_VIEW (dict_view));
179 g_value_set_enum (value, gtk_tree_selection_get_mode (selection));
182 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
190 psppire_dict_view_class_init (PsppireDictViewClass *class)
192 GObjectClass *object_class = G_OBJECT_CLASS (class);
194 GParamSpec *model_spec =
195 g_param_spec_object ("model",
197 _("The dictionary to be displayed by this widget"),
199 G_PARAM_READABLE | G_PARAM_WRITABLE);
201 GParamSpec *predicate_spec =
202 g_param_spec_pointer ("predicate",
204 _("A predicate function"),
205 G_PARAM_READABLE | G_PARAM_WRITABLE);
208 GParamSpec *selection_mode_spec =
209 g_param_spec_enum ("selection-mode",
211 _("How many things can be selected"),
212 GTK_TYPE_SELECTION_MODE,
213 GTK_SELECTION_MULTIPLE,
214 G_PARAM_CONSTRUCT | G_PARAM_READABLE | G_PARAM_WRITABLE);
217 object_class->set_property = psppire_dict_view_set_property;
218 object_class->get_property = psppire_dict_view_get_property;
220 g_object_class_install_property (object_class,
224 g_object_class_install_property (object_class,
228 g_object_class_install_property (object_class,
230 selection_mode_spec);
235 psppire_dict_view_base_init (PsppireDictViewClass *class)
237 GObjectClass *object_class = G_OBJECT_CLASS (class);
239 object_class->finalize = psppire_dict_view_finalize;
245 psppire_dict_view_base_finalize(PsppireDictViewClass *class,
253 dv_get_base_model (GtkTreeModel *top_model, GtkTreeIter *top_iter,
254 GtkTreeModel **model, GtkTreeIter *iter
259 while (GTK_IS_TREE_MODEL_FILTER (*model))
261 GtkTreeIter parent_iter = *iter;
262 GtkTreeModelFilter *parent_model = GTK_TREE_MODEL_FILTER (*model);
264 *model = gtk_tree_model_filter_get_model (parent_model);
266 gtk_tree_model_filter_convert_iter_to_child_iter (parent_model,
271 g_assert (PSPPIRE_IS_DICT (*model));
276 /* A GtkTreeCellDataFunc which renders the name and/or label of the
279 var_description_cell_data_func (GtkTreeViewColumn *col,
280 GtkCellRenderer *cell,
281 GtkTreeModel *top_model,
282 GtkTreeIter *top_iter,
285 struct variable *var;
288 gboolean prefer_labels = FALSE;
290 PsppireConf *conf = psppire_conf_new ();
292 psppire_conf_get_boolean (conf, "dialog-boxes", "prefer-labels",
295 dv_get_base_model (top_model, top_iter, &model, &iter);
297 g_assert (PSPPIRE_IS_DICT (model));
300 gtk_tree_model_get (model,
301 &iter, DICT_TVM_COL_VAR, &var, -1);
303 if ( var_has_label (var) && prefer_labels)
305 gchar *text = g_strdup_printf (
306 "<span stretch=\"condensed\">%s</span>",
307 var_get_label (var));
309 char *utf8 = pspp_locale_to_utf8 (text, -1, NULL);
312 g_object_set (cell, "markup", utf8, NULL);
317 char *name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
318 g_object_set (cell, "text", name, NULL);
325 /* A GtkTreeCellDataFunc which sets the icon appropriate to the type
328 var_icon_cell_data_func (GtkTreeViewColumn *col,
329 GtkCellRenderer *cell,
334 struct variable *var;
335 gtk_tree_model_get (model, iter, DICT_TVM_COL_VAR, &var, -1);
337 if ( var_is_alpha (var))
339 g_object_set (cell, "stock-id", "var-string", NULL);
343 const struct fmt_spec *fs = var_get_write_format (var);
344 int cat = fmt_get_category (fs->type);
345 switch ( var_get_measure (var))
347 case MEASURE_NOMINAL:
348 g_object_set (cell, "stock-id", "var-nominal", NULL);
350 case MEASURE_ORDINAL:
351 g_object_set (cell, "stock-id", "var-ordinal", NULL);
354 if ( ( FMT_CAT_DATE | FMT_CAT_TIME ) & cat )
355 g_object_set (cell, "stock-id", "var-date-scale", NULL);
357 g_object_set (cell, "stock-id", "var-scale", NULL);
360 g_assert_not_reached ();
366 /* Sets the tooltip to be the name of the variable under the cursor */
368 set_tooltip_for_variable (GtkTreeView *treeview,
371 gboolean keyboard_mode,
379 GtkTreeModel *tree_model;
380 struct variable *var = NULL;
384 gtk_tree_view_convert_widget_to_bin_window_coords (treeview,
387 if (!gtk_tree_view_get_path_at_pos (treeview, bx, by,
388 &path, NULL, NULL, NULL))
391 tree_model = gtk_tree_view_get_model (treeview);
394 gtk_tree_view_set_tooltip_row (treeview, tooltip, path);
396 ok = gtk_tree_model_get_iter (tree_model, &iter, path);
398 gtk_tree_path_free (path);
403 gtk_tree_model_get (tree_model, &iter, DICT_TVM_COL_VAR, &var, -1);
405 if ( ! var_has_label (var))
410 gboolean prefer_labels = FALSE;
412 PsppireConf *conf = psppire_conf_new ();
414 psppire_conf_get_boolean (conf, "dialog-boxes", "prefer-labels",
418 tip = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
420 tip = pspp_locale_to_utf8 (var_get_label (var), -1, NULL);
422 gtk_tooltip_set_text (tooltip, tip);
432 psppire_dict_view_init (PsppireDictView *dict_view)
434 GtkTreeViewColumn *col;
436 GtkCellRenderer *renderer;
438 col = gtk_tree_view_column_new ();
439 gtk_tree_view_column_set_title (col, _("Variable"));
441 renderer = gtk_cell_renderer_pixbuf_new ();
442 gtk_tree_view_column_pack_start (col, renderer, FALSE);
444 gtk_tree_view_column_set_cell_data_func (col, renderer,
445 var_icon_cell_data_func,
449 renderer = gtk_cell_renderer_text_new ();
450 gtk_tree_view_column_pack_start (col, renderer, TRUE);
451 gtk_tree_view_column_set_cell_data_func (col, renderer,
452 var_description_cell_data_func,
455 g_object_set (renderer, "ellipsize-set", TRUE, NULL);
456 g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL);
458 gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
460 /* FIXME: make this a value in terms of character widths */
461 gtk_tree_view_column_set_min_width (col, 150);
463 gtk_tree_view_append_column (GTK_TREE_VIEW (dict_view), col);
465 g_object_set (dict_view, "has-tooltip", TRUE, NULL);
467 g_signal_connect (dict_view, "query-tooltip",
468 G_CALLBACK (set_tooltip_for_variable), NULL);
473 psppire_dict_view_new (void)
475 return GTK_WIDGET (g_object_new (psppire_dict_view_get_type (), NULL));
481 psppire_dict_view_get_selected_variable (PsppireDictView *treeview)
483 struct variable *var;
484 GtkTreeModel *top_model;
485 GtkTreeIter top_iter;
490 GtkTreeSelection *selection =
491 gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
493 if (! gtk_tree_selection_get_selected (selection,
494 &top_model, &top_iter))
499 dv_get_base_model (top_model, &top_iter, &model, &iter);
501 g_assert (PSPPIRE_IS_DICT (model));
503 gtk_tree_model_get (model,
504 &iter, DICT_TVM_COL_VAR, &var, -1);