GtkTreeview: GtkEntry not showing for editing

Hi!!

I have a curious problem. The following code is for displaying a Liststore with icon:

#include <gtk/gtk.h>
enum
{
	   ICON,
	   ENT_TEXT,
	   ISDIR,
	   COLUMNS
};

void LoadStore(GtkWidget *view) {
	GtkTreeIter iter1;
	GdkPixbuf *iconFold;
    GError        *error = NULL;

	iconFold = gdk_pixbuf_new_from_file ("Folder-icon.png",&error);
    if (error) {
      g_warning ("Could not load icon: %s\n", error->message);
      g_error_free(error);
      error = NULL;
    }
    gtk_tree_view_set_model(GTK_TREE_VIEW(view),NULL);
	GtkListStore *Lstore = gtk_list_store_new(COLUMNS,GDK_TYPE_PIXBUF,
			G_TYPE_STRING,G_TYPE_BOOLEAN);
	gtk_list_store_append(Lstore, &iter1);
    gtk_list_store_set(Lstore, &iter1,ICON,iconFold,ENT_TEXT,"First Data",
    		ISDIR,TRUE,-1);
	gtk_list_store_append(Lstore, &iter1);
    gtk_list_store_set(Lstore, &iter1,ICON,iconFold,ENT_TEXT,"Second Data",
    		ISDIR,TRUE,-1);
	gtk_list_store_append(Lstore, &iter1);
    gtk_list_store_set(Lstore, &iter1,ICON,iconFold,ENT_TEXT,"Third Data",
    		ISDIR,TRUE,-1);
	gtk_list_store_append(Lstore, &iter1);
    gtk_list_store_set(Lstore, &iter1,ICON,iconFold,ENT_TEXT,"Fourth Data",
    		ISDIR,TRUE,-1);
    gtk_tree_view_set_model(GTK_TREE_VIEW(view),GTK_TREE_MODEL(Lstore));
	g_object_unref(Lstore);
}

void InitView(GtkWidget *view) {

    GtkTreeViewColumn *column1 = gtk_tree_view_column_new();
    gtk_tree_view_column_set_title(column1, "Name");

    GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new();
    gtk_tree_view_column_pack_start(column1, renderer, FALSE);
    gtk_tree_view_column_set_attributes(column1, renderer,
                                        "pixbuf", ICON,NULL);
    renderer = gtk_cell_renderer_text_new();
    gtk_tree_view_column_pack_start(column1, renderer, TRUE);
    gtk_tree_view_column_set_attributes(column1, renderer,"text", ENT_TEXT,NULL);
    g_object_set(renderer, "editable", TRUE, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(view), column1);

}
void on_button_clicked(GtkButton *button,GtkWidget *tree_view) {
    LoadStore(tree_view);
	GtkTreePath *SelPath = gtk_tree_path_new_from_string ("3");
	GtkTreeViewColumn *column1 =gtk_tree_view_get_column (GTK_TREE_VIEW(tree_view),0);
	gtk_tree_view_set_cursor (GTK_TREE_VIEW(tree_view),	SelPath,column1,TRUE);
}

int main(void) {
	GtkWidget *window;
	GtkWidget *Fixed1,*buttonRename,*view1,*Paned,*scrawledwinOpen1;
	gtk_init(NULL, NULL);
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_default_size(GTK_WINDOW(window), 400, 600);
	g_signal_connect (window,"destroy",G_CALLBACK(gtk_main_quit),NULL);
    Paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
	gtk_container_add (GTK_CONTAINER (window),Paned);
	Fixed1 = gtk_fixed_new();
	gtk_widget_set_size_request (Fixed1, 400, 50);
    gtk_paned_add1(GTK_PANED(Paned), Fixed1);
    buttonRename = gtk_button_new_with_label("Rename");
	gtk_container_add (GTK_CONTAINER (Fixed1),buttonRename);
	scrawledwinOpen1 = gtk_scrolled_window_new(NULL, NULL);
    gtk_paned_add2(GTK_PANED(Paned), scrawledwinOpen1);
    gtk_widget_set_hexpand(scrawledwinOpen1, TRUE);
    gtk_widget_set_vexpand(scrawledwinOpen1, TRUE);
    view1 = gtk_tree_view_new();
    InitView(view1);
    LoadStore(view1);
    g_signal_connect(buttonRename,"clicked",G_CALLBACK(on_button_clicked),view1);
	gtk_container_add (GTK_CONTAINER (scrawledwinOpen1),view1);
	gtk_widget_show_all(window);
	gtk_main();
	return 0;
}

