PDA

View Full Version : Changing index in combobox delegate only calls setModelData after losing focus



Meladi
26th May 2014, 12:53
Hi all, I hope you can help me with this problem.

I have a QTableView in which the first row contains comboboxes (>100). The comboboxes influence the rest of the contents of the QTableView.
I've noticed that the setModelData() method does get called (and the table gets properly updated), but not immediately after selecting a new item from the combobox, but you need to click somewhere else (lose focus) before it gets called. This is quite inconvenient, and I'd like to know how to skip that click.

My comboboxes are made by calling setItemDelegateForRow for the first row of the table. The implementation of createEditor, setEditorData and setModelData is standard. My comboboxdelegate is derived from QStyledItemDelegate. Here is my code from ComboboxDelegate.cpp:


MainComboBoxDelegate::MainComboBoxDelegate(QObject *parent, MainTableListModel *model) : QStyledItemDelegate(parent)
{
m_model = model;
}

QWidget *MainComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & option , const QModelIndex & index) const
{
if(index.row() == 0 && index.column() != 0)
{
QComboBox* editor = new QComboBox(parent);

editor->setModel(m_model);
editor->setEditable(false);
return editor;
}
else
return QStyledItemDelegate::createEditor(parent, option, index);
}

void MainComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if(index.row() == 0)
{
QString temp = index.model()->data(index, Qt::EditRole).toString();
QComboBox *comboBox = static_cast<QComboBox*>(editor);
comboBox->setCurrentIndex(comboBox->findText(temp));
}
}

void MainComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if(index.row() == 0)
{
QComboBox *comboBox = static_cast<QComboBox*>(editor);
QString value = comboBox->currentText();
model->setData(index, value, Qt::EditRole);
}
}

void MainComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}

And this is how I create them in my view class:


ui->Main_Table_View->setItemDelegateForRow(0, new MainComboBoxDelegate(ui->Main_Table_View, Maintablelistmodel));
for(int i = 1; i < Maintablemodel->columnCount(); ++i)
ui->Main_Table_View->openPersistentEditor(Maintablemodel->index(0, i));

The Maintablelistmodel is a QSortFilterProxyModel which contains only one column.
As the comboboxes get created this way, it's hard to pick up signals from them manually, but it may be an option.
Is there something I'm doing wrong, or is it some kind of limitation? Am I missing something?

Any help is highly appreciated.

Zampano
30th May 2014, 10:13
Same problem here:



void PropertyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QVariant value = index.data(Qt::EditRole);
QVariant::Type type = index.data(SensorPropertyModel::PropertyTypeRole). type();

switch(type) {

case QVariant::StringList:
{
QComboBox* comboBox = static_cast<QComboBox*>(editor);
value = index.data(SensorPropertyModel::ListIndexRole);
comboBox->setCurrentIndex(value.toInt());
break;
}

default:
break;
}
}


void PropertyItemDelegate::setModelData(QWidget* editor,
QAbstractItemModel* model,
const QModelIndex& index) const
{
if(!index.isValid()) {
return;
}
QVariant value = index.data(Qt::EditRole);
QVariant::Type type = index.data(SensorPropertyModel::PropertyTypeRole). type();

switch(type) {

case QVariant::StringList:
{
QComboBox* comboBox = static_cast<QComboBox*>(editor);
value = comboBox->currentText();
int nValue = comboBox->currentIndex();
model->setData(index, nValue, SensorPropertyModel::ListIndexRole);
break;
}

default:
break;
}

model->setData(index, value, Qt::EditRole);
}

Any help is appreciated!

Added after 18 minutes:

Found a workaround:


case QVariant::StringList:
{
QComboBox* comboBox = static_cast<QComboBox*>(editor);
value = index.data(SensorPropertyModel::ListIndexRole);
connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
comboBox->setCurrentIndex(value.toInt());
break;
}

Notice the connect-line.


void PropertyItemDelegate::onCurrentIndexChanged(int nIndex)
{
QComboBox* cb = static_cast<QComboBox*>(sender());
if(cb) {
emit commitData(cb);
}
}

See here: http://qt-project.org/forums/viewthread/4531

Meladi
4th June 2014, 09:20
For me this worked too, but I had to put the connect into another method than setModelData, because that method is hit only when you click somewhere outside the combobox - which is part of the problem. Putting it in createEditor or setEditorData works.