Problem
Suppose you have set up a treeview that allow the user to enter some search criteria to filter the listing.
You would like to highlight the first occurence of a match and also scroll to that row as shown below:
Solution
- Use GtkTreeView::scroll_to_cell() to scroll to a particular row in treeview.
- Use GtkTreeSelection::select_path() to highlight a particular row.
Sample Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 136 137 138 139 140 141 144 145 146 147 148 149 150 151 152 153 162 | <?php $window = new GtkWindow(); $window->set_title($argv[0]); $window->set_size_request(400, 210); $window->connect_simple('destroy', array('Gtk','main_quit')); $window->add($vbox = new GtkVBox()); // display title $title = new GtkLabel("Highlight and scroll to a particular row in treeview\n". " using row ID"); $title->modify_font(new PangoFontDescription("Times New Roman Italic 10")); $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff")); $title->set_size_request(-1, 40); $vbox->pack_start($title, 0, 0); $vbox->pack_start(new GtkLabel(), 0, 0); $vbox->pack_start($hbox = new GtkHBox(), 0); // note 1 $hbox->pack_start(new GtkLabel('Enter item description: '), 0); $hbox->pack_start($search_entry = new GtkEntry(), 0); $hbox->pack_start($search_button = new GtkButton('Search'), 0); $search_entry->set_size_request(80, -1); $search_button->connect('clicked', 'on_search_button'); $search_entry->connect_simple('activate', array($search_button, 'clicked')); // the 2D table $data = array( array('1001', 'item 12', 2, 3.1), array('1002', 'item 36', 20, 6.21), array('1003', 'item 21', 8, 9.36), array('1004', 'item 45', 11, 12.4), array('1005', 'item 68', 5, 15.5), array('1006', 'item 72', 17, 18.6), array('1007', 'item 93', 20, 21.73)); $view = display_table($vbox, $data); $window->show_all(); Gtk::main(); function display_table($vbox, $data) { // Set up a scroll window $scrolled_win = new GtkScrolledWindow(); $scrolled_win->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); $vbox->pack_start($scrolled_win); // Creates the list store if (defined("GObject::TYPE_STRING")) { $model = new GtkListStore(GObject::TYPE_STRING, GObject::TYPE_STRING, GObject::TYPE_LONG, GObject::TYPE_DOUBLE); } else { $model = new GtkListStore(Gtk::TYPE_STRING, Gtk::TYPE_STRING, Gtk::TYPE_LONG, Gtk::TYPE_DOUBLE); } $field_header = array('Row ID', 'Description', 'Qty', 'Price'); $field_justification = array(0.5, 0.0, 0.5, 1.0); // Creates the view to display the list store $view = new GtkTreeView($model); $scrolled_win->add($view); // Creates the columns for ($col=0; $col<count($field_header); ++$col) { $cell_renderer = new GtkCellRendererText(); $cell_renderer->set_property("xalign", $field_justification[$col]); $column = new GtkTreeViewColumn($field_header[$col], $cell_renderer, 'text', $col); $column->set_alignment($field_justification[$col]); $column->set_sort_column_id($col); // set the header font and color $label = new GtkLabel($field_header[$col]); $label->modify_font(new PangoFontDescription("Arial Bold")); $label->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000FF")); $column->set_widget($label); $label->show(); // setup self-defined function to display alternate row color $column->set_cell_data_func($cell_renderer, "format_col", $col); $view->append_column($column); } // pupulates the data for ($row=0; $row<count($data); ++$row) { $values = array(); for ($col=0; $col<count($data[$row]); ++$col) { $values[] = $data[$row][$col]; } $model->append($values); } $selection = $view->get_selection(); $selection->connect('changed', 'on_selection'); return $view; } // self-defined function to format the price column function format_col($column, $cell, $model, $iter, $col_num) { $path = $model->get_path($iter); // get the current path $row_num = $path[0]; // get the row number if ($col_num==3) { $amt = $model->get_value($iter, 3); $cell->set_property('text', '$'.number_format($amt,2)); } $row_color = ($row_num%2==1) ? '#dddddd' : '#ffffff'; $cell->set_property('cell-background', $row_color); } // the function that is called when user selects a row function on_selection($selection) { list($model, $iter) = $selection->get_selected(); $desc = $model->get_value($iter, 1); $qty = $model->get_value($iter, 2); $price = $model->get_value($iter, 3); print "You have selected $desc: $qty ($price)\n"; } function on_search_button($button) { print "bp201. search_button\n"; global $view, $search_entry; $search_str = $search_entry->get_text(); $model = $view->get_model(); $n = $model->iter_n_children(NULL); for ($i=0; $i<$n; ++$i) { // note 2 $iter = $model->get_iter($i); $row_id = $model->get_value($iter, 0); $desc = $model->get_value($iter, 1); echo "Processing $row_id: $desc\n"; if (preg_match("/$search_str/i", $desc)) { // note 3 // highlight row $view->scroll_to_cell($i); // note 4 $selection = $view->get_selection(); // note 5 $selection->select_path($i); // note 6 $view->grab_focus(); break; } } } ?> |
Output
As shown above.
Explanation
We make use of the code from How to display a 2D array in GtkTreeView - Part 5 - get user selection?
What's new here:
- Set up search field.
- Loop through the entire list to search for the string.
- Is this a match? Note that I used a preg_match() here. So it will do a partial match e.g. enter "93" will also match "item 93".
- Yes, scroll to the row.
- Get the treeview selection.
- Highlight the row.
Read more...