4

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
}
Magnus
  • 55
  • 1
  • 6

1 Answers1

4

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

Daniel Castro
  • 1,290
  • 2
  • 11
  • 22
  • Thank you very much! It works now, the methods are being called, the widgets are being created and they also show up in the combobox. Referring to your question: The combobox should hold items that can be deleted by the user by klicking on a pushbutton that belongs to the specific item. Also I am thinking about adding another pushbutton to get some information about the item and a small image which indicates its type. That's why I wanted an additional widget. – Magnus Nov 19 '12 at 19:42
  • It sounds strange, but yes, maybe combobox is the way to go. Glad it worked – Daniel Castro Nov 19 '12 at 19:55