cas2006 has asked for the wisdom of the Perl Monks concerning the following question:

is it possible to have a popup menu as one of the fields in a Gtk2::SimpleList?

if so, how do i do it - at a guess, Gtk2::SimpleList->add_column_type would be used, but the documentation is fairly minimal and i can't figure it out.

back-story: i'm writing a very quick and dirty POS system using perl, gtk2, and postgres to replace a completely bletcherous ancient DOS + COBOL program that came on the windows box when we bought our bookshop. i want to get rid of the windows box and replace it with a linux box. more importantly, i want access to our sales data so i can write whatever queries we need.

all the POS system needs to do is allow the user to enter sales items, calculate totals, print receipts, and store the transaction in postgres. the reports will be completely separate, and probably web-based.

so, i've figured out how to do menus, and SimpleLists to display the items. now i want the user to be able to override the RRP with either a fixed-price or a percentage discount for each item. that requires a "discount field" and a discount type field (popup menu: "None", "Fixed", "Percentage").

Replies are listed 'Best First'.
Re: popup menu in Gtk2::SimpleList
by zentara (Cardinal) on Mar 04, 2006 at 13:00 UTC
    UPDATE MAR 6,2006.... please see simpler example in Re^3: popup menu in Gtk2::SimpleList below

    I'm sure it can be done, but I don't have an example handy at the moment. But, if you look at the perldoc for Gtk2::SimpleList, there is a method

    Gtk2::SimpleList->add_column_type ($type_name, ...) $type_name (string)

    Which lets you add any custom type column, and you want to add a CellRendererCombo.

    Now it just so happens, that a Gtk2-perl developer , Daniel Kasak just posted a sample script to the Gtk2-perl maillist, where he questioned whether such a combo cell acted buggy in a plain ListStore. You could either drop the requirement for SimpleList and go with ListStore, or pull the drop down combo model code from the script below, and add it as a column type to your SimpleList. I'll see if I can get it working later today, if not, muppet on the maillist would know. (but I hate to overwork the poor guy, :-) )

    So here is the ListStore example, from which you could extract the combo model for the drop down.

    #!/usr/bin/perl use warnings; use strict; use Gtk2 -init; use Glib qw/TRUE FALSE/; # Danial Kasak posted this as having # some sort of bug, but it works fine for me. # if you select a number in the 3rd column combobox, # then hit dump, before hitting enter in the cell, # or click somewhere in the treeview, the number # change won't take effect. Seems like a feature to me :-) my $window = Gtk2::Window->new( "toplevel" ); $window->signal_connect( "destroy", sub { Gtk2->main_quit(); } ); my $vbox = Gtk2::VBox->new( 0, 5 ); my $model = Gtk2::ListStore->new( "Glib::String", "Glib::String", "Gli +b::Int" ); $model->set( $model->append, 0, "Hi", 1, "There", 2, 5 ); my $renderer_1 = Gtk2::CellRendererText->new; $renderer_1->set( editable => TRUE ); $renderer_1->signal_connect( edited => sub { &process_editing( @_, 0 ) +; } ); my $renderer_2 = Gtk2::CellRendererText->new; $renderer_2->set( editable => TRUE ); $renderer_2->signal_connect( edited => sub { &process_editing( @_, 1 ) +; } ); my $column_1 = Gtk2::TreeViewColumn->new_with_attributes( "Some Text", $renderer_1, 'text' => 0 ); my $column_2 = Gtk2::TreeViewColumn->new_with_attributes( "More Text", $renderer_2, 'text' => 1 ); my $combo_model = Gtk2::ListStore->new( "Glib::Int", "Glib::String" ); foreach my $thingy ( [ 1, "one" ], [ 2, "two" ], [ 3, "three" ], [ 4, +"four" ], [ 5, "five" ] ) { $combo_model->set( $combo_model->append, 0, $$thingy[ 0 ], 1, $$thingy[ 1 ] ); } my $renderer_3 = Gtk2::CellRendererCombo->new; $renderer_3->set( editable => TRUE, text_column => 1, has_entry => TRUE, model => $combo_model ); $renderer_3->signal_connect( edited => sub { &process_editing( @_, 2 ) +; } ); my $column_3 = Gtk2::TreeViewColumn->new_with_attributes( "A Combo", $renderer_3, te +xt => 2 ); $column_3->set_cell_data_func( $renderer_3, sub { &render_combo_cell( +@_ ); } ); my $treeview = Gtk2::TreeView->new( $model ); $treeview->set_rules_hint( TRUE ); $treeview->append_column( $column_1 ); $treeview->append_column( $column_2 ); $treeview->append_column( $column_3 ); my $sw = Gtk2::ScrolledWindow->new( undef, undef ); $sw->set_shadow_type( "etched-in" ); $sw->set_policy( "never", "always" ); $sw->add( $treeview ); $vbox->pack_start( $sw, TRUE, TRUE, 0 ); my $button = Gtk2::Button->new( "Dump Values" ); $button->signal_connect( "clicked" => sub { &dump_values( @_ ); } ); $vbox->pack_start( $button, TRUE, TRUE, 0 ); $window->add( $vbox ); $window->show_all; Gtk2->main; sub process_editing { my ( $renderer, $text_path, $new_text, $columnno ) = @_; my $path = Gtk2::TreePath->new_from_string( $text_path ); my $iter = $model->get_iter( $path ); if ( $columnno == 2 ) { # Column 2 is a combo - we need to fetch the ID from the combo +'s model my $combo_model; $combo_model = $renderer->get( "model" ); my $combo_iter = $combo_model->get_iter_first; my $found_match = FALSE; while ( $combo_iter ) { if ( $combo_model->get( $combo_iter, 1 ) eq $new_text ) { $found_match = TRUE; $new_text = $combo_model->get( $combo_iter, 0 ) ; # It's possible that this is a bad idea last; } $combo_iter = $combo_model->iter_next( $combo_iter ); } # If we haven't found a match, default to a zero if ( !$found_match ) { $new_text = 0; } } $model->set( $iter, $columnno, $new_text ); } sub dump_values { my $iter = $model->get_iter_first; print "Column 0 contains: " . $model->get( $iter, 0 ) . "\n"; print "Column 1 contains: " . $model->get( $iter, 1 ) . "\n"; print "Column 2 contains: " . $model->get( $iter, 2 ) . "\n"; print "\n"; } sub render_combo_cell { my ( $tree_column, $renderer, $model, $iter ) = @_; # Get the ID that represents the text value to display my $key_value = $model->get( $iter, 2 ); # 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 ) { if ( $combo_model->get( $combo_iter, 0 ) && $key_value && $combo_model->get( $combo_iter, 0 ) == $key_value ) { $found_match = TRUE; $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 => "" ); } }

    I'm not really a human, but I play one on earth. flash japh
      thanks, i'll have a play with that. i've been sidetracked a little exploring Gtk2::Ex::FormFactory (which has necessitated a few more sidetracks, like exploring Class::DBI which has been on my list of things to learn for a while now. I really like Class::DBI and G:E:FF looks great too), but i'll get back to plain Gtk2 in a little while.

      btw, speaking of Class::DBI, i notice that there's also DBIx::Class which says it is inspired by Class::DBI (compatible with it but adding some new features). anyone know if there is any really compelling reason to use one over the other? DBIx::Class claims to do more, but Class::DBI seems to have much better documentation - which is a winner for me.

        Hi, yeah, that example was not the best, it is unecessarily complex, which may be a turn off. I'm working on a "general recipe list example" which contains all the various customcellrenderers in a simple manner, so they can be easily setup. I'm stuck right now, on getting the spinbutton cell renderer to work right, but below is a simple example of doing the combotext. Notice there are 2 ways to do a combo .... with entry and dropdown list, and a non-editable popup. I post a better example later in the snippets section, when I figure it out. :-)

        I'm not really a human, but I play one on earth. flash japh