Search code examples
c++qtqt5qtreewidgetqtreewidgetitem

Drag and drop with two QTreeWidget, filter QTreeWidgetItem's acording to their previous set data


Im my project I have two qTreeWidgets (let's say A and B), I want to drag Items from treeWidget A to treeWidget B.

I have multiple problems:

Not all of the items stored in A should be draggale. At other parts of my code I seperate them by defining the "type" within the constructor:

 QTreeWidgetItem *newDatatype = new  QTreeWidgetItem(TreeWidgetItemTypes::Datatype);

I can check them by using:

if(itemDroppedFromHeaven.type() == TreeWidgetItemTypes::Datatype) ...

Therefore I have a enum to seperate all the different kinds of Items.

  • Does drag and drop copy the set data?
  • How can I detect the kind of Item while dragging?
  • How to set dragging for some kind of Items enabled/disabled?

Iv'e tried to overload the dropEvent of the treeWidget B, to filter the dropped Items:

class CustomTreeWidget : public QTreeWidget
{
    Q_OBJECT

public:
    using QTreeWidget::QTreeWidget;
    void dropEvent(QDropEvent *event) override
    {
        QString format = event->mimeData()->formats().at(0);
        QString data = event->mimeData()->text();

        qDebug () << data;

        QStandardItem *sitem = new QStandardItem;

        QString itemName = sitem->text();
        qDebug() << itemName;

        if (itemName == "Messages" || itemName == "Datatypes" || itemName == "Enums")
        {
                event->setDropAction(Qt::IgnoreAction);
                return;
        }
        else
        {
            QTreeWidget::dropEvent(event);
            emit itemDropped();
        }
    }

signals:
    void itemDropped();
};

But with this idea I can only get the visible Item Name set with:

 newDatatype->setData(0, Qt::ItemDataRole::DisplayRole, datName);

even data set as user role are not copied:

 newDatatype->setData(0, Qt::ItemDataRole::UserRole, datObjKey);

I'm thankful for every idea! Best


Solution

  • You do not have to overwrite anything, you just have to deactivate the flag Qt::ItemIsDragEnabled with:

    item->setFlags(item->flags() &= ~Qt::ItemIsDragEnabled);
    

    Example:

    #include <QtWidgets>
    
    static void populate_treewidget(QTreeWidget *tree_widget){
        for(int i=0; i<5; ++i){
            QTreeWidgetItem *item = new QTreeWidgetItem(tree_widget);
            if(i%2 == 0){
                item->setText(0, "Not Dragable");
                item->setFlags(item->flags() &= ~Qt::ItemIsDragEnabled);
            }
            else
                item->setText(0, "Normal");
            for(int j=0; j<4; ++j){
                QTreeWidgetItem *child_item = new QTreeWidgetItem(item);
                if(j%2 == 1){
                    child_item->setText(0, "Not Dragable");
                    child_item->setFlags(child_item->flags() &= ~Qt::ItemIsDragEnabled);
                }
                else
                    child_item->setText(0, "Normal");
            }
        }
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QWidget w;
        QTreeWidget A;
        A.setDragEnabled(true);
        populate_treewidget(&A);
        QTreeWidget B;
        B.setAcceptDrops(true);
        QHBoxLayout *hlay = new QHBoxLayout(&w);
        hlay->addWidget(&A);
        hlay->addWidget(&B);
        A.expandAll();
        w.resize(640, 480);
        w.show();
        return a.exec();
    }