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++)
124 char str[2] = { '0' + i, '\0' };
126 gtk_list_store_append (model, &iter);
128 gtk_list_store_set (model, &iter,
129 COLUMN_NUMBER_TEXT, str,
133 return GTK_TREE_MODEL (model);
139 add_item (GtkWidget *button, gpointer data)
143 GtkTreeModel *model = (GtkTreeModel *)data;
145 g_return_if_fail (articles != NULL);
148 foo.product = g_strdup ("Description here");
150 g_array_append_vals (articles, &foo, 1);
152 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
153 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
154 COLUMN_ITEM_NUMBER, foo.number,
155 COLUMN_ITEM_PRODUCT, foo.product,
156 COLUMN_ITEM_YUMMY, foo.yummy,
161 remove_item (GtkWidget *widget, gpointer data)
164 GtkTreeView *treeview = (GtkTreeView *)data;
165 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
166 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
168 if (gtk_tree_selection_get_selected (selection, NULL, &iter))
173 path = gtk_tree_model_get_path (model, &iter);
174 i = gtk_tree_path_get_indices (path)[0];
175 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
177 g_array_remove_index (articles, i);
179 gtk_tree_path_free (path);
184 separator_row (GtkTreeModel *model,
191 path = gtk_tree_model_get_path (model, iter);
192 idx = gtk_tree_path_get_indices (path)[0];
194 gtk_tree_path_free (path);
200 editing_started (GtkCellRenderer *cell,
201 GtkCellEditable *editable,
205 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (editable),
206 separator_row, NULL, NULL);
210 cell_edited (GtkCellRendererText *cell,
211 const gchar *path_string,
212 const gchar *new_text,
215 GtkTreeModel *model = (GtkTreeModel *)data;
216 GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
219 gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column"));
221 gtk_tree_model_get_iter (model, &iter, path);
225 case COLUMN_ITEM_NUMBER:
229 i = gtk_tree_path_get_indices (path)[0];
230 g_array_index (articles, Item, i).number = atoi (new_text);
232 gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
233 g_array_index (articles, Item, i).number, -1);
237 case COLUMN_ITEM_PRODUCT:
242 gtk_tree_model_get (model, &iter, column, &old_text, -1);
245 i = gtk_tree_path_get_indices (path)[0];
246 g_free (g_array_index (articles, Item, i).product);
247 g_array_index (articles, Item, i).product = g_strdup (new_text);
249 gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
250 g_array_index (articles, Item, i).product, -1);
255 gtk_tree_path_free (path);
259 add_columns (GtkTreeView *treeview,
260 GtkTreeModel *items_model,
261 GtkTreeModel *numbers_model)
263 GtkCellRenderer *renderer;
266 renderer = gtk_cell_renderer_combo_new ();
267 g_object_set (renderer,
268 "model", numbers_model,
269 "text-column", COLUMN_NUMBER_TEXT,
273 g_signal_connect (renderer, "edited",
274 G_CALLBACK (cell_edited), items_model);
275 g_signal_connect (renderer, "editing-started",
276 G_CALLBACK (editing_started), NULL);
277 g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_ITEM_NUMBER));
279 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
280 -1, "Number", renderer,
281 "text", COLUMN_ITEM_NUMBER,
285 renderer = gtk_cell_renderer_text_new ();
286 g_object_set (renderer,
289 g_signal_connect (renderer, "edited",
290 G_CALLBACK (cell_edited), items_model);
291 g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_ITEM_PRODUCT));
293 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
294 -1, "Product", renderer,
295 "text", COLUMN_ITEM_PRODUCT,
299 renderer = gtk_cell_renderer_progress_new ();
300 g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_ITEM_YUMMY));
302 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
303 -1, "Yummy", renderer,
304 "value", COLUMN_ITEM_YUMMY,
311 do_editable_cells (GtkWidget *do_widget)
320 GtkTreeModel *items_model;
321 GtkTreeModel *numbers_model;
323 /* create window, etc */
324 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
325 gtk_window_set_screen (GTK_WINDOW (window),
326 gtk_widget_get_screen (do_widget));
327 gtk_window_set_title (GTK_WINDOW (window), "Shopping list");
328 gtk_container_set_border_width (GTK_CONTAINER (window), 5);
329 g_signal_connect (window, "destroy",
330 G_CALLBACK (gtk_widget_destroyed), &window);
332 vbox = gtk_vbox_new (FALSE, 5);
333 gtk_container_add (GTK_CONTAINER (window), vbox);
335 gtk_box_pack_start (GTK_BOX (vbox),
336 gtk_label_new ("Shopping list (you can edit the cells!)"),
339 sw = gtk_scrolled_window_new (NULL, NULL);
340 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
341 GTK_SHADOW_ETCHED_IN);
342 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
343 GTK_POLICY_AUTOMATIC,
344 GTK_POLICY_AUTOMATIC);
345 gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
348 items_model = create_items_model ();
349 numbers_model = create_numbers_model ();
351 /* create tree view */
352 treeview = gtk_tree_view_new_with_model (items_model);
353 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
354 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
355 GTK_SELECTION_SINGLE);
357 add_columns (GTK_TREE_VIEW (treeview), items_model, numbers_model);
359 g_object_unref (numbers_model);
360 g_object_unref (items_model);
362 gtk_container_add (GTK_CONTAINER (sw), treeview);
365 hbox = gtk_hbox_new (TRUE, 4);
366 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
368 button = gtk_button_new_with_label ("Add item");
369 g_signal_connect (button, "clicked",
370 G_CALLBACK (add_item), items_model);
371 gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
373 button = gtk_button_new_with_label ("Remove item");
374 g_signal_connect (button, "clicked",
375 G_CALLBACK (remove_item), treeview);
376 gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
378 gtk_window_set_default_size (GTK_WINDOW (window), 320, 200);
381 if (!GTK_WIDGET_VISIBLE (window))
382 gtk_widget_show_all (window);
385 gtk_widget_destroy (window);