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

Qt-interest Archive, April 2007
QSqlTableModel


Message 1 in thread

hello all

do you know about any workaround for this, please?
http://www.trolltech.com/developer/task-tracker/index_html?method=entry&id=153785

BTW I'm testing my app with Qt4.3beta. I have QSqlTableModel in the
OnManualSubmit mode. But when I call removeRows() I don't get a "!" mark in
the row Header. When I call insertRows() in the same transaction the "!"
appears in the correct place.

Any advices?

all the best
Petr Vanek

--
 [ signature omitted ] 

Message 2 in thread

Petr Vanek wrote:

> hello all
> 
> do you know about any workaround for this, please?
>
http://www.trolltech.com/developer/task-tracker/index_html?method=entry&id=153785
> 
> BTW I'm testing my app with Qt4.3beta. I have QSqlTableModel in the
> OnManualSubmit mode. But when I call removeRows() I don't get a "!" mark
> in the row Header. When I call insertRows() in the same transaction the
> "!" appears in the correct place.
> 
> Any advices?

A few, fortunately.
It seems that removeRows (as implemented in QSqlTableModel up to 4.2.3) does
not emit a dataChanged signal, so the view is never told something changed
in the model.
Other submit policies call select() at the end of removeRows(), which will
immediately result in updating the table. It seems that OnManualSubmit was
kind of forgotten.

A workaround is of course to subclass QSqlTableModel and reimplement
removeRows():

bool SubClassedModel::removeRows( int row, int count, const QModelIndex&
parent )
{
        bool returnValue = QSqlTableModel::removeRows( row, count, parent );
        emit dataChanged( index( row, 0 ), index( row+count-1, columnCount()-1 ) );
        return returnValue;
}

This works for me, but I wonder whether this is a bug (or a feature?).
Surely I do not understand the utility of changing the model but not
telling the view, but maybe there's a good reason (or a kosher way to do it
that does not involve subclassing).

Note that this way only data is updated, you should also emit whatever
signal is there to update the horizontal header.

If you do not emit the signals, the user may make the new values appear by
selecting the record (because the data() function is called, I suppose),
but of course this is not very user-friendly.

To remove the rows immediately I suppose you could define a new signal for
SubClassedModel to connect to QTableView's hideRow slot.

As a side note, you do not get a "!" with insertRows, but a '*'. If you got
a '!' then something's wrong...

Cheers!
-Federico

--
 [ signature omitted ] 

Message 3 in thread

Federico Zenith wrote:
> To remove the rows immediately I suppose you could define a new signal for
> SubClassedModel to connect to QTableView's hideRow slot.

Answering myself, this is not necessary. Just emit beforeDelete(row) in your
reimplementation of removeRows(). It is already connected to QTableView
from the moment you set the model.

Now, why (and how) this works I do not know since I cannot find where this
signal is connected to anything in the Qt source, but somehow it works (in
Qt 4.2.0 at least).

Cheers,
-Federico
(who should really read the docs first and write later)

--
 [ signature omitted ] 

Message 4 in thread

Federico Zenith wrote:
> Answering myself, this is not necessary. Just emit beforeDelete(row) in
> your reimplementation of removeRows(). It is already connected to
> QTableView from the moment you set the model.
> 
> Now, why (and how) this works I do not know since I cannot find where this
> signal is connected to anything in the Qt source, but somehow it works (in
> Qt 4.2.0 at least).

Proceeding this interesting discussion with myself, the reason it worked was
simply that I had connected QSqlTableModel::beforeDelete(int) to
QTableView::hideRow(int) myself to begin with, and forgotten about that
shortly thereafter.

D'oh.

Cheers,
-Federico

--
 [ signature omitted ] 

Message 5 in thread

Federico Zenith wrote:
>> Now, why (and how) this works I do not know since I cannot find where
>> this signal is connected to anything in the Qt source, but somehow it
>> works (in Qt 4.2.0 at least).
> 
> Proceeding this interesting discussion with myself, the reason it worked
> was simply that I had connected QSqlTableModel::beforeDelete(int) to
> QTableView::hideRow(int) myself to begin with, and forgotten about that
> shortly thereafter.

hmm, cool. It's nice to suprise yourself ;)

I've choose a different approach of the row hiding. I mark it with a special
color. You can see it (working finally) in this diff:
http://tools.assembla.com/sqliteman/changeset/149

Anyway - thanks a lot for your help.

I'm still thinking about a bugreport with this issue.

cheers
Petr

--
 [ signature omitted ] 

Message 6 in thread

Petr Vanek wrote:

> Federico Zenith wrote:
>>> Now, why (and how) this works I do not know since I cannot find where
>>> this signal is connected to anything in the Qt source, but somehow it
>>> works (in Qt 4.2.0 at least).
>> 
>> Proceeding this interesting discussion with myself, the reason it worked
>> was simply that I had connected QSqlTableModel::beforeDelete(int) to
>> QTableView::hideRow(int) myself to begin with, and forgotten about that
>> shortly thereafter.
> 
> hmm, cool. It's nice to suprise yourself ;)
> 
> I've choose a different approach of the row hiding. I mark it with a
> special color. You can see it (working finally) in this diff:
> http://tools.assembla.com/sqliteman/changeset/149
> 
> Anyway - thanks a lot for your help.
> 
> I'm still thinking about a bugreport with this issue.

Hi,
I just sent one in. It will probably pop up in the next hours in the
Trolltech task tracker.

Cheers,
-Federico

--
 [ signature omitted ] 

Message 7 in thread

Federico Zenith wrote:
>> I'm still thinking about a bugreport with this issue.
> 
> Hi,
> I just sent one in. It will probably pop up in the next hours in the
> Trolltech task tracker.

For those interested, it has been inserted into the Task Tracker:
http://www.trolltech.com/developer/task-tracker/index_html?id=160135&method=entry

A simple way to reproduce the bug is to add the following code to
examples/sql/tablemodel/tablemodel.cpp:

int rows = QInputDialog::getInteger( 0, "Test", "How many rows", 0, 0, 5 );
model.removeRows(0,rows);

just before app.exec().

Cheers,
-Federico

--
 [ signature omitted ] 

Message 8 in thread

Federico Zenith wrote:
> 
> For those interested, it has been inserted into the Task Tracker:
>
http://www.trolltech.com/developer/task-tracker/index_html?id=160135&method=entry

perfect. I'm looking forward the solution. And I hope it will be before
Qt5.0 ;)

petr

--
 [ signature omitted ] 

Message 9 in thread

hello Frederico,

Federico Zenith wrote:

> It seems that removeRows (as implemented in QSqlTableModel up to 4.2.3)
> does not emit a dataChanged signal, so the view is never told something
> changed in the model.
> Other submit policies call select() at the end of removeRows(), which will
> immediately result in updating the table. It seems that OnManualSubmit was
> kind of forgotten.

agree (after source studying)
>
> A workaround is of course to subclass QSqlTableModel and reimplement
> removeRows():
> 
> bool SubClassedModel::removeRows( int row, int count, const QModelIndex&
> parent )
> {
>         bool returnValue = QSqlTableModel::removeRows( row, count, parent
>         ); emit dataChanged( index( row, 0 ), index( row+count-1,
>         columnCount()-1 ) ); return returnValue;
> }

strange when I use it (in already subclassed model):
...
#include <QtDebug>
bool SqlTableModel::removeRows ( int row, int count, const QModelIndex &
parent)
{
qDebug() << 1;
        m_pending = true;
        bool ret = QSqlTableModel::removeRows(row, count, parent);
        emit dataChanged( index(row, 0), index(row+count-1, columnCount()-1) );
        emit headerDataChanged(Qt::Vertical, row, row+count);
        return ret;
}
...

I get the same behaviour as before - user has to change table cell to
promote the changes. Do you have sample source, please?

> This works for me, but I wonder whether this is a bug (or a feature?).
> Surely I do not understand the utility of changing the model but not
> telling the view, but maybe there's a good reason (or a kosher way to do
> it that does not involve subclassing).

It's a bug IMHO - and I'll report it propably later.

...
> As a side note, you do not get a "!" with insertRows, but a '*'. If you
> got a '!' then something's wrong...

You're right. It was my typo.

all the best
Petr

--
 [ signature omitted ] 

Message 10 in thread

Petr Vanek wrote:
> #include <QtDebug>
> bool SqlTableModel::removeRows ( int row, int count, const QModelIndex &
> parent)
> {
> qDebug() << 1;
>         m_pending = true;
>         bool ret = QSqlTableModel::removeRows(row, count, parent);
>         emit dataChanged( index(row, 0), index(row+count-1,
columnCount()-1) );
>         emit headerDataChanged(Qt::Vertical, row, row+count);

(note: you probably want "...row+count-1);", not that it should crash your
program or anything, but you never know)

>         return ret; 
> }
> ...
> 
> I get the same behaviour as before - user has to change table cell to
> promote the changes. Do you have sample source, please?

Sample source, unfortunately not (that's the problem when working with
closed source...), but can you confirm that you got the qDebug message on
the command line?

I have not overridden the model much more than this function (in any case,
nothing else regarding signals/slots), but it seems to work fine on my
implementation. Did you subclass the view and changed something along the
way maybe? Myself, I am using a plain QTableView.

Cheers,
-Federico

--
 [ signature omitted ]