Re: SimpleList: connecting a signal to a CellRendererToggle

Grégory SCHMITT said:
Here's the deal: I have three columns of ticking boxes. When clicking on
a tick in the first column, it should untick the 2nd column and tick the
3rd one (it's an example; in reality, the behaviour should be à la radio
button, but I would prefer to have ticking boxes).

you can tell the renderer to draw itself like a radiobutton.

  # create the simplelist; this will create the actual cell renderer that
  # will be used.
  $simplelist = Gtk2::SimpleList->new (...);
  # now fetch the renderer you want and futz with it.
  $n = the index of the column with the toggle renderer
  my @r = $simplelist->get_column ($n)->get_cell_renderers;
  $r[0]->set (radio => TRUE); # assuming the toggle renderer is the only one

My idea was then to
create a column type and connect a signal to the column.

Here's the code:

                      type     => 'Glib::Boolean',
                      renderer => 'Gtk2::CellRendererToggle',
                      attr     =>
                      sub {
                           my ($column, $cell, $model, $iter, $nb_col) = @_;

                           my $renderer = $column->get_cell_renderers;
                           $renderer->set('activatable' => 1);

this is redundant --- the callback has already received a reference to the
cell renderer being operated on, in $cell!

                           $renderer->signal_connect(toggled => sub {

this will connect a new toggled handler to the cell *every* *time* the
treeviewcolumn calls the cell data function (which is really, really often). 
that will blow up exponentially.  what you really want is to connect this just
after creating the simplelist, by the same method as i showed above for
setting the radio property.

                              my ($renderer, $row, $col) = @_;
                              my $iter = $model->iter_nth_child(undef, $row);
                              my $val = $model->get($iter, $col);

                              $model->set($iter, $col, !$val);
                              $model->set($iter, $col+1, 0);
                              $model->set($iter, $col+2, 1);

not sure you want hard-coded values here, don't you want $val and !$val?

                              print("$row - $col\n");
                              print("Valeur: " . $model->get($iter, $nb_col) . "\n");
                           }, $nb_col);

There are 2 problems with it:

- clicking on a tick box in the first column do untick and tick the
other columns, but the clicked tick box doesn't look like ticked (it
stays empty).

you've supplied an attr function to add_column_type(); this function is used
as the cell data callback, the function the column calls to set up the cell
renderer to draw a particular cell for the proper attributes of the model. 
however, you never actually set the active property of the renderer.

the cell data function is the wrong place to connect the callback, and when
you take that out, it doesn't do anything.  instead, you want the toggle to
reflect the value in the model.  thus, tell simple list that for this column,
the attribute to sync with the model is "active".

    attr => 'active',  # instead of the subroutine reference

- for an unknow reason, clicking only once outputs a lot of information
(as stated in the two print lines at the end of the code). Worse, the
last print gives me a "Valeur: 0" whereas it should be 1 !

the "lots of information" bit is because of the extraneous connections, as i
said above.

I'm using Perl-Gtk2 1.021, Perl 5.8.3, libgtk-2.2.

wow, only 9 months old and already 1.021 seems like ancient history.  ;-)

1.043 has lots of little bugfixes that you might want, and a
guaranteed-not-to-be-broken API.  we're also planning 1.060 for gnome 2.8. 
please consider upgrading.  =)

try it like this:

  use strict;
  use Gtk2 -init;
  use Gtk2::SimpleList;

                    type     => 'Glib::Boolean',
                    renderer => 'Gtk2::CellRendererToggle',
                    attr     => 'active',

  my $slist = Gtk2::SimpleList->new ('one' => 'mybool',
                                     'two' => 'bool',
                                     'three' => 'bool');
  my ($renderer) = $slist->get_column (0)->get_cell_renderers;
  $renderer->set (activatable => 1);

  $renderer->signal_connect (toggled => sub {
        my ($renderer, $pathstr, $model) = @_;
        my $path = Gtk2::TreePath->new_from_string ($pathstr);
        my $iter = $model->get_iter ($path);
        my $val = $model->get($iter, 0);

        $model->set($iter, 1, !$val);
        $model->set($iter, 2, !$val);
  }, $slist->get_model);

  @{$slist->{data}} = (
        [ 0, 1, 1 ],
        [ 1, 0, 0 ],
        [ 0, 1, 1 ],
        [ 1, 0, 0 ],

  my $window = Gtk2::Window->new;
  $window->add ($slist);
  $window->signal_connect (destroy => sub {Gtk2->main_quit});

muppet <scott at asofyet dot org>

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]