Problem with special drag'n'drop with QTreeView and custom model
-
I have a custom model derived from QAbstractItemModel. This model implements dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) method.
Model assigned to the custom view widget, inheritted from QTreeView. Now I want to implement drag'n'drop of the view's items but in special way. First, when items is dragged inside same view, they should be just moved (e.g. to reorder items within tree). But when item dragged outside the view both copy and move actions should be proposed, so the host widget can choose what to do with dropped item (copy or move it).
First I defined supported drop actions for a model
Qt::DropActions MyTreeModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; }
And then reimplement dropEvent() handler in my view
void MyTreeView::dropEvent(QDropEvent *event) { // if we dragging in the same view than actually we want to move if ( event->source() == this && event->proposedAction() == Qt::CopyAction) { event->setDropAction(Qt::MoveAction); } event->accept(); QTreeView::dropEvent(event);
But it does not works this way. When I drop item inside same view it completely disappeared. What I missed or doing wrong?
P.S. sorry for my English, it is not my native language.
-
the model implementation is the interesting part here.
Maybe you also want to read this thread for some clarification. -
@raven-worx thanks for the reply.
In my model I already have implemented mimeData(), mimeTypes(), dropMimeData() and supportedDropActions(). Until I tried to implement this special drag'n'drop case all worked fine: in supportedDropActions() i have only Qt::MoveAction and there is no need in the overloaded dropEvent(). Items moved inside view as expected.Now I can not figure out how to enable move only inside same view widget and allow both move and copy when dragging items outside view to another view.
-
@voltron
ok now i think i got you.You almost had it. You should rather call event->setDropAction(Qt::MoveAction); in the dragEnter() event handler than in the dropEvent() handler.
And return copy and move actions in your model. -
thanks a lot for your help and time. I tried to follow your suggestion. In my model both actions are supported, as defined by supportedDropActions() method
Qt::DropActions MyTreeModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; }
Also I removed dropEvent() handler from my view and added instead dragEnterEvent() handler with following implementation
void MyTreeView::dragEnterEvent( QDragEnterEvent * event ) { event->setDropAction( Qt::MoveAction ); event->accept(); }
Unfortunatelly this does not works as I want. I can drag items inside my view, but they are copied not moved. Maybe I missed something or misunderstood you?
The good thing is that I can also copy items to other views. Still need to restrict drag operations to move only when this drag'n'drop happens inside same view.
-
Hi and welcome to devnet,
It should rather be
Qt::InternalMove
when you want to move a row inside a view. Since you have a custom model, are you implementing the move related methods ? -
@SGaist thanks for our reply!
As I understandQt::InternalMove
forbid moving/copying view items from/to other views. Am I right?My model is custom, but it is based on the
QAbstractItemModel
and all important methods are implemented (e.g.data()
,dropMimeData()
). Also initially it has support only for moving items because insupportedDropActions()
I have onlyQt::MoveAction
enabled and move operation worked fine. So I think all methods required for moving works. -
You can return more than one action in
supportedDropActions()
-
@SGaist
yes, I know. Let me explain again.
Initially I have custom model wheresupportedDropActions()
returns onlyQt::MoveAction
, so it is possible only move items when dragging them outside view. This works fine, item dragged and moved nicely to other views and inside same view (reordering).
But now I want to implement following behavior. When item is dragged and dropped inside view — just move it (reorder). When item moved outside view — allow both operations copy and move. In same time I want to be able to copy/move items in both directions from my custom view to other views and from other views to my custom view.It is very easy to allow copy and move operations, just to return corresponding flags in
supportedDropActions()
. And I have it in my codeQt::DropActions MyTreeModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; }
But if I only change
supportedDropActions()
I can not move items inside my custom view, they copied. But when dragging items to other views I can choose what to do copy or move.There is a
Qt::InternalMove
flag which looks like a solution. But as I understandQt::InternalMove
forbids moving/copying view items from/to other views. Please correct me if I'm wrong.So now i'm looking for solution which will allow me to only move items inside my custom view and in same time move and copy items from/to other views.