I used QSortFilterProxyModel to filter the model data and display it in a tableView. Then I want to aggregate the filtered data, so I created a new tableView2 to display the filtered data aggregation.
I created a new QSortFilterProxyModel to aggregate the data, but I don’t know how to get the source data, and then increase the data
But with my current knowledge of QSortFilterProxyModel, I seem to be unable to start.
import sys from PyQt5 import QtWidgets from PyQt5 import QtCore from PyQt5.QtCore import Qt class FilterProxyModel(QtCore.QSortFilterProxyModel): def __init__(self, headers): super(FilterProxyModel, self).__init__(parent=None) self._headers = headers def headerData(self, section, orientation, role): if role == Qt.DisplayRole: if orientation == Qt.Horizontal: if self.columnCount() < section+1: return QtCore.QVariant() else: return self._headers[section] return super().headerData(section, orientation, role) def data(self, index, role=None): if role == Qt.DisplayRole: if index.row() < 1: return 1 else: return QtCore.QVariant() def rowCount(self, parent=None, *args, **kwargs): return 1 def columnCount(self, parent=None, *args, **kwargs): return len(self._headers) class TableModel(QtCore.QAbstractTableModel): def __init__(self, datas): super(TableModel, self).__init__() self._datas = datas def data(self, index, role=Qt.DisplayRole): if role == Qt.DisplayRole: return self._datas[index.row()][index.column()] def rowCount(self, parent=QtCore.QModelIndex()): return len(self._datas) def columnCount(self, parent=QtCore.QModelIndex()): if self._datas: return len(self._datas[0]) else: return 0 class MainWidget(QtWidgets.QWidget): def __init__(self, parent=None): super(MainWidget, self).__init__(parent) self.datas = [('a1', 'b1', 'c'), ('a2', 'b1', 'c'), ('a3', 'b1', 'c'), ('a4', 'b1', 'c')]*25 self.model = TableModel(self.datas) self.proxy_model = QtCore.QSortFilterProxyModel() self.proxy_model.setSourceModel(self.model) self.proxy_model.setFilterRegExp(QtCore.QRegExp('a1|a3')) self.proxy_model.setFilterKeyColumn(0) self.proxy_model2 = FilterProxyModel(['a1', 'a3']) self.proxy_model2.setSourceModel(self.model) self.proxy_model2.setFilterRegExp(QtCore.QRegExp('a1|a3')) self.proxy_model2.setFilterKeyColumn(0) self.treeview = QtWidgets.QTableView() self.treeview.setModel(self.proxy_model) self.treeview2 = QtWidgets.QTableView() self.treeview2.setModel(self.proxy_model2) layout = QtWidgets.QVBoxLayout(self) hlayout = QtWidgets.QHBoxLayout() hlayout.addWidget(self.treeview) hlayout.addWidget(self.treeview2) layout.addLayout(hlayout) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) main = MainWidget() main.show() sys.exit(app.exec_())
This is the effect I want to achieve according to the specified head key (a1, a3) to perform data aggregation:
Advertisement
Answer
A proxymodel is used to map items but in this case the goal is to count, so using a proxymodel seems unnecessary to me. Instead it is easier to use match()
to count and connect the signals that indicate some change in the model to recalculate it.
import sys from PyQt5 import QtCore, QtGui, QtWidgets class TableModel(QtCore.QAbstractTableModel): def __init__(self, datas): super(TableModel, self).__init__() self._datas = datas def data(self, index, role=QtCore.Qt.DisplayRole): if role == QtCore.Qt.DisplayRole: return self._datas[index.row()][index.column()] def rowCount(self, parent=QtCore.QModelIndex()): return len(self._datas) def columnCount(self, parent=QtCore.QModelIndex()): if self._datas: return len(self._datas[0]) else: return 0 class MainWidget(QtWidgets.QWidget): def __init__(self, parent=None): super(MainWidget, self).__init__(parent) self.datas = [ ("a1", "b1", "c"), ("a2", "b1", "c"), ("a3", "b1", "c"), ("a4", "b1", "c"), ] * 25 self.model = TableModel(self.datas) self.proxy_model = QtCore.QSortFilterProxyModel() self.proxy_model.setSourceModel(self.model) self.proxy_model.setFilterRegExp(QtCore.QRegExp("a1|a3")) self.proxy_model.setFilterKeyColumn(0) self.model2 = QtGui.QStandardItemModel() self.model2.setHorizontalHeaderLabels(["a1", "a3"]) self.view1 = QtWidgets.QTableView() self.view1.setModel(self.proxy_model) self.view2 = QtWidgets.QTableView() self.view2.setModel(self.model2) layout = QtWidgets.QVBoxLayout(self) hlayout = QtWidgets.QHBoxLayout() hlayout.addWidget(self.view1) hlayout.addWidget(self.view2) layout.addLayout(hlayout) self.model.dataChanged.connect(self.update_model2) self.model.rowsInserted.connect(self.update_model2) self.model.rowsRemoved.connect(self.update_model2) self.model.columnsInserted.connect(self.update_model2) self.model.columnsRemoved.connect(self.update_model2) self.model.modelReset.connect(self.update_model2) self.update_model2() def update_model2(self): self.model2.setRowCount(0) column = 0 for i in range(self.model2.columnCount()): header_item = self.model2.horizontalHeaderItem(i) if header_item is None: return text = header_item.text() indexes = self.model.match( self.model.index(0, column), QtCore.Qt.DisplayRole, text, hits=-1, flags=QtCore.Qt.MatchExactly, ) item = QtGui.QStandardItem() item.setData(len(indexes), QtCore.Qt.DisplayRole) self.model2.setItem(0, i, item) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) main = MainWidget() main.show() sys.exit(app.exec_())