14.2. Editing Text in a Gtk2::TreeView

14.2.1. Introduction

A Gtk2::TreeView offers you the opportunity to manually change displayed text.

This lesson will discuss how to go about editing text displayed by Gtk2::CellRendererText.

14.2.2. Requirements

Tip

It is good practice to declare constants for each column in the Gtk2::TreeModel at the start of your program. EG:

use constant COLUMN_EDITABLE       => 2;
assigns a constant of "COLUMN_EDITABLE" to the int value "2". When using this constant, you know what it is suppose to represent.

The same can be done with the cell renderer "data-rider" values.

#Create a constant to differentiate different renderers;
#This makes things easy to discover which renderer in the view
#was changed
use constant RENDERER_FIRST_TEXT       => 0;
Remember that Gtk2::TreeViewColumns are unrelated to Gtk2::TreeModel columns. During the callback routine we need to link them up in code.

Tip

To see which properties are available to set for each cell renderer, look at Gtk2::CellRenderer's man page, and also at the man page of the specific cell renderer you are using, like Gtk2::CellRendererText.

14.2.3. Working example

A working example can be found here: 'Editing text in a Gtk2::TreeView'

This program is not much different from the previous demo, so it would waste space showing the whole program again. We will only discuss the parts of interest here.

14.2.3.1. "cell_edited"

  • The "cell_edited" sub is handed the following:

    my ($cell, $path_string, $new_text, $model) = @_;
    We will then use the variables handed to the sub, to update the model.

  • To discover which Gtk2::CellRenderer inside the Gtk2::TreeView was edited, we extract the value of 'render_number' from the cell renderer. We then decide in code which column of the Gtk2::TreeModel needs to be updated.

    #Get the renderer number;
    my $column_of_model;
    if ($cell->{'renderer_number'} == RENDERER_FIRST_TEXT) {
        
        $column_of_model = MODEL_FIRST_COLUMN;
    }
    The way you associate the 'renderer_number' value to a Gtk2::TreeModel column does not need to be a simple "if" statement. You can use a more slick lookup hash.

    Note

    The above may seem like an overkill, because we only have one Gtk2::CellRenderer. This is true, but it is used for a demonstration when you end up having a few of these Gtk2::CellRenderers and each one can be edited, but they also use the same callback.

  • We generate a Gtk2::TreePath, by using $path_string as a argument to the new_from_string method of Gtk2::TreePath.

    my $path = Gtk2::TreePath->new_from_string ($path_string);
    This will give us a "geographical" indication which row was edited.

  • We then get the Gtk2::TreeIter of the Gtk2::TreePath, $path.

    my $iter = $model->get_iter ($path);
    $iter is now referring to a row in model-speak.

  • Remember the actual goal of changing a value in the model? We accomplish our goal with the following:

    $model->set_value ($iter, $column_of_model, $new_text); 

Looking at it as a unit:

sub cell_edited {
    my ($cell, $path_string, $new_text, $model) = @_;

    #Get the renderer number;
    my $column_of_model;
    if ($cell->{'renderer_number'} == RENDERER_FIRST_TEXT) {
        $column_of_model = MODEL_FIRST_COLUMN;
    }
    
    my $path = Gtk2::TreePath->new_from_string ($path_string);
    my $iter = $model->get_iter ($path);
    $model->set_value ($iter, $column_of_model, $new_text); 
    
}

14.2.4. Same ice-cream, different topping

The above principle is also used on the Gtk2::CellRendererToggle. In order to make changes apply to the underlying model, you have to connect a signal callback to its "toggled" signal.

The callback will receive the following:

my ($cell, $path_str, $model) = @_;
You then need to read the current state of the Gtk2::CellRendererToggle from the model, invert it and write it back to the model so it can again be reflected by the Gtk2::CellRendererToggle that was "toggled". The rest can be done in much the same way Gtk2::CellRendererText did it.