PDA

View Full Version : QTreeWidget Drag and drop



zell99
2nd March 2007, 16:50
Hi, this is my first post here. I'm new to QT and I have to do special things with my QTreeWidget reguarding Drag and drop.

When I drop an item, I need to make a verification before it is "finalized". I need to know exactly which functions need to be reimplemented? I couldn't find good examples for this.

Do I need to play with Events? (mouseMoveEvent, mousePressEvent, dragMoveEvent?)
QDrag and QMimeData? (dropMimeData() ?)

I made a new class MyTreeWidget() : public QTreeWidget() so I can reimplement some of these functions, but I'm not sure which ones I should use. I need to have access to the QTreeWidgetItem that is being dragged and the one on which it is dropped (so the validation will be done when it's dropped).

Any help would be greatly appreciated. Thank you!

wysota
2nd March 2007, 20:16
You need to reimplement dropMimeData and possibly dragEnterEvent and dragMoveEvent (but it depends when you want to do the check).

fullmetalcoder
2nd March 2007, 20:28
I made a new class MyTreeWidget() : public QTreeWidget() so I can reimplement some of these functions, but I'm not sure which ones I should use. I need to have access to the QTreeWidgetItem that is being dragged and the one on which it is dropped (so the validation will be done when it's dropped).!
The function you have to reimplement is obviously dropMimeData(). It gives you an access to the target item but not directly to the dragged one(s). There are two ways to workaround this :

Reimplementing mimeData(QList<QTreeWidgetItem*>) so that proper (custom) QMimeData object is created when dragging and retrieving and item list from it
using the list of selectedItems()Hope this helps. :)

zell99
6th March 2007, 18:11
Thanks for your answers this far.

I have another question. I want the default action, when drag-and-dropping on my QTreeWidget, to be a "move" action instead of a "copy". I know if I hold shift while dragging, it will do a "move" action but I can't find where this decision is made.

Can anyone direct me to the function(s) that I need to work with here?

Thank you very much.

PS: I am using Qt 4.2.2

fullmetalcoder
6th March 2007, 19:00
Thanks for your answers this far.

I have another question. I want the default action, when drag-and-dropping on my QTreeWidget, to be a "move" action instead of a "copy". I know if I hold shift while dragging, it will do a "move" action but I can't find where this decision is made.

Can anyone direct me to the function(s) that I need to work with here?