The functionality is to show the Liststore with icon and when you press the ‘Rename’ button it should start editing the 4th row. It works in the ordinary case. But if you click on the icon in one of the entries in treeview (i.e., selecting the entry in treeview by clicking the icon) and then click the ‘Rename’ button, the GtkEntry doesn’t show up for editing. Can anyone help me out here.

Thanks,

Siji Sukumaran

Why should the behave be different?
Your program does what you it suppose to do and works fine.

I made some modification on your code and use text renderer instead of pixbuf renderer just to help you to understand your code:

#include <gtk/gtk.h>
enum
{
    ICON,
    ENT_TEXT,
    ISDIR,
    COLUMNS
};

void on_button_clicked ( GtkButton *button, GtkWidget *tree_view );

void LoadStore ( GtkWidget *view );
void LoadStore ( GtkWidget *view )
{
    GtkTreeIter iter1;
    gtk_tree_view_set_model ( GTK_TREE_VIEW ( view ), NULL );
    GtkListStore *Lstore = gtk_list_store_new ( COLUMNS, G_TYPE_STRING,
                           G_TYPE_STRING, G_TYPE_BOOLEAN );

    gtk_list_store_append ( Lstore, &iter1 );
    gtk_list_store_set ( Lstore, &iter1, ICON, "text_1    ", ENT_TEXT, "First Data",
                         ISDIR, TRUE, -1 );

    gtk_list_store_append ( Lstore, &iter1 );
    gtk_list_store_set ( Lstore, &iter1, ICON, "text_2    ", ENT_TEXT, "Second Data",
                         ISDIR, TRUE, -1 );

    gtk_list_store_append ( Lstore, &iter1 );
    gtk_list_store_set ( Lstore, &iter1, ICON, "text_3    ", ENT_TEXT, "Third Data",
                         ISDIR, TRUE, -1 );

    gtk_list_store_append ( Lstore, &iter1 );
    gtk_list_store_set ( Lstore, &iter1, ICON, "text_4    ", ENT_TEXT, "Fourth Data",
                         ISDIR, TRUE, -1 );

    gtk_tree_view_set_model ( GTK_TREE_VIEW ( view ), GTK_TREE_MODEL ( Lstore ) );
    g_object_unref ( Lstore );
}

void InitView ( GtkWidget *view );
void InitView ( GtkWidget *view )
{

    GtkTreeViewColumn *column1 = gtk_tree_view_column_new();
    gtk_tree_view_column_set_title ( column1, "Name" );

    GtkCellRenderer *renderer = gtk_cell_renderer_text_new();


    gtk_tree_view_column_pack_start ( column1, renderer, FALSE );
    gtk_tree_view_column_set_attributes ( column1, renderer, "text", ICON, NULL );
    g_object_set ( renderer, "editable", TRUE, NULL );

    /// ***
    renderer = gtk_cell_renderer_text_new();
    gtk_tree_view_column_pack_start ( column1, renderer, TRUE );

    gtk_tree_view_column_set_attributes ( column1, renderer, "text", ENT_TEXT, NULL );
    g_object_set ( renderer, "editable", TRUE, NULL );
    gtk_tree_view_append_column ( GTK_TREE_VIEW ( view ), column1 );
}

void on_button_clicked ( GtkButton *button, GtkWidget *tree_view )
{
    g_return_if_fail ( GTK_IS_BUTTON ( button ) );

    GtkTreePath *SelPath = gtk_tree_path_new_from_string ( "3" );
    GtkTreeViewColumn *column1 = gtk_tree_view_get_column ( GTK_TREE_VIEW ( tree_view ), 0 );

    gtk_tree_view_set_cursor ( GTK_TREE_VIEW ( tree_view ),	SelPath, column1, TRUE );
}

int main ( void )
{
    GtkWidget *window;
    GtkWidget *Fixed1, *buttonRename, *view1, *Paned, *scrawledwinOpen1;

    gtk_init ( NULL, NULL );

    /// ***
    window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
    gtk_window_set_default_size ( GTK_WINDOW ( window ), 400, 600 );
    g_signal_connect ( window, "destroy", G_CALLBACK ( gtk_main_quit ), NULL );

    /// ***
    Paned = gtk_paned_new ( GTK_ORIENTATION_VERTICAL );
    gtk_container_add ( GTK_CONTAINER ( window ), Paned );

    /// ***
    Fixed1 = gtk_fixed_new();
    gtk_widget_set_size_request ( Fixed1, 400, 50 );
    gtk_paned_add1 ( GTK_PANED ( Paned ), Fixed1 );

    /// ***
    buttonRename = gtk_button_new_with_label ( "Rename" );
    gtk_container_add ( GTK_CONTAINER ( Fixed1 ), buttonRename );

    /// ***
    scrawledwinOpen1 = gtk_scrolled_window_new ( NULL, NULL );
    gtk_paned_add2 ( GTK_PANED ( Paned ), scrawledwinOpen1 );
    gtk_widget_set_hexpand ( scrawledwinOpen1, TRUE );
    gtk_widget_set_vexpand ( scrawledwinOpen1, TRUE );

    /// ***
    view1 = gtk_tree_view_new();

    /// ***
    InitView ( view1 );
    g_signal_connect ( buttonRename, "clicked", G_CALLBACK ( on_button_clicked ), view1 );
    
    /// ***
    LoadStore ( view1 );

    /// ***
    gtk_container_add ( GTK_CONTAINER ( scrawledwinOpen1 ), view1 );
    gtk_widget_show_all ( window );
    
    /// ***
    gtk_main();
    return 0;
}

Now click on text_1 and then on that rename button and you will see how things are working in your code.

EDIT:
In other words, what you need is to make your callback to point to the right column no matter where the pointer is.

Change your void InitView ( GtkWidget *view ) with this one:

void InitView ( GtkWidget *view )
{

    GtkTreeViewColumn *column1;
    GtkTreeViewColumn *column2;
    GtkCellRenderer *renderer;

    /// ***
    column1 = gtk_tree_view_column_new();
    column2 = gtk_tree_view_column_new();

    /// ***
    gtk_tree_view_column_set_title ( column1, "Name_1" );
    gtk_tree_view_column_set_title ( column2, "Name_2" );

    /// ***
    renderer = gtk_cell_renderer_pixbuf_new();
    gtk_tree_view_column_pack_start ( column1, renderer, FALSE );
    gtk_tree_view_column_set_attributes ( column1, renderer, "pixbuf", ICON, NULL );
    gtk_tree_view_append_column ( GTK_TREE_VIEW ( view ), column1 );

    /// ***
    renderer = gtk_cell_renderer_text_new();
    g_object_set ( renderer, "editable", TRUE, NULL );
    gtk_tree_view_column_pack_start ( column2, renderer, TRUE );
    gtk_tree_view_column_set_attributes ( column2, renderer, "text", ENT_TEXT, NULL );
    gtk_tree_view_append_column ( GTK_TREE_VIEW ( view ), column2 );

    /// ***
    g_object_set_data ( G_OBJECT ( view ), "column", column2 );
}

and inside your on_button_clicked callback function replace:

GtkTreeViewColumn *column1 = gtk_tree_view_get_column ( GTK_TREE_VIEW ( tree_view ), 0 );

with:

GtkTreeViewColumn *column1 = g_object_get_data ( G_OBJECT ( tree_view ), "column" );

Thanks Michael!!

I kind of did a work-around. I got some cue from other applications to abandon editing in the treeview and instead used a dialog instead.
By the way… great tutorials. Was of immense help to me.

Thanks

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.