Dragging QListWidgetItem into QGraphicScene and create QGraphicsItem



  • Hey.

    I do have an object in my software which I have declared a QMetaType so I can store it in a QVariant. Now I have a QListWidget that shows all instances of this object with its value stored inside the individual QListWidgetItems as UserType.

    Module module("Module A");
    QListWidget* list = new QListWidget();
    [...]
    
    QListWidgetItem* item = new QListWidgetItem(module.name());
    item->setData(Qt::UserRole, QVariant::fromValue(module));
    list->addItem(item);
    

    Now I want to drag this item onto a QGraphicsScene and extract the QVariant contained in the QListWidgetItem inside the QGraphicsScene::dropEvent(...) and create a new custom QGraphicsItem that is a graphical representation of the Module there, as well.

    I was reading in the Drag & Drop Framework documentation as well as the documentation for QGraphicsView but since the QListWidgetItem supports drag&drop by default, I was wondering if there isn't an easy way to get this done.

    Any help is really appreciated!


  • Moderators

    @tobiSF
    IIRC thats not cleanly possible with QListWidget.

    the model needs to provide the drop-data and a mime-type you can listen to in the QGraphicsScene (see this). QListWidget / QStandardItemModel lacks such a possibility.
    In the QGraphicsScene dropEvent handler you then can listen for your custom mime-type and read the drop-data (item-type, content,...) from the model.



  • @raven-worx, I was afraid this was the answer. Which is too bad, when seemingly everything you'd need is in place on one side of the drag&drop operation and you would only need to access that information on the receiving end.


  • Moderators

    @tobiSF
    it's not that bad. All you have to do is just implement a new model class.



  • @raven-worx not bad in a hard/difficult way. More disappointing that there's no straightforward way. Thank you, anyway!



  • I did not test it but it looks like everything is already in Qt, just not documented.

    void dropEvent(QGraphicsSceneDragDropEvent *event){
    	const QByteArray mimeData = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
    	QDataStream mimeReader(mimeData);
    	int row,col;
    	QMap<int,QVariant> modelData;
    	for(;;){
    		mimeReader.startTransaction();
    		mimeReader >> row >> col >> modelData;
    		if(!mimeReader.commitTransaction())
    			break;
    		const auto userRoleIter = modelData.constFind(Qt::UserRole);
    		if(userRoleIter!=modelData.cend())
    			doSomethingWithModule(userRoleIter->value<Module>());
    	}
    }
    


  • @VRonin said in Dragging QListWidgetItem into QGraphicScene and create QGraphicsItem:

    const QByteArray mimeData = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
    QDataStream mimeReader(mimeData);
    int row,col;
    QMap<int,QVariant> modelData;
    for(;;){
    mimeReader.startTransaction();
    mimeReader >> row >> col >> modelData;
    if(!mimeReader.commitTransaction())
    break;
    const auto userRoleIter = modelData.constFind(Qt::UserRole);
    if(userRoleIter!=modelData.cend())
    doSomethingWithModule(userRoleIter->value<Module>());
    }

    @VRonin, thank you very much. This works like a charm and does exactly what I was looking for.


  • Moderators

    @tobiSF
    @VRonin
    that's what i meant it's not "cleanly possible". I knew that some internal data was in the mime-data, but i believed that you need a reference to the model afterall, thus "not cleanly". But thats not the case.

    Sorry for not being more specific on this.



  • @raven-worx no worries, your help is appreciated and I think I understood you correctly.


Log in to reply
 

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