model for CellRendererCombo




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});

}




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