[SOLVED] Overload QtSql.QSqlRelationalTableModel data and setData methods
-
So your workflow would be something like: double click on a cell (let's call it C1) to open a QFileDialog then store the return value in that cell. Once that done, double click on the adjacent cell (or another in the same line) which should open a QComboBox with its list populated from the file which path is to be found in C1. Correct ?
If so, in setEditorData, you can access C1, get the path, open and parse the file and fill the QComboBox with the result of the parsing.
Colorado is a bit far away currently ;) But thanks for the invitation :)
-
Is the way I am using a signal and slot correct to open the new dialog when the pushbutton is clicked? Can this all be done in the delegate?
@class NaturalResourceDelegate(QtSql.QSqlRelationalDelegate):
def init(self, parent=None):
super(NaturalResourceDelegate, self).init(parent)def createEditor(self, parent, option, index): column = index.column() if column == IMPORT_SPATIAL: button = QtGui.QPushButton("select Spatial Data", parent) button.clicked.connect(self.parent().open_spatial) return button
class NaturalResourceTool(QtGui.QDialog, ui_Grit_tool_3.Ui_natural_resource_Dialog):
def __init__(self, database = None, table = None, parent=None): super(NaturalResourceTool, self).__init__(parent) self.setupUi(self) self._dbfname = database self._table = table self.file_browser = importgtlf.ImportGTLF(database = self._dbfname, parent = self) self.index = [] self.selection_model = self.natural_resource_tableView.selectionModel() self.selection_model.currentChanged.connect(self.item) def item(self): """ We needed to capture the index in order to use the QDialog for selecting a file. The dialog cannot be opened from the delegate. Therefore we are currentChanged slot to capture the current index. However, clicking sometimes returns an empty list. As a result, this method is called to capture the last valid index (ie not empty) in this list. Then open_spatial is a slot called from setModelData in the delegate, which opens the file dialog, retrieves the path, then passes this path and the selected index back to the data model using setData. """ if len(self.selection_model.selectedIndexes()) > 0: self.index.append(self.selection_model.selectedIndexes()[-1]) def open_spatial(self): self.item() if self.file_browser.exec_(): self.model.setData(self.index[0], self.file_browser.path, role=QtCore.Qt.EditRole ) desc = arcpy.Describe(str(self.file_browser.path)) desc.shapeType index = self.model.index(self.index[0].row(), VECTOR_TYPE) self.model.setData(index, desc.shapeType, role=QtCore.Qt.EditRole) self.fieldlist = [] field_list = arcpy.ListFields(str(self.file_browser.path), '', ["Double", "Interger", "String", "Single"] ) for field in field_list: self.fieldlist.append(field.name) print self.fieldlist self.index = []
@
Thank you
-
Not really clean, you should rather implement a custom editor (even if it's a QPushButton subclass) so that everything is handled through the editor, even the model update. In your model add a Q_PROPERTY named e.g. path with USER true so you don't even need to re-implement setModelData
-
Don't I need setModelData to validate that the line edit is actually a float for a different column?
-
What does the custom editor look like?
-
No, the editor is responsible for accepting only adequate data e.g. through a QValidator.
A custom editor looks the way you want it to. In your case probably QPushButton
-
I'm lost then. I was trying to follow this example: http://www.gulon.co.uk/2013/01/30/button-delegate-for-qtableviews/.
I have the createEditor method and that is where I setup the pushbutton.
-
Ok I see what you mean, that's an alternative technique which doesn't use a real editor as when using a custom delegate implementation like "this C++":http://qtadventures.wordpress.com/2012/02/04/adding-button-to-qviewtable/ implementation.
I was more focused on a 100% custom delegate for a better integration to the model/view paradigm. Also, depending on the size of your table, having so many widgets can have performance implications
-
Thank you SGaist.
-
For anyone that is struggling to subclass SqlTableModel this should help you. This is the subclass for data() and setData(). I wish I had this information.
@
ID, IMPORT_SPATIAL, VECTOR_TYPE, DESCRIPTION, SPATIAL_WEIGHT, MAP_RATIO, NSSDA = range(7)
def data(self, index, role=QtCore.Qt.DisplayRole):
'''Returns the data stored under the given role for the item referred to by the index. '''
row = index.row()
column = index.column()
if not index.isValid():
return QtCore.QVariant()
if role == QtCore.Qt.DisplayRole:
if column == ID:
id = super(model, self).data(index, role)
return QtCore.QVariant(id)
elif column == IMPORT_SPATIAL:
import_spatial = super(model, self).data(index, role)
return QtCore.QVariant(import_spatial)
elif column == VECTOR_TYPE:
vector_type = super(model, self).data(index, role)
return QtCore.QVariant(vector_type)
elif column == DESCRIPTION:
desc = super(model, self).data(index, role)
return QtCore.QVariant(desc)
elif column == SPATIAL_WEIGHT:
spatial_weight = super(model, self).data(index, role)
return QtCore.QVariant(spatial_weight)
elif column == MAP_RATIO:
map_ratio = super(model, self).data(index, role)
return QtCore.QVariant(map_ratio)
elif column == NSSDA:
nssda = super(model, self).data(index, role)
return QtCore.QVariant(nssda)elif role == QtCore.Qt.BackgroundColorRole: if column == 0: return QtCore.QVariant(QtGui.QColor(224, 224, 224)) return super(model, self).data(index, role) def setData(self, index, value, role=QtCore.Qt.EditRole): '''The base class implementation returns false. This function and data() must be reimplemented for editable models. ''' column = index.column() if index.isValid(): if column == IMPORT_SPATIAL: return super(model, self).setData(index, value, role) elif column == VECTOR_TYPE: return super(model, self).setData(index, value, role) elif column == DESCRIPTION: return super(model, self).setData(index, value, role) elif column == SPATIAL_WEIGHT: return super(model, self).setData(index, value, role) elif column == MAP_RATIO: return super(model, self).setData(index, value, role) elif column == NSSDA: return super(model, self).setData(index, value, role) else: return super(model, self).setData(index, value, role)
@