Gtk2::TreeSelection
. One of the most basic features of a list or tree view is that rows can be selected or unselected. Selections are handled using the Gtk2::TreeSelection
object of a Gtk2::TreeView
. Every Gtk2::TreeView
automatically has a Gtk2::TreeSelection
associated with it, and you can get it using Gtk2::TreeView
's get_selection
method. Selections are handled completely on the tree view side, which means that the model knows nothing about which rows are selected or not.
There is no particular reason why selection handling could not have been implemented with functions that access the tree view widget directly, but for reasons of API cleanliness and code clarity the Gtk+ developers decided to create this special Gtk2::TreeSelection
object that then internally deals with the tree view widget. You will never need to create a tree selection object, it will be created for you automatically when you create a new tree view. You only need to use the get_selection
method to get a pointer to the Gtk2::TreeSelection
object.
This lesson will show you how to determine the value of a selection. We will start off with a simple demo program on selections. We will then discuss the pieces of code that is important to us.
Table 14-4. Gtk2
object classes used
Gtk2 Class Name |
---|
Gtk2::Window |
Gtk2::VBox |
Gtk2::HSeparator |
Gtk2::Button |
Gtk2::Label |
Gtk2::ComboBox |
Gtk2::TreeStore |
Gtk2::TreeView |
Gtk2::TreeViewColumn |
Gtk2::CellRendererText |
Gtk2::TreeSelection |
The program can be found here: 'Finding a selection'
1 #! /usr/bin/perl -w 2 3 use strict; 4 use Gtk2 '-init'; 5 use Glib qw/TRUE FALSE/; 6 7 #standard window creation, placement, and signal connecting 8 my $window = Gtk2::Window->new('toplevel'); 9 $window->signal_connect('delete_event' => sub { Gtk2->main_quit; }); 10 $window->set_border_width(5); 11 $window->set_position('center_always'); 12 13 #this vbox will geturn the bulk of the gui 14 my $vbox = &ret_vbox(); 15 16 #add and show the vbox 17 $window->add($vbox); 18 $window->show(); 19 20 #our main event-loop 21 Gtk2->main(); 22 23 24 sub ret_vbox { 25 26 my $vbox = Gtk2::VBox->new(FALSE,5); 27 28 $vbox->pack_start(Gtk2::Label->new("Selection Mode:"),FALSE,FALSE,5); 29 30 #------------------ 31 #get a list of Gtk2::SelectionModes and fill a combo box with it 32 my $cmb_box = Gtk2::ComboBox->new_text; 33 34 foreach my $s_type (Glib::Type->list_values ('Gtk2::SelectionMode')){ 35 36 $cmb_box->append_text($s_type->{'nick'}); 37 } 38 39 $cmb_box->set_active(0); 40 #------------------ 41 42 $vbox->pack_start($cmb_box,FALSE,FALSE,0); 43 44 $vbox->pack_start(Gtk2::HSeparator->new(),FALSE,FALSE,0); 45 46 #this is one of the provided base Gtk2::TreeModel classes. 47 my $tree_store = Gtk2::TreeStore->new(qw/Glib::String/); 48 49 #fill it with arbitry data 50 foreach (1..3) { 51 52 my $parent_nr = $_; 53 #the iter is a pointer in the treestore. We 54 #use to add data. 55 my $iter = $tree_store->append(undef); 56 $tree_store->set ($iter,0 => "Parent $parent_nr"); 57 58 foreach (1..3){ 59 #here we append child iters to the parent iter 60 #and add data to those chils iters. 61 my $iter_child = $tree_store->append($iter); 62 $tree_store->set ($iter_child,0 => "Child $_ of Parent $parent_nr"); 63 } 64 } 65 66 #this will create a treeview, specify $tree_store as its model 67 my $tree_view = Gtk2::TreeView->new($tree_store); 68 69 #create a Gtk2::TreeViewColumn to add to $tree_view 70 my $tree_column = Gtk2::TreeViewColumn->new(); 71 $tree_column->set_title ("Select Something"); 72 73 my $renderer = Gtk2::CellRendererText->new; 74 75 $tree_column->pack_start ($renderer, FALSE); 76 $tree_column->add_attribute($renderer, text => 0); 77 78 #add $tree_column to the treeview 79 $tree_view->append_column ($tree_column); 80 81 $vbox->set_size_request (300, 300); 82 83 84 #--------------------------------------------------- 85 #get the Gtk2::TreeSelection of $tree_view 86 my $treeselection = $tree_view->get_selection; 87 #set its initial mode 88 $treeselection->set_mode($cmb_box->get_active_text); 89 90 #connect the combo box's changed signal so that it will 91 #change the mode of the Gtk2::TreeSelection on each change. 92 $cmb_box->signal_connect('changed' => sub { 93 94 $treeselection->set_mode($cmb_box->get_active_text); 95 }); 96 #----------------------------------------------------- 97 98 $vbox->pack_start($tree_view,TRUE,TRUE,0); 99 $vbox->pack_start(Gtk2::HSeparator->new(),FALSE,FALSE,0); 100 101 my $btn_show_sel = Gtk2::Button->new("_Show Selected"); 102 $btn_show_sel->signal_connect("clicked" => sub { 103 104 my $treeselection = $tree_view->get_selection; 105 106 $treeselection->selected_foreach (sub{ 107 #this sub wil receive the following: 108 my ($model,$path,$iter) =@_; 109 110 #we want data at the model's column 0 111 #where the iter is pointing 112 my $value = $model->get($iter,0); 113 print $value."\n"; 114 115 }); 116 }); 117 118 $vbox->pack_end($btn_show_sel,FALSE,FALSE,0); 119 120 $vbox->show_all(); 121 return $vbox; 122 }
The Gtk2::TreeSelection
belonging to a Gtk2::TreeView
can be used to define selection modes. To define its selection mode, we use its "set_mode"
method. In our program we extract a list of possible values for the selection mode, by making use of Glib::Type
's "list_values"
method. We then use this and populate a Gtk2::ComboBox
. This will enable us to change the selection mode.
#------------------ #get a list of Gtk2::SelectionModes and fill a combo box with it my $cmb_box = Gtk2::ComboBox->new_text; foreach my $s_type (Glib::Type->list_values ('Gtk2::SelectionMode')){ $cmb_box->append_text($s_type->{'nick'}); } $cmb_box->set_active(0); #------------------
To find out more about the values returned by |
We set an initial selection mode and then we connect the Gtk2::ComboBox
's "changed"
signal to a sub that will change the selection mode of the Gtk2::TreeView
accordingly (by making use of it's Gtk2::TreeSelection
's "set_mode"
method) to the selected text value of the Gtk2::ComboBox
.
#--------------------------------------------------- #get the Gtk2::TreeSelection of $tree_view my $treeselection = $tree_view->get_selection; #set its initial mode $treeselection->set_mode($cmb_box->get_active_text); #connect the combo box's changed signal so that it will #change the mode of the Gtk2::TreeSelection on each change. $cmb_box->signal_connect('changed' => sub { $treeselection->set_mode($cmb_box->get_active_text); }); #-----------------------------------------------------
To get a selection from a Gtk2::TreeView
we have a few methods at our disposal.
If the select mode is such that only one item can be selected, we can use the "get_selected"
method. This will return a Gtk2::TreeIter
, pointing to the selected row in the model.
For one and more selectable items, we can use the "selected_foreach"
method. This is used to loop the selected items, calling a subroutine for each. We use this one in our program, since we can have a select mode where one or more items is selectable.
my $treeselection = $tree_view->get_selection; $treeselection->selected_foreach (sub{ #this sub wil receive the following: my ($model,$path,$iter) =@_; #we want data at the model's column 0 #where the iter is pointing my $value = $model->get($iter,0); print $value."\n"; });
The "get_selected_rows"
method will return a list of Gtk2::TreePath
s pointing to each selected row. This can then be further used to get the selected values from the model. We get the Gtk2::TreeIter
by using the model's "get_iter"
method, and passing it the Gtk2::TreePath
as argument.
When you used Pango markup in a renderer, the returned value will be in the markup form. This can be annoying when you actually need to get the value WITHOUT the markup. To get only the value, make use of Perl's shinning feature caller regular expressions. $markup =~ s/<[^>]*>//gwill filter out all the tags, leaving you with a "clean" value. |