I would like the edit trigger of one of the columns in my table to create a modal dialog (and then feed the data from the dialog back to the widget/model). Is there a simple way to do that just using the tableWidget/View, or do I have to use a delegate for that?
I currently have a delegate for that, but given the relative simplicity of my table I was wondering it’s overkill and there is a simpler way to achieve this.
Related question: I am creating a QDialog as the editor used by my delegate. It has a confirm and a cancel button. How should I handle the cancel button in my delegate class? Right now I have the cancel button connected to the dialog’s close() method. However when that gets called the setModelData() method on the delegate still gets called. Why is that? Should I connect the cancel button to a method on my delegate that calls self.closeEditor.emit() instead? Or should the setModelData() method validate the status of the dialog to determine whether to set or skip?
This is all new to me so if I’m approaching this the wrong way feel free to point that out as well.
reject works, but when I call reject() in the dialog, setModelData() gets called in the delegate class. Should I check the status of the editor in setModelData and then determine whether to set the data or not, or is there a different approach that won’t trigger setModelData?
it may always call setModelData, with normal controls i don’t think theres a notion of accepted or rejected. For example, if oyu have a string value and the editor is a lineedit, even if you hit escape, it still calls setData on the model. So you should probably see if the dialog result() before calling setData()
dialog.result() returns the same thing when I hit accept or reject.
Here’s a simplified example using a listView. The dialog buttons connect to accept and reject, and the delegate’s setModelData queries the result() of the editor, which is always 0.
EDIT: I ended up just calling setResult() in the dialog before closing it and then checking the result in the delegate. That is working so far.
from PySide import QtCore, QtGui
class TestEditor(QtGui.QDialog):
def __init__(self, parent=None):
super(TestEditor, self).__init__(parent)
self.setModal(True)
self.field = QtGui.QLineEdit()
bLayout = QtGui.QHBoxLayout()
self.okButton = QtGui.QPushButton("Set")
self.cancelButton = QtGui.QPushButton("Cancel")
bLayout.addWidget(self.okButton)
bLayout.addWidget(self.cancelButton)
self.okButton.clicked.connect(self.accept)
self.cancelButton.clicked.connect(self.reject)
layout = QtGui.QVBoxLayout()
layout.addWidget(self.field)
layout.addLayout(bLayout)
self.setLayout(layout)
def showEvent(self, event):
# Show the dialog at the current mouse position
geom = self.frameGeometry()
geom.moveCenter(QtGui.QCursor.pos())
self.setGeometry(geom)
super(TestEditor, self).showEvent(event)
@property
def text(self):
return self.field.text()
class TestDelegate(QtGui.QItemDelegate):
def __init__(self, parent=None):
super(TestDelegate, self).__init__(parent)
def createEditor(self, parent, option, index):
editor = TestEditor(parent)
return editor
def setModelData(self, editor, model, index):
""" Get the data from our custom editor and stuffs it into the model.
"""
print "setModelData editor result: {0}".format(editor.result())
model.setData(index, editor.text)
class TestListModel(QtCore.QAbstractListModel):
def __init__(self, parent=None):
super(TestListModel, self).__init__(parent)
self._data = range(10)
def rowCount(self, parent):
return len(self._data)
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
return self._data[index.row()]
def setData(self, index, value, role=QtCore.Qt.EditRole):
if role == QtCore.Qt.EditRole:
self._data[index.row()] = value
return True
return False
def flags(self, index):
return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
table = QtGui.QListView()
table.show()
table.setItemDelegate(TestDelegate())
model = TestListModel()
table.setModel(model)
sys.exit(app.exec_())