Simon Hibbs
Simon Hibbs

Reputation: 6211

Displaying QComboBox text rather than index value in QStyledItemDelegate

So I have a model and one of the columns contains a country. However because I want to display a combo box to choose the country from a list of options, I don't store the country name in the model directly. Instead I store an index value into a list of allowable countries. This allows me to use a QComboBox in my form view as recommended in the Qt docs. The problem is I also have a table view, and the table view displays the index integer, not the country name. I have set up a QStyledItemDelegate and implemented createEditor so if you click in the world cell it does pop up the ComboBox, but when you're not editing the country you see the index value.

I'm part way to a solution. I have implemented a paint method to do the work, but it's displaying the value offset to it's proper position and I can't figure out how to get it to display correctly. I think option.rect.topLeft() in the render method is wrong, but I can't figure out how to set the drawing correctly.

def paint(self, painter, option, index):
    if index.column() == COUNTRY:
        painter.save()
        countryRef, ok = inex.data().toInt()
        countryStr = country_list[countryRef]
        widget = QLineEdit()
        widget.setGeometry(option.rect)
        widget.setText(countryStr)
        widget.render(painter, option.rect.topLeft())
        painter.store()
    else:
        QStylyedItemDelegate.paint(self, painter, option, index)

Upvotes: 2

Views: 1832

Answers (1)

Kaleb Pederson
Kaleb Pederson

Reputation: 46469

Models have different item data roles for different data. There's a Qt::DisplayRole, Qt::EditRole, and a Qt::UserRole among others. In this case, you want to display something different than your actual data, so add a new role, let's say Qt::UserRole+1 that's used for your index.

Then you want your delegate to set the appropriate data in setModelData:

def setModelData(self, editor, model, index):
    cbIndex = editor.currentIndex()
    model.setData(index, cbIndex, Qt.UserRole+1)
    # we want a nice displayable though
    model.setData(index, countryIndexToDisplayable(cbIndex), Qt.DisplayRole)

Of course, you'll retrieve the data to set in the editor in a similar fashion:

def setEditorData(self, widget, index):
    widget.setCurrentIndex(index.data(Qt.UserRole+1))

Depending on your model and view, you might be able to use Qt::EditRole which is pretty much intended for that purpose. If you then use a native type for the display role, you shouldn't need to do any custom painting, although you can if you like.

Upvotes: 4

Related Questions