1 /* Tree View/Editable Cells
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. It also shows how to use the
6 * GtkCellRenderer::editing-started signal to do custom setup of the
9 * The cell renderers used in this demo are GtkCellRendererText,
10 * GtkCellRendererCombo and GtkCellRendererProgress.
17 static GtkWidget *window = NULL;
41 static GArray *articles = NULL;
48 g_return_if_fail (articles != NULL);
51 foo.product = g_strdup ("bottles of coke");
53 g_array_append_vals (articles, &foo, 1);
56 foo.product = g_strdup ("packages of noodles");
58 g_array_append_vals (articles, &foo, 1);
61 foo.product = g_strdup ("packages of chocolate chip cookies");
63 g_array_append_vals (articles, &foo, 1);
66 foo.product = g_strdup ("can vanilla ice cream");
68 g_array_append_vals (articles, &foo, 1);
71 foo.product = g_strdup ("eggs");
73 g_array_append_vals (articles, &foo, 1);
77 create_items_model (void)
84 articles = g_array_sized_new (FALSE, FALSE, sizeof (Item), 1);
88 /* create list store */
89 model = gtk_list_store_new (NUM_ITEM_COLUMNS, G_TYPE_INT, G_TYPE_STRING,
90 G_TYPE_INT, G_TYPE_BOOLEAN);
93 for (i = 0; i < articles->len; i++)
95 gtk_list_store_append (model, &iter);
97 gtk_list_store_set (model, &iter,
99 g_array_index (articles, Item, i).number,
101 g_array_index (articles, Item, i).product,
103 g_array_index (articles, Item, i).yummy,
107 return GTK_TREE_MODEL (model);
110 static GtkTreeModel *
111 create_numbers_model (void)
118 /* create list store */
119 model = gtk_list_store_new (NUM_NUMBER_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
122 for (i = 0; i < N_NUMBERS; i++)
129 gtk_list_store_append (model, &iter);
131 gtk_list_store_set (model, &iter,
132 COLUMN_NUMBER_TEXT, str,
136 return GTK_TREE_MODEL (model);
142 add_item (GtkWidget *button, gpointer data)
146 GtkTreeModel *model = (GtkTreeModel *)data;
148 g_return_if_fail (articles != NULL);
151 foo.product = g_strdup ("Description here");
153 g_array_append_vals (articles, &foo, 1);
155 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
156 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
157 COLUMN_ITEM_NUMBER, foo.number,
158 COLUMN_ITEM_PRODUCT, foo.product,
159 COLUMN_ITEM_YUMMY, foo.yummy,
164 remove_item (GtkWidget *widget, gpointer data)
167 GtkTreeView *treeview = (GtkTreeView *)data;
168 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
169 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
171 if (gtk_tree_selection_get_selected (selection, NULL, &iter))
176 path = gtk_tree_model_get_path (model, &iter);
177 i = gtk_tree_path_get_indices (path)[0];
178 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
180 g_array_remove_index (articles, i);
182 gtk_tree_path_free (path);
187 separator_row (GtkTreeModel *model,
194 path = gtk_tree_model_get_path (model, iter);
195 idx = gtk_tree_path_get_indices (path)[0];
197 gtk_tree_path_free (path);
203 editing_started (GtkCellRenderer *cell,
204 GtkCellEditable *editable,
208 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (editable),
209 separator_row, NULL, NULL);
213 cell_edited (GtkCellRendererText *cell,
214 const gchar *path_string,
215 const gchar *new_text,
218 GtkTreeModel *model = (GtkTreeModel *)data;
219 GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
222 gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column"));
224 gtk_tree_model_get_iter (model, &iter, path);
228 case COLUMN_ITEM_NUMBER:
232 i = gtk_tree_path_get_indices (path)[0];
233 g_array_index (articles, Item, i).number = atoi (new_text);
235 gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
236 g_array_index (articles, Item, i).number, -1);
240 case COLUMN_ITEM_PRODUCT:
245 gtk_tree_model_get (model, &iter, column, &old_text, -1);
248 i = gtk_tree_path_get_indices (path)[0];
249 g_free (g_array_index (articles, Item, i).product);
250 g_array_index (articles, Item, i).product = g_strdup (new_text);
252 gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
253 g_array_index (articles, Item, i).product, -1);
258 gtk_tree_path_free (path);
262 add_columns (GtkTreeView *treeview,
263 GtkTreeModel *items_model,
264 GtkTreeModel *numbers_model)
266 GtkCellRenderer *renderer;
269 renderer = gtk_cell_renderer_combo_new ();
270 g_object_set (renderer,
271 "model", numbers_model,
272 "text-column", COLUMN_NUMBER_TEXT,
276 g_signal_connect (renderer, "edited",
277 G_CALLBACK (cell_edited), items_model);
278 g_signal_connect (renderer, "editing-started",
279 G_CALLBACK (editing_started), NULL);
280 g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_ITEM_NUMBER));
282 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
283 -1, "Number", renderer,
284 "text", COLUMN_ITEM_NUMBER,
288 renderer = gtk_cell_renderer_text_new ();
289 g_object_set (renderer,
292 g_signal_connect (renderer, "edited",
293 G_CALLBACK (cell_edited), items_model);
294 g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_ITEM_PRODUCT));
296 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
297 -1, "Product", renderer,
298 "text", COLUMN_ITEM_PRODUCT,
302 renderer = gtk_cell_renderer_progress_new ();
303 g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_ITEM_YUMMY));
305 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
306 -1, "Yummy", renderer,
307 "value", COLUMN_ITEM_YUMMY,
312 do_editable_cells (GtkWidget *do_widget)
321 GtkTreeModel *items_model;
322 GtkTreeModel *numbers_model;
324 /* create window, etc */
325 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
326 gtk_window_set_screen (GTK_WINDOW (window),
327 gtk_widget_get_screen (do_widget));
328 gtk_window_set_title (GTK_WINDOW (window), "Shopping list");
329 gtk_container_set_border_width (GTK_CONTAINER (window), 5);
330 g_signal_connect (window, "destroy",
331 G_CALLBACK (gtk_widget_destroyed), &window);
333 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
334 gtk_container_add (GTK_CONTAINER (window), vbox);
336 gtk_box_pack_start (GTK_BOX (vbox),
337 gtk_label_new ("Shopping list (you can edit the cells!)"),
340 sw = gtk_scrolled_window_new (NULL, NULL);
341 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
342 GTK_SHADOW_ETCHED_IN);
343 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
344 GTK_POLICY_AUTOMATIC,
345 GTK_POLICY_AUTOMATIC);
346 gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
349 items_model = create_items_model ();
350 numbers_model = create_numbers_model ();
352 /* create tree view */
353 treeview = gtk_tree_view_new_with_model (items_model);
354 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
355 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
356 GTK_SELECTION_SINGLE);
358 add_columns (GTK_TREE_VIEW (treeview), items_model, numbers_model);
360 g_object_unref (numbers_model);
361 g_object_unref (items_model);
363 gtk_container_add (GTK_CONTAINER (sw), treeview);
366 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
367 gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
368 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
370 button = gtk_button_new_with_label ("Add item");
371 g_signal_connect (button, "clicked",
372 G_CALLBACK (add_item), items_model);
373 gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
375 button = gtk_button_new_with_label ("Remove item");
376 g_signal_connect (button, "clicked",
377 G_CALLBACK (remove_item), treeview);
378 gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
380 gtk_window_set_default_size (GTK_WINDOW (window), 320, 200);
383 if (!gtk_widget_get_visible (window))
384 gtk_widget_show_all (window);
387 gtk_widget_destroy (window);