Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Drag and Drop in ItemView dependant on Item



  • Hello,

    I have a QTreeView with a model where I want to be able to drag and drop Items of type A onto Items of type B, and also Items of type C onto items of type D.

    I've implemented drag and drop for items of type A to B by returning Qt::ItemIsDragEnabledflags for A and Qt::ItemIsDropEnabled flags for B.

    However I do not know how I can switch the Qt::ItemIsDropEnabled flag depending on the item that is currently dragged around? What would be the right way to implement this?



  • You should implement a method to change the Qt::ItemIsDropEnabled flag for an index in the model (e.g MyModel::setFlags(const QModelIndex&,Qt::ItemFlags) basically the same as QStandardItem::setFlags for QStandardItemModel) then do something like this:

    class MyView : public QTreeView {
        Q_OBJECT
        Q_DISABLE_COPY(MyView)
    public:
        MyView(QWidget *parent = nullptr) 
            : QTreeView (parent)
        {}
    protected:
        void dragMoveEvent(QDragMoveEvent *event) override{
            const QModelIndex index = indexAt(event->pos());
            const bool canBeDropped = checkIfItemDraggedCanBeDroppedOnIndex(index); // this depends on your logic
            const Qt::ItemFlags oldFlags = model()->flags(index);
            MyModel* mdl = nullptr;
            if(!canBeDropped && index.isValid() && (oldFlags & Qt::ItemIsDropEnabled)){
                mdl = dynamic_cast<MyModel*>(model());
                Q_ASSERT(mdl);
                mdl->setFlags(index,oldFlags & ~Qt::ItemIsDropEnabled);
            }
            QTreeView::dragMoveEvent(event);
            if(mdl)
                mdl->setFlags(index,oldFlags);
        }
    };
    


  • Thanks, that brought me a step further, but I still don't get how I find the item that is currently drag and dropped inside checkIfItemDraggedCanBeDroppedOnIndex(index) because the results depends on the type of that item.



  • index is the model index of the destination item if what you don't know what the source item is then you can access its data as described here



  • Yeah, I mean the source item.
    Since I didn't want to mess around with the mime data I now ended up with another approach:
    In the mimeData() method of my model I set a boolen flag on the item that is currently the one that is dragged around. Now in the flags() method I get the flagged item from the model and look what type it is and depending on that I can decide whether drops are enabled on the underlying item or not. This works fine, however it still looks like a bit of a hack.


Log in to reply