PDA

View Full Version : QTreeView default drag action



onamatic
11th November 2008, 13:32
Using QT4.4.3 X11, I have run into the same problem as others regarding the non-standard default drag action of QTreeView. It's documented here: QTreeView drag and drop Bug - defaults to Qt::CopyAction instead of Qt::MoveAction (http://lists.trolltech.com/qt-interest/2008-07/thread00135-0.html) but I can't find any solutions.

As far as I'm concerned, dragging an item within a tree view should default to moving the item (a la Konqueror, Windows file manager etc.); dragging from another application into the tree view should copy it.

I've spent a day trying to rectify the problem by implementing dragMoveEvent, dragEnterEvent etc. and setting the drag action explicitly:


void QAbstractItemView::dragMoveEvent ( QDragMoveEvent * event ) {
...
//force a move action unless control key is pressed
if (event->keyboardModifiers() & Qt::ControlModifier)
event->setDropAction(Qt::CopyAction);
else
event->setDropAction(Qt::MoveAction);
event->accept();
event->acceptProposedAction(); //causes cursor icon to change and target item to get highlighted
...
}

The above code works fine whilst dragging is taking place (ie: the "+" cursor copy icon disappears) but, by the time model's dropMimeData executes, the dropAction has always reverted to the default CopyAction.
Setting the treeView's dragDropMode to InternalMove is not a solution as you can not then set the DropAction to Qt::CopyAction if the user presses the control key.

QUESTION: Where can I fix the QTreeView's default drop action? Is there some kind of compatibility switch at Application level?

onamatic
17th November 2008, 13:39
QUESTION: Where can I fix the QTreeView's default drop action? Is there some kind of compatibility switch at Application level?

To answer my own question (please jump in if I've missed something):

There doesn't appear to be any "compatibility" switch anywhere.

The erroneous default dropAction is caused by a mistake in the default implementation of QAbstractItemView::startDrag; override it to get the correct behaviour.

The example below does most of what the default implementation does but without access to protected members it doesn't emulate the fancy drag icon creation; you just get the standard drag box instead of the item's title. Thanks to another contributor to this forum (whose name I've lost) for most of the code.


void QAbstractItemView::startDrag(Qt::DropActions supportedActions)
{
qDebug() << "QAbstractItemView::startDrag; begin";
QModelIndexList indexes = selectedIndexes();
QList<QPersistentModelIndex> persistentIndexes;

if (indexes.count() > 0) {
QMimeData *data = model()->mimeData(indexes);
if (!data)
return;
for (int i = 0; i<indexes.count(); i++){
QModelIndex idx = indexes.at(i);
qDebug() << "\tDragged item to delete" << i << " is: \"" << idx.data(NODE_TITLE).toString() << "\"";
qDebug() << "Row is: " << idx.row();
persistentIndexes.append(QPersistentModelIndex(idx ));
}

QPixmap pixmap = indexes.first().data(Qt::DecorationRole).value<QPixmap>();
QDrag *drag = new QDrag(this);
drag->setPixmap(pixmap);
drag->setMimeData(data);
drag->setHotSpot(QPoint(pixmap.width()/2, pixmap.height()/2));

Qt::DropAction defaultDropAction = Qt::IgnoreAction;
if (supportedActions & Qt::MoveAction && dragDropMode() != QAbstractItemView::InternalMove)
defaultDropAction = Qt::MoveAction; //was Qt::CopyAction THIS WAS THE CULPRIT!

if ( drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction ){
//when we get here any copying done in dropMimeData has messed up our selected indexes
//that's why we use persistent indexes
for (int i = 0; i<indexes.count(); i++){
QPersistentModelIndex idx = persistentIndexes.at(i);
qDebug() << "\tDragged item to delete" << i << " is: " << idx.data(NODE_TITLE).toString();
qDebug() << "Row is: " << idx.row();
if (idx.isValid()){ //the item is not top level
model()->removeRow(idx.row(), idx.parent());
}
else{
model()->removeRow(idx.row(), QModelIndex());
}
}
}
}
}

Amitai
1st March 2010, 08:37
AHA!!!

This was a positive life saver for me - solved exactly the problem I was facing (and spent all of yesterday trying to solve). I read through ten or so other posts in this forum before getting to this one.

Thanks a lot!

I'll just add some more keywords to the thread, to make this information more accessible for people who face the same problem:

QTreeView, QAbtractItemView, MoveAction, CopyAction

Amitai.