[Development] Regression / Behavioral Change in QSqlTableModel / QTableView in Qt 5

Mark Brand mabrand at mabrand.nl
Tue Sep 11 14:49:22 CEST 2012


Maemi Carrer wrote:

>> ... each edit causes the table to be requeried and the model reset, which
>> breaks navigation in the view.
> Do you mind elaborating in which way this breaks navigation?

In Qt 4, QSqlTableModel calls select() immediately after submitting 
changes to the database. This invokes QSqlQueryModel::setQuery(). In the 
process, the rows and columns of the model are removed and replaced. The 
view (QTableView) is notified about this by signals. The current index 
and selections are therefore lost.

>> It sounds like you are using OnFieldChange or OnRowChange strategy. This is
>> by design. The deleted row remains in the cache until select() is called
>> again.
> I see. Is there any possibility to update the model (so the row is removed in
> the view, not just cleared out) without 'resetting' the model using select()?
>
> I just want to have the row deleted (yes, at the cost of losing navigation and
> selection in the view), but without having to repopulate the data from the
> database (which is implied by select()).

If you just want the Qt 4 behavior, then you should just use select() 
like it does.

You might also consider using QSortFilterProxyModel to hide the deleted 
rows.

Now, what you are asking for is a way to make QSqlTableModel remove 
model rows corresponding to submitted DELETEs. There are some things to 
consider.

First of all, there is no guarantee that a record is deleted in the 
database afterwards, perhaps because a foreign key prevents it, a 
database trigger reinterprets the DELETE, or another user puts the 
record back. If the row were removed from the model, the user would have 
no way to see what the actual status of the record is.

We could consider removing the row from the model only after verifying 
that the corresponding record no longer exists in the database table. 
This is a possibility, but it would complicate the mapping between the 
query result set and the table model. Also, it removes information from 
the model about what has been done to the records returned by the last 
select(). If we were to add this, I think it should be an option. What 
do you think? If you would like to pursue this, could you follow this up 
with a feature request at http://bugreports.qt-project.org?

>>> Inserations for example using insertRecord() are not reflected as well
>>> (no visible changes in the view, although data is added to the table).
>> This is not the expected behavior and I cannot reproduce it. Can you provide
>> an example?
> I tried to boil down the code to a simple example and I now can nail down the
> problem. It only affects tables having an AUTOINCREMENT primary key, causing
> an empty row to be inserted (with an exclamation mark in the view, same as
> for a deleted row) and a select() is required to get the actual data
> into the view
> (and obviously the model as well).
>
> Tables having a primary key not beeing AUTOINCREMENT (although they are
> set by the database as well) seem to be not effected (data is shown
> immediately).

That's interesting. When the model refreshes the affected row after 
submitting changes, it uses the primary key values of the record to get 
the changes from the database table. It obviously doesn't have the key 
values for AUTOINCREMENT. Sound likes a bug. Maybe it can be solved at 
least partly by getting the inserted IDs in these cases. Could you 
please make a bug for this on http://bugreports.qt-project.org?

regards,

Mark





More information about the Development mailing list