PDA

View Full Version : How to programmatically change the Index of comboBox using QStandardItemModel



Ahmed Abdellatif
31st October 2018, 20:46
How to use the QStandardItemModel :: setData function to set the current value for a combobox that is found in a certain cell for example at index (0,0) and call the ComboBoxItemDelegate :: setModelData function.
I know that ComboBoxItemDelegate :: setModelData function is called when an item is selected from the combo box but my problem is that ComboBoxItemDelegate :: setModelData function is not called by calling the combobox::setData. So i want to call combobox::setData or (any other function that) programatically that will call ComboBoxItemDelegate :: setModelData

d_stranz
2nd November 2018, 16:50
Delegates are used only for editing models from within a view - in other words, it is one way. When editing is finished, the editor (combobox) is destroyed and the view is updated with the text returned by the model using Qt::DisplayRole.

I think what you are asking is "When I double-click on the cell to create the combobox and start editing, how do I set the combobox to the right index, based on the content in the model for that QModelIndex?"

The solution is probably to derive your own QItemDelegate class and override the setEditorData() method. You would call the base class to actually load the strings into the combobox delegate, and then add your own code to set the combobox index to the right value. You can store and retrieve this value in your model using Qt::UserRole.

Ahmed Abdellatif
2nd November 2018, 16:59
first of all thank you for your interest and answering my question. I have got the point. But the part that is not clear for me is the last part that is "You can store and retrieve this value in your model using Qt::UserRole". I do not know what is the benefit from item role?

d_stranz
3rd November 2018, 00:03
I do not know what is the benefit from item role?

Somehow you need to recover the combobox index (an integer) that is associated with the string that is the DisplayRole or EditRole data for the QModelIndex you are about to edit.

One way to do it would be to search the set of strings that are loaded into the combobox (QCombobox::findText()). Another way is to store it in your model as a special integer field that you set when the delegate calls setData() on your model. setData() is going to give you the currently selected string, which you can then convert to the integer. The use of Qt::UserRole is a way for you to store and retrieve this integer easily.



// Method 1: look up the string in the combobox
void MyComboDelegate::setEditorData( QWidget * pEditor, const QModelIndex & index ) const
{
QItemDelegate::setEditorData( pEditor, index ); // use base class to fill the strings

QComboBox * pCombo = qobject_cast< QComboBox * >( pEditor );
if ( pCombo )
{
QString displayStr = index.data( Qt::DisplayRole ).toString();
int selected = pCombo->findText( displayStr );
if ( selected > -1 )
pCombo->setCurrentIndex( selected );
}
}

// Method 2: use Qt::UserRole to store the index in the model
void MyComboDelegate::setEditorData( QWidget * pEditor, const QModelIndex & index ) const
{
QItemDelegate::setEditorData( pEditor, index ); // use base class to fill the strings

QComboBox * pCombo = qobject_cast< QComboBox * >( pEditor );
if ( pCombo )
{
int selected = index.data( Qt::UserRole ).toInt();
if ( selected > -1 )
pCombo->setCurrentIndex( selected );
}
}

void MyComboDelegate::setModelData( QWidget * pEditor, QAbstractItemModel * pModel, const QModelIndex & index ) const
{
QItemDelegate::setModelData( pEditor, pModel, index ); // base class sets Qt::DisplayRole string

QComboBox * pCombo = qobject_cast< QComboBox * >( pEditor );
if ( pCombo )
{
int selected = pCombo->currentIndex();
pModel->setData( index, QVariant( selected ), Qt::UserRole );
}
}


void MyModel::setData( const QModelIndex & index, const QVariant & value, int role )
{
if ( index.column() == 0 && role == Qt::UserRole )
{
int selected = value.toInt();
// store "selected" as a field in your model for that row.
}
else if ( role == Qt::EditRole )
{
// do whatever you would do otherwise to update your model
}
}

QVariant MyModel::data( const QModelIndex & index, int role ) const
{
if ( index.column() == 0 && role == Qt::UserRole )
{
int selected; // retrieve "selected" from the field in your model for that row.
return QVariant( selected );
}
else if ( role == Qt::DisplayRole ) (or EditRole or whatever)
{
// do whatever you would do otherwise to get data from your model
}
}