Kim,
I started with the "editable_list" demo code and boiled it down to
something
simpler and more portable. I also added hooks for error checking.
Maybe this code will be of some use to you:
#include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
enum { COL_ID, COL_KEY, NUM_COLUMNS };
GtkWidget *main_app_window; // Application's main window.
typedef struct {GCallback edited; GType type; char *label;} COL_PARAMS;
void table_add_item (GtkWidget *button, gpointer data)
{
GtkTreeIter iter;
GtkTreeView *treeview = (GtkTreeView *)data;
GtkTreeModel *model = gtk_tree_view_get_model (treeview);
GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
gtk_tree_selection_select_iter (selection, &iter);
}
void table_remove_item (GtkWidget *button, gpointer data)
{
GtkTreeIter iter;
GtkTreeView *treeview = (GtkTreeView *)data;
GtkTreeModel *model = gtk_tree_view_get_model (treeview);
GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
{
int index=0, n_columns, i;
char *path_string;
gpointer cell_val;
index = atoi(path_string = gtk_tree_model_get_string_from_iter
(model, &iter));
g_free (path_string);
// Free any data stored dynamically by the model.
n_columns = gtk_tree_model_get_n_columns (model);
for (i=0; i<n_columns; i++)
{
switch (gtk_tree_model_get_column_type (model, i))
{
case G_TYPE_STRING:
case G_TYPE_POINTER:
gtk_tree_model_get (model, &iter, i, &cell_val, -1);
g_free (cell_val);
break;
}
}
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
// Select the row above the deleted row.
if (gtk_tree_model_get_iter_first (model, &iter)) // Skip if list is
now empty.
{
asprintf(&path_string, "%d", (index ? --index : 0));
gtk_tree_model_get_iter_from_string (model, &iter, path_string);
g_free (path_string);
gtk_tree_selection_select_iter (selection, &iter);
}
}
}
GtkTreeView *table_create (int n_columns, COL_PARAMS *cp)
{
gint i;
GtkListStore *model;
GtkTreeView *treeview;
GtkTreeIter iter;
GtkCellRenderer *renderer;
GType *types = malloc (n_columns * sizeof(GType));
for (i=0; i<n_columns; i++) types[i] = cp[i].type;
model = gtk_list_store_newv (n_columns, types);
free(types);
treeview = (GtkTreeView *)gtk_tree_view_new_with_model ((GtkTreeModel
*)model);
for (i=0; i<n_columns; i++)
{
renderer = gtk_cell_renderer_text_new ();
g_signal_connect (renderer, "edited", cp[i].edited, model);
g_object_set_data (G_OBJECT(renderer), "column", (gpointer)i);
g_object_set ((gpointer)renderer, "editable", (gpointer)TRUE,
NULL);
gtk_tree_view_insert_column_with_attributes
(treeview, -1, cp[i].label, renderer, "text", (gpointer)i, NULL);
}
return treeview;
}
int key_is_OK (const int id, const char *key)
{
int retval;
if (id && key && *key)
{
// The next line is totally FAKE!
retval = 1 & (id ^ (key[strlen(key)-1]));
if (! retval)
{
// Pop up an error dialog.
GtkWidget *dialog, *label;
dialog = gtk_message_dialog_new
((GtkWindow *)main_app_window, GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE, "Invalid ID/Key: %d/%s", id, key);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
}
else retval = TRUE;
return retval;
}
void key_cell_edited
(GtkCellRendererText *cell, const gchar *path_string, const gchar
*new_text, gpointer data)
{
GtkTreeModel *model = (GtkTreeModel *)data;
GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
GtkTreeIter iter;
int old_id, new_id, column;
char *old_key=NULL;
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter, COL_ID, &old_id, COL_KEY, &old_key,
-1);
switch (column = (int)g_object_get_data (G_OBJECT (cell), "column"))
{
case COL_ID:
{
if ((sscanf(new_text, "%d", &new_id)) && key_is_OK (new_id,
old_key))
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
column, new_id, -1);
}
break;
case COL_KEY:
{
if (key_is_OK (old_id, new_text))
{
g_free (old_key);
gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
new_text, -1);
}
}
break;
}
gtk_tree_path_free (path);
}
gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data )
{
gtk_main_quit ();
return FALSE;
}
int main( int argc, char *argv[] )
{
GtkWidget *vbox, *hbox, *sw, *treeview, *button;
GtkTreeModel *model;
GtkTreeIter iter;
int i;
struct { int id; char *key; } foo[] = { {999, "ABC123"}, {0,NULL}
};
COL_PARAMS col_params[] =
{
{ G_CALLBACK(key_cell_edited), G_TYPE_INT, "Tag ID"},
{ G_CALLBACK(key_cell_edited), G_TYPE_STRING, "Key" }
};
/* create window, vbox packing container, scrolled window for table, etc
*/
gtk_init (&argc, &argv);
main_app_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (main_app_window), "Editable 2");
g_signal_connect (G_OBJECT (main_app_window), "delete_event", G_CALLBACK
(delete_event), NULL);
vbox = gtk_vbox_new (FALSE, 5);
gtk_container_add (GTK_CONTAINER (main_app_window), vbox);
gtk_box_pack_start
(GTK_BOX (vbox), gtk_label_new ("Decryption Keys"), FALSE, FALSE, 0);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy
(GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
/* create model & view */
treeview = (GtkWidget *)table_create (NUM_COLUMNS, col_params);
// Stripe rows (depends on theme)
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
gtk_tree_selection_set_mode
(gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
GTK_SELECTION_SINGLE);
// Initialize the data in the table.
model = gtk_tree_view_get_model ((GtkTreeView *)treeview);
for (i=0; foo[i].id; i++)
{
gtk_list_store_append ((GtkListStore *)model, &iter);
gtk_list_store_set
((GtkListStore *)model, &iter, COL_ID, foo[i].id, COL_KEY, foo[i].key,
-1);
}
gtk_container_add (GTK_CONTAINER (sw), treeview);
/* some buttons */
hbox = gtk_hbox_new (TRUE, 4);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Add ID/Key");
g_signal_connect (button, "clicked", G_CALLBACK (table_add_item),
treeview);
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
button = gtk_button_new_with_label ("Remove this ID/Key");
g_signal_connect (button, "clicked", G_CALLBACK (table_remove_item),
treeview);
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
gtk_window_set_default_size (GTK_WINDOW (main_app_window), 400, 300);
gtk_widget_show_all (main_app_window);
gtk_main ();
return 0;
}
Joe Orgren
Senior Engineer
Organizational Strategies Inc.
Supporting the Applied Technology Division/OIT
Bureau of Customs & Border Protection
United States Department of Homeland Security
202-927-3967
202-927-2002
Date: Tue, 05 Aug 2003 21:10:42 +1000
From: kadil <ksadil bigpond com>
Subject: treeview question
To: gtk-app-devel-list gnome org
Reply-To: ksadil bigpond com au
I would like to use a tree-table type widget in my new application. I
understand that a "Tree View" widget acomplishes this, however it is
undocumented in the Tutorial and the API is quite "clinical" for a novice
such as myself. Can someone please direct me to an example that has more
has
a Tree View with more than one column so I can experiment with the API.
Thanks,
Kim
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list