QDataWidgetMapper addMapping to propertyName
-
Im using pyside6, but I'm referencing these c++ docs and example
https://doc.qt.io/qt-6/qdatawidgetmapper.html#addMapping-1
https://doc.qt.io/qt-6/qtwidgets-itemviews-combowidgetmapper-example.htmlI've ported the above c++ example to python/pyside. What I don't understand is how is the addMapping working under the hood in regard to referncing the combobox's currentIndex property?
self.mapper.addMapping(self.typeComboBox, 2, QByteArray("currentIndex"))
I understand you can use .currentIndex to retrieve the selected combo item for saving to the model, but I don't understand the mechanism that allows the mapper to know what combbox item to select/present as the mapper moves through the main model.
Finally, if I were to subclass combobox how exactly would I define my own property that I could utilize with mapper.addMapping?
import sys from PySide6.QtCore import QStringListModel, QByteArray from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QLabel,\ QLineEdit, QTextEdit, QComboBox, QPushButton, QDataWidgetMapper, QGridLayout from PySide6.QtGui import QStandardItemModel, QStandardItem class MyCombo(QComboBox): def __init__(self, parent=None): super().__init__(parent=parent) def xyz(self): print("xyz called") return self.currentIndex() + 1 def setXyz(self): print("setter was called") class MyWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.setupModel() self.nameLabel = QLabel("Na&me:") self.nameEdit = QLineEdit() self.addressLabel = QLabel("&Address:") self.addressEdit = QTextEdit() self.typeLabel = QLabel("&Type:", ) self.typeComboBox = QComboBox() self.nextButton = QPushButton("&Next") self.previousButton = QPushButton("&Previous") self.nameLabel.setBuddy(self.nameEdit) self.addressLabel.setBuddy(self.addressEdit) self.typeLabel.setBuddy(self.typeComboBox) self.typeComboBox.setModel(self.typeModel) self.mapper = QDataWidgetMapper(self) self.mapper.setModel(self.model) self.mapper.addMapping(self.nameEdit, 0) self.mapper.addMapping(self.addressEdit, 1) self.mapper.addMapping(self.typeComboBox, 2, QByteArray("currentIndex")) #self.mapper.addMapping(self.typeComboBox, 2, QByteArray("xyz")) self.previousButton.clicked.connect(self.mapper.toPrevious) self.nextButton.clicked.connect(self.mapper.toNext) self.mapper.currentIndexChanged.connect(self.updateButtons) self.layout = QGridLayout() self.layout.addWidget(self.nameLabel, 0, 0, 1, 1) self.layout.addWidget(self.nameEdit, 0, 1, 1, 1) self.layout.addWidget(self.previousButton, 0, 2, 1, 1) self.layout.addWidget(self.addressLabel, 1, 0, 1, 1) self.layout.addWidget(self.addressEdit, 1, 1, 2, 1) self.layout.addWidget(self.nextButton, 1, 2, 1, 1) self.layout.addWidget(self.typeLabel, 3, 0, 1, 1) self.layout.addWidget(self.typeComboBox, 3, 1, 1, 1) self.centralWidget = QWidget(self) self.centralWidget.setLayout(self.layout) self.setCentralWidget(self.centralWidget) self.setWindowTitle("Delegate Widget Mapper") self.mapper.toFirst() def updateButtons(self, row): self.previousButton.setEnabled(row > 0) self.nextButton.setEnabled(row < self.model.rowCount()) def setupModel(self): items = ["Home", "Work", "Other"] self.typeModel = QStringListModel(items) self.model = QStandardItemModel(5, 3, self) names = ["Alice", "Bob", "Carol", "Donald", "Emma"] addresses = ["<qt>123 Main Street<br/>Market Town</qt>", "<qt>PO Box 32<br/>Mail Handling Service", "<br/>Service City</qt>", "<qt>The Lighthouse<br/>Remote Island</qt>", "<qt>47338 Park Avenue<br/>Big City</qt>", "<qt>Research Station<br/>Base Camp<br/>Big Mountain</qt>"] types = ["0", "1", "2", "0", "2"] for row in range(5): item = QStandardItem(names[row]) self.model.setItem(row, 0, item) item = QStandardItem(addresses[row]) self.model.setItem(row, 1, item) item = QStandardItem(types[row]) self.model.setItem(row, 2, item) if __name__ == '__main__': app = QApplication() win = MyWindow() win.show() sys.exit(app.exec())
-
Okay, I think I've figured it out. I remember the docs mentioned 'user property' but I glossed over it. Turns out I didn't understand what a QtCore.Property was.
Here's relevant docs: https://doc-snapshots.qt.io/qtforpython-dev/PySide6/QtCore/Property.html
Here's a working subclassed combo example that uses a custom property.from PySide6.QtCore import Property from PySide6.QtWidgets import QComboBox class MyCombo(QComboBox): def __init__(self, parent=None): super().__init__(parent=parent) def readXyz(self): print("read xyz called") return self.currentIndex() def setXyz(self, i): print("set xyz called") self.setCurrentIndex(i) xyz = Property(int, readXyz, setXyz)
Or a more pythonic(?) version of property getters and setters that I'm used to:
from PySide6.QtCore import Property from PySide6.QtWidgets import QComboBox class MyCombo(QComboBox): @Property(int) def xyz(self): print("read xyz called") return self.currentIndex() @xyz.setter def xyz(self, i): print("set xyz called") self.setCurrentIndex(i)
-