My DataTable class is derived from QAbstractTableModel. It uses the QSqlTableModel object internally to retrieve data from the db table. It represents an entry for each row in db (it does more, but the number of records is always equal to the number of rows in the db table).
With MySql, my implementation of DataTable :: rowCount () just calls rowCount () in the QSqlTableModel, which works well.
Now with SQLite, the Qt SQLite driver returns 256 rows if there are more than 256 rows in the db table, so my DataTable class also returns 256 - which is wrong. the documentation tells me to call while (sql_model->canFetchMore()) sql_model->fetchMore(); . Calling fetchMore () immediately after creating the internal QSqlTableModel actually calls the next call to rowCount () to return the correct value. But as soon as something has changed in the database (my class will call insertRow () or setData () in QSqlTableModel), the next call to QSqlTableModel :: rowCount () will again return 256.
The database is changed only by my class, which in turn uses this particular QSqlTableModel object (or a view that uses my DataTable model as a model, can update something). Thus, there is no other process that could insert rows into the database.
So, when does my DataTable class call fetchMore () for rowCount () to always return the actual row counter?
I think my class should connect some of the signals emitted by QSqlTableModel to a slot that will call fetchMore (), although I'm not sure if this is the correct / reliable way to do this?
Update
Here is the code to demonstrate the main problem.
QSqlTableModel *model = new QSqlTableModel(0, database); //QSqlDatabase model->setTable("tablename"); qDebug() << "0 row count" << model->rowCount(); //0 row count 0 model->setEditStrategy(QSqlTableModel::OnManualSubmit); model->select(); qDebug() << "1 row count" << model->rowCount(); //1 row count 256 while (model->canFetchMore()) model->fetchMore(); qDebug() << "2 row count" << model->rowCount(); //2 row count 1520 //... other methods ... model->setData(model->index(0, 0), "TEST"); model->submitAll(); qDebug() << "3 row count" << model->rowCount(); //3 row count 256 while (model->canFetchMore()) model->fetchMore(); qDebug() << "4 row count" << model->rowCount(); //4 row count 1520
After loading the sql model, rowCount () returns 256 (1), so you need to call the fetchMore () function. rowCount () then returns the actual number of rows.
Later the data changes, after which rowCount () returns 256 (3) again.
So it seems that fetchMore () needs to be called after every write operation in the sql model. But instead of putting this while / canFetchMore () / fetchMore () loop at the end of every method that modifies the model, I wonder if it is enough to connect beforeInsert (QSqlRecord &), beforeUpdate (int, QSqlRecord &) and beforeDelete (int) to the slot, which then calls fetchAll ()? Would it be reliable and appropriate?
Correction : not earlier than * signals (too early), but probably layoutChanged (), dataChanged (), rowsInserted () and rowsRemoved ().
Update 2 :
A note on SQL . I know that I could send a separate SELECT COUNT SQL query to the database theoretically, but this does not answer the question. While I can avoid SQL, I will not write SQL. In my opinion, sending such an SQL query does not match the purpose of the QAbstractTableModel object-oriented class. Plus rowCount () is const (shouldn't send requests) and should be fast. Anyway, this will not fix rowCount ().
I ended up plugging in a slot that calls fetchMore () for the corresponding signals (see above) And , claiming that everything was selected in rowCount ():
assert(!sql_model->canFetchMore())
This is due to the fact that rowCount () cannot report the correct number of rows, counting as a failure state, therefore, an assertion. In other words, I would rather have my application crash than using the wrong number of rows.
Simply connecting to the dataChanged () signal (as indicated in the first answer : I would probably try to use dataChanged signal. ) I would probably try to use dataChanged signal. not enough. I connected it to dataChanged(const QModelIndex&, const QModelIndex&) , rowsInserted(const QModelIndex&, int, int) , rowsRemoved(const QModelIndex&, int, int) and layoutChanged() .
This seems to work, the statement hasn't worked yet.
If someone can specifically confirm this (or explain why it does not always work), I would appreciate a response.