507. How to highlight and scroll to a particular row in treeview using row ID?

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:

How to highlight and scroll to a particular row in treeview using row ID?


Solution


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:

  1. Set up search field.
  2. Loop through the entire list to search for the string.
  3. 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".
  4. Yes, scroll to the row.
  5. Get the treeview selection.
  6. Highlight the row.

Related Links

Add comment


Security code
Refresh