How to remove selected items from a Gtk::TreeView using gtkmm? The painless way.

I am building an application using C++/gtkmm-3.0. The development process is sometimes nice and sometimes too complicated in my opinion. The worst part until now was when I wanted to remove the selected items from a tree view.

This is a tree view:


Behind a tree view there is a “store” which holds the information for the view, like a model in MVC. Sometimes you need to enable the user to choose multiple items from the view and delete them. Should be simple, right?

I was expecting something like

treeview.removeSelected();

or

store.remove(treeview.getSelected());

but no, it won’t be that simple.
According to the official documentation you have to reviece a “selection” object from the treeview and keep it. Then you have to create a (wasn’t so easy for me to find it’s structure) callback function that deletes an item, and when the user presses delete you tell the “selection” something like

selection.selected_foreach_iter(pointer to the callback function);

And that’s supposed to do it. I was surprised to see the steps needed, and even after it did somewhat work, Gtk wrote on the command line that this way of iterating over a selection is for reading only and for manipulating the store I have to use another way. Well, I wasn’t the one who came up with that method, I saw it in a few examples and tutorials and it was used to delete items.

I became tired of the over complication and found a simple little way to do it. I don’t know if it “right”, but it is simple and it works.

We have our class, with the view, store, and selection as private members.

Gtk::TreeView treeview;
Glib::RefPtr<Gtk::ListStore> store;
Glib::RefPtr<Gtk::TreeSelection> selection;

In the constructor we initialize the selection

selection = treeview.get_selection();
selection->set_mode(Gtk::SELECTION_MULTIPLE); // enable multiple selection

And then, all we have to do in order to remove the selecte items is:

void MainWindow::_remove_selected()
{
    vector<Gtk::TreeModel::Path> paths = selection->get_selected_rows();
    for(int i = paths.size()-1; i>=0; i--)
        store->erase(store->get_iter(paths));
}

That’s all. 3 lines of code. Why not do it like that? Why the over complication? Who knows.