[Qt-interest] Custom model and delegate for QComboBox

Wolfgang Pausch wolfgang.pausch at uibk.ac.at
Wed Oct 28 16:53:16 CET 2009


Hello,

sorry for asking again.  I´ve spent several hours trying to figure out where my mistake is, but I didn´t make it work yet :-(

What do I have?
- A QComboBox
- A custom model for the QComboBox
- A custom delegate implementing setEditorData for the QComboBox
- Optionally a QDataWidgetMapper which maps the QComboBox and some other widgets.  (the problem doesn´t disappear if I remove the QComboBox from the mapper).

Am I right that those objects should interact in the following way: 
- The QComboBox has some items
- Each of them corresponds to one QModelIndex in my QComboBox-internal custom model
- The setEditorData method in my QComboBox-internal custom delegate should translate the values from the custom model into the values displayed by the QComboBox
- The mapping enforced by the QDataWidgetMapper at each time only knows about the current item, mapping it to some QModelIndex entry of the model of the widget containing my QComboBox

Problem:
- I see the entries of my custom model 1:1 in the QComboBox, i.e. I see 1, 2, 3.
- My custom delegates setEditorData would translate 1,2,3 into some human readable strings FOO, BAR, etc.
- But it is not called, and I have no idea why not.

What I could debug:
- After setting the delegate, it actually is being set.
- The only setEditorData methods in any *Delegate classes are called from my QDataWidgetMapper during toFirst().  
- However, my problem doesn´t disappear if I remove my QComboBox from the mapper.

Does anyone have some hint for me? 

Thanks,

Wolfgang

On Fri, 23 Oct 2009 15:03:50 +0200
Wolfgang Pausch <wolfgang.pausch at uibk.ac.at> wrote:

> Hello,  
> 
> I am trying to implement a custom model and a custom delegate for a QComboBox.  What I want to do is:
> 
> - the model contains some codes loaded from a datamodel
> - the delegate transforms them into human-readable strings
> 
> However, my implementation so far simply doesn´t call setModelData. It seems to ignore the delegate.  
> Can anyone, based on the code snippets below, give me a hint regarding what is my mistake? 
> Especially: I don´t want to edit anything in my ComboBox, just choose one of several choices.  Am I correct that I only need to overwrite setEditorData?
> 
> Do I have to do something special in order to use this delegate?  Do I have to take care about the view?  Is my assumption correct that once the model is set, it should call the delegate itself, so I don´t have to call some dataChanged signals etc. explicitely in the code below (e.g. in addChoice)?
> 
> I once became problems because I missed a const keyword when overwriting some model method, but as far as I see, the signature of ComboBoxDelegate::setEditorData is correct.  Do you see any problem here?  (if this method would be called anything would be fine).
> 
> Thanks,
> 
> Wolfgang
> 
> Where I set things up:
> 
> QComboBox* MitgliedAttributeWidgetFactory::constructMitgliedsartComboBox(DatabaseContext *databaseContext) {
> 	CodeManager *codeManager = databaseContext->getCodeManager();
> 
> 	ComboBoxModel *model = new ComboBoxModel();
> 	model->addChoice(codeManager, "LANDESVERBAND_ORDENTLICH");
> 	model->addChoice(codeManager, "LANDESVERBAND_AUSSERORDENTLICH");
> 	model->addChoice(codeManager, "LANDESVERBAND_VEREINSMITGLIED");
> 
> 	ComboBoxDelegate *delegate = new ComboBoxDelegate(databaseContext);
> 
> 	QComboBox* mitgliedsartComboBox = new QComboBox();
> 	mitgliedsartComboBox->setItemDelegate(delegate);
> 	mitgliedsartComboBox->setModel(model);
> 	return mitgliedsartComboBox;
> }
> 
> The model:
> 
> class ComboBoxModel : public QAbstractListModel {
> 
> public:
> 	ComboBoxModel();
> 	~ComboBoxModel();
> 
> 	void addChoice(CodeManager *codeManager, QString name);
> 
>     int rowCount(const QModelIndex &parent) const;
>     QVariant data(const QModelIndex &index, int role) const;
> 
> private:
> 	std::vector<CodeValue*> choices;
> 
> };
> 
> ComboBoxModel::ComboBoxModel() {
> 	choices = std::vector<CodeValue*>();
> }
> 
> ComboBoxModel::~ComboBoxModel() {
> 	for (std::vector<CodeValue*>::const_iterator it = choices.begin(); it != choices.end(); it++) {
> 		CodeValue* choice = *it;
> 		delete choice;
> 	}
> }
> 
> void ComboBoxModel::addChoice(CodeManager *codeManager, QString name) {
> 	CodeValue* choice = codeManager->getCodeValueByName(name);
> 	choices.push_back(choice);
> }
> 
> int ComboBoxModel::rowCount(const QModelIndex &parent) const {
> 	return choices.size();
> }
> 
> QVariant ComboBoxModel::data(const QModelIndex &index, int role) const {
>     if (!index.isValid()) {
>         return QVariant();
>     }
> 
>     if (role == Qt::TextAlignmentRole) {
>         return int(Qt::AlignRight | Qt::AlignVCenter);
>     } else if (role == Qt::DisplayRole || role == Qt::EditRole) {
>         int row = index.row();
> 		CodeValue *choice = choices[row];
> 		int choiceId = choice->getId();
> 		return QVariant(choiceId);
>     } else {
>         return QVariant();
>     }
> }
> 
> 
> The delegate:
> 
> class ComboBoxDelegate : public QItemDelegate {
> 	Q_OBJECT
> 
> public:
> 	ComboBoxDelegate(DatabaseContext *ndatabaseContext);
> 	void setEditorData(QWidget *editor, const QModelIndex &index ) const;
> 	void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const;
> 
> private:
> 	DatabaseContext *databaseContext;
> };
> 
> ComboBoxDelegate::ComboBoxDelegate(DatabaseContext *ndatabaseContext) {
> 	databaseContext = ndatabaseContext;
> }
> 
> void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index ) const {
> 	std::cout << "called setEditorData" << std::endl;
> 
> 	QComboBox *comboBox = qobject_cast<QComboBox*>(editor);
> 
> 	const QAbstractItemModel *model = index.model();
> 	QVariant data = model->data(index, Qt::DisplayRole);
> 	bool transformOk;
> 	int codeBehindCombobox = data.toInt(&transformOk);
> 
> 	if (comboBox == NULL) {
> 		std::cerr << "ComboBoxDelegate::setEditorData says: comboBox is NULL.  Maybe this is a bug." << std::endl;
> 	} else if (!transformOk) {
> 		std::cerr << "ComboBoxDelegate::setEditorData says: Value behind comboBox is not an int.  Maybe this is a bug." << std::endl;
> 	} else {
> 		CodeManager *codeManager = databaseContext->getCodeManager();
> 		CodeValue *codeValue = codeManager->getCodeValueById(codeBehindCombobox);
> 
> 		int row = index.row();
> 		int column = index.column();
> 		std::cout << "ComboBoxDelegate::setEditorData called for row " << row << " and column " << column << std::endl;
> 
> 		comboBox->setItemText(row, codeValue->getKurzText());
> 		delete codeValue;
> 	}
> }
> 
> 
> _______________________________________________
> Qt-interest mailing list
> Qt-interest at trolltech.com
> http://lists.trolltech.com/mailman/listinfo/qt-interest




More information about the Qt-interest-old mailing list