Re: [gtkmm] Erasing TreeModel rows...



Dennis Craven wrote:
Hey,

I've been following the documentation and examples online and in the
distribution. They are helpful, but a little unclear about removing rows
from TreeModels. Here is the function that I have attempting to do the
dirty work.

void MyTreeView::deleteRow(Glib::ustring title)
{
  Gtk::TreeModel::Children children = treestore->children();

  for(Gtk::TreeModel::Children::iterator iter = children.begin(); iter
!= children.end(); ++iter)
  {
    Gtk::TreeModel::Row row = *iter;
    if (row[columns.m_col_name] == title) {

      ////
// Segfaults on this erase line. "treestore" is declared as // Glib::RefPtr<Gtk::TreeStore> treestore; // and is a protected member of the MyTreeView class.
      ////
      treestore->erase(iter);
      break;
    }
  }
}

When execution gets to the point of failure (the erase statement), the
iter is in fact valid and is at correct row. I can print out information
stored on that row, this is why I'm certain. Execution does not get
beyond that line.

I've looked around for row removal examples, and had no luck. Anyone
here have any pointers?

Looping through a TreeModel and deleting things as you do above is very liable to lead you to segfaults or unusual behaviour, as once you've deleted the row indicated by iter, iter is no longer valid so you cannot perform iter++ on it to move to the next row. This is a familiar situation from using STL containers as well.

So while this might seem the most elegant solution, it unfortunately isn't. You could try using Gtk::TreeModel::foreach using a suitable callback function to check the values and delete rows appropriately, but I'm not actually sure if that would be any more successful, as it depends entirely on how foreach is implemented. Therefore I would suggest that you have to do this in two stages.

1) use a for loop or a foreach() callback to run through the TreeModel and build up a list, slist, vector or some other suitable container of TreePaths or TreeIters which match the criteria for deletion 2) loop through that structure BACKWARDS and delete each Path or Iter individually, so that you start at the end of the TreeModel and move towards the front. This is necessary in order to avoid invalidating paths pointing ahead of the position you just erased. For Iterators you may actually be okay going forwards, I'm not sure. Try it and see; I suggest Paths largely because my most recent example of doing something like this was when I needed to delete all the selected rows in a multi-select TreeView, which you get as an ArrayHandle<TreePath>. Iters may keep track of their elements if you delete an element before them, but Paths certainly won't. So going backwards is safest.

Hopefully that will prove of some assistance.




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]