PDA

View Full Version : QComboBox multi-column popup selection quirks [SOLVED]



ChrisW67
23rd January 2011, 23:52
Hi All,

I have a quick question regarding the behaviour of QComboBox with a multi-column QTableView custom view.

I have the combo box set up like this:


TypeModel *model = new TypeModel(this);

QComboBox *combo = new QComboBox(central);
QTableView *view = new QTableView(this);
view->setModel(model);
view->resizeColumnsToContents();
view->resizeRowsToContents();
view->verticalHeader()->setVisible(false);
view->setMinimumWidth(view->horizontalHeader()->length());
view->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded );
view->setSelectionMode(QAbstractItemView::SingleSelectio n);
view->setSelectionBehavior(QAbstractItemView::SelectRows );
view->setAutoScroll(false);

combo->setModel(model);
combo->setModelColumn(0);
combo->setView(view);

TypeModel is a simple table model returning code-meaning pairs. The flags() method looks like:


// column 0 is the code, column 1 is the meaning
Qt::ItemFlags TypeModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags theFlags = QAbstractItemModel::flags(index);
if (index.isValid()) {
theFlags &= ~Qt::ItemIsEditable;
if (index.column() != 0)
theFlags &= ~Qt::ItemIsSelectable;
}
return theFlags;
}

If lines 7 and 8 are as above then the combo pop-up only allows clicking on items in the first column, and the resulting code is displayed in the combo box. If lines 7-8 are omitted then the user can click on either column of the popup but the text of the cell they clicked on, which may be a meaning, is put in the combo box. Setting the model column for the combo box does not change this. In either case the combo box current index is correct.

Is there a way to have the popup clickable anywhere but have the code placed in the combo box?

Regards,
Chris

Full code attached. I am using Qt 4.6.3 on Linux.

saa7_go
24th January 2011, 01:03
In MainWindow constructor you can add:

connect(combo, SIGNAL(currentIndexChanged(int)), combo, SLOT(setCurrentIndex(int)));

ChrisW67
24th January 2011, 01:15
A touch incestuous but it works ;) I was looking at writing a slot to manually do something similar but this is the short version. It still strikes me as odd that the combo box happily displays a value that is not from the model column the combo box is set to use.

Thanks.

wysota
24th January 2011, 01:30
Setting the model column for the combo box does not change this.
Hmm... that's a bit strange since every code path I can see that leads to updating the combo's text goes through this method:


QString QComboBox::itemText(int index) const
{
Q_D(const QComboBox);
QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
return d->itemText(mi);
}

... which would suggest the column model should be respected.

Added after 12 minutes:

I'd say it's a bug in QComboBoxPrivate::setCurrentIndex.

It says:

void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi)
{
Q_Q(QComboBox);
bool indexChanged = (mi != currentIndex);
if (indexChanged)
currentIndex = QPersistentModelIndex(mi);
if (lineEdit) {
QString newText = q->itemText(currentIndex.row());
if (lineEdit->text() != newText)
lineEdit->setText(newText);
updateLineEditGeometry();
}
if (indexChanged) {
q->update();
_q_emitCurrentIndexChanged(currentIndex);
}
}

and should be:

void QComboBoxPrivate::setCurrentIndex(QModelIndex mi)
{
Q_Q(QComboBox);
mi = model->index(mi.row(), modelColumn, mi.parent());
bool indexChanged = (mi != currentIndex);
if (indexChanged)
currentIndex = QPersistentModelIndex(mi);
if (lineEdit) {
QString newText = q->itemText(currentIndex.row());
if (lineEdit->text() != newText)
lineEdit->setText(newText);
updateLineEditGeometry();
}
if (indexChanged) {
q->update();
_q_emitCurrentIndexChanged(currentIndex);
}
}

ChrisW67
24th January 2011, 02:56
Indeed, and someone has beaten us to it: http://bugreports.qt.nokia.com/browse/QTBUG-10491