Skinkie
Skinkie

Reputation: 23

How does any value from a QDataWidgetMapper get delegated (for example) on a QtComboBox?

I am trying to understand a very specific concept where values available from a model, are made available towards widgets. A specific widget that would require some internal lookups is QComboBox.

QDataWidgetMapper adds a QComboBox towards an index in a model via "addMapping", specific properties can be set too. The most naive method "just works" if the text is present in the values within the QComboBox. Under the hood there is likely some QItemDelegate that does the magic where the model can have a plain string, and the QComboBox would correctly select the right item.

I am trying to find the actual implementation in C++. I would expect it would happen as the QComboBoxDelegate, but nothing there suggest that any index lookup is done. In the super class QStyledItemDelegate hints setEditorData with editor->setProperty(n, v) is used. Is from that point on setCurrentText just called? Is editor->metaObject()->userProperty().name(); working due to Q_PROPERTY(QString currentText READ currentText WRITE setCurrentText NOTIFY currentTextChanged USER true)?

QStyledItemDelegate: commit QComboBox value to model on click QDataWidgetMapper ignoring inheritance

Upvotes: 0

Views: 51

Answers (1)

musicamante
musicamante

Reputation: 48444

When a new QDataWidgetMapper instance is created, it internally creates and sets a basic QItemDelegate as its initial delegate[1].

There are two ways to use addMapping(): by using the widget and section, or by also providing a property name specific to that widget.

When the widgets are being updated[2] only the widget and section are used for addMapping(), QDataWidgetMapper calls setEditorData() on the delegate:

The default implementation stores the data in the editor widget's user property.

The USER property of QComboBox is, indeed, the currentText[3]:

The setter setCurrentText() simply calls setEditText() if the combo box is editable. Otherwise, if there is a matching text in the list, currentIndex is set to the corresponding index.

If you need finer control over the behavior of the mapper with a combo box, you have different possibilities:

  • create a custom USER property (the last declared user property is always considered the actual one);
  • set another property (even a custom one) and provide its name in the other addMapping() overload; in this case, Qt will simply call setProperty() on the widget with the given property name;
  • use a custom QItemDelegate, then override setEditorData() and, possibly, setModelData();

Note that, for the third choice, the basic QItemDelegate (or even QAbstractItemDelegate) should suffice. For some reason, Qt6 uses QStyledItemDelegate instead.

[1] See the constructor in qdatawidgetmapper.cpp (Qt5 sources, codebrowser.dev).
[2] See the populate() function in the same code (Qt, codebrowser).
[3] Sets the text on the line edit if the combo is editable, otherwise use findText() and eventually setCurrentIndex() if the index is >= 0.

Upvotes: 0

Related Questions