PDA

View Full Version : QComboBox::insertItem() not honoring id?



mikro
4th October 2006, 15:57
hi,
The Manual tells us:


void QComboBox::insertItem ( int index, const QString & text, const QVariant & userData = QVariant() )
Inserts the text and userData into the combobox at the given index.

therefore i would expect QCombobox to honor the ids i give it? Please see attached mini-project: it does not. (at least not Version 4.1.4 on Windows XP)
Is this normal? Is there a different Result on different Computers?

jpn
4th October 2006, 16:13
You cannot insert an item at index 4 to an empty combo box. It will end up being at index 0 because the combo box was empty before inserting. If you already had items in the combo box, you could insert in between those items.

mikro
4th October 2006, 16:42
great - that means i will have go through 6.000 lines of code hoping to find any instance of where i had expected this to work (unfortunately i usually didn't have a chance to see that it behaved differently, as most of my tables happened to be sorted the way i wanted the output in the ComboBox to be sorted.
Couldn't they have possibly said
Inserts the text and userData into the combobox at the given index if by some happy chance every id smaller is allready present

jpn
4th October 2006, 16:50
Huh, how would you expect it to work then? If you'd insert item at index 55, what would you expect there to be at indexes between 0 and 54? Do you really think that QComboBox should insert some 55 "empty" items there or what?

mikro
4th October 2006, 16:53
also the result is inconsistent:

void MainWindow::fillCombo() {
comboBox->insertItem(4,"Four"); // lands on 0
comboBox->insertItem(2,"Two"); // lands on 2
comboBox->insertItem(1,"One"); // lands on 1
comboBox->insertItem(3,"Three");// lands on 3
comboBox->insertItem(5,"Five"); // lands on 4
}
so "Four" will land on 0 because there is none before. But why then does "Two" manage to be on key 2 and not on 1?
For me this does look as if they are actually trying to do as they say in the manual, but don't succeed. So i'd say it's a bug and at least people should be warned.

jpn
4th October 2006, 16:59
But why then does "Two" manage to be on key 2 and not on 1?
Because you insert an item at index 1 afterwards.


For me this does look as if they are actually trying to do as they say in the manual, but don't succeed. So i'd say it's a bug and at least people should be warned.
Sorry.. but it's not a bug. :)

wysota
4th October 2006, 17:08
so "Four" will land on 0 because there is none before. But why then does "Two" manage to be on key 2 and not on 1?
Oh, that's simple, look:


comboBox->insertItem(4,"Four");
0: Four


comboBox->insertItem(2,"Two");
0: Four
1: Two


comboBox->insertItem(1,"One");
0: Four
1: One (the item gets inserted inbetween Four and Two)
2: Two


comboBox->insertItem(3,"Three");
0: Four
1: One
2: Two
3: Three


comboBox->insertItem(5,"Five");
0: Four
1: One
2: Two
3: Three
4: Five


For me this does look as if they are actually trying to do as they say in the manual, but don't succeed.
They do, and they do succeed.


So i'd say it's a bug and at least people should be warned.
As you see it is not a bug, but a misjudgement or misunderstanding on your side :)

BTW. It's an index, not an id.

mikro
5th October 2006, 10:04
ok, thank you. i understand why this happens now. And yes, i also understand why this is a sensible behaviour for a normal combobox.
nevertheless, when i use a combobox to work with data from the database this is not the behaviour i need. So i subclassed QComboBox, added some QMaps to hold the relation between row (their index) and id (my database-id) and rewrote some of the QComboBox-functions to use those maps before calling the original functions. Now my little testapp works the way i want it :cool:
i really think that this is a practical approach, especially considering the new QDataWidgetMapper in Qt 4.2.0: if i want to directly connect a combobox to my database-model i just can't work with a combobox that will return it's own linenumbers instead of my database-ids.
if anybody sees any problems in that code i'd be happy with some corrections. especially i did not understand how to implement the destructor. Trying to call ~QComboBox() always gave me an errormessage that QComboBox() could not be found but there would be a ~QComboBox() available :confused:

wysota
5th October 2006, 11:56
I think you can avoid additional code by assuming that the combobox returns the row number from the model and then you can query the model to return proper data according to the index (be it an id, name or whatever column/role from the model you want).


int in = combobox->currentIndex();
QModelIndex index = model->index(in, 0 /* id column */);
quint32 id = model->data(index, Qt::DisplayRole).toUInt();

mikro
5th October 2006, 13:34
i doubt that. Admittedly it would work as you said, but still that would require using a model for every single combobox i use, instead of being able to simply fill the combobox directly. And it would make it impossible to use the nice QDataWidgetMapper they have intro'd in 4.2.0

imagine a table
persons:
idm | name | occupation
0 | mike | 1
1 | hans | 4
2 | achim | 1

and a second table occupations:
ido | name
1 | civil engineer
4 | administrator
(numbers 2 and 3 have been deleted at some time)

now imagine creating a widget that you want to use with QDataWidgetMapper to work on persons. You will probably have a simple lineedit for the persons'name and a combobox for the occupation. now i can fill the combobox:

do a "select * from occupation order by name"
this will output
4 | administrator
1 | civil engineer
and i can simply do a
while (query.next()) {
comboBox->insertItem(query.value(0).toInt(),query.value(1).t oString());
}

and the QDataWidgetMapper can use all the usual QComboBox::setCurrentIndex() etc.. never even knowing that it is not directly accessing the rownumbers within the combobox but actually getting the ids from my database as it should.

I'd say this is the ONLY way to map this using QDataWidgetMapper, and well, probably the code i produced is quite ugly, but i'd say it's neat :)

wysota
5th October 2006, 13:52
I don't really see the point. Neither QDataWidgetMapper nor QComboBox (nor any other widget) is a panaceum to all problems. I just said that if you already have a model, you don't need any additional structures or code to map between combobox indexes and the contents of the model. The combobox displays data from some model, doesn't it(To tell the truth, each combobox has its own mini-model embedded inside it, so you are using a model for every combobox and I don't see why you shouldn't take advantage of that anyway)? So you don't need any separate models, you only need to know, which column from the model the combobox uses.