How can I implement drag and drop in a QTreeWidget?
Answer:
In order to implement drag and drop in a QTreeWidget, you need to reimplement dragEnterEvent() and dragMoveEvent() to accept the event in addition to dropMimeData(). If you want to change what data you drag you can reimplement mimeData() as well, otherwise it will default to streaming the item. In the example below mimeData() is reimplemented and is called with a list of the selected items when you start a drag. It provides a serialized description of the selected items in the QTreeWidget. dropMimeData() is called when data is dropped in the widget and the mime data returned in mimeData() is passed in here and it is processed to get the information that we supplied to create our new items with.
#include <QTreeWidget>
#include <QApplication>
#include <QDropEvent>
class TSTree : public QTreeWidget
{
public:
TSTree( QWidget* parent = 0 );
bool dropMimeData(QTreeWidgetItem *parent, int index, const
QMimeData *data, Qt::DropAction action);
QMimeData *mimeData(const QList<QTreeWidgetItem *> items) const;
protected:
void dragEnterEvent(QDragEnterEvent *e) { e->accept(); }
void dragMoveEvent(QDragMoveEvent *e) { e->accept(); }
};
TSTree::TSTree( QWidget* parent ) : QTreeWidget( parent )
{
setColumnCount(2);
// The tree can accept drops
setAcceptDrops( true );
// The tree supports dragging of its own items
setDragEnabled(true);
QTreeWidgetItem *itemOne = new QTreeWidgetItem(this);
QTreeWidgetItem *itemTwo = new QTreeWidgetItem(this);
QTreeWidgetItem *itemThree = new QTreeWidgetItem(this);
itemOne->setText(0, "One");
itemTwo->setText(0, "Two");
itemThree->setText(0, "Three");
}
QMimeData *TSTree::mimeData(const QList<QTreeWidgetItem *> items) const
{
// Create a QByteArray to store the data for the drag.
QByteArray ba;
// Create a data stream that operates on the binary data
QDataStream ds(&ba, QIODevice::WriteOnly);
// Add each item's text for col 0 to the stream
for (int i=0;i<items.size();i++)
ds << items.at(i)->text(0);
QMimeData *md = new QMimeData;
// Set the data associated with the mime type foo/bar to ba
md->setData("foo/bar", ba);
return md;
}
bool TSTree::dropMimeData(QTreeWidgetItem *parent, int index, const
QMimeData *data, Qt::DropAction action)
{
if (parent) {
// Create a QByteArray from the mimedata associated with foo/bar
QByteArray ba = data->data("foo/bar");
// Create a data stream that operates on the binary data
QDataStream ds(&ba, QIODevice::ReadOnly);
while (!ds.atEnd()) {
QString str;
// Read a byte from the stream into the string
ds >> str;
// Create a new item that has the item that is dropped on as a parent
QTreeWidgetItem *newItem = new QTreeWidgetItem(parent);
newItem->setText(0, str);
}
}
return true;
}
int main( int argc, char** argv )
{
QApplication app(argc, argv);
TSTree tw;
tw.show();
return app.exec();
}