Move qtreeview rows



  • Hello,

    I have a qtreeview with a qstandarditemmodel..

    I would move a row with all subentries to a new position.

    I tried:
    @ moveRow( customerItem->parent()->index(), customerItem->row(),
    _customerGroupsToItems[groupId]->index(), 0);@

    And now, i readed in the documentation auf moveRows:
    @The base class implementation does nothing and returns false.@

    How can i solve my issue?


  • Lifetime Qt Champion

    Hi,

    This is because QStandardItemModel doesn't know anything about your underlying data so it can't move things around for you.

    You have to implement moveRows for your model if you want to use moveRow.

    Hope it helps



  • Hi,
    I had the same problem moving a row within a flat QStandardItemModel. It took some figuring out to get the move operation working properly with eg. QML ListView. I ended up doing:

    @void MyModel::move(int from, int to, int)
    {
    ... //range checking etc.

    int toSignal = to;
    if(from < to){
        toSignal += 1;
    }
    
    if(!beginMoveRows(QModelIndex(), from, from, QModelIndex(), toSignal)){
        return;
    }
    blockSignals(true);
    QStandardItem* fromItem = takeItem(from);
    removeRow(from);
    insertRow(to, fromItem);
    blockSignals(false);
    endMoveRows();
    

    }@



  • @David-Stiel
    Thanks!
    I adapted your example to work with a QTreeView with more than 1 column, as follows (only 1 step up/down per invocation)

    bool StandardItemModel::move(int from, bool isUp)
    {
        //range checking etc.
        const int numRows = rowCount();
    
        if (from<0 || from>=numRows || (from==0 && isUp) || (from==numRows-1 && !isUp))
            return false;
    
        const int to = isUp ? from - 1: from + 1;
    
        //See documentation
        //http://doc.qt.io/qt-5/qabstractitemmodel.html#beginMoveRows
        //on why this is needed?
        const int toSignal = isUp ? to : to + 1;
    
        if (!beginMoveRows(QModelIndex(), from, from, QModelIndex(), toSignal))
            return false;
    
        blockSignals(true);
        QList<QStandardItem*> fromRow = takeRow(from); //this also removes it from the model!
        insertRow(to, fromRow); //but the actual insertion must be done using to, not toSignal!
        blockSignals(false);
    
        endMoveRows();
    
        return true;
    }
    

    Note that there is no removeRow(from) in the adapted code, as takeRow(from) seems to already take care of that.
    In a dialog, I have Move Up and Move Down buttons that call the following dialog method:

    void changeOrderDialog::moveCurrentRow(bool isUp)
    {
        const QModelIndex index = ui->treeView->currentIndex();
    
        if (index.isValid())
        {
            StandardItemModel* model = qobject_cast<StandardItemModel*>(ui->treeView->model());
            const int row = index.row();
    
            if (model->move(row, isUp))
            {
                const QModelIndex newIndex = model->index(isUp ? row-1 : row+1, 0);
                ui->treeView->setCurrentIndex(newIndex);
            }
        }
    }
    


  • @Diracsbracket
    Although this seems to work correctly in the QTreeView, I get the error messages in the Debugger as explained in this post.
    https://forum.qt.io/topic/86021/qabstractitemmodel-endmoverows-invalid-index


Log in to reply
 

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