QComboBox delegate question
-
I have a few questions with a custom combobox delegate in a table model. How do you allow the user to only edit certain items and not others based on index? There will be a list of values and certain values are editable and others in the list are not. Combo.setEditable(True) means that any value can be edited. This is what I have so far.
def createEditor(self, parent, option, index): ''' This creates the editors in the delegate. Reimplemented from QAbstractItemDelegate::createEditor(). Returns the widget used to edit the item specified by index for editing. T he parent widget and style option are used to control how the editor widget appears. ''' arcpy.env.workspace = str(self._dbfname).replace(".db", ".gdb") column = index.column() if column == BUFF_DIST: combobox = QtGui.QComboBox(parent) combobox.setEditable(True) combobox.setInsertPolicy(QtGui.QComboBox.InsertAtTop) validator = QtGui.QDoubleValidator(0, 10000000, 10, combobox) validator.setNotation(QtGui.QDoubleValidator.StandardNotation) combobox.lineEdit().setValidator(validator) combobox.addItem("0.00") combobox.setItemData(0,'0.00', QtCore.Qt.DisplayRole) index_path = index.model().index(index.row(), IMPORT_SPATIAL) path = index.model().data(index_path, role = QtCore.Qt.DisplayRole).toString() if path != '': QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) QtGui.QApplication.processEvents() field_list = arcpy.ListFields(str(path)) for field in field_list: if not field.required: if field.type in ["Double", "Interger", "Single"]: if QAQC: print field.name combobox.addItem(field.name) QtGui.QApplication.restoreOverrideCursor() #combobox.lineEdit().returnPressed.connect(self.commitAndCloseEditor) return combobox else: return super(Delegate, self).createEditor(parent, option, index) def setEditorData(self, editor, index): ''' Once the editor has been created and given to the view the view calls setEditorData(). This gives the delegate the opportunity to populate the editor with the current data, ready for the user to edit. Sets the contents of the given editor to the data for the item at the given index. Note that the index contains information about the model being used. The base implementation does nothing. If you want custom editing you will need to reimplement this function. ''' column = index.column() text = index.model().data(index, QtCore.Qt.DisplayRole).toString() if column == BUFF_DIST: #i = editor.findText(text) # if i == -1: # i = 0 #editor.setCurrentIndex(i) editor.setEditText(text) else: return super(Delegate, self).setEditorData(editor, index) def setModelData(self, editor, model, index): ''' Sets the data for the item at the given index in the model to the contents of the given editor. The base implementation does nothing. If you want custom editing you will need to reimplement this function. If the user confirms their edit the editor's data must be written back to the model. The model will then notify the views that the item has changed, and those views that are showing the item will request fresh data to display. In each case we simply retrieve the value from the appropriate editor, and call setData (), passing the values as QVariants. ''' column = index.column() if column == BUFF_DIST: text = editor.currentText() model.setData(index, QtCore.QVariant(text)) editor.insertItem(index.row(),text) else: super(Delegate, self).setModelData(editor, model, index)
-
Hi,
Maybe a silly question but something's not clear, do you want to disable editing of some of your table cells ?
-
How do you support having some items in the combobox be editable and other items in the combobox be not editable based on index? Buffer distance can either be a distance or a field name. This application handles spatial data. Buffer distance can be per polygon. In which case then the user would specify a field name in the shapefile. How do I allow the user not to be able to edit the field names, but be able to edit the distance item. I am using a validator, but the user could change the field name to be a numeric value. How would you prevent that? setReadOnly does not work on individual items.
if column == BUFF_DIST: combobox = QtGui.QComboBox(parent) combobox.setEditable(True) combobox.addItem("0.00") index_path = index.model().index(index.row(), IMPORT_SPATIAL) path = index.model().data(index_path, role = QtCore.Qt.DisplayRole).toString() QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) QtGui.QApplication.processEvents() field_list = arcpy.ListFields(str(path)) for field in field_list: if not field.required: if field.type in ["Double", "Interger", "Single"]: if QAQC: print field.name combobox.addItem(field.name) QtGui.QApplication.restoreOverrideCursor() for i in range(combobox.count()): if combobox.itemText(i).toDouble()[1]: validator = QtGui.QDoubleValidator(0, 1000000000, 10, combobox) validator.setNotation(QtGui.QDoubleValidator.StandardNotation) combobox.lineEdit().setValidator(validator) else: combobox.lineEdit().setReadOnly(True) combobox.lineEdit().returnPressed.connect(self.commitAndCloseEditor) return combobox
-
So If I understand you correctly, you can have two different types on data in the same column ?
-
Yes items in the combobox can be two different types. Some are editable and other items are not. I think I can use combobox.model() and set the items flags for individual items and handle it that way. But it seems that the delegate doesn't recognize the combobox index.
-
It looks like you are trying to solve a complex situation with a much more complex tool. Wouldn't it be simpler and also clearer to rather add a column that lets the user select the type of input he wants to use and then in your other column you'll show him only the data that he needs to have access to ?