Search code examples
gtkvala

how to use the set_cell_data_func function in vala to change the layout of my cell depending on its content?


I'm trying to use the set_cell_data_func on a Gtk.TreeViewColumn. My code compiles but gives a segmentation error when running. I have also tried the insert_column_with_data_func instead but the result is the same.

Here is my code, i hope you'll be able to help me :)

public class Application : Gtk.Window {
    public Application () {
        this.destroy.connect (Gtk.main_quit);
        this.set_default_size (600, 400);

        Gtk.ListStore store = new Gtk.ListStore (2, typeof(int),
            typeof(string));
        Gtk.TreeIter iter;

        store.append (out iter);
        store.set (iter, 0, 0, 1, "A");
        store.append (out iter);
        store.set (iter, 0, 1, 1, "B");
        store.append (out iter);
        store.set (iter, 0, 0, 1, "C");
        store.append (out iter);
        store.set (iter, 0, 0, 1, "D");

        Gtk.TreeView view = new Gtk.TreeView.with_model (store);
        this.add(view);

        Gtk.CellRendererText cell = new Gtk.CellRendererText ();
        Gtk.TreeViewColumn col = new Gtk.TreeViewColumn.with_attributes (
            "Value", cell, "text", 1);
        col.set_cell_data_func (cell, (Gtk.CellLayoutDataFunc)render_value);
        view.append_column (col);
    }

    public void render_value (Gtk.TreeViewColumn column, Gtk.CellRendererText
        cell, Gtk.TreeModel model, Gtk.TreeIter iter) {
        var val = Value (typeof(int));
        model.get_value (iter, 0, out val);
        if ((int)val==1) (cell as Gtk.CellRendererText).background = "#b8cb04";
        val.unset ();
    }

    public static int main (string[] args) {
        Gtk.init (ref args);
        Application app = new Application ();
        app.show_all ();
        Gtk.main ();
        return 0;
    }
}

Solution

  • After debugging the translated c sources i found the bug.

    vala translates

    public void render_value                            (Gtk.TreeViewColumn column, 
                                                         Gtk.CellRendererText cell, 
                                                         Gtk.TreeModel model, 
                                                         Gtk.TreeIter iter)
    

    from your code to the following c equivalent

    void application_render_value                       (Application* self,
                                                         GtkTreeViewColumn* column,
                                                         GtkCellRendererText* cell,
                                                         GtkTreeModel* model, 
                                                         GtkTreeIter* iter)
    

    I compared this with the reference docs.

    There the signature of the data function is defined as follows

    void                (*GtkCellLayoutDataFunc)        (GtkCellLayout *cell_layout,
                                                         GtkCellRenderer *cell,
                                                         GtkTreeModel *tree_model,
                                                         GtkTreeIter *iter,
                                                         gpointer data);    
    

    With regard to the method you have implemented that means that the arguments are shifted by one to the right. So the following applies to your data func/method

    • column is in fact the cell renderer
    • cell is the tree model
    • model is the iterator and
    • iter is the data that is passed to the function/method

    If you change the declaration of your data func/method to

    public void render_value (Gtk.CellRendererText cell, 
                              Gtk.TreeModel model, Gtk.TreeIter iter, Object data)
    

    everything should work fine.

    Maybe the reason of this is that CellLayoutDataFunc is defined as public delegate void. But since i don't know anything about vala it's just a guess. If it's not the case you may post this on a related vala mailing list.