Revert "Fixed a use after free error when manipulating datasets."
[pspp] / src / ui / gui / psppire-checkbox-treeview.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2007, 2012, 2013  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 /*
19    This module provides a subclass of GtkTreeView, designed for dialogs
20    which need lists of annotated checkbox items.
21    The object contains the necessary model and renderers, which means that
22    the user does not have to create these herself.
23  */
24
25 #include <config.h>
26 #include <gtk/gtk.h>
27
28 #include "psppire-checkbox-treeview.h"
29
30
31 #include "gettext.h"
32 #define _(msgid) gettext (msgid)
33 #define N_(msgid) msgid
34
35 static void psppire_checkbox_treeview_init          (PsppireCheckboxTreeview      *cbtv);
36
37 GType
38 psppire_checkbox_treeview_get_type (void)
39 {
40   static GType psppire_checkbox_treeview_type = 0;
41
42   if (!psppire_checkbox_treeview_type)
43     {
44       static const GTypeInfo psppire_checkbox_treeview_info =
45       {
46         sizeof (PsppireCheckboxTreeviewClass),
47         (GBaseInitFunc) NULL,
48         (GBaseFinalizeFunc) NULL,
49         (GClassInitFunc) NULL,
50         (GClassFinalizeFunc) NULL,
51         NULL,
52         sizeof (PsppireCheckboxTreeview),
53         0,
54         (GInstanceInitFunc) psppire_checkbox_treeview_init,
55       };
56
57       psppire_checkbox_treeview_type =
58         g_type_register_static (GTK_TYPE_TREE_VIEW, "PsppireCheckboxTreeview",
59                                 &psppire_checkbox_treeview_info, 0);
60     }
61
62   return psppire_checkbox_treeview_type;
63 }
64
65
66
67 /* Callback for checkbox cells in the statistics tree view.
68    Toggles the checkbox. */
69 static void
70 toggle (GtkCellRendererToggle *cell_renderer, const gchar *path_str, gpointer data)
71 {
72   GtkTreeView *tv = GTK_TREE_VIEW (data);
73   GtkTreeModel *model = gtk_tree_view_get_model (tv);
74   GtkTreeIter iter;
75   GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
76   gboolean selected;
77
78   gtk_tree_model_get_iter (model, &iter, path);
79   gtk_tree_model_get (model, &iter, CHECKBOX_COLUMN_SELECTED, &selected, -1);
80   gtk_list_store_set (GTK_LIST_STORE (model), &iter, CHECKBOX_COLUMN_SELECTED,
81                       !selected, -1);
82   gtk_tree_path_free (path);
83 }
84
85 /* Create the necessary columns and renderers and add them to the widget */
86 static void
87 treeview_checkbox_populate (GtkTreeView *treeview)
88 {
89   /* Checkbox column. */
90   GtkTreeViewColumn *col = gtk_tree_view_column_new ();
91   GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new ();
92
93   gtk_tree_view_column_pack_start (col, renderer, TRUE);
94
95   gtk_tree_view_append_column (treeview, col);
96
97   gtk_tree_view_column_add_attribute  (col, renderer, "active", CHECKBOX_COLUMN_SELECTED);
98
99   g_signal_connect (renderer, "toggled", G_CALLBACK (toggle), treeview);
100
101   /* Label column. */
102   col = gtk_tree_view_column_new ();
103   gtk_tree_view_column_set_title (col, _("Statistic"));
104   renderer = gtk_cell_renderer_text_new ();
105   gtk_tree_view_column_pack_start (col, renderer, TRUE);
106
107   gtk_tree_view_column_add_attribute  (col, renderer, "text", CHECKBOX_COLUMN_LABEL);
108
109   g_object_set (renderer, "ellipsize-set", TRUE, NULL);
110   g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
111   gtk_tree_view_column_set_min_width (col, 200);
112   gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
113   gtk_tree_view_column_set_resizable (col, TRUE);
114   gtk_tree_view_append_column (treeview, col);
115 }
116
117 static void
118 psppire_checkbox_treeview_init (PsppireCheckboxTreeview *cbtv)
119 {
120   cbtv->list = GTK_TREE_MODEL (gtk_list_store_new (N_CHECKBOX_COLUMNS,
121                                                    G_TYPE_STRING,
122                                                    G_TYPE_BOOLEAN,
123                                                    G_TYPE_STRING));
124
125   gtk_tree_view_set_model (GTK_TREE_VIEW (cbtv), cbtv->list);
126   g_object_unref (cbtv->list);
127
128   treeview_checkbox_populate (GTK_TREE_VIEW (cbtv));
129 }
130
131
132 /*
133   Load the object's model from the array ITEMS.
134   N_ITEMS is the size of the array.
135   DEFAULT_ITEMS is a bitwise field indicating the initial state
136   of the items.
137 */
138 void
139 psppire_checkbox_treeview_populate (PsppireCheckboxTreeview *cbtv,
140                                     guint default_items,
141                                     gint n_items,
142                                     const struct checkbox_entry_item *items)
143 {
144   size_t i;
145   for (i = 0; i < n_items; ++i)
146     {
147       GtkTreeIter iter;
148       gtk_list_store_append (GTK_LIST_STORE (cbtv->list), &iter);
149       gtk_list_store_set (GTK_LIST_STORE (cbtv->list), &iter,
150                           CHECKBOX_COLUMN_LABEL, gettext (items[i].label),
151                           CHECKBOX_COLUMN_SELECTED,  (default_items & (1u << i)) != 0,
152                           CHECKBOX_COLUMN_TOOLTIP, gettext (items[i].tooltip),
153                           -1);
154     }
155
156   gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (cbtv), CHECKBOX_COLUMN_TOOLTIP);
157 }