Important: Please read the Qt Code of Conduct -

Invalid QVariants in a for loop when iterating a QTableView / QStandardItemModel

  • Hi,

    I'm iterating through the content in a QTableView / QStandardItemModel as soon as the program starts to removed any row where the date is less or equal equal to currentDate, everything seems to be working fine except that there is something I cannot understand why which in reality is not creating any problems I just don't understand it.

    Here is the function:

    @void MainWindow::checkIfCurrentDateExistsInTableView()
    int row = model->rowCount();

    for (int i = 0; i < row ; ++i)
            QVariant content = model->data(model->index(i, 0), Qt::DisplayRole); // date
            qDebug()<< "content" << content;
            QString dateAsQString = content.toString();// get date as string
            QDate qDateFromRows = QDate::fromString(dateAsQString, "ddd MMM dd yyyy");// convert string date to QDate
            if(qDateFromRows <= QDate::currentDate())


    Now lets pretend that there are three dates that are smaller than currentDate and the function runs, it removes the dates but for some reason and this is where I'm confused is the fact that the for loop continues for a few more cycles after all of the rows have been removed.

    Here is the output:
    @content QVariant(QString, "Sun Sep 01 2013")
    content QVariant(QString, "Mon Sep 02 2013")
    content QVariant(QString, "Tue Sep 03 2013")

    content QVariant(Invalid) // this is what I dont know understand
    content QVariant(Invalid) // this is what I dont know understand
    content QVariant(Invalid) // this is what I dont know understand@

    Can someone be so kind and explain why the Invalid QVariant?


  • I guess the problem here is that the rowCount changes within the loop (removeRow). A easy trick to avoid this is to iterate backwards.

  • Thank you for your replay.

    What do you mean by iterate backwards? Can you explain this a little bit?

  • Simple. You're using this loop:
    for (int i = 0; i < row ; ++i) { ... }

    That means, you start at index 0, and increase it with every iteration. Instead, try this:

    for (int i = row - 1; i >= 0 ; --i) { ... }
    Now you start at the last row in your table, and end at the first row.

    Because removing rows affect the row numbers after the current index, you run into problems iterating forward. After removing, the index of the last row is no longer row, but row - 1. After removing the item that you wanted to iterate over next as the row number of the item you just removed! You could compensate your forward loop for that, but that is a bit tricky and frankly quite ugly. But iterating backwards is always fine: even if you removed the current row, the rows before this row are not affected at all.

    Note that your old program doesn't work properly either. What happens if two items next to each other need to be removed?

    Edit: fixed start backwards iteration at row -1 instead of row

  • Thank you both for your help, iterating this way solved the problem, the only thing I had to change is I subtracted 1 to the total number of row because of the way arrays are counted. The first iteration was coming as an invalid QVariant.

    @ int row = model->rowCount();
    row = row - 1;// remove one to the total number of rows
    for (int i = row; i >= 0 ; --i)@

    Note that your old program doesn’t work properly either. What happens if two items next to each other need to be removed?

    I have tried this in a lot different ways and everything seems to be working fine, it removes any row if it is smaller or equal to current date regardless of its position and leaves any date that doesn't meet that criteria.

    Off topic question:
    Are you planning on updating QTimeSpan to work in Qt5 anytime soon?


  • Yes, true, you need to start iterating from row-1. Corrected in previous post.

Log in to reply