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 ? :/


  • Moderators

    @Dariusz
    between the undo / redo command calls, does your model get updated (rows/columns added/removed)?



  • Hey

    Nope, I'm only clicking on new rows. I have added my mouseReleaseEvent code in 1st post to show how I'm gathering the items.



  • @Dariusz said in QTreeView selecting items programatically issue:

    no modelIndexes as they get messed up once I do drag/drop

    QPersistentModelIndex should not get messed up unless the drag-drop implementation has a bug



  • 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


Log in to reply
 

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