Reputation: 31
So I'm building the books example in the Qt documentation, and I can't get editing to work using combo boxes. Basically, I have a QSqlRelationalTableModel mapped to a QTableView, and to several other controls (one of which is a combo box) through a QDataWidgetMapper. Both the table view and the mapper are using a default QSqlRelationalDelegate. The default delegate enables editing, even for fields that are foreign keys into other tables - it creates a combo box right there on the table.
I can edit anything I want in the table, and it works just fine. I can also make edits using the controls mapped through the widget mapper, except with the combo box. The combo box populates correctly, and updates correctly when I change my selection in the table, but changing it's value has no effect on the model. However making edits directly in the table (using the combo box created by QSqlRelationalDelegate) does work.
From reading the examples and documentation, it seems like this should work. I've even tried implementing a custom delegate, however it's setModelData() method never even gets called when making changes to the combo box (why not?).
Has anyone else had this problem? How did you solve it? I feel like I must be missing something obvious. Relevant sections of code below:
# Create the model
self.model = QSqlRelationTableModel(self.tableView)
self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
self.model.setTable('products')
categoryIdx = self.model.fieldIndex('category')
# Set the relation for the category field
self.model.setRelation(categoryIdx, QSqlRelation('categories', 'id', 'name'))
# Populate the model
self.model.select()
# Connect the model and the table
self.tableView.setModel(self.model)
self.tableView.setItemDelegate(QSqlRelationalDelegate(self))
# Set up the controls
self.categoryBox.setModel(self.model.relationModel(categoryIdx))
self.categoryBox.setModelColumn(self.model.relationModel(categoryIdx).fieldIndex('name')
mapper = QDataWidgetMapper(self)
mapper.setModel(self.model)
mapper.setItemDelegate(QSqlRelationalDelegate(self))
mapper.addMapping(self.categoryBox, categoryIdx)
... # Add mappings to the other controls
mapper.setSubmitPolicy(QDataWidgetMapper.AutoSubmit)
self.tableView.selectionModel().currentRowChanged.connect(mapper.setCurrentModelIndex)
I've even tried specifying the currentIndex property like so:
mapper.addMapping(self.categoryBox, categoryIdx, 'currentIndex')
but that doesn't work either. I'm using PyQt5, FWIW.
Upvotes: 3
Views: 1579
Reputation: 10154
Set the QComboBox focusPolicy to ClickFocus or StrongFocus (Qt Designer or in code)
widget.setFocusPolicy(Qt.StrongFocus)
Upvotes: 0
Reputation: 8634
Many thanks Garrett and Georg Schölly for these posts! I ran into the same issue as well, and could resolve it with your answers. In my case I've made a QDataWidgetMapper
subclass that makes the required signal-slot connection automatically:
class DataWidgetMapper(QDataWidgetMapper):
def addMapping(self, widget, section, propertyName=None):
if propertyName is None:
super().addMapping(widget, section)
else:
super().addMapping(widget, section, propertyName)
if isinstance(widget, QComboBox):
delegate = self.itemDelegate()
widget.currentIndexChanged.connect(lambda: delegate.commitData.emit(widget))
Upvotes: 3