Reputation: 39
Example of table model data
I have a gui with a tabWidget and inside each I have a tableview. Each tab describes a folder (see column type) with subdirs from which I pull the data. I want to have one main model that drives all views by attaching a QSortFilterProxy Model inbetween each tableview that filters the main model for the "type" of each individual TableView (passed into the subclass RenderTypeProxyModel). Bonus: Ideally, they should be sorted as well, so that the most recent view (see date column) comes out on top. Here is my current version but the table remains blank for a reason I can't figure out:
import sys
import os
from datetime import datetime
from pprint import pprint
from PySide2 import QtCore, QtGui, QtWidgets
#To be replaced by env variable
pathToProject = "/run/media/centos7/Data/Projects/Programming/Pipeline/SampleProject"
allowedExportTypes = ["img-prv", "img-final", "img-cg", "img-src", "camera"]
class ExportTableModel(QtCore.QAbstractTableModel):
def __init__(self, exportData, horizontalHeaders, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent)
self.__exportData = exportData
self.__horizontalHeaders = horizontalHeaders
def rowCount(self, parent):
return len(self.__exportData)
def columnCount(self, parent):
return len(self.__horizontalHeaders)
def data(self, index, role): #Returns the data stored under the given role for the item referred to by the index.
if role == QtCore.Qt.DisplayRole:
row = index.row()
column = index.column()
value = self.__exportData[row][column]
return value
def headerData(self, section, orientation, role):
if role == QtCore.Qt.DisplayRole:
if orientation == QtCore.Qt.Horizontal:
if section < len(self.__horizontalHeaders):
return self.__horizontalHeaders[section]
else:
return "not implemented"
def tableSetup(tableView):
tableView.setAlternatingRowColors(True)
tableView.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
tableView.setSortingEnabled(True)
class RenderTypeProxyModel (QtCore.QSortFilterProxyModel): #Custom Proxy Model
def __init__(self, type, parent=None):
super(RenderTypeProxyModel,self).__init__(parent)
self.__type = type
def filterAcceptsRow(self, row, parent): #returns true if the given row should be included in the model
model = self.sourceModel()
index = model.index(row, 3, parent)
if model.data(index,QtCore.Qt.DisplayRole) == type:
return True
else:
return False
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
horizontalHeaders = ["status", "comment", "task", "type", "version", "user", "date", "filepath"] #horizontal header data
#exportData = #insert sample data list of lists here for testing
tableView = QtWidgets.QTableView()
tableView.show()
model = ExportTableModel(exportData,horizontalHeaders)
proxyModel = RenderTypeProxyModel("img-prv")
proxyModel.setSourceModel(model)
tableView.setModel(proxyModel)
tableSetup(tableView)
sys.exit(app.exec_())
Here is sample data to use for debugging: https://pastebin.com/AB1XvKju
Just feed it into the exportData variable inside the __main__
method.
Upvotes: 1
Views: 4492
Reputation: 244291
The error is caused because type is a reserved word in python:
if model.data(index,QtCore.Qt.DisplayRole) == type:
you must use self.__type
.
On the other hand if you want to sort the data by date it is not necessary to enable setSortingEnabled()
, just use sort()
.
from PySide2 import QtCore, QtGui, QtWidgets
#To be replaced by env variable
allowedExportTypes = ["img-prv", "img-final", "img-cg", "img-src", "camera"]
class ExportTableModel(QtCore.QAbstractTableModel):
def __init__(self, exportData, horizontalHeaders, parent=None):
super(ExportTableModel, self).__init__(parent)
self.__exportData = exportData
self.__horizontalHeaders = horizontalHeaders
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.__exportData)
def columnCount(self, parent=QtCore.QModelIndex()):
return len(self.__horizontalHeaders)
def data(self, index, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
row = index.row()
column = index.column()
value = self.__exportData[row][column]
return value
def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal:
if section < self.columnCount():
return self.__horizontalHeaders[section]
return "not implemented"
def tableSetup(tableView):
tableView.setAlternatingRowColors(True)
tableView.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
class RenderTypeProxyModel (QtCore.QSortFilterProxyModel): #Custom Proxy Model
def __init__(self, _type, parent=None):
super(RenderTypeProxyModel,self).__init__(parent)
self.__type = _type
def filterAcceptsRow(self, row, parent):
_type = self.sourceModel().index(row, 3, parent).data()
return _type == self.__type
def lessThan(self, left, right):
fmt = "yyyy-MM-dd hh:mm:ss"
left_data = self.sourceModel().data(left)
right_data = self.sourceModel().data(right)
return QtCore.QDateTime.fromString(left_data, fmt) < QtCore.QDateTime.fromString(right_data, fmt)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
horizontalHeaders = ["status", "comment", "task", "type", "version", "user", "date", "filepath"] #horizontal header data
exportData = # ...
model = ExportTableModel(exportData, horizontalHeaders)
tab_widget = QtWidgets.QTabWidget()
for _type in allowedExportTypes:
tableView = QtWidgets.QTableView()
c = horizontalHeaders.index("date")
tableSetup(tableView)
proxy = RenderTypeProxyModel(_type, tableView)
proxy.setSourceModel(model)
proxy.sort(c, QtCore.Qt.AscendingOrder)
tableView.setModel(proxy)
tab_widget.addTab(tableView ,_type)
tab_widget.show()
sys.exit(app.exec_())
Update:
In the next part I have made improvements to your original code avoiding overwriting unnecessary methods and adding a delegate:
from PySide2 import QtCore, QtGui, QtWidgets
#To be replaced by env variable
allowedExportTypes = ["img-prv", "img-final", "img-cg", "img-src", "camera"]
class DateDelegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super(DateDelegate, self).initStyleOption(option, index)
option.text = index.data().toString("yyyy-MM-dd hh:mm:ss")
class ExportTableModel(QtCore.QAbstractTableModel):
def __init__(self, exportData, horizontalHeaders, parent=None):
super(ExportTableModel, self).__init__(parent)
self.__exportData = exportData
self.__horizontalHeaders = horizontalHeaders
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.__exportData)
def columnCount(self, parent=QtCore.QModelIndex()):
return len(self.__horizontalHeaders)
def data(self, index, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
row = index.row()
column = index.column()
value = self.__exportData[row][column]
header = self.headerData(column, QtCore.Qt.Horizontal)
if header == "date":
value = QtCore.QDateTime.fromString(value, "yyyy-MM-dd hh:mm:ss")
return value
def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal:
if section < self.columnCount():
return self.__horizontalHeaders[section]
return "not implemented"
def create_tableview():
tableView = QtWidgets.QTableView()
tableView.setAlternatingRowColors(True)
tableView.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
return tableView
class RenderTypeProxyModel (QtCore.QSortFilterProxyModel):
def __init__(self, c_type, _type, c_date, model, parent=None):
super(RenderTypeProxyModel,self).__init__(parent)
self.setSourceModel(model)
self.setFilterKeyColumn(c_type)
self.setFilterFixedString(_type)
self.sort(c_date, QtCore.Qt.AscendingOrder)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
horizontalHeaders = ["status", "comment", "task", "type", "version", "user", "date", "filepath"] #horizontal header data
exportData = # ...
c_date = horizontalHeaders.index("date")
c_type = horizontalHeaders.index("type")
tab_widget = QtWidgets.QTabWidget()
for _type in allowedExportTypes:
tableView = create_tableview()
tab_widget.addTab(tableView ,_type)
proxy = RenderTypeProxyModel(c_type, _type, c_date, model, tableView)
tableView.setModel(proxy)
delegate = DateDelegate(tableView)
tableView.setItemDelegateForColumn(c_date, delegate)
tab_widget.show()
sys.exit(app.exec_())
Upvotes: 2