OK I think I understand a little more what you're getting at. Looking at my
own code, from about 8 years back, I do exactly the same thing as you -
loop through each iter in the combo's model, looking for a match (
see render_combo_cell() in Gtk2::Ex::Datasheet::DBI ). Sorry it's taken
this long to understand what you were trying to do.

Alternatively, I guess we could cache the ID ==> text mappings in a hash
and use that instead of iterating over all the possible values. I don't see
a way around using one of these approaches. The problem is that the value
displayed in the treeview 'normally' is quite distinct from the
CellRendererCombo that is brought to life when you actually begin editing.

Anyway it's not so bad. Once you abstract it away once, you can *kinda*
forget about it. It's not so cool for large models. For example when I try
to render a datasheet with 1,000,000 records, if I put a combo in there,
it's SLOW. But I understand that what I'm trying to do isn't really what
most people are doing - just showing a list of folders underneath the
current one, or whatever. It's unlikely we're going to get a more optimised
version unless we write it ourselves.

Dan


On Thu, Feb 13, 2014 at 2:50 AM, RAPPAZ Francois
<francois.rap...@unifr.ch>wrote:

>
> I'm still struggling with the cellRendererCombo. The combo has 2 columns
> (say id, name) one which holds a numeric value  not displayed (id) and, the
> visible column which holds a text (name).
>
> The suggestion at
>
> http://stackoverflow.com/questions/3534665/gtk-trouble-modifying-treeview-model-on-cellrenderercombo-changed-signal
>
> led me to the code below where I get a ref of the underlaying Gtk2::Combo
> with the sub on editing-started event. That ref can be used to get an
> active iterator in the sub fired with the edited event and I can get the
> value selected with the combo.
>
> There are 2 problems at least:
> - I need a hash of the whole combo content to diplay the name in the combo
> using the id, but someway these should be already in the model
> - I would prefer using the CellRendercombo model to display the name
> rather then calling a sub with set_cell_data_func
>
> Can anyone show me how to change this ?
>
> Thanks, François
>
> #! /usr/bin/perl -w
>
> use strict;
> use Gtk2 '-init';
> use Glib qw/TRUE FALSE/;
> use Data::Dumper;
>
>
>
> my %render = (
>         text => sub { return Gtk2::CellRendererText->new; },
>         hidden => sub { return Gtk2::CellRendererText->new;   },
>         number => sub { return Gtk2::CellRendererText->new;    },
>         toggle => sub { return Gtk2::CellRendererToggle->new;   },
>         combo => sub {  return Gtk2::CellRendererCombo->new;   },
>         progress => sub { return Gtk2::CellRendererProgress->new;   },
>         status_column => sub { return Gtk2::CellRendererPixbuf->new; },
>         image => sub { return Gtk2::CellRendererPixbuf->new;   },
> );
>
> my %signals = (
>         'Gtk2::CellRendererText' => [ 'edited' , sub { cell_edited(@_)}],
>         ' Gtk2::CellRendererToggle' => ['toggled',  sub {
> toggle_edited(@_)}],
>         'Gtk2::CellRendererCombo' => ['edited', sub { combo_edited(@_)}],
>
> );
> #'Gtk2::CellRendererCombo' => ['changed', sub { combo_changed(@_)}],
> my @fields = ("a","b","c");
>
> my %combo = (1 => "one", 2 => "two", 3 => "three");
>
> #standard window creation, placement, and signal connecting
> my $window = Gtk2::Window->new('toplevel');
> $window->signal_connect('delete_event' => sub { Gtk2->main_quit; });
> $window->set_border_width(5);
> $window->set_position('center_always');
>
> #this vbox will geturn the bulk of the gui
> my $vbox = &ret_vbox();
>
> my $maincombo;
>
> #add and show the vbox
> $window->add($vbox);
> $window->show();
>
> #our main event-loop
> Gtk2->main;
>
>
> sub ret_vbox {
>
> my $vbox = Gtk2::VBox->new(FALSE,5);
> $vbox->set_size_request (300, 300);
>
>         #this is one of the provided base Gtk2::TreeModel classes.
> my $tree = Gtk2::TreeView->new();
> my $pos=0;
>
> my @listedef;
>
>         foreach my $field (@fields) {
>
>                 my $renderer =  ($pos == 0 ?
> $render{"combo"}():$render{"text"}());
>
>                  my $cell_ref = ref $renderer;
>                 print "$cell_ref\n";
>
>                 $renderer->set( editable => TRUE );
>                 if ($pos == 0){
>                         setup_combo($pos, $field, $renderer, $tree);
>
>                 } #else {
>                 #$renderer->signal_connect (edited => sub {
> cell_edited(@_)}, $tree);
>                 #}
>                 $renderer->{column}=$pos;
>                 my $col =
>  Gtk2::TreeViewColumn->new_with_attributes($field, $renderer, "text" =>
> $pos);
>                 $tree->append_column($col);
>
>                  my $label = Gtk2::Label->new;
>                  $label->set_text("$field");
>                  $label->visible( 1 );
>                 $col->set_widget($label);
>                 push @listedef, "Glib::String";
>
>                 if (exists $signals{$cell_ref}) {
>                             my $coderef =  $signals{$cell_ref}[1];
>
>                             $renderer->signal_connect (
> $signals{$cell_ref}[0] =>  \&$coderef, $tree  );
>                }
>
>                if ( $pos== 0){
>                              $renderer->signal_connect ( "editing-started"
> =>  \&start_editable  );
>                      #$renderer->signal_connect ( "edited" =>
>  \&combo_edited, $tree  );
>
>
>                      $col->set_cell_data_func($renderer, sub{
> process_combo(@_); });
>                 }
>                 $pos++;
>         }
>
>
>         my $liste = Gtk2::ListStore->new(@listedef);
>
>
>         #fill it with arbitry data
>
>           foreach (0..3){
>
>                 $pos = 0;
>                 my @model_row;
>
>
>                 # $tree->append_column($col++);
>
>                 #my $iter = $tree->append(undef);
>                 #$tree_store->set ($iter,MODEL_FIRST_COLUMN, "Parent
> $parent_nr");
>
>                 foreach my $field (@fields) {
>
>
>
>
>                         if ($pos == 0) {
>                                  push @model_row, $liste->append, $pos,
>  $_;
>                         } else {
>
>
>                                 push @model_row,  $pos, $field . " ". $_;
>                         }
>                         $pos++;
>                 }
>
>                 $liste->set(@model_row);
>         }
>         $liste->signal_connect( "row-changed" => sub { changed(@_) } );
>
>         $tree->set_model($liste);
>
>
> $vbox->pack_start($tree,TRUE,TRUE,0);
> $vbox->show_all();
> return $vbox;
> }
>
> sub cell_edited {
>   my ($cell, $path_string, $new_text, $tree) = @_;
>   print "cell_edited\n";
>   # return unless ($tree);
>  my $model = $tree->get_model;
>   my $path = Gtk2::TreePath->new_from_string ($path_string);
>   #my $model = $tree->get_model;
>    my $col = $cell->{column};
>
>   my $iter = $model->get_iter($path);
>
>   $model->set_value ($iter, $col, $new_text);
>
> }
>
> sub changed {
>         my ( $liststore, $treepath, $iter ) = @_;
>
>  print "changed\n";
>
> }
>
> sub combo_changed_notused {
>         my ($combo, $path_string, $new_iter, $tree) = @_;
>         #my $path = Gtk2::TreePath->new_from_string( $path_string );
>         # my $iter = $combo->get_iter ( $path );
>         #my  $new_text = $combo->get( $new_iter, 0 );
>         my $event = Gtk2::Gdk::Event->new('focus-change');
>         $event->window ($tree->get_bin_window);
>         $event->send_event(TRUE);
>         $event->in(FALSE);
>         $maincombo->signal_emit('focus-out-event', $event);
>         # print "combo_changed: ", $new_iter, "\n";
>
>                 # $combo_model->set ( $combo_iter,0, $new_text );
>                 #$combo->set($iter,  $renderer->{column}, $new_text);
>
>
> }
>
> sub start_editable {
>         my ($cell, $editable, $path) = @_;
>          print "start_editable\n";
>         # print Dumper($editable);
>           $maincombo = $editable;
>
> }
>
> sub setup_combo {
>          my ($column_no, $fieldname, $renderer, $tree ) = @_;
>
>         print "set_upcombo\n";
>
>         my @combo_key = keys %combo;
>         my @cols = ("key", "values");
>
>     my @liste_def;
>
>      my $pos = 0;
>     foreach my $name (@cols){
>              if ($pos++ == 0) {
>
>                      push @liste_def, "Glib::Int";
>                      # push @liste_def, "Glib::String";
>             } else {
>                     push @liste_def, "Glib::String";
>             }
>
>     }
>
>     my $model = Gtk2::ListStore->new( @liste_def );
>
>
>     foreach  my $key ( @combo_key ) {
>
>         my @model_row;
>
>         push @model_row, $model->append;
>         $pos = 0 ;
>         foreach my $name ( @cols) {
>
>             push @model_row, $pos, ($pos == 0 ? $key : $combo{$key});
>
>             $pos++;
>         }
>         $model->set( @model_row );
>         # combo_edited($renderer, $combo{$key}, $combo{$key}, $tree);
>
>     }
>
>
>          $renderer->set(
>                     editable        => TRUE,
>                     text_column     => 1,
>                      has_entry       => FALSE,
>                      model => $model,
>
>               );
>
>
>
>
>  }
>
>
>  sub combo_edited {
>         my  ($renderer, $path_string, $new_text, $tree) = @_;
>         # return unless ($tree);
>         #  treeViewModel[path][columnNumber] = newText
>         my $model = $tree->get_model;
>          print("combo_edited " . $new_text . "\n");
>                                         #       $cell->get("model");
> #       $model->set ($iter, $cell->{column}, $new_text);
>         my $path = Gtk2::TreePath->new_from_string( $path_string );
>         my $citer = $maincombo->get_active_iter;
>         my $cmodel = $maincombo->get_model;
>         my $value = $cmodel->get($citer, 0);
>         print("combo_edited value :" . $value . "\n");
>          my $iter = $model->get_iter ( $path );
>                 # $combo_model->set ( $combo_iter,0, $new_text );
>         $model->set($iter,  $renderer->{column}, $new_text);
> }
>
>
>
>  sub process_combo {
>      my ($tree_column, $renderer, $model, $iter ) = @_;
>
>         my $id = $model->get( $iter, 0 );
>
>          $renderer->set( text    => $combo{$id} ) if (exists $combo{$id});
>
> }
>
>
> _______________________________________________
> gtk-perl-list mailing list
> gtk-perl-list@gnome.org
> https://mail.gnome.org/mailman/listinfo/gtk-perl-list
>
_______________________________________________
gtk-perl-list mailing list
gtk-perl-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtk-perl-list

Reply via email to