Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-interest Archive, March 2008
QDataWidgetMapper and invalid indexes


Message 1 in thread

Hi,

I have a database aware form, that shows the content of a single row from a 
database table in a form. I use QDataWidgetMapper to map a 
QSqlRelationalTableModel to the widgets in the form, and have the edit policy 
to OnFieldChange. This works fine... for exactly one commit(). After the any 
field on the form is changed/tabbed out of, no  further changes are committed 
to the database. After a lot of debugging, I tracked it down to the fact that 
commit() invalidates any QSqlIndex that might be pointing at it,which means 
all calls to commit fails in QDataWidgetMapperPrivate::commit(const 
WidgetMapper&) because the model's current index is no longer valid. 

So I am not sure what to do here. One solution would be to have the 
QDataWidgetMapper to reset the current index whenever the closeEditor() 
signal is emitted (from QItemDelegate::eventFilter()). This works, but is 
hardly elegant! For one thing, the index is reset a lot more than strictly 
neccessary. Is this really the way to do it? It seems to me (at least) that 
it is quite seldom that you want to have a form where only one field can be 
changed, yet this seems the default behaviour. 

Advice?

(Using qt 4.3.2. opensource edition on linux(ubuntu), if that matters).

-- 
 [ signature omitted ] 

Message 2 in thread

On Tuesday 04 March 2008 21:43:18 Esben Mose Hansen wrote:
> Hi,
>
> I have a database aware form, that shows the content of a single row from a
> database table in a form. I use QDataWidgetMapper to map a
> QSqlRelationalTableModel to the widgets in the form, and have the edit
> policy to OnFieldChange. This works fine... for exactly one commit(). After
> the any field on the form is changed/tabbed out of, no  further changes are
> committed to the database. After a lot of debugging, I tracked it down to
> the fact that commit() invalidates any QSqlIndex that might be pointing at
> it,which means all calls to commit fails in
> QDataWidgetMapperPrivate::commit(const WidgetMapper&) because the model's
> current index is no longer valid.
>
> So I am not sure what to do here. One solution would be to have the
> QDataWidgetMapper to reset the current index whenever the closeEditor()
> signal is emitted (from QItemDelegate::eventFilter()). This works, but is
> hardly elegant! For one thing, the index is reset a lot more than strictly
> neccessary. Is this really the way to do it? It seems to me (at least) that
> it is quite seldom that you want to have a form where only one field can be
> changed, yet this seems the default behaviour.
>
> Advice?
>
> (Using qt 4.3.2. opensource edition on linux(ubuntu), if that matters).

Since noone was able to help me, perhaps I should record to any followers my 
finding so far:

To make QWidgetMapper work with an QSqlTableModel, you need to avoid using 
editpolicy onFieldChange. That editpolicy kindly invalidates every index 
whenever anything is submitted. That means that if you call 
QWidgetMapper::submit(), only the first widget will be commited, the rest 
will fail since the index is now invalid. Nice :o) It's a good thing I had 
the source code, many thanks to the trolls for making Qt open source!

Using QWidgetMapper AutoSubmit is still beyond me. It seems to me the row is 
never changed now or something like that. But it can work using 
OnManualSubmit, if you then connect the mapper->itemDelegate's signal 
commitData(QWidget) to a slot that does 2 things in order:
calls the QWidgetMapper->submit(), and then reset the current index. You can 
get the current index before calling submit, so you don't have to store it. 

I still find it extremely puzzling why this is not the default behaviour, but 
at least it works this way. 

-- 
 [ signature omitted ]