When is AbstractItemModel's data() method called ?



  • Is there documentation for when AbstractItemModel's data() method is called ?

    It seems that my application has many unnecessary calls to AbstractItemModel::data(). I'm using AbstractTableModel and I understand that data() must be called multiple times for the various roles of an index. I would expect data() to be called when the table is initially drawn and when a modification is made to a cell. Also, I'm not manually redrawing the anywhere in code.

    I tried to get more details by having the rowCount() and columnCount() return 1 so I essentially have a table with only one cell. Next, I put a print statement inside data() and I could see it is being called for roles 6,7,9,10,1,0, and 8. The problem is that it does this four times so it's being called 28 times (7 roles * 4 times = 28) for only one cell in the table.

    Understanding the sequence of calls for the Model/View architecture is critical to my doing well on this project. Any documentation on the sequence of calls (i.e. when is data()/setData() etc. called) ? Any advice ? I can provide code if necessary.


  • Moderators

    The timing and order of data() calls is implementation detail of Qt and will likely change. It is not documented (officially).

    The recommendation is that data() should be implemented to be "as fast as possible". You shouldn't make any assumptions on when or how many times certain data role will be polled. Optimally a data() implementation should be a switch with bunch of returns and no (or almost no) calculations.
    If you need some heavy calculations for particular data roles you should consider caching it. You can take a look at QCache or QContiguousCache classes to see if they can help you out.



  • Thank you Chris.

    I just noticed one thing. Here is main.cpp:

    @#include "CMainWindow.h"
    #include <QApplication>

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    CMainWindow w;
    w.show();
    return a.exec();
    }@

    If I remove line 9, then data() gets called as many times as I would expect for the one table cell (i.e. getting each role ONCE upon launch). However, when I add the line, there are many more calls to data(). What is there about entering the main event loop (via exec()) that does this ?


  • Moderators

    As I said - that's an implementation detail so I can only speculate.

    I implemented an example just like you described:
    @#include <QApplication>
    #include <QAbstractItemModel>
    #include <QTableView>
    #include <QDebug>

    class Model : public QAbstractItemModel {
    public:
    Model(QObject* parent = nullptr) : QAbstractItemModel(parent) {}
    QModelIndex index(int row, int column, const QModelIndex&) const {
    return createIndex(row, column);
    }
    QModelIndex parent(const QModelIndex&) const {
    return QModelIndex();
    }
    int rowCount(const QModelIndex&) const {
    return 1;
    }
    int columnCount(const QModelIndex&) const {
    return 1;
    }
    QVariant data(const QModelIndex&, int role) const {
    qDebug() << role;
    return QVariant();
    }
    };

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    QTableView w;
    w.setModel(new Model());
    w.show();
    return a.exec();
    }@
    The output is "6 7 9 10 1 0 8" and that's it. It's like that even if I hide and show the widget multiple times. When you look at the Qt::ItemDataRole definition these are all roles needed to draw a cell - a font, text, colors, decoration etc.

    So if you're getting these calls multiple times you're probably doing something else that forces the view to update. Check if you're not setting the model multiple times, resize the window(or just the widget), call setGeometry, resetModel, emit some signals that could trigger an update etc. I can't really help you more without seeing the whole context.



  • Thank you Chris!

    I looked at my data() function and I was creating a copy of a map with 44000+ elements. This was the reason my interface lagged and not the many calls to data(). Your statement "data() should be implemented to be “as fast as possible” made me take a second look at my code. I still haven't figured out the reason for the many calls to data() (it's probably one of the things you listed), but I can at least continue with development.


  • Lifetime Qt Champion

    Hi,

    AFAIK, as soon as there is an update needed then data will be called. An update can be triggered for many reasons: moving the widget, moving another window over your widget, minimize/maximize and lots of other things that depends also on your model, if you called reset, layoutChanged etc.


Log in to reply
 

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