4 Attachment(s)
When should QTreeWidget::dropMimeData be called?
I'm trying to create a dialog with a (derived) QListWidget on the left and a (derived) QTreeWidget on the right. Users should be able to drag items from the list widget and drop them into the tree widget. Child items in the tree widget can also be moved to a different parent (top level item).
I initially reimplemented startDrag() in the list widget, and dragEnterEvent(), dragMoveEvent(), and dropEvent() in the tree widget. I encoded some mime data in startDrag(), and decoded it in dropEvent(), and removed the dragged-and-dropped items from the list widget if all went well. This all worked more or less, but I couldn't figure out how to make the "drop indicator" appear in the tree widget when I was dragging an item in. While searching for a solution, I discovered I was doing things all wrong, and tried a different approach.
I've reimplemented mimeData() in the list widget, and reimplemented dropMimeData() in the tree widget. This doesn't work: dropMimeData() is never called. I've got the following options set up on the tree widget:
Code:
theTreeWidget->setDragEnabled(true);
theTreeWidget->setAcceptDrops(true);
So first question: Why isn't dropMimeData() called? I tried changing the drag drop mode to DragDrop, because I though this might help. When I do, dropMimeData() is called, but ONLY when I drag and drop items from within the tree, not from the list widget. Also, tree widget items are copied, rather than moved (I guess this is expected behaviour). So I tried to reimplement the supportedDropActions() function so that only MoveAction is returned. Now dropMimeData is no longer called, and I get weird behaviour:
1. When I have two top-level items, and one child item under the first, I try to move the child to the other top-level item. The child becomes a top-level item and its parent is deleted. Some screen shots, before: Attachment 10189 and after: Attachment 10190
2. When I have two top-level items, and two children under the first, I try to move the second child to the other top-level item. The child moves appropriately, but its "sibling" is deleted. Before: Attachment 10192, and after:Attachment 10191
Second question: Is this normal behaviour? I've looked through my code, and there's only one function where I delete or take items from the tree widget, and it isn't called during dragging and dropping (I added a qDebug() call to make sure).
4 Attachment(s)
Re: When should QTreeWidget::dropMimeData be called?
I've figured out most of my problem. I'm still not sure about the weirdness when QTreeWidget::supportedDropActions() is reimplemented, but I've got the rest of it. I'm posting my solution because I've seen other related questions and I think that my solution might lead to an answer for a few people.
- In addition to reimplementing QListWidget::mimeData() and QTreeWidget::dropMimeData(), I needed to reimplement mimeTypes() in both classes. This was well-documented in the http://doc.qt.io/qt-4.8/model-view-programming documentation, but apparently I can't read.
- Using QTreeWidget::setDragDropMode() to set the drag/drop mode to QAbstractItemView::DragDrop is important for receiving drag/drop events from the list widget as well as allowing internal drag and drop (within the tree widget).
- I also had to reimplement QTreeWidget::mimeData() so that internal drag and drop events in the tree widget would be handled properly. This probably wasn't entirely necessary, but I think it simplified forcing internal drag and drop events to be move actions later.
- At this stage, drag and drop worked, but only to copy items. Reimplementing QTreeWidget::supportedDropActions() to allow only Qt::MoveAction did NOT work. As stated above, it just resulted in items being deleted that shouldn't have been... I'm pretty sure this is a Qt bug (I'm using Qt 4.8).
- Getting my whole setup to move things (as opposed to copying) required reimplementing QListWidget::startDrag() QTreeWidget::startDrag() in order to create QDrag instances that executed MoveActions.
Without further ado, here's a working example!
Attachment 10196
Attachment 10197
Attachment 10194
Attachment 10195