[SOLVED] supportedDropActions() in QAbstractItemModel



  • I've got class based on QAbstractItemModel and need realize drag'n'drop using it. Model is based on a 2-level tree structure. 2-level elements can be draged and dropped inside its parent and from one parent to another. I done almost all and stacked in supportedDropActions(). I need to move items by default and copy them if Ctrl key is pressed when dropping. But I can't return right flag to do this. Looking for examples or anything that can help.



  • I reimplement :dropMimeData, mimeData and mimeTypes functions and now my supportedDropActions functions looks like this:
    @Qt::DropActions GroupsModel::supportedDropActions() const
    {
    return Qt::CopyAction | Qt::MoveAction;
    }@
    But only move action works.



  • Define "works"! Do you actually support the copy in your model?



  • All that I've got is : DropMImeData function:
    @
    bool GroupsModel::dropMimeData( const QMimeData * data, Qt::DropAction action, int row, int col, const QModelIndex & parent )
    {
    QByteArray encodedData = data->data("text/plain");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);

    int takedGpIndex, takedSubIndex;

    while (!stream.atEnd()) {
    stream >> takedGpIndex >> takedSubIndex;

    if(takedGpIndex == -1 || takedSubIndex == -1)
    continue;

    // *********************************take item calculations ***********************//

    // get place in structure
    Group * takedGp = m_groups.getGroupByIndex(takedGpIndex);

    if(takedGp == NULL)
    continue;

    GroupSubscriber * sub = takedGp->getSubscriberByIndex(takedSubIndex);

    if(sub == NULL)
    continue;

    // ********************************* drop place calculations ***********************//

    // get place in structure

    int putGpNdx = -1;

    if(parent.isValid())
    if(parent.internalId() != -1)
    putGpNdx = parent.row();
    else
    putGpNdx = row;

    if(putGpNdx == -1)
    continue;

    Group * putGp = m_groups.getGroupByIndex(putGpNdx);

    if(putGp == NULL)
    continue;

    // put data

    QModelIndex putParent = index(putGpNdx,eID,m_null);

    if(takedGp == putGp)
    {
    if(row == -1)
    continue;

    if(row >= putGp->count())
    {
    int pRow = putGp->count();
    beginInsertRows(putParent,pRow,pRow);
    GroupSubscriber * newSub = new GroupSubscriber(*sub);
    putGp->addSubscriber(newSub);
    endInsertRows();
    }
    else
    {
    beginInsertRows(putParent,row,row);
    takedGp->copySubscriber(takedSubIndex,row);
    endInsertRows();

    if(takedSubIndex>row)
     takedSubIndex++;
    

    }
    }
    else
    {
    if(row == -1)
    {
    int pRow = putGp->count();
    beginInsertRows(putParent,pRow,pRow);
    GroupSubscriber * newSub = new GroupSubscriber(*sub);
    putGp->addSubscriber(newSub);
    endInsertRows();
    }
    else
    {
    beginInsertRows(putParent,row,row);
    GroupSubscriber * newSub = new GroupSubscriber(*sub);
    putGp->insertSubscriber(newSub,row);
    endInsertRows();
    }
    }

    m_bChanged = true;

    if(action == Qt::MoveAction)
    {
    QModelIndex takeParent = index(takedGpIndex,eID,m_null);
    // if non-copy event need to delete old item and structure data

    //remove data from structure
    beginRemoveRows(takeParent,takedSubIndex,takedSubIndex);
    takedGp->removeSubscriber(takedSubIndex);
    endRemoveRows();
    }

    }

    return true;
    }@
    MimeData :
    @QMimeData * GroupsModel::mimeData( const QModelIndexList & indexes ) const
    {
    QMimeData * mimeData = new QMimeData();
    QByteArray encodedData;

    QDataStream stream(&encodedData, QIODevice::WriteOnly);

    foreach (QModelIndex index, indexes) {
    if (index.isValid() == false)
    continue;

    if(index.column() != eID)
    continue;

    int gpNdx = -1;
    int subNdx = -1;

    if(index.parent().isValid())
    {
    // this is subscriber
    gpNdx = index.parent().row();
    subNdx = index.row();
    }

    stream << gpNdx << subNdx;
    }

    mimeData->setData("text/plain", encodedData);
    return mimeData;
    }@
    MimeTypes:
    @
    QStringList GroupsModel::mimeTypes() const
    {
    QStringList types;
    types << "text/plain";
    return types;
    }@
    And supportedDropActions. I made standart treeView in *.ui file and set this model to it. So what I need to do to support copy in my model?



  • When I put a breakpoint and get to dropMimeData function action always is MoveAction, but visually I can see "+" near my item when holding "ctrl" key.



  • One more question: did I need reimplement removeRow() function from QAbstractItemModel, can it be the reason why action doesn't changes ?



  • Eureka ! Only one thing that I need to do just change dragDropMode in QTreeView from InternalMove to DragDrop. And Modified version of dropMimeData now looks like this :
    @bool GroupsModel::dropMimeData( const QMimeData * data, Qt::DropAction action, int row, int col, const QModelIndex & parent )
    {
    QByteArray encodedData = data->data("text/plain");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);

    int takedGpIndex, takedSubIndex;

    QModelIndexList deleteList;

    while (!stream.atEnd()) {
    stream >> takedGpIndex >> takedSubIndex;

    if (takedGpIndex < 0 || takedSubIndex < 0)
    continue;

    // ********************************* take item calculations ***********************//

    // get place in structure
    Group * takedGp = m_groups.getGroupByIndex(takedGpIndex);
    if (takedGp == NULL)
    continue;

    GroupSubscriber * sub = takedGp->getSubscriberByIndex(takedSubIndex);
    if(sub == NULL)
    continue;

    // ********************************* drop place calculations ***********************//

    // get place in structure

    int putGpNdx = -1;

    if (parent.isValid() && parent.internalId() <= 0)
    putGpNdx = parent.row();
    else
    putGpNdx = row;

    Group * putGp = m_groups.getGroupByIndex(putGpNdx);

    if(putGp == NULL)
    continue;

    // put data

    QModelIndex putParent = index(putGpNdx,eID,m_null);

    if(takedGp == putGp)
    {
    if(row == -1)
    continue;

    if(row >= putGp->count())
    {
    int pRow = putGp->count();
    beginInsertRows(putParent,pRow,pRow);
    GroupSubscriber * newSub = new GroupSubscriber(*sub);
    putGp->addSubscriber(newSub);
    endInsertRows();
    }
    else
    {
    beginInsertRows(putParent,row,row);
    takedGp->copySubscriber(takedSubIndex,row);
    endInsertRows();

    if(takedSubIndex>row)
     takedSubIndex++;
    

    }
    }
    else
    {
    if(row == -1)
    {
    int pRow = putGp->count();
    beginInsertRows(putParent,pRow,pRow);
    GroupSubscriber * newSub = new GroupSubscriber(*sub);
    putGp->addSubscriber(newSub);
    endInsertRows();
    }
    else
    {
    beginInsertRows(putParent,row,row);
    GroupSubscriber * newSub = new GroupSubscriber(*sub);
    putGp->insertSubscriber(newSub,row);
    endInsertRows();
    }
    }

    m_bChanged = true;

    QModelIndex takeParent = index(takedGpIndex,eID,m_null);
    deleteList.append(takeParent.child(takedSubIndex,eID));

    }

    if(action == Qt::MoveAction)
    

    removeItems(deleteList,false);

    return true;
    }@


Log in to reply
 

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