341. How to delete multiple rows in GtkTreeView using GtkListStore - Part 2 - by pressing delete key?

Problem

Suppose you would like to allow users to delete multiple rows in a linear list (i.e. using GtkTreeView with GtkListStore).

In Part 1 the user has to press the "Delete Selected Rows" button to delete the rows.

In this Part 2, the user can also press the Delete key to delete the selected rows as shown below:

How to delete multiple rows in GtkTreeView using GtkListStore - Part 2 - by pressing delete key?


Solution

  • Register key-press-event on the treeview.
  • When the Delete key is pressed, delete the selected rows using the technique as outlined in Part 1.

Sample Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
15   
16   
17   
18   
19   
20   
21   
22   
23   
24   
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   
75   
76   
77   
78   
79   
80   
81   
82   
83   
84   
85   
86   
87   
88   
89   
90   
91   
92   
93   
95   
96   
97   
98   
99   
100   
101   
105   
106   
107   
108   
109   
110   
111   
112   
113   
114   
115   
116   
117   
118   
119   
120   
121   
122   
123   
125   
126   
127   
128   
129   
130   
131   
132   
133   
136   
137   
140   
141   
142   
143   
144   
145   
146   
147   
148   
149   
151   
152   
153   
154   
155   
156   
157   
158   
<?php
$window = new GtkWindow();
$window->set_size_request(400, 230);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

// display title
$title = new GtkLabel("Delete multiple rows in linear list\n".
"  Part 2 - by pressing Delete key");
$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(
    'You can also delete the rows by pressing the Delete key'), 0);

$vbox->pack_start($hbox = new GtkHBox(), 0);
$hbox->pack_start($button = new GtkButton('Delete Selected Rows'), 0);
$button->connect('clicked', 'on_process_button');

// the 2D table
$data = array(
array('row0', 'item 42', 2, 3.1),
array('row1', 'item 36', 20, 6.21),
array('row2', 'item 21', 8, 9.36),
array('row3', 'item 10', 11, 12.4),
array('row4', 'item 7', 5, 15.5),
array('row5', 'item 4', 17, 18.6),
array('row6', 'item 3', 20, 21.73));

$view = display_table($vbox, $data);
$view->connect('key-press-event', 'on_keypress'); // note 1

$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 #', 'Description', 'Qty', 'Price');
    $field_justification = array(0.0, 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->set_mode(Gtk::SELECTION_MULTIPLE);
    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);
}

function delete_rows() { // note 3
    global $view;
    $model = $view->get_model();
    $selection = $view->get_selection();
    list($model, $selected_rows) =
        $selection->get_selected_rows();
    if (count($selected_rows)==0) return;

    $i = 0;
    $rows_to_remove = array();
    foreach($selected_rows as $path) {
        $iter = $model->get_iter($path);
        $desc = $model->get_value($iter, 1);
        $qty = $model->get_value($iter, 2);
        $price = $model->get_value($iter, 3);
        print "Selection $i: $desc: $qty ($price)\n";
        ++$i;
        $rows_to_remove[] = $path[0];
    }

    for ($i=count($rows_to_remove)-1; $i>=0; --$i) {
        print "remove row: $rows_to_remove[$i]\n";
        unset($model[$rows_to_remove[$i]]);
     }
}

function on_process_button($button) {
    delete_rows();
}

function on_keypress($widget, $event) {
    if ($event->keyval==Gdk::KEY_Delete) { // note 2
        delete_rows(); // note 3
        return true;
    } else {
        return false;
    }
}

?>

Output

As shown above.

 

Explanation

We make use of the code from How to delete multiple rows in GtkTreeView using GtkListStore - Part 1?

What's new here:

  1. Register the signal key-press-event on the treeview.
  2. Check if this is Delete key.
  3. Yes, it's Delete key. Remove the selected rows!

Related Links

Add comment


Security code
Refresh