]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/editable_cells.c
const fix
[~andy/gtk] / demos / gtk-demo / editable_cells.c
1 /* Tree View/Editable Cells
2  *
3  * This demo demonstrates the use of editable cells in a GtkTreeView. If
4  * you're new to the GtkTreeView widgets and associates, look into
5  * the GtkListStore example first.
6  *
7  */
8
9 #include <gtk/gtk.h>
10 #include <string.h>
11 #include <stdlib.h>
12
13 static GtkWidget *window = NULL;
14
15 typedef struct
16 {
17   gint     number;
18   gchar   *product;
19   gboolean editable;
20 }
21 Item;
22
23 enum
24 {
25   COLUMN_NUMBER,
26   COLUMN_PRODUCT,
27   COLUMN_EDITABLE,
28   NUM_COLUMNS
29 };
30
31 static GArray *articles = NULL;
32
33 static void
34 add_items (void)
35 {
36   Item foo;
37
38   g_return_if_fail (articles != NULL);
39
40   foo.number = 3;
41   foo.product = g_strdup ("bottles of coke");
42   foo.editable = TRUE;
43   g_array_append_vals (articles, &foo, 1);
44
45   foo.number = 5;
46   foo.product = g_strdup ("packages of noodles");
47   foo.editable = TRUE;
48   g_array_append_vals (articles, &foo, 1);
49
50   foo.number = 2;
51   foo.product = g_strdup ("packages of chocolate chip cookies");
52   foo.editable = TRUE;
53   g_array_append_vals (articles, &foo, 1);
54
55   foo.number = 1;
56   foo.product = g_strdup ("can vanilla ice cream");
57   foo.editable = TRUE;
58   g_array_append_vals (articles, &foo, 1);
59
60   foo.number = 6;
61   foo.product = g_strdup ("eggs");
62   foo.editable = TRUE;
63   g_array_append_vals (articles, &foo, 1);
64 }
65
66 static GtkTreeModel *
67 create_model (void)
68 {
69   gint i = 0;
70   GtkListStore *model;
71   GtkTreeIter iter;
72
73   /* create array */
74   articles = g_array_sized_new (FALSE, FALSE, sizeof (Item), 1);
75
76   add_items ();
77
78   /* create list store */
79   model = gtk_list_store_new (NUM_COLUMNS, G_TYPE_INT, G_TYPE_STRING,
80                               G_TYPE_BOOLEAN);
81
82   /* add items */
83   for (i = 0; i < articles->len; i++)
84     {
85       gtk_list_store_append (model, &iter);
86
87       gtk_list_store_set (model, &iter,
88                           COLUMN_NUMBER,
89                           g_array_index (articles, Item, i).number,
90                           COLUMN_PRODUCT,
91                           g_array_index (articles, Item, i).product,
92                           COLUMN_EDITABLE,
93                           g_array_index (articles, Item, i).editable,
94                           -1);
95     }
96
97   return GTK_TREE_MODEL (model);
98 }
99
100 static void
101 add_item (GtkWidget *button, gpointer data)
102 {
103   Item foo;
104   GtkTreeIter iter;
105   GtkTreeModel *model = (GtkTreeModel *)data;
106
107   g_return_if_fail (articles != NULL);
108
109   foo.number = 0;
110   foo.product = g_strdup ("Description here");
111   foo.editable = TRUE;
112   g_array_append_vals (articles, &foo, 1);
113
114   gtk_list_store_append (GTK_LIST_STORE (model), &iter);
115   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
116                       COLUMN_NUMBER, foo.number,
117                       COLUMN_PRODUCT, foo.product,
118                       COLUMN_EDITABLE, foo.editable,
119                       -1);
120 }
121
122 static void
123 remove_item (GtkWidget *widget, gpointer data)
124 {
125   GtkTreeIter iter;
126   GtkTreeView *treeview = (GtkTreeView *)data;
127   GtkTreeModel *model = gtk_tree_view_get_model (treeview);
128   GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
129
130   if (gtk_tree_selection_get_selected (selection, NULL, &iter))
131     {
132       gint i;
133       GtkTreePath *path;
134
135       path = gtk_tree_model_get_path (model, &iter);
136       i = gtk_tree_path_get_indices (path)[0];
137       gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
138
139       g_array_remove_index (articles, i);
140
141       gtk_tree_path_free (path);
142     }
143 }
144
145 static void
146 cell_edited (GtkCellRendererText *cell,
147              const gchar         *path_string,
148              const gchar         *new_text,
149              gpointer             data)
150 {
151   GtkTreeModel *model = (GtkTreeModel *)data;
152   GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
153   GtkTreeIter iter;
154
155   gint *column;
156
157   column = g_object_get_data (G_OBJECT (cell), "column");
158
159   gtk_tree_model_get_iter (model, &iter, path);
160
161   switch ((gint) column)
162     {
163     case COLUMN_NUMBER:
164       {
165         gint i;
166
167         i = gtk_tree_path_get_indices (path)[0];
168         g_array_index (articles, Item, i).number = atoi (new_text);
169
170         gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
171                             g_array_index (articles, Item, i).number, -1);
172       }
173       break;
174
175     case COLUMN_PRODUCT:
176       {
177         gint i;
178         gchar *old_text;
179
180         gtk_tree_model_get (model, &iter, column, &old_text, -1);
181         g_free (old_text);
182
183         i = gtk_tree_path_get_indices (path)[0];
184         g_free (g_array_index (articles, Item, i).product);
185         g_array_index (articles, Item, i).product = g_strdup (new_text);
186
187         gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
188                             g_array_index (articles, Item, i).product, -1);
189       }
190       break;
191     }
192
193   gtk_tree_path_free (path);
194 }
195
196 static void
197 add_columns (GtkTreeView *treeview)
198 {
199   GtkCellRenderer *renderer;
200   GtkTreeModel *model = gtk_tree_view_get_model (treeview);
201
202   /* number column */
203   renderer = gtk_cell_renderer_text_new ();
204   g_signal_connect (G_OBJECT (renderer), "edited",
205                     G_CALLBACK (cell_edited), model);
206   g_object_set_data (G_OBJECT (renderer), "column", (gint *)COLUMN_NUMBER);
207
208   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
209                                                -1, "Number", renderer,
210                                                "text", COLUMN_NUMBER,
211                                                "editable", COLUMN_EDITABLE,
212                                                NULL);
213
214   /* product column */
215   renderer = gtk_cell_renderer_text_new ();
216   g_signal_connect (G_OBJECT (renderer), "edited",
217                     G_CALLBACK (cell_edited), model);
218   g_object_set_data (G_OBJECT (renderer), "column", (gint *)COLUMN_PRODUCT);
219
220   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
221                                                -1, "Product", renderer,
222                                                "text", COLUMN_PRODUCT,
223                                                "editable", COLUMN_EDITABLE,
224                                                NULL);
225 }
226
227 GtkWidget *
228 do_editable_cells (void)
229 {
230   if (!window)
231     {
232       GtkWidget *vbox;
233       GtkWidget *hbox;
234       GtkWidget *sw;
235       GtkWidget *treeview;
236       GtkWidget *button;
237       GtkTreeModel *model;
238
239       /* create window, etc */
240       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
241       gtk_window_set_title (GTK_WINDOW (window), "Shopping list");
242       gtk_container_set_border_width (GTK_CONTAINER (window), 5);
243       g_signal_connect (G_OBJECT (window), "destroy",
244                         G_CALLBACK (gtk_widget_destroyed), &window);
245
246       vbox = gtk_vbox_new (FALSE, 5);
247       gtk_container_add (GTK_CONTAINER (window), vbox);
248
249       gtk_box_pack_start (GTK_BOX (vbox),
250                           gtk_label_new ("Shopping list (you can edit the cells!)"),
251                           FALSE, FALSE, 0);
252
253       sw = gtk_scrolled_window_new (NULL, NULL);
254       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
255                                            GTK_SHADOW_ETCHED_IN);
256       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
257                                       GTK_POLICY_AUTOMATIC,
258                                       GTK_POLICY_AUTOMATIC);
259       gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
260
261       /* create model */
262       model = create_model ();
263
264       /* create tree view */
265       treeview = gtk_tree_view_new_with_model (model);
266       g_object_unref (G_OBJECT (model));
267       gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
268       gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
269                                    GTK_SELECTION_SINGLE);
270
271       add_columns (GTK_TREE_VIEW (treeview));
272
273       gtk_container_add (GTK_CONTAINER (sw), treeview);
274
275       /* some buttons */
276       hbox = gtk_hbox_new (TRUE, 4);
277       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
278
279       button = gtk_button_new_with_label ("Add item");
280       g_signal_connect (G_OBJECT (button), "clicked",
281                         G_CALLBACK (add_item), model);
282       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
283
284       button = gtk_button_new_with_label ("Remove item");
285       g_signal_connect (G_OBJECT (button), "clicked",
286                         G_CALLBACK (remove_item), treeview);
287       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
288
289       gtk_window_set_default_size (GTK_WINDOW (window), 320, 200);
290     }
291
292   if (!GTK_WIDGET_VISIBLE (window))
293     gtk_widget_show_all (window);
294   else
295     {
296       gtk_widget_destroy (window);
297       window = NULL;
298     }
299
300   return window;
301 }