You can basically restrain the type of actions to be allowed through the supportedDropActions() (http://doc.trolltech.com/4.1/qabstractitemmodel.html#supportedDropActions) virtual method. Then the most important step is what you actually do in the dropMimeData() method. Indeed you can choos to always move items or always copy them, regardless to the action parameter or you can decide to stick to that parameter and allo both actions...

zell99
6th March 2007, 19:31
The thing is that in a QTreeWidget the default drag and drop action is Copy, to make a Move action you have to hold SHIFT. I was wondering if I could change it so I don't have to hold shift in order to make a Move action. I restricted actions to MoveAction using the "supportedActions()" function and "setSupportedActions()". Now, it works if I shift-drag but if I just drag normally it doesn't work (since it's trying to make a Copy action which is not supported)

I have another newbie question. I have a class (MyMainWindow) which reimplements QMainWindow and in that class, I created the MyTreeWidget class (which inherits QTreeWidget). I understand that in MyTreeWidget I can use the "parentWidget()" function which returns a QWidget pointer on my parent (MyMainWindow), but how can I have access to the private variables I have in MyMainWindow, since the pointer is of QWidget type?

Thanks.

fullmetalcoder
6th March 2007, 19:43
The thing is that in a QTreeWidget the default drag and drop action is Copy, to make a Move action you have to hold SHIFT. I was wondering if I could change it so I don't have to hold shift in order to make a Move action. I restricted actions to MoveAction using the "supportedActions()" function and "setSupportedActions()". Now, it works if I shift-drag but if I just drag normally it doesn't work (since it's trying to make a Copy action which is not supported)

You can always reimplement QWidget::mousePressEvent(QMouseEvent*) and create your own QDrag object specifying the drag type (move or copy) by hand.



I have another newbie question. I have a class (MyMainWindow) which reimplements QMainWindow and in that class, I created the MyTreeWidget class (which inherits QTreeWidget). I understand that in MyTreeWidget I can use the "parentWidget()" function which returns a QWidget pointer on my parent (MyMainWindow), but how can I have access to the private variables I have in MyMainWindow, since the pointer is of QWidget type?
You shouldn't ask two very different questions in the same thread (and especially you shouldn't ask this one at all :P ). All you have to do is to use
qobject_cast<MyMainWindow*>(parentWidget()) to get a pointer of the type you're interested in. Then you shall use friendship to let your tree widget access private members of your main window.

zell99
7th March 2007, 16:20
You shouldn't ask two very different questions in the same thread (and especially you shouldn't ask this one at all :P ). All you have to do is to use
qobject_cast<MyMainWindow*>(parentWidget()) to get a pointer of the type you're interested in. Then you shall use friendship to let your tree widget access private members of your main window.

I tried to cast it before but it didn't work. :o I was using static_cast though, that might be the reason why. Thanks for your help!

I noticed something odd now though. When I am doing a MoveAction on MyTreeWidget, the MyTreeWidget::dropMimeData() function doesn't get called. It gets called from a CopyAction though. How do I make it so that it gets called from a MoveAction too? (My drop acceptation is in dropMimeData())

Thanks and sorry for all the newbish questions :confused:

fullmetalcoder
7th March 2007, 17:42
[quote=zell99;30976]
I noticed something odd now though. When I am doing a MoveAction on MyTreeWidget, the MyTreeWidget::dropMimeData() function doesn't get called. It gets called from a CopyAction though. How do I make it so that it gets called from a MoveAction too? (My drop acceptation is in dropMimeData())/quote]
A piece of code would be of a great help here (including supportedDropActions() and dropMimeData() and anything else you think may be relevant)... :rolleyes:

zell99
7th March 2007, 18:15
A piece of code would be of a great help here (including supportedDropActions() and dropMimeData() and anything else you think may be relevant)... :rolleyes:

Sure, here is the constructor:



GgdTreeWidget::GgdTreeWidget(QWidget * parent) : QTreeWidget(parent)
{
// Only the Move action is possible
//model()->QAbstractItemModel::setSupportedDragActions(Qt::Mo veAction);
}


The "setSupportedDragActions" is in commentary so I could test a CopyAction. Here is the dropMimeData() function.



bool GgdTreeWidget::dropMimeData(QTreeWidgetItem *parent, int index,
const QMimeData *data, Qt::DropAction action)
{
// PROBLEM: FUNCTION IS NOT CALLED FROM A MOVE ACTION !

// The destination item is *parent

// The item that is being dragged is in selectedItems()
QList<QTreeWidgetItem *> selectList;
QTreeWidgetItem * myDraggedItem;
selectList = this->selectedItems();
myDraggedItem = selectList.at(0);

////////// TEST
GgdMainWindow * myMainWindow = qobject_cast<GgdMainWindow*>(parentWidget());
myMainWindow->setTitleText("dragged=" + myDraggedItem->text(0));
//////////

QModelIndex idx;
if (parent) idx = indexFromItem(parent);
bool isAccepted = model()->QAbstractItemModel::dropMimeData(data, action , index, 0, idx);
return isAccepted;
}


Here is the supportedActions()



Qt::DropActions GgdTreeWidget::supportedDropActions() const
{
// Only the Move action is possible
return Qt::MoveAction;
}


If I add "| Qt::CopyAction" and do a normal drag and drop (copy) the dropMimeData function gets called (I tested by placing a Breakpoint in it). If I hold shift and do a move action, it never steps into the dropMimeData function.

Is that the code you needed?


Here is the part where I create the TreeWidget from my MainWindow:



void GgdMainWindow::createTreeWidget()
{
// Creates and sets dimensions for the Tree Widget
mTree = new GgdTreeWidget(this);
mTree->setGeometry(QRect(10, 10, 171, 411));
mTree->headerItem()->setText(0, QApplication::translate("GgdMainWindow", "Elements", 0, QApplication::UnicodeUTF8));

// Sets drag and drop
mTree->setColumnCount(1);
mTree->setSelectionMode(QAbstractItemView::SingleSelectio n);
mTree->setDragEnabled(true);
mTree->setAcceptDrops(true);
mTree->setDropIndicatorShown(true);
mTree->show();
}

fullmetalcoder
7th March 2007, 18:31
The "setSupportedDragActions" is in commentary so I could test a CopyAction.

I've never heard about such a function... What Qt version are you using???





Qt::DropActions GgdTreeWidget::supportedDropActions() const
{
// Only the Move action is possible
return Qt::MoveAction;
}
If I add "| Qt::CopyAction" and do a normal drag and drop (copy) the dropMimeData function gets called (I tested by placing a Breakpoint in it). If I hold shift and do a move action, it never steps into the dropMimeData function.

Sounds puzzling... Actually I never faced any trouble when implementing D'nD in tree models. That may come from the fact that I use models of my own and force a move action in dropMimeData() but I can confirm (just tested) that dropMimeData() (of the custom model in my case) gets called when holding shift key down while dragging... Maybe you could send me the full source so that I can do in-depth testing...

zell99
7th March 2007, 19:08
I'm using 4.2.2. I can send you the source code at the email registered on your account, is that ok?

fullmetalcoder
7th March 2007, 19:09
I'm using 4.2.2. I can send you the source code at the email registered on your account, is that ok?
Yep. I'll check it ASAP. :)

nokkie
7th August 2009, 09:28
Hello, I was wondering if this issue was ever resolved? I'm having the exact same problem with QTableWidget's, the dropMimeData() never gets called.

Experiment_57b
27th July 2010, 22:34
Is there a final code out there? I want to inverse the shift-function by move and copy too

KrishnaPG
7th August 2010, 14:28
For QTreeWidget derived class dropMimeData() gets called only when there is a "data drop", so to say. For move operations, it does not get called. It gets called when you try to copy the data. For Move or Internal move operations QTreeWidget::dropEvent() gets called.

Gopalakrishna Palem (http://gpalem.web.officelive.com/)
Creator of CFugue Runtime (http://gpalem.web.officelive.com/CFugue.html) for Programming Music in C++