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:
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:
- Register the signal
key-press-event
on the treeview. - Check if this is Delete key.
- Yes, it's Delete key. Remove the selected rows!
Read more...