[SOLVED] QTreeWidget drag and drop signals



  • Hi everyone !

    I've been working with a QTreeWidget for a article editor application. The QTreeWidget shows all opened articles in a tree where articles can be children of others. What I want to do is to dynamically set the parent-child relationship by dragging and dropping articles in the tree view to others.
    I tried to reimplement dropEvent on thre treewidget but it doesn't work with QTreeWidgetItems wich doesn't seem to inherit QWidget.
    I also tried to connect the QTreeWidget::itemChanged() signal to a custom slot but it doesn't seem to be emited on drag and drop operations.
    How should I handle such an event ?

    Thanks in advance !


  • Moderators

    please post some code than we can help you more efficiently.

    • Did you try to implement QTreeWidget::dropMimeData() ?
    • did you try treeWidget->setDragDropMode(QAbstractItemView::InternalMove) ?


  • Thanks for the fast answer.

    I think dropMimeData() is what i was looking for. However, after implementing it, it still misses something to get it to work.

    Here's the code:

    @
    #ifndef WORKSPACEWIDGET_H
    #define WORKSPACEWIDGET_H

    #include <QTreeWidget>
    #include <QDropEvent>

    class WorkspaceWidget : public QTreeWidget
    {
    Q_OBJECT
    public:
    explicit WorkspaceWidget(QWidget *parent = 0);

    protected:
    virtual bool dropMimeData ( QTreeWidgetItem * parent, int index, const QMimeData * data, Qt::DropAction action );
    void dropEvent(QDropEvent *event);

    };

    #endif // WORKSPACEWIDGET_H
    @
    @
    #include "workspacewidget.h"
    #include <QDropEvent>
    #include <QMessageBox>

    WorkspaceWidget::WorkspaceWidget(QWidget *parent) :
    QTreeWidget(parent)
    {
    QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
    sizePolicy.setHorizontalStretch(0);
    sizePolicy.setVerticalStretch(0);
    sizePolicy.setHeightForWidth(this->sizePolicy().hasHeightForWidth());
    setSizePolicy(sizePolicy);

    setAcceptDrops(true);
    setDragEnabled(true);
    setDragDropMode(QAbstractItemView::InternalMove);
    
    this->setHeaderItem(new QTreeWidgetItem(QStringList("Workspace")));
    

    }

    bool WorkspaceWidget::dropMimeData( QTreeWidgetItem * parent, int index, const QMimeData * data, Qt::DropAction action ){
    QTreeWidget::dropMimeData(parent, index, data, action);
    QMessageBox::information(this, "", parent->text(currentColumn()) + "dropped");

    return true;
    

    }

    void WorkspaceWidget::dropEvent(QDropEvent *event)
    {
    QTreeWidget::dropEvent(event);

    QMessageBox::information(this, "", event->source()->objectName());
    

    }

    @

    I get a message box from the dropEvent, which is empty since QTreeWidgetItem isn't a QWidget, but I don't get any message from dropMimeData() ?


  • Moderators

    Currently in your dropEvent you retrieve the widget which has started the drag (thats your tree widget) and return it's objectName, which is by default an empty string (as long as you haven't explicitly set it).
    But what you want is the data of the drag, which you get with event->mimeData(). This contains the dragged QTreeItems you want.

    I don't know what format the dropData has though, because i never worked with Qt standard item implementations (only used custom models,views,...).
    But you can iterate over all formats of the QMimeData objects using it's methods or you can quickly use the Qt DropSite example to check what mime types the drag has.



  • Thank you ! It works.

    Here's the code:

    @

    void WorkspaceWidget::dropEvent(QDropEvent *event)
    {
    //MimeData: application/x-qabstractitemmodeldatalist"

    QTreeWidget::dropEvent(event);
    
    
    const QMimeData* qMimeData = event->mimeData();
    
    QByteArray encoded = qMimeData->data("application/x-qabstractitemmodeldatalist");
    QDataStream stream(&encoded, QIODevice::ReadOnly);
    
    while (!stream.atEnd())
    {
        int row, col;
        QMap<int,  QVariant> roleDataMap;
    
        stream >> row >> col >> roleDataMap;
    
        QString dropped = roleDataMap[0].toString();
    
        QString into = this->itemAt(event->pos())->text(0);
    
        QMessageBox::information(this, "", "DROPPING:" + dropped + "\nINTO:" +
                                 into);
    }
    

    }

    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.