Search code examples
c++qtqt5qtreewidgetqtreewidgetitem

Drag and drop file into QTreeWidget inside of QDialog


I've been searching online for days and I cant find anything to help out with my specific problem. I'm trying to set up this dialog to accept files to be dropped into the QTreeWidget, named filesTreeWidget, but everything I've been searching online doesn't seem to make a difference. I'm pretty new to QT and C++ as well, so I'm sure that doesn't help. Thanks for any help

Header

class FileIQ : public QDialog
{
   Q_OBJECT

protected:
   void dropEvent(QDropEvent *event);
   void dragEnterEvent(QDragEnterEvent *event);
   void dragMoveEvent(QDragMoveEvent *event);
   void dragLeaveEvent(QDragLeaveEvent *event);
}

Cpp

 FileIQ::FileIQ(QWidget *parent, DR::EnginePtr engine)
 : QDialog(parent)
 , ui(new Ui::FileIQ)
 , engine_(engine)
 {
   ui->filesTreeWidget->setAcceptDrops(true);
   ui->filesTreeWidget->setDropIndicatorShown(true);
   setAcceptDrops(true);
 }

 void FileIQ::dropEvent(QDropEvent *event)
 {
   foreach(const QUrl &url, event->mimeData()->urls()) {
      QString filename = url.toLocalFile();
      qDebug() << "Dropped file:" << filename;
      QTreeWidgetItem *item = new QTreeWidgetItem(ui->filesTreeWidget);
      item->setText(0, filename);
  }

 }


 void FileIQ::dragEnterEvent(QDragEnterEvent *event)
 {
     event->accept();
 }

 void FileIQ::dragMoveEvent(QDragMoveEvent * event)
 {
     event->accept();
 }

 void FileIQ::dragLeaveEvent(QDragLeaveEvent * event)
 {
     event->accept();
 }

Solution

  • First, the right thing is to implement drag and drop within QTreeWidget, not inside QDialog. To do this we must create a class that inherits from QTreeWidget and we must implement the following protected methods:

    bool QTreeWidget::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)

    Handles the data supplied by a drag and drop operation that ended with the given action in the index in the given parent item.

    The default implementation returns true if the drop was successfully handled by decoding the mime data and inserting it into the model; otherwise it returns false.

    QStringList QTreeWidget::mimeTypes() const

    Returns a list of MIME types that can be used to describe a list of treewidget items.

    Qt::DropActions QTreeWidget::supportedDropActions() const

    Returns the drop actions supported by this view.

    From the above we implemented this class:

    #ifndef TREEWIDGET_H
    #define TREEWIDGET_H
    
    #include <QDropEvent>
    #include <QTreeWidget>
    #include <QMimeData>
    #include <QFileInfo>
    
    class FilesTreeWidget : public QTreeWidget
    {
        Q_OBJECT
    public:
        FilesTreeWidget(QWidget *parent= Q_NULLPTR):
            QTreeWidget(parent)
        {
            setAcceptDrops(true);
            setDropIndicatorShown(true);
            setColumnCount(2);
        }
    
    protected:
        bool dropMimeData(QTreeWidgetItem *parent, int /*index*/, const QMimeData *data, Qt::DropAction /*action*/)
        {
    
            for(const QUrl url: data->urls()) {
                const QFileInfo info( url.toLocalFile());
                if(info.isFile()){
                    QTreeWidgetItem *item;
                    if (parent){
                        item = new QTreeWidgetItem(parent);
                        parent->setExpanded(true);
                    }
                    else
                        item = new QTreeWidgetItem(this);
                    item->setText(0, info.fileName());
                    item->setText(1, info.filePath());
                }
            }
            return true;
        }
    
        QStringList mimeTypes () const
        {
            return QStringList()<<"text/uri-list";
        }
    
        Qt::DropActions supportedDropActions () const
        {
            return Qt::CopyAction;
        }
    
    };
    
    #endif // TREEWIDGET_H
    

    The complete example can be found in the following link. If you already have a QTreeWidget assigned by Qt Designer the simplest solution is to promote the Qt Designer QTreeWidget to use the new class.

    Output:

    enter image description here