views:

135

answers:

2

I have a ListStore that is filtered and then sorted. It looks something like this:

// Create a model for the cards
cardListStore = new ListStore (typeof (Card));

// Set up the tree view
cardFilter = new TreeModelFilter (cardListStore, null);
cardFilter.VisibleFunc = new TreeModelFilterVisibleFunc (FilterCards);
cardSort = new TreeModelSort (cardFilter);
cardTreeView.Model = cardSort;

I want to have a get a context menu specific for each row when I right-click on it. My click handler looks something like this:

[GLib.ConnectBeforeAttribute]
void HandleCardTreeViewButtonPressEvent (object o, ButtonPressEventArgs args)
{
 if (args.Event.Button != 3)
  return;

 TreePath path;
 // If right click on empty space
 if (!cardTreeView.GetPathAtPos (Convert.ToInt32 (args.Event.X),
                                 Convert.ToInt32 (args.Event.Y),
                                 out path)) {
  MakeCardEmptySpaceContextMenu ().Popup ();
  return;
 }

 TreeIter iter;
 if (!cardListStore.GetIter (out iter, path))
  return;

 Card card = (Card) cardListStore.GetValue (iter, 0);

 MakeCardContextMenu (card, iter).Popup ();
}

This works when the ListStore is not filtered or sorted. But when it is, it gives the wrong row.

For example, say the rows look like this before they are sorted:

A
B
C

And after they are sorted, they look like this:

B
A
C

Right-clicking on the second row ("A") will give you "B", because that's where B was before the model was sorted. The same thing happens for filtering. Say the model, after it is filtered, looks like this:

A
C

Right-clicking on the second row ("C") would still give you "B".

Any idea how to work around this?

A: 

Looks like there is a filter between you and the data, and that is what is displayed by the tree. You are looking at the data behind the tree...

Now, I'm not familiar with GTK, but perhaps something like

TreeModelSort.convert_path_to_child_path ?

There must bet a way to get what row of the VIEW of the MODEL you are looking at, and then translate that back to real model data.

Andrew Backer
`ConvertPathToChildPath` (and `ConvertChildPathToPath`) don't seem to have any effect. I also tried messing around with `ConvertIterToChildIter` and `ConvertChildIterToIter`, but they cause null-reference exceptions.
Matthew
The thing is, the `Model` of `cardTreeView` is `cardSort`, not `cardListStore` (see the last line of the first code snippet). So you would think `cardTreeView` would be able to tell that's what you wanted in the second code snippet. I donno. But thanks for the idea!
Matthew
+1  A: 

I just needed to get the iter and the value from cardSort, instead of cardListStore.

if (!cardListStore.GetIter (out iter, path))
    return;

Card card = (Card) cardListStore.GetValue (iter, 0);

becomes

if (!cardSort.GetIter (out iter, path))
    return;

Card card = (Card) cardSort.GetValue (iter, 0);
Matthew