Help with Gtk2::CellRendererCombo



Hi there,

I'm trying to use a CellRendererCombo in a tree. The combo has 2 columns one which holds a key (numeric) not 
displayed and, the visible column which holds a text.

The only way I got it working is with two sub that searches the whole combo content for a match and then 
display the value found in the tree, or take the value from the tree to display the corresponding row in the 
combo.

There is a similar code in perlmonks
http://www.perlmonks.org/?node_id=952244

Is there no short way to do this ?

My code is below.

Thanks for any help

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(@_)}],

);

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

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

                } #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){
                         $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 setup_combo {
         my ($column_no, $fieldname, $renderer ) = @_;
 
        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 );
  
    }

         $renderer->set(
                    editable        => TRUE,
                    text_column     => 1,
                     has_entry       => FALSE,
                     model => $model
              );       

 }
 #combo -> tree
 sub combo_changed_todel {
        my ($cell,  $new_text, $iter, $tree) = @_;
        # return unless ($tree);
  print Dumper($new_text);
        my $model = $tree->get_model;
         print("combo_edited " . $new_text . "\n");
                                        #       $cell->get("model");
        $model->set ($iter, $cell->{column}, $new_text); }

 sub combo_edited_todel {
        my  ($renderer, $path_string, $new_text, $tree) = @_;
        # return unless ($tree);
        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 $iter = $model->get_iter ( $path );
                # $combo_model->set ( $combo_iter,0, $new_text );
        $model->set($iter,  $renderer->{column}, $new_text); }

 sub combo_edited {
         my ($renderer, $path_string, $new_text, $tree) = @_;
        my $combo_model;
        
        #  return unless ($renderer);
         $combo_model = $renderer->get("model");
       print("combo_edited : " . $new_text. "\n");   
        print Dumper($path_string);     
       my $combo_iter = $combo_model->get_iter_first;
       #
       # my $combo_iter = $combo_model->get_active_iter;
        my $found_match = FALSE;

        while ( $combo_iter ) {
                # $self->{log}->debug("combo_edited  testing: ".  $combo_model->get( $combo_iter, 1 ));
            if ( $combo_model->get( $combo_iter, 1 ) eq $new_text ) {
                $found_match = TRUE;
                $new_text = $combo_model->get( $combo_iter, 0 );
                print("combo_edited  found: " . $new_text. "\n");   
                last;
            }
            
            $combo_iter = $combo_model->iter_next( $combo_iter );
            
        }
        


#if (  $found_match ) {
        if ($combo_iter){
                  my $path = Gtk2::TreePath->new_from_string( $path_string );
                    my $model = $tree->get_model;
                    my $iter = $model->get_iter ( $path );
                # $combo_model->set ( $combo_iter,0, $new_text );
                $model->set($iter,  $renderer->{column}, $new_text);
        }
    
 }

# $tree -> $combo
 sub process_combo {
     my ($tree_column, $renderer, $model, $iter ) = @_;
    
    # Get the ID that represents the text value to display
    my $key_value = $model->get( $iter, $renderer->{column} );
    # print Dumper($tree_column);
    print("process_combo  col: " . $renderer->{column}. " val: " . $key_value . "\n");
    my $combo_model = $renderer->get( "model" );
    
    if ( $combo_model ) {
        
        # Loop through our combo's model and find a match for the above ID to get our text value
        my $combo_iter = $combo_model->get_iter_first;
        my $found_match = FALSE;
        
        while ( $combo_iter ) {
            
           print "testing : ",$combo_model->get( $combo_iter, 0 ), "\n";
                if ( $combo_model->get( $combo_iter, 0 )  && $key_value && $combo_model->get( $combo_iter, 0 
) == $key_value ) {
                    $found_match = TRUE;
                    print("process combo found match " .  $combo_model->get( $combo_iter, 0 ) . "\n");
                    $renderer->set( text    => $combo_model->get( $combo_iter, 1 ) );
                    last;
                }
           
            
            $combo_iter = $combo_model->iter_next( $combo_iter );
            
        }
        
        # If we haven't found a match, default to displaying an empty value
        if ( ! $found_match ) {
            $renderer->set( text    => "" );
        }
 
  }
}




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