Sections

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();
}

back