PDA

View Full Version : QSortFilterProxyModel trouble when inserting row



saknopper
4th February 2007, 16:58
Hi all,

I'm having trouble using a proxy model in a tableview, everything was just fine when is used the qsqltablemodel directly. Though, using a proxy model, there are some issues.

When I'm adding a row (code below) and edit the row which just has been added, the proxy model takes care of sorting the items again. This causes an empty row to appear, at the position at which the row was initially inserted.

When I restart the application or manually set the model again in the tableview, it shows the items correctly again.



int row = 0;
model->insertRow(row);
QModelIndex index = model->index(row, 1);

countriesView->setCurrentIndex(index);
countriesView->edit(index);


model = QSortFilterProxyModel
countriesView = QTableView

Like I said, it used to work perfectly when model is an QSqlTableModel.

jpn
4th February 2007, 20:11
Sounds like the dynamic sorting causes that the edited model index is actually something different than the inserted one. I think you should add the row into the actual model and then use QAbstractProxyModel::mapFromSource() to get the correct model index.

saknopper
5th February 2007, 10:15
Thanks for your suggestion jpn, though it didn't work out as expected unfortunately.

I currently use the following code instead of the code above to create a new row:



int row = 0;
model->sourceModel()->insertRow(row);
QModelIndex index = model->sourceModel()->index(row, 1);


As you can see, I don't call edit() to enable the user to edit the field right away. So after adding a new row an empty row appears in the tableview, which can be edited when you double click on it. This itself works flawless, though when you're done editing and press enter to save the value it still adds an empty row at the top of the tableview. The table view is sorted correctly though.

I hope you haven't run out of suggestions yet... :rolleyes:

jpn
5th February 2007, 11:45
Does this work as desired? Which exact version of Qt are you using?

PS. Rows and columns can be added through the context menu..

saknopper
5th February 2007, 12:10
Yes, it works perfectly.

I'm using Qt 4.2.2

saknopper
5th February 2007, 12:21
It's weird that when I calculate the position of the to be inserted row with model->rowCount() and then call insertRow() at that position. It still adds the row at the top of the table. While in your example in inserts the row at the bottom.

jpn
5th February 2007, 12:22
Hmm, so maybe it happens only when using QSortFilterProxyModel + QSqlTableModel?

saknopper
5th February 2007, 12:27
Perhaps... If that would be true, is there a way I can work around this problem that you know of?

jpn
5th February 2007, 13:01
Could you, by any chance, prepare a minimal example reproducing the problem we could play with? :) You could for example modify the earlier example of mine to use an SQLite db or so..

wysota
5th February 2007, 13:02
Can you provide a minimal compilable example reproducing the problem? I'd like to take a look...

saknopper
5th February 2007, 13:03
Sure, I'll do that.

saknopper
5th February 2007, 13:34
I made an example with an in memory sqlite database for you, it illustrates the problem very clearly (in my opinion).

Some steps to reproduce the problem:

1) Sort on country (instead of id)
2) Add a new row
3) Enter for example "Italy" in the textbox
4) Press enter

The view resorts itself, but there's an empty row at the top.

Let me know if I can help you any further.

Thanks for looking into it.

wysota
5th February 2007, 14:13
Looks like the edit call causes the malfunction, probably because the "id" field is set to "0" instead of the proper index.

I changed the addRow() method and it works fine now:

void Table::addRow()
{
int row = proxyModel->sourceModel()->rowCount();
proxyModel->sourceModel()->insertRow(row);
QModelIndex idx = proxyModel->sourceModel()->index(row, 1);
if (idx.isValid())
{
proxyModel->sourceModel()->setData(idx.sibling(idx.row(), 0), row); // added here
idx = proxyModel->mapFromSource(idx);
setCurrentIndex(idx);
edit(idx);
}
}

saknopper
5th February 2007, 17:00
I'll check it out when I get home, thanks for helping!

saknopper
6th February 2007, 13:37
It's weird, but your solution which worked for you doesn't work for me.

When I add your line of code to the example program and add a new country the id gets set immediately with a value that's already present in de database. After editing the table doesn't get sorted either.

Are you also using Qt 4.2.2 with sqlite3?

wysota
6th February 2007, 13:41
When I add your line of code to the example program and add a new country the id gets set immediately with a value that's already present in de database. After editing the table doesn't get sorted either.
Try replacing the whole slot as I also changed the model calls to reference the source model everywhere. Also try moving the setData call out of the if statement - that was where I placed it at first. There shouldn't be any difference but who knows...


Are you also using Qt 4.2.2 with sqlite3?

I'm using 4.2.0 here, but that shouldn't matter.

jpn
6th February 2007, 13:42
I would have though that setting the column as "auto increment" could have solved the problem but seems not.. :)

saknopper
6th February 2007, 13:52
Try replacing the whole slot as I also changed the model calls to reference the source model everywhere. Also try moving the setData call out of the if statement - that was where I placed it at first. There shouldn't be any difference but who knows...


Waarrghhh, I'm going crazy. Still the same. I copy -> pasted the whole function and also placed the setData call out of the if statement. No changes though.

And indeed, adding AUTOINCREMENT doesn't solve it either.

wysota
6th February 2007, 14:06
I tested against Qt4.2.2. Looks like it works if you set an id which is already there (row), but doesn't if you pass a correct one (row+1). Anyway this is just cased by the way the sqltablemodel works. The proxy is just confused because the index changes. Reseting the model should help, but you'll lose selection and position of the view as it will also be reset.