How to correctly use "application/x-qabstractitemmodeldatalist" mime type in derived model/view classes drag and drop operations?



  • Hi, all,

    I'm building an application using QAbstractItemModel for custom types of items in a QListView and in a QTreeView. Those items have to be dragged/dropped inside the QTreeView - both copy and move - and dragged from the QListView and dropped to the QTreeView.

    Although much of the functionality is already working, on the tree model class, in the "dropMimeData" method, I don't get the "row" and "column" the data was dropped to, they always come as -1. Also, the "parent" comes as the header item.

    I know the problem is that I have derived QAbstractItemModel for a model view of a QTreeView and also derived the QTreeView, adding my own mouse event handlers to generate a QDrag object, carrying the needed information to move/create new items in the QTreeView, and it only started to work when I switched to "application/x-qabstractitemmodeldatalist" mime type, encoding and decoding my data to it.

    Although many sample code found here and there suggests that this mime type would also carry a location, I also could not manage to recover it, as far as I did not encoded it at first, but I don't think this is what I am looking for.



  • [quote author="frares" date="1342010749"]
    Although much of the functionality is already working, on the tree model class, in the "dropMimeData" method, I don't get the "row" and "column" the data was dropped to, they always come as -1. Also, the "parent" comes as the header item.
    [/quote]

    Do you set the Qt::ItemIsDropEnabled-flag in the flags()-method of your model for all Items that can be a drop target? If not, this may be the reason why you don't get row and column...



  • Thanks for your repply.

    Yes, there is a Qt::ItemIsDropEnabled-flag in the flags()-method, there is the code:

    @Qt::ItemFlags CTreeModel::flags(const QModelIndex & index) const {
    if (index.isValid()) {
    if (index.column() == 0) {
    return Qt::ItemIsEditable |
    Qt::ItemIsSelectable |
    Qt::ItemIsEnabled |
    Qt::ItemIsDragEnabled |
    Qt::ItemIsDropEnabled ;
    } else {
    return Qt::ItemIsSelectable |
    Qt::ItemIsEnabled |
    Qt::ItemIsDragEnabled |
    Qt::ItemIsDropEnabled ;
    }
    } else {
    return Qt::ItemIsSelectable |
    Qt::ItemIsEnabled |
    Qt::ItemIsDropEnabled ;
    }
    }
    @



  • Ok, then the flags aren't the problem, so its probablyl your mouseevent handlers/the creation of your QDrag-Object...
    Could you post the code for this method?



  • Thanks again for your repply, here goes the code:

    This goes in a custom QTreeView class:
    @
    void CTreeView::mousePressEvent ( QMouseEvent *event ) {
    if (event->button() == Qt::LeftButton)
    mDragStartPos = event->pos();
    // event->accept();
    // QTreeView::mousePressEvent(event);
    }

    void CTreeView::mouseMoveEvent ( QMouseEvent * event ) {
    if (event->buttons() == Qt::LeftButton &&
    (mDragStartPos - event->pos()).manhattanLength() >=
    QApplication::startDragDistance()) {
    clearSelection();
    QDrag * drag = new QDrag(this);
    QMimeData * mimeData = new QMimeData;

    QModelIndex index = indexAt(mDragStartPos);
    CTreeItem * item = static_cast<CTreeItem*>(index.internalPointer());
    if (item) {
    qint8 toolType = item->data(5).toInt();
    QString toolCode = item->data(8).toString();
    QString toolIcon = item->data(4).toString();

    QByteArray mdata;
    QDataStream stream(&mdata, QIODevice::WriteOnly);
    QMap<int, QVariant> roleDataMap;
    roleDataMap[0] = QVariant(toolType);
    roleDataMap[1] = QVariant(toolCode);
    stream << roleDataMap;
    mimeData->setData(QString("application/x-qabstractitemmodeldatalist"),
    mdata);

    drag->setPixmap(toolIcon);
    drag->setMimeData(mimeData);
    drag->exec(Qt::CopyAction | Qt::MoveAction | Qt::IgnoreAction,
    Qt::MoveAction);
    }
    }
    // event->accept();
    // QTreeView::mouseMoveEvent(event);
    }
    @

    As you can see, I have tried to keep the QTreeView event processing for both cases. Also tried to ignore and to accept the events, with no noticeable effect.

    This goes in a custom QAbstractItemModel, which is set as the model/view class of the previous one:

    @
    Qt::DropActions CTreeModel::supportedDropActions () const {
    return Qt::CopyAction | Qt::MoveAction;
    }

    bool CTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
    int row, int column, const QModelIndex &parent) {

    if ( data->hasFormat("application/x-qabstractitemmodeldatalist") &&
    ( (action == Qt::MoveAction) || (action == Qt::CopyAction) ) ) {

    QByteArray encoded = data->data("application/x-qabstractitemmodeldatalist");
    QDataStream stream(&encoded, QIODevice::ReadOnly);

    QMap<int, QVariant> roleDataMap;
    while (!stream.atEnd()) {
    stream >> roleDataMap;
    }
    mDroppedCode = roleDataMap[1].toString();

    if (parent.isValid()) {
    QModelIndex index = this->index(row, column, parent);
    CTreeItem * it = item(index);
    int i = it->childCount();
    i++;
    }
    return true;
    } else {
    return false;
    }
    }
    @

    Thanks again.
    Francisco


Log in to reply
 

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