PDA

View Full Version : drag and drop misbehaving



KShots
10th September 2008, 19:47
I have a model/view system where I am attempting to implement drag and drop. The actual drag and drop seems to be operating correctly... but the model::removeRows() function doesn't appear to be working as documented.

Here's an example... take the tree describe below



rootnode
|
|----A
|----B
|----CI can drag C to go under B, but QtGui calls removeRows() with C as the parent, rather than rootnode (invalid QModelIndex).

the relevant code:
bool modelPlugins::removeRows(int row, int count, const QModelIndex & parent)
{
int index(0);
modelPluginItem * parentItem;
if(row < 0 || row + count > rowCount(parent))
return false;
if(parent.isValid())
parentItem = static_cast<modelPluginItem *>(parent.internalPointer());
else
parentItem = rootItem;
beginRemoveRows(parent, row, row + count - 1);
for(; index < count; index++)
parentItem->nondestructiveremovechild(row);
endRemoveRows();
return true;
}In my debugger, the modelPluginItems each have a unique id... the root node has ID 0, and C has ID 3... parentItem has ID 3. I can see this if Qt were to attempt to remove all children before removing the item, but it never tries to remove row 2 with an invalid parent index. How can I fix this?

wysota
11th September 2008, 14:07
The behaviour is correct. There is a difference between dropping on an item and between items. In the latter case you'll have an invalid root index as the parent in all related methods (dropMimeData, before all).

KShots
11th September 2008, 14:46
Yes, that's understood... but that has nothing to do with the removeRows() function. As I stated, the drag and drop operation itself is working fine. It's the cleanup (removeRows()) that I'm not understanding correctly.

When C is moved under B, then removeRows() should be performed on an invalid QModelIndex() with row 2 to remove C. Instead, a removeRows() call is made with C as the parent, which then attempts to remove row 0 under C (which doesn't exist), which returns false (failed operation), and it never attempts to remove C as described at the start of this paragraph.

wysota
11th September 2008, 17:22
Could you provide a minimal compilable example reproducing the problem?

KShots
15th September 2008, 20:22
While producing my minimal example, I spotted the problem on my end.

I was trying to be efficient by re-assigning the parent of the moving node on the drop operation... can't do that. The drop worked fine (interestingly), but Qt couldn't remove the node properly.

The tree structure still held a link from the old parent to the data item, but the data item now thought its parent was the parent at the new location. The solution was to do a copy operation rather than a re-parent operation. Both nodes continued to exist until Qt called the removeRows() function, at which point the old node got removed.

I'm still fairly efficient in that the copy operation involved copying a pointer rather than an object... I just needed to be careful on how the object was removed via the removeRows() function.