PDA

View Full Version : QItemDelegate's QComboBox default value?



jkrienert
28th January 2015, 14:20
Is there a legitimate means of setting a models value via a delegated QComboBox's default value (within a QtableView)?
Upon clicking the ComboBox, the model data is properly registered - but prior to this, the data is empty.

This is because @ the comboBox's creation, the index is effectively '-1' correct?

I have tried to emplace various calls to:
QComboBox.setCurrentIndex(0) within the delegate, but because it has yet to return the editor object to the View, the signal for 'currentIndexChanged' is never called, and thus the data model is never updated.

I suppose I could blunt code editing of the model data from the View class with hard strings for the default values - but I wondered if there was a means of keeping in 'sync' with the comboBox.


[SIDE NOTE: Is it possible to set a stylesheet within the delegate for the combobox? Currently unable to with 'confinedCombo.setStyleSheet(...)']

Thanks.


class quiteANiceView(QtGui.QDialog, QtGui.QWidget):
def __init__(self, iface, editorType, directory, parent=None):
super(shapeCSVeditor, self).__init__(parent)
self.iface = iface
self.interpol = interpol()
self.editorType = editorType
self.directory = directory
self.tableView = QtGui.QTableView(self)
...
if 'Layer-Options' in self.editorType:
self.tableView.setItemDelegateForColumn(1,confineC omboDelegate(self.tableView))
self.tableView.openPersistentEditor(self.tableData .index(row, 1)
...

class confineComboDelegate(QtGui.QItemDelegate):
def __init__(self, parent):
QtGui.QItemDelegate.__init__(self, parent)
def createEditor(self, parent, option, index):
confiningChoices = ['True','False']
confineCombo = QtGui.QComboBox(parent)
confineCombo.addItems(self.confiningChoices)
confineCombo.currentIndexChanged[int].connect(self.currentIndexChanged)
return confineCombo
def setEditorData(self, editor, index):
editor.blockSignals(True)
try: idxConversion = self.confiningChoices.index(index.model().data(ind ex,Qt.DisplayRole))
except: idxConversion = 0
editor.setCurrentIndex(int(idxConversion))
editor.blockSignals(False)
def setModelData(self, editor, model, index):
model.setData(index, self.confiningChoices[editor.currentIndex()],Qt.EditRole)
@QtCore.pyqtSlot(int)
def currentIndexChanged(self):
self.commitData.emit(self.sender())

ChrisW67
28th January 2015, 20:13
If you want to set the opening value in the editor, either from the model's current value or a default value, then you do this in setEditorData() as in your example. After that, there is no connection between the data in the editor and the data in the model until the editor is closed (by leaving the cell etc.) and the setModelData() function is called.

If your model needs to have a default value in a column then the model should probably do that in insertRows(). Failing that, you can probably call setData() from a slot attached to the rowsInserted() signal of the model or, as a last resort, in setModelData() when the existing data is a null QVariant.

jkrienert
29th January 2015, 13:04
then you do this in setEditorData() as in your example.

I am a bit confused of a small aspect of this. Via my example, the try:/except: block sets the index to zero... and while the initial table view displays in accordance with the index setting, the actual value is not emplaced in the data model - as discovered by simply saving the changes immediately after starting the table view (and checking the output file). IF a cell (comboBox) is clicked, then subsequently the unaltered / altered value is properly registered to the data model and observed in the file Output.
(hopefully that made sense).

It seems that another work-around is in order to get the default values to be properly inserted into the dataModel, even if the user does not make an initial selection of the cell (comboBox). My initial actions are warranted based on setModelData not initially being called, so possibly calling it 'manually' upon startup would be a solution? Yet, I am curious as to how the delegate sources the model information - as I get an error with the following (based on the model argument) mainly because I am a bit novice on how to instance the QAbstractTableModel in this circumstance:


class averageComboDelegate(QtGui.QItemDelegate):
def __init__(self, parent):
QtGui.QItemDelegate.__init__(self, parent)
def createEditor(self, parent, option, index):
self.averageChoices = ['Arithmetic','Harmonic','Logarithmic']
averageCombo = QtGui.QComboBox(parent)
averageCombo.addItems(self.averageChoices)
averageCombo.currentIndexChanged[int].connect(self.currentIndexChanged)
return averageCombo
def setEditorData(self, editor, index):
editor.blockSignals(True)
try: idxConversion = self.averageChoices.index(index.model().data(index ,Qt.DisplayRole))
except ValueError: idxConversion = 0
editor.setCurrentIndex(int(idxConversion))
editor.blockSignals(False)
self.setModelData(self,editor,???,index) #<<============================?
def setModelData(self, editor, model, index):
model.setData(index, self.averageChoices[editor.currentIndex()],Qt.EditRole)
@QtCore.pyqtSlot(int)
def currentIndexChanged(self):
self.commitData.emit(self.sender())

Added after 5 minutes:
Also:

When I turn the block off during 'priming' of the comoboBox - the signal to change data is not called, I suspect because this is occurring during the initialization of the widget? (frankly both these links could be omitted if this worked, but this could possibly create an infinite loop correct?)


...
averageCombo.currentIndexChanged[int].connect(self.currentIndexChanged)
return averageCombo
def setEditorData(self, editor, index):
editor.blockSignals(False) #<<=======================Was originally 'True'
try: idxConversion = self.averageChoices.index(index.model().data(index ,Qt.DisplayRole))
except ValueError: idxConversion = 0
editor.setCurrentIndex(int(idxConversion))
editor.blockSignals(False)
def setModelData(self, editor, model, index):
model.setData(index, self.averageChoices[editor.currentIndex()],Qt.EditRole)


then you do this in setEditorData() as in your example.

I am a bit confused of a small aspect of this. Via my example, the try:/except: block sets the index to zero... and while the initial table view displays in accordance with the index setting, the actual value is not emplaced in the data model - as discovered by simply saving the changes immediately after starting the table view (and checking the output file). IF a cell (comboBox) is clicked, then subsequently the unaltered / altered value is properly registered to the data model and observed in the file Output.
(hopefully that made sense).

It seems that another work-around is in order to get the default values to be properly inserted into the dataModel, even if the user does not make an initial selection of the cell (comboBox). My initial actions are warranted based on setModelData not initially being called, so possibly calling it 'manually' upon startup would be a solution? Yet, I am curious as to how the delegate sources the model information - as I get an error with the following (based on the model argument) mainly because I am a bit novice on how to instance the QAbstractTableModel in this circumstance:


class averageComboDelegate(QtGui.QItemDelegate):
def __init__(self, parent):
QtGui.QItemDelegate.__init__(self, parent)
def createEditor(self, parent, option, index):
self.averageChoices = ['Arithmetic','Harmonic','Logarithmic']
averageCombo = QtGui.QComboBox(parent)
averageCombo.addItems(self.averageChoices)
averageCombo.currentIndexChanged[int].connect(self.currentIndexChanged)
return averageCombo
def setEditorData(self, editor, index):
editor.blockSignals(True)
try: idxConversion = self.averageChoices.index(index.model().data(index ,Qt.DisplayRole))
except ValueError: idxConversion = 0
editor.setCurrentIndex(int(idxConversion))
editor.blockSignals(False)
self.setModelData(self,editor,???,index) #<<============================?
def setModelData(self, editor, model, index):
model.setData(index, self.averageChoices[editor.currentIndex()],Qt.EditRole)
@QtCore.pyqtSlot(int)
def currentIndexChanged(self):
self.commitData.emit(self.sender())

Added after 39 minutes:

'Bleck...'
The code below is the solution I have settled upon (which isn't to kind on the eyes); and its the only one I have found to work (so far).
I suppose there might be an alternative, and if its discovered - I will update this posting for the probably miniscule list of people whom might be searching for a similar solution.

Its merely a function within the QAbstractTableModel which houses the default values for each particular column.
If the initlized values in the table (from source file) are found to be None-Type, then the defaults are inserted respectively.


def setDefaultCombos(self):
if 'Layer-Options' in self.editorType:
for row in range(len(self.rows)):
if self.rows[row][1] == '': \
self.setData(self.index(row,1,QtCore.QModelIndex() ),'True',Qt.EditRole)
if self.rows[row][2] == '': \
self.setData(self.index(row,2,QtCore.QModelIndex() ),'Confined',Qt.EditRole)
if self.rows[row][3] == '': \
self.setData(self.index(row,3,QtCore.QModelIndex() ),'Arithmetic',Qt.EditRole)
if self.rows[row][5] == '': \
self.setData(self.index(row,5,QtCore.QModelIndex() ),'Actual Value',Qt.EditRole)
if self.rows[row][6] == '': \
self.setData(self.index(row,6,QtCore.QModelIndex() ),'Active',Qt.EditRole)
if 'Stress Period-Options' in self.editorType:
for row in range(len(self.rows)):
if self.rows[row][4] == '': \
self.setData(self.index(row,4,QtCore.QModelIndex() ),'Steady State',Qt.EditRole)