/* testtreeedit.c * Copyright (C) 2001 Red Hat, Inc * Author: Jonathan Blandford * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library. If not, see . */ #include "config.h" #include typedef struct { const gchar *string; gboolean is_editable; gboolean is_sensitive; gint progress; } ListEntry; enum { STRING_COLUMN, IS_EDITABLE_COLUMN, IS_SENSITIVE_COLUMN, ICON_NAME_COLUMN, LAST_ICON_NAME_COLUMN, PROGRESS_COLUMN, NUM_COLUMNS }; static ListEntry model_strings[] = { {"A simple string", TRUE, TRUE, 0 }, {"Another string!", TRUE, TRUE, 10 }, {"", TRUE, TRUE, 0 }, {"Guess what, a third string. This one can't be edited", FALSE, TRUE, 47 }, {"And then a fourth string. Neither can this", FALSE, TRUE, 48 }, {"Multiline\nFun!", TRUE, FALSE, 75 }, { NULL } }; static GtkTreeModel * create_model (void) { GtkTreeStore *model; GtkTreeIter iter; gint i; model = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); for (i = 0; model_strings[i].string != NULL; i++) { gtk_tree_store_append (model, &iter, NULL); gtk_tree_store_set (model, &iter, STRING_COLUMN, model_strings[i].string, IS_EDITABLE_COLUMN, model_strings[i].is_editable, IS_SENSITIVE_COLUMN, model_strings[i].is_sensitive, ICON_NAME_COLUMN, "document-new", LAST_ICON_NAME_COLUMN, "edit-delete", PROGRESS_COLUMN, model_strings[i].progress, -1); } return GTK_TREE_MODEL (model); } static void editable_toggled (GtkCellRendererToggle *cell, gchar *path_string, gpointer data) { GtkTreeModel *model = GTK_TREE_MODEL (data); GtkTreeIter iter; GtkTreePath *path = gtk_tree_path_new_from_string (path_string); gboolean value; gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (model, &iter, IS_EDITABLE_COLUMN, &value, -1); value = !value; gtk_tree_store_set (GTK_TREE_STORE (model), &iter, IS_EDITABLE_COLUMN, value, -1); gtk_tree_path_free (path); } static void sensitive_toggled (GtkCellRendererToggle *cell, gchar *path_string, gpointer data) { GtkTreeModel *model = GTK_TREE_MODEL (data); GtkTreeIter iter; GtkTreePath *path = gtk_tree_path_new_from_string (path_string); gboolean value; gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (model, &iter, IS_SENSITIVE_COLUMN, &value, -1); value = !value; gtk_tree_store_set (GTK_TREE_STORE (model), &iter, IS_SENSITIVE_COLUMN, value, -1); gtk_tree_path_free (path); } static void edited (GtkCellRendererText *cell, gchar *path_string, gchar *new_text, gpointer data) { GtkTreeModel *model = GTK_TREE_MODEL (data); GtkTreeIter iter; GtkTreePath *path = gtk_tree_path_new_from_string (path_string); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_store_set (GTK_TREE_STORE (model), &iter, STRING_COLUMN, new_text, -1); gtk_tree_path_free (path); } static void pressed_cb (GtkGesture *gesture, int n_press, double x, double y, GtkWidget *widget) { /* Deselect if people click outside any row. */ if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget), x, y, NULL, NULL, NULL, NULL)) gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget))); } typedef struct { GtkCellArea *area; GtkCellRenderer *renderer; } CallbackData; static void align_cell_toggled (GtkToggleButton *toggle, CallbackData *data) { gboolean active = gtk_toggle_button_get_active (toggle); gtk_cell_area_cell_set (data->area, data->renderer, "align", active, NULL); } static void expand_cell_toggled (GtkToggleButton *toggle, CallbackData *data) { gboolean active = gtk_toggle_button_get_active (toggle); gtk_cell_area_cell_set (data->area, data->renderer, "expand", active, NULL); } static void fixed_cell_toggled (GtkToggleButton *toggle, CallbackData *data) { gboolean active = gtk_toggle_button_get_active (toggle); gtk_cell_area_cell_set (data->area, data->renderer, "fixed-size", active, NULL); } enum { CNTL_EXPAND, CNTL_ALIGN, CNTL_FIXED }; static void create_control (GtkWidget *box, gint number, gint cntl, CallbackData *data) { GtkWidget *checkbutton; GCallback callback = NULL; gchar *name = NULL; switch (cntl) { case CNTL_EXPAND: name = g_strdup_printf ("Expand Cell #%d", number); callback = G_CALLBACK (expand_cell_toggled); break; case CNTL_ALIGN: name = g_strdup_printf ("Align Cell #%d", number); callback = G_CALLBACK (align_cell_toggled); break; case CNTL_FIXED: name = g_strdup_printf ("Fix size Cell #%d", number); callback = G_CALLBACK (fixed_cell_toggled); break; default: g_assert_not_reached (); } checkbutton = gtk_check_button_new_with_label (name); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), cntl == CNTL_FIXED); gtk_container_add (GTK_CONTAINER (box), checkbutton); g_signal_connect (G_OBJECT (checkbutton), "toggled", callback, data); g_free (name); } static void quit_cb (GtkWidget *widget, gpointer data) { gboolean *done = data; *done = TRUE; g_main_context_wakeup (NULL); } gint main (gint argc, gchar **argv) { GtkWidget *window; GtkWidget *scrolled_window; GtkWidget *tree_view; GtkWidget *vbox, *hbox, *cntl_vbox; GtkTreeModel *tree_model; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkCellArea *area; CallbackData callback[4]; GtkGesture *gesture; gboolean done = FALSE; gtk_init (); if (g_getenv ("RTL")) gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL); window = gtk_window_new (); gtk_window_set_title (GTK_WINDOW (window), "GtkTreeView editing sample"); g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_window_set_child (GTK_WINDOW (window), vbox); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (scrolled_window), TRUE); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_set_vexpand (scrolled_window, TRUE); gtk_container_add (GTK_CONTAINER (vbox), scrolled_window); tree_model = create_model (); tree_view = gtk_tree_view_new_with_model (tree_model); gesture = gtk_gesture_click_new (); g_signal_connect (gesture, "pressed", G_CALLBACK (pressed_cb), tree_view); gtk_widget_add_controller (tree_view, GTK_EVENT_CONTROLLER (gesture)); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), TRUE); column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (column, "String"); area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column)); renderer = gtk_cell_renderer_pixbuf_new (); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "icon-name", ICON_NAME_COLUMN, "sensitive", IS_SENSITIVE_COLUMN, NULL); callback[0].area = area; callback[0].renderer = renderer; renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "text", STRING_COLUMN, "editable", IS_EDITABLE_COLUMN, "sensitive", IS_SENSITIVE_COLUMN, NULL); callback[1].area = area; callback[1].renderer = renderer; g_signal_connect (renderer, "edited", G_CALLBACK (edited), tree_model); g_object_set (renderer, "placeholder-text", "Type here", NULL); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "text", STRING_COLUMN, "editable", IS_EDITABLE_COLUMN, "sensitive", IS_SENSITIVE_COLUMN, NULL); callback[2].area = area; callback[2].renderer = renderer; g_signal_connect (renderer, "edited", G_CALLBACK (edited), tree_model); g_object_set (renderer, "placeholder-text", "Type here too", NULL); renderer = gtk_cell_renderer_pixbuf_new (); g_object_set (renderer, "xalign", 0.0, NULL); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "icon-name", LAST_ICON_NAME_COLUMN, "sensitive", IS_SENSITIVE_COLUMN, NULL); callback[3].area = area; callback[3].renderer = renderer; gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); renderer = gtk_cell_renderer_toggle_new (); g_signal_connect (renderer, "toggled", G_CALLBACK (editable_toggled), tree_model); g_object_set (renderer, "xalign", 0.0, NULL); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), -1, "Editable", renderer, "active", IS_EDITABLE_COLUMN, NULL); renderer = gtk_cell_renderer_toggle_new (); g_signal_connect (renderer, "toggled", G_CALLBACK (sensitive_toggled), tree_model); g_object_set (renderer, "xalign", 0.0, NULL); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), -1, "Sensitive", renderer, "active", IS_SENSITIVE_COLUMN, NULL); renderer = gtk_cell_renderer_progress_new (); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), -1, "Progress", renderer, "value", PROGRESS_COLUMN, NULL); gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled_window), tree_view); gtk_window_set_default_size (GTK_WINDOW (window), 800, 250); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_container_add (GTK_CONTAINER (vbox), hbox); /* Alignment controls */ cntl_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); gtk_container_add (GTK_CONTAINER (hbox), cntl_vbox); create_control (cntl_vbox, 1, CNTL_ALIGN, &callback[0]); create_control (cntl_vbox, 2, CNTL_ALIGN, &callback[1]); create_control (cntl_vbox, 3, CNTL_ALIGN, &callback[2]); create_control (cntl_vbox, 4, CNTL_ALIGN, &callback[3]); /* Expand controls */ cntl_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); gtk_container_add (GTK_CONTAINER (hbox), cntl_vbox); create_control (cntl_vbox, 1, CNTL_EXPAND, &callback[0]); create_control (cntl_vbox, 2, CNTL_EXPAND, &callback[1]); create_control (cntl_vbox, 3, CNTL_EXPAND, &callback[2]); create_control (cntl_vbox, 4, CNTL_EXPAND, &callback[3]); /* Fixed controls */ cntl_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); gtk_container_add (GTK_CONTAINER (hbox), cntl_vbox); create_control (cntl_vbox, 1, CNTL_FIXED, &callback[0]); create_control (cntl_vbox, 2, CNTL_FIXED, &callback[1]); create_control (cntl_vbox, 3, CNTL_FIXED, &callback[2]); create_control (cntl_vbox, 4, CNTL_FIXED, &callback[3]); gtk_widget_show (window); while (!done) g_main_context_iteration (NULL, TRUE); return 0; }