I have subclasses of QTreeView
and QAbstractItemModel
and currently I'm using drag-drop to move items from one parent index to another. I want to also add the ability to rearrange the order of items within the same parent index. When the user drops an item in-between two other items, I need to determine whether the drop should be into, or in-between them. I would also like to draw a dark line between the two items as the mouse is moved, to hint as to what will occur, similar to many other tree-type views (e.g. file explorers on most operating systems) as in the attached pictures:
Drag into an existing item:
Insert between two existing items:
Does Qt automate this part of drag/drop behavior, or do I have to manually calculate the mouse position relative to the edge of the tree item? Also, how can I draw a temporary line between two items in the QTreeView
?
I did almost the same thing some time ago, and I can think of 3 things :
dropEvent()
, and maybe your dragMoveEvent()
;Here's a very minimal example of what I was doing.
In the dragMoveEvent()
, I was showing the drop indicator. This way, you will always have your drop indicator shown when you're dragging an object.
void MyTreeView::dragMoveEvent(QDragMoveEvent* event)
{
setDropIndicatorShown(true);
QTreeView::dragMoveEvent(event);
}
In the dropEvent()
, I was managing each case, that's to say if the item I was dragging was on another item, above it, below it or on the viewport. Then, according to it, I was managing my own drop, and at the end of the event, I hid the drop indicator.
void MyTreeView::dropEvent(QDropEvent* event)
{
bool dropOK = false;
DropIndicatorPosition dropIndicator = dropIndicatorPosition();
switch (dropIndicator)
{
case QAbstractItemView::AboveItem:
dropOK = true;
break;
case QAbstractItemView::BelowItem:
dropOK = true;
break;
case QAbstractItemView::OnItem:
dropOK = false;
break;
case QAbstractItemView::OnViewport:
dropOK = false;
break;
}
if(dropOK)
{
// Here, you need to manage yourself the case of dropping an item
}
setDropIndicatorShown(false); // hide the drop indicator once the drop is done
}
"Bonus" : you can access the drop indicator in your own style by the PrimitiveElement PE_IndicatorItemViewItemDrop
.
You can see how to customize it here and here.