QTreeView selecting items programatically issue
-
Hey
I'm trying to create undo/redo command system but oh boy getting the selection to work is a headache.
in my undo I store a list of column 0 elements of all selected items as nodes - no modelIndexes as they get messed up once I do drag/drop.
The idea was store as items > retrieve their indexes during undo/redo & select them again. But for some reason I cant get it to work.
Here is how I gather the items:
void myView::mouseReleaseEvent(QMouseEvent *event) { dragActive = false; QTreeView::mouseReleaseEvent(event); //_newSelection = selectionModel()->selection(); //// Cant use QModelIndex, affter drag/drop/etc they all go bad. _newSelectionX = selectedIndexes(); //if (_newSelectionX != _oldSelectionX) { std::vector<myNode *> _newSelectedNodes; for (int x = 0; x < _newSelectionX.size(); x += model()->columnCount()) { //// get only 1st item from 0 column, well use sibling later to create full selection from indexes. myNode *node = static_cast<myNode*>(_newSelectionX[x].internalPointer()); _newSelectedNodes.emplace_back(node); } std::vector<myNode *> _oldSelectedNodes; for (int x = 0; x < _oldSelectionX.size(); x += model()->columnCount()) { myNode *node = static_cast<myNode*>(_oldSelectionX[x].internalPointer()); _oldSelectedNodes.emplace_back(node); } selectionCommand::selectionData data; data._newSel = _newSelectedNodes; data._oldSel = _oldSelectedNodes; data._tree = this; emit selectionHasChanged(data);
Here is how I undo/redo :
void myView::changeMySelection(selectionCommand::selectionData data, bool undo) { clearSelection(); int columnC = 1;//model()->columnCount() - 2; if (undo) { for (int x = 0; x < data._oldSel.size(); ++x) { QModelIndex itemIndex = data._oldSel[x]->index(); QModelIndex siblingIndex = itemIndex.sibling(data._oldSel[x]->row(), columnC); qDebug() << itemIndex << siblingIndex; selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select); //selectionModel()->select(QItemSelection(itemIndex, siblingIndex), QItemSelectionModel::Select); } } else { for (int x = 0; x < data._newSel.size(); ++x) { QModelIndex itemIndex = data._newSel[x]->index(); QModelIndex siblingIndex = itemIndex.sibling(data._newSel[x]->row(), columnC); qDebug() << itemIndex << siblingIndex; selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select); } } }
Here is the log
QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(13,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
Only some of the selections actually undo/redo. I can not understand at all why on earth I'm getting wrong QModelIndexes. The left model index is valid, so right one next column should be valid as well. duhh !
I even tried on selecting just 1 item (current example) and that only works in some cases. What am I doing wrong here ? :/
-
Hey
I'm trying to create undo/redo command system but oh boy getting the selection to work is a headache.
in my undo I store a list of column 0 elements of all selected items as nodes - no modelIndexes as they get messed up once I do drag/drop.
The idea was store as items > retrieve their indexes during undo/redo & select them again. But for some reason I cant get it to work.
Here is how I gather the items:
void myView::mouseReleaseEvent(QMouseEvent *event) { dragActive = false; QTreeView::mouseReleaseEvent(event); //_newSelection = selectionModel()->selection(); //// Cant use QModelIndex, affter drag/drop/etc they all go bad. _newSelectionX = selectedIndexes(); //if (_newSelectionX != _oldSelectionX) { std::vector<myNode *> _newSelectedNodes; for (int x = 0; x < _newSelectionX.size(); x += model()->columnCount()) { //// get only 1st item from 0 column, well use sibling later to create full selection from indexes. myNode *node = static_cast<myNode*>(_newSelectionX[x].internalPointer()); _newSelectedNodes.emplace_back(node); } std::vector<myNode *> _oldSelectedNodes; for (int x = 0; x < _oldSelectionX.size(); x += model()->columnCount()) { myNode *node = static_cast<myNode*>(_oldSelectionX[x].internalPointer()); _oldSelectedNodes.emplace_back(node); } selectionCommand::selectionData data; data._newSel = _newSelectedNodes; data._oldSel = _oldSelectedNodes; data._tree = this; emit selectionHasChanged(data);
Here is how I undo/redo :
void myView::changeMySelection(selectionCommand::selectionData data, bool undo) { clearSelection(); int columnC = 1;//model()->columnCount() - 2; if (undo) { for (int x = 0; x < data._oldSel.size(); ++x) { QModelIndex itemIndex = data._oldSel[x]->index(); QModelIndex siblingIndex = itemIndex.sibling(data._oldSel[x]->row(), columnC); qDebug() << itemIndex << siblingIndex; selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select); //selectionModel()->select(QItemSelection(itemIndex, siblingIndex), QItemSelectionModel::Select); } } else { for (int x = 0; x < data._newSel.size(); ++x) { QModelIndex itemIndex = data._newSel[x]->index(); QModelIndex siblingIndex = itemIndex.sibling(data._newSel[x]->row(), columnC); qDebug() << itemIndex << siblingIndex; selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select); } } }
Here is the log
QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(13,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
Only some of the selections actually undo/redo. I can not understand at all why on earth I'm getting wrong QModelIndexes. The left model index is valid, so right one next column should be valid as well. duhh !
I even tried on selecting just 1 item (current example) and that only works in some cases. What am I doing wrong here ? :/
@Dariusz
between the undo / redo command calls, does your model get updated (rows/columns added/removed)? -
Hey
I'm trying to create undo/redo command system but oh boy getting the selection to work is a headache.
in my undo I store a list of column 0 elements of all selected items as nodes - no modelIndexes as they get messed up once I do drag/drop.
The idea was store as items > retrieve their indexes during undo/redo & select them again. But for some reason I cant get it to work.
Here is how I gather the items:
void myView::mouseReleaseEvent(QMouseEvent *event) { dragActive = false; QTreeView::mouseReleaseEvent(event); //_newSelection = selectionModel()->selection(); //// Cant use QModelIndex, affter drag/drop/etc they all go bad. _newSelectionX = selectedIndexes(); //if (_newSelectionX != _oldSelectionX) { std::vector<myNode *> _newSelectedNodes; for (int x = 0; x < _newSelectionX.size(); x += model()->columnCount()) { //// get only 1st item from 0 column, well use sibling later to create full selection from indexes. myNode *node = static_cast<myNode*>(_newSelectionX[x].internalPointer()); _newSelectedNodes.emplace_back(node); } std::vector<myNode *> _oldSelectedNodes; for (int x = 0; x < _oldSelectionX.size(); x += model()->columnCount()) { myNode *node = static_cast<myNode*>(_oldSelectionX[x].internalPointer()); _oldSelectedNodes.emplace_back(node); } selectionCommand::selectionData data; data._newSel = _newSelectedNodes; data._oldSel = _oldSelectedNodes; data._tree = this; emit selectionHasChanged(data);
Here is how I undo/redo :
void myView::changeMySelection(selectionCommand::selectionData data, bool undo) { clearSelection(); int columnC = 1;//model()->columnCount() - 2; if (undo) { for (int x = 0; x < data._oldSel.size(); ++x) { QModelIndex itemIndex = data._oldSel[x]->index(); QModelIndex siblingIndex = itemIndex.sibling(data._oldSel[x]->row(), columnC); qDebug() << itemIndex << siblingIndex; selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select); //selectionModel()->select(QItemSelection(itemIndex, siblingIndex), QItemSelectionModel::Select); } } else { for (int x = 0; x < data._newSel.size(); ++x) { QModelIndex itemIndex = data._newSel[x]->index(); QModelIndex siblingIndex = itemIndex.sibling(data._newSel[x]->row(), columnC); qDebug() << itemIndex << siblingIndex; selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select); } } }
Here is the log
QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(13,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0)) QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
Only some of the selections actually undo/redo. I can not understand at all why on earth I'm getting wrong QModelIndexes. The left model index is valid, so right one next column should be valid as well. duhh !
I even tried on selecting just 1 item (current example) and that only works in some cases. What am I doing wrong here ? :/
-
Hey
Yeah not sure to be honest. I dont use persistend model indexes, they are quite heavy from what I read and sicne I will have thousands of items. I though its more efficient to store pointer to items and then get their indexes from model. I tried storing before the QSelectionModel()->selection() and restoring that, it worked on QTreeWidget system, but on my QAbstractItemModel&treeView seems to be broken. I attached video with me dragging lots of stuff(https://goo.gl/zCiMhv), It seems to be working fine. I fire the before/after remove/add commands and so on. Its puzzling :- ( Over there I store pointers to items in an array>store that in my custom mimeData. The mimeData is used to carry the dragging of data as it should, and at the end of dropMimeData (before row removal/insertion) I store source item row/parent data/ to restore it later/ snipped below.
//// Drop mime data function .... for (int i = count - 1; i >= 0; --i) { if (nodes[i]->row() < row && parentNode == nodes[i]->parentNode()) --row; // Remove from old position moveCommand::moveData mData; mData._node = nodes[i]; mData._source = sourceModel; mData._destination = this; mData._sourceRow = nodes[i]->row(); mData._destinationRow = row; //mData._oldParentIndex = createIndex(nodes[i]->row(), 0, nodes[i]); /// obsolete - removed now after clean up - never used it //mData._newParentIndex = parent; /// obsolete - removed now after clean up - never used it mData._oldParent = nodes[i]->parentNode(); mData._newParent = parentNode; moveData.push_back(mData); sourceModel->removeNode(nodes[i]); // Insert at new position beginInsertRows(parent, row, row); parentNode->insertChild(row, nodes[i]); endInsertRows(); ++row; } emit treeModelItemMoved(moveData);
Updated snipped a little.
-
SOLVED!
In QAbstractItemModel ::indexFromitem() I had wrong argument passed in createIndex(), I was passing item.parent() instead of item as third arg.. argh!!! Thanks for juggling my brain :- )
The only thing I have to solve now is to re-select items properly after drop action. I wonder whats wrong humhhhh