Unsolved 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/cdIfOThe 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 -
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..
-
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 ?