Re: model for CellRendererCombo



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 rappaz 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



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