QTreeView- Subclassing dropMimeData causes weird issues...



  • Hey

    I'm in need of calling a specific function upon drop items to refresh their status. I figured I could subclass the dropMimeData and then just call function when I rebuild items. But the rebuild is very weird...

    The issue:
    https://imgur.com/a/cdIfO

    The subclass : pretty much copy/paste from source code except for using myItem instead of qt createItem function:

    void myModel::decodeDataRecursive(QDataStream &stream, QStandardItem *item) {
        int colCount, childCount;
        stream >> *item;
        stream >> colCount >> childCount;
        item->setColumnCount(colCount);
    
        int childPos = childCount;
    
        while (childPos > 0) {
            childPos--;
            QStandardItem *child = new myItem();
            decodeDataRecursive(stream, child);
            item->setChild(childPos / colCount, childPos % colCount, child);
        }
    }
    
    bool myModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
        qDebug()<<"Im running drop mime data?";
        // check if the action is supported
        if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
            return false;
        // check if the format is supported
        QStringList types = mimeTypes();
        QString format = types.at(0);
        if (!data->hasFormat(format))
            return QAbstractItemModel::dropMimeData(data, action, row, column, parent);
    
        if (row > rowCount(parent))
            row = rowCount(parent);
        if (row == -1)
            row = rowCount(parent);
        if (column == -1)
            column = 0;
    
        // decode and insert
        QByteArray encoded = data->data(format);
        QDataStream stream(&encoded, QIODevice::ReadOnly);
    
    
        //code based on QAbstractItemModel::decodeData
        // adapted to work with QStandardItem
        int top = INT_MAX;
        int left = INT_MAX;
        int bottom = 0;
        int right = 0;
        QVector<int> rows, columns;
        QVector<QStandardItem *> items;
    
        while (!stream.atEnd()) {
            int r, c;
            QStandardItem *item = new myItem();
            stream >> r >> c;
            decodeDataRecursive(stream, item);
    
            rows.append(r);
            columns.append(c);
            items.append(item);
            top = qMin(r, top);
            left = qMin(c, left);
            bottom = qMax(r, bottom);
            right = qMax(c, right);
        }
    
        // insert the dragged items into the table, use a bit array to avoid overwriting items,
        // since items from different tables can have the same row and column
        int dragRowCount = 0;
        int dragColumnCount = right - left + 1;
    
        // Compute the number of continuous rows upon insertion and modify the rows to match
        QVector<int> rowsToInsert(bottom + 1);
        for (int i = 0; i < rows.count(); ++i)
            rowsToInsert[rows.at(i)] = 1;
        for (int i = 0; i < rowsToInsert.count(); ++i) {
            if (rowsToInsert.at(i) == 1) {
                rowsToInsert[i] = dragRowCount;
                ++dragRowCount;
            }
        }
        for (int i = 0; i < rows.count(); ++i)
            rows[i] = top + rowsToInsert.at(rows.at(i));
    
        QBitArray isWrittenTo(dragRowCount * dragColumnCount);
    
        // make space in the table for the dropped data
        int colCount = columnCount(parent);
        if (colCount < dragColumnCount + column) {
            insertColumns(colCount, dragColumnCount + column - colCount, parent);
            colCount = columnCount(parent);
        }
        insertRows(row, dragRowCount, parent);
    
        row = qMax(0, row);
        column = qMax(0, column);
    
        QStandardItem *parentItem = itemFromIndex(parent);
        if (!parentItem)
            parentItem = invisibleRootItem();
    
        QVector<QPersistentModelIndex> newIndexes(items.size());
        // set the data in the table
        for (int j = 0; j < items.size(); ++j) {
            int relativeRow = rows.at(j) - top;
            int relativeColumn = columns.at(j) - left;
            int destinationRow = relativeRow + row;
            int destinationColumn = relativeColumn + column;
            int flat = (relativeRow * dragColumnCount) + relativeColumn;
            // if the item was already written to, or we just can't fit it in the table, create a new row
            if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
                destinationColumn = qBound(column, destinationColumn, colCount - 1);
                destinationRow = row + dragRowCount;
                insertRows(row + dragRowCount, 1, parent);
                flat = (dragRowCount * dragColumnCount) + relativeColumn;
                isWrittenTo.resize(++dragRowCount * dragColumnCount);
            }
            if (!isWrittenTo.testBit(flat)) {
                newIndexes[j] = index(destinationRow, destinationColumn, parentItem->index());
                isWrittenTo.setBit(flat);
            }
        }
    
        for (int k = 0; k < newIndexes.size(); k++) {
            if (newIndexes.at(k).isValid()) {
                parentItem->setChild(newIndexes.at(k).row(), newIndexes.at(k).column(), items.at(k));
            } else {
                delete items.at(k);
            }
        }
    
        return true;
    }```
    
    
    

    Only error print I get is this :

    Trying to construct an instance of an invalid type, type id: 3670118
    Trying to construct an instance of an invalid type, type id: 553673728
    Trying to construct an instance of an invalid type, type id: 6357041
    Trying to construct an instance of an invalid type, type id: 587215360
    Trying to construct an instance of an invalid type, type id: 3735603
    Trying to construct an instance of an invalid type, type id: 838874112
    Trying to construct an instance of an invalid type, type id: 3211319


  • Lifetime Qt Champion

    Hi,

    Can you explain what you need to do exactly to refresh your data structure ?



  • @SGaist said in QTreeView- Subclassing dropMimeData causes weird issues...:

    Hi,

    Can you explain what you need to do exactly to refresh your data structure ?

    Uhh humhhh I think I wanted it to check its parent Qt::UserRole for specific flag upon drop so that if the parent is lets say "disabled"(checkbox) then the dropped item should be of specific color - and if the state is different to items current state then he should notify its child items to adjust their state as well...

    The idea was to do for(auto &item:items){item->setData("",Qt::UserRole+99) this would then kick off the check state recursive loop

    The items is from the QT QList Items created above in source code more or less..


  • Lifetime Qt Champion

    Shouldn't that rather be done in the data function of your model ?

    That the children checks the state of their parents and changes the colour accordingly ?


Log in to reply
 

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