Reputation: 1189
I'm implementing a view and a model where I want to support both moving items internally (by dragging), and copying items (by pressing Ctrl while dragging). I've done everything I need to do according to the instructions. I've set up the mime functions, I've implemented removeRows(), and flags(). The problem is when I drag, it defaults to a copy operation (I get the arrow cursor with a plus sign, and it indeed copies the item by creating a new one in the model).
The only difference I can see is this: If I return only Qt::MoveAction in supportedDropActions(), it only moves. If I return (Qt::CopyAction | Qt::MoveAction), it only copies.
Any ideas? I want it to work like files in Nautilus (Gnome) or Windows file Explorer: drag moves icons around, ctrl+drag copies them.
Upvotes: 6
Views: 2460
Reputation: 1189
I'm sorry I didn't follow up by answering this question when I found what I was doing wrong. The code that messed me up was in QAbstractItemView::startDrag()
:
if (d->defaultDropAction != Qt::IgnoreAction && (supportedActions & d->defaultDropAction))
defaultDropAction = d->defaultDropAction;
else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove)
defaultDropAction = Qt::CopyAction;
The problem is I wasn't setting the defaultDropAction property on the widget as in setDefaultDropAction( Qt::MoveAction );
Therefore startDrag() was defaulting to CopyAction. If the defaultDropAction is Qt::MoveAction, then you can use the keyboard Ctrl to switch a drag in progress to a copy action, which is my desired behavior.
I love Qt, but there sure are a lot of confusing and somewhat intertwined properties related to drag/drop. It's easy to to not get the right combination of properties.
Bottom line: make sure to set the defaultDropAction to Qt::MoveAction.
Upvotes: 1
Reputation: 2193
This is what I would do:
enable the copy action. Then listen to drap&drop signals or override virtual methods (or whatever Qt offers, I didn't check) and if the action you meant is move, remove the row "manually". When a drop is made, save the action you prefer.
If there's no way to determine the desired action from Qt data, check the Ctrl key status and save a boolean saying whether it's copy or move. Now, when Qt signals something was dropped, check the action you chose, and delete the moved row by yourself.
(I personally use gtkmm, where copy-if-Ctrl-is-pressed works pefectly)
Upvotes: 0
Reputation: 359
what if you try this way First write a keyPressEvent and set whether ctrl key is pressed or not '
keyPressEvent(QKeyEvent *e)
{
if(e->key() == Qt::Key_Control)
bControlKeyPressed = true;
}
keyReleaseEvent (QKeyEvent *e)
{
if(e->key() == Qt::Key_Control)
bControlKeyPressed = false;
}
And in mouse pressEvent check whether ctrl key is pressed
`mousePressEvent()
{
if (bControlKeyPressed)
//enable Qt::CopyAction
else
//enable Qt::MoveAction
}`
Upvotes: 0