c++qtdelegatesqcomboboxmodel-view

QComboBox not calling Delegate methods


I want to customize a QComboBox by inserting QWidgets (instead of strings) through a model and a delegate:

QComboBox *cb = new QComboBox(this);

FeatureModel *featureModel = new FeatureModel(cb);
cb->setModel(featureModel);

ComboBoxItemDelegate *comboBoxItemDelegate = new ComboBoxItemDelegate(cb);
cb->setItemDelegate(comboBoxItemDelegate);

FeatureModel inherits from QAbstractListModel and ComboBoxItemDelegate inherits from QStyledItemDelegate.

The problem is that the delegates methods are never called and therefore my custom widget is not inserted (I only see the strings of the FeatureModel). However, if I use a QTableView instead of a QComboBox, it works as it should.

Does someone know where the error lies? Am I missing some important aspect of the QT Model/View concept?

EDIT: Here is my Delegate. Except of the constructor (of course), none of the following methods are called (no ouput on the console).

ComboBoxItemDelegate::ComboBoxItemDelegate(QObject *parent) :
QStyledItemDelegate(parent)
{
    qDebug() << "Constructor ComboBoxItemDelegate";
}

ComboBoxItemDelegate::~ComboBoxItemDelegate()
{
}

QWidget* ComboBoxItemDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
    qDebug() << "createEditor"; // never called
    QWidget *widget = new QWidget(parent);

    Ui::ComboBoxItem cbi;
    cbi.setupUi(widget);

    cbi.label->setText(index.data().toString());
    widget->show();

    return widget;
}


void ComboBoxItemDelegate::setEditorData ( QWidget *editor, const QModelIndex &index ) const
{
    qDebug() << "setEditorData"; // never called
}


void ComboBoxItemDelegate::setModelData ( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
{
    qDebug() << "setModelData"; // never called
}

Solution

  • I think I found the problem.

    First, make sure the view in the QComboBox allows editing:

    cb->view()->setEditTriggers(QAbstractItemView::AllEditTriggers);
    

    I'm not sure if that's a good practice, but that was the only way I could make it work. The default value for editTriggers is QAbstractItemView::NoEditTriggers

    Second, make sure your model allows editing:

    Qt::ItemFlags MyModel::flags(const QModelIndex &index) const
    {
        if (!index.isValid())
            return Qt::ItemIsEnabled;
    
        return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
    }
    
    bool MyModel::setData(const QModelIndex &index,
                               const QVariant &value, int role)
    {
        if (index.isValid() && role == Qt::EditRole) {
            // Modify data..
    
            emit dataChanged(index, index);
            return true;
        }
        return false;
    }
    

    It has a problem, though. The first time you see the ComboBox, you can change the current item text, and it won't call the delegate methods for editing. You have to select one item and then you'll be able to edit it.

    Anyway, I find that using a QComboBox for editable items is counter-intuitive. Are you sure that you need a QComboBox for this task?

    Hope it helps