Project

General

Profile

Actions

Bug #589

closed

WTreeView selection uses stale index after row removal (follow up from #546)

Added by Johny Mattsson over 13 years ago. Updated about 13 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Target version:
-
Start date:
11/04/2010
Due date:
% Done:

0%

Estimated time:

Description

Hello again,

While I'm pleased to say that the issue I reported in 546 indeed seems to have been fixed for that case, I'm afraid the fix didn't go quite far enough.

If selection is enabled and a node is selected which is subsequently affected by index shifting, the index from the selection survives the beginRemoveRow() and parent() is called for the stale index during endRemoveRows() processing.

I have not tried with row insertion, nor any other views at this point.

I've attached a test case demonstrating this issue (with Wt-3.1.6).

Regards,

/Johny


Files

treeview_stale_index2.cc (4.76 KB) treeview_stale_index2.cc Johny Mattsson, 11/04/2010 08:26 AM
Actions #1

Updated by Koen Deforche over 13 years ago

  • Status changed from New to Feedback

Hey Johnny,

I believe I underestimated the problem indeed. It seems that without adding considerable complexity to all of the views and proxy models, this problem is hard to fix.

The problem is that during rowsAboutToBeXXX() a view cannot create the new indexes, and during rowsXXX(), a view cannot read old indexes reliably. Thus a view would need to create a data structure which is (parent(), row, column) of indexes that shifted during rowsAboutToBeXXX(), and then actualy creat the new indexes during rowsXXX().

We've debated this issue internally since this is obviously a major oversight in our model-view design. We have concluded that we will not change all the view classes with this increased complexity but instead relax the conditions for a stale index by defining how internal data of an index should be organized. The motivation is that adapting all views for the current (unspecified) situation adds complexity to views implemented by Wt and others, while specifying how internal data should be organized should instead result in a more optimized model implementation and avoids redundancy in the internal model index representation.

We are thus updating the documentation of WAbstractItemModel:

virtual WModelIndex parent(const WModelIndex& index) const = 0:

An implementation should use createIndex() to create a model index that corresponds to the parent of a given index.

Note that the index itself may be stale (referencing a row/column within the parent that is outside the model geometry), but its parent (identified by the WModelIndex::internalPointer()) is referencing an existing parent.

WModelIndex createIndex(int row, int column, void *ptr) const;

Use this method to create a model index. \p ptr is an internal pointer that may be used to identify the parent of the corresponding item. For a flat table model, \p ptr can thus always be 0.

I hope this does not cause too much of a convenience for your model implementation, but instead makes it more efficient.

Regards,

koen

Actions #2

Updated by Johny Mattsson over 13 years ago

Hi Koen,

Thanks for the update. I appreciate this wasn't an easy nut to crack. Your decided approach is probably the most rational one given the pickle of backwards compatibility. One question however - would it be possible to officially limit the usage of stale indexes to not go past rowsXXX()?

In my case the WAbstractItemModel derivative is really just a wrapper/translator for an existing (large) tree structure. This means that I'm essentially creating a map from WModelIndex to a node in the actual tree. Due to look-up cost of going from parent to child-N what the cache map really stores is a key for the actual entry, not the parent, and a pointer to this key is what is contained in the WModelIndex. I also keep a cache of key-to-child to parent-node. My main concern however is that I need to keep these caches up-to-date and prevent them from growing indefinitely. Currently the way I deal with the original issue is that I delay the removal of these key entries from the caches until after I've fired rowsRemoved(). This means that the parent() calls can succeed as the keys are still in the cache, but I still get to maintain the caches properly. If on the other hand the use of stale indexes is relaxed to the degree suggested by the updated documentation, this strategy could no longer work (for me or anyone else in a situation similar to mine). If you are willing (and able?) to officially limit the use of stale indexes to only cover the rowsAboutToBeXXX()/rowsXXX() pairs, that would provide more flexibility for the implementers of custom data models, while hopefully still accurately describing the contract.

Thoughts?

Regards,

/Johny

Actions #3

Updated by Koen Deforche over 13 years ago

Hey Johny,

Thanks for your understanding. Obviously, the use of stale indexes is currently confined to the twilight zone while making changes to the model, and so it is currently the idea and I do not see a problem to add that the documentation.

Regards,

koen

Actions #4

Updated by Koen Deforche over 13 years ago

  • Status changed from Feedback to Resolved
Actions #5

Updated by Koen Deforche about 13 years ago

  • Status changed from Resolved to Closed
Actions

Also available in: Atom PDF