How to use Filter Option in QTableWidget - follow-up issue with PyQt5

33 Views Asked by At

I am trying to make use of eyllanesc's brilliant answer to this post using PyQt5. I had to adapt the code for PyQt5 (original was with PyQt4) but I am running into some issues with the function

self.filterdata()

in particular the statement

self.keywords[i]

I can't figure out the logic here and hence I am stuck.

    def filterdata(self):

        columnsShow = dict([(i, True) for i in range(self.qPerformanceReport_table.rowCount())])

        for i in range(self.qPerformanceReport_table.rowCount()):
            for j in range(self.qPerformanceReport_table.columnCount()):
                item = self.qPerformanceReport_table.item(i, j)
                if self.keywords[j]:
                    if item.text() not in self.keywords[j]:
                        columnsShow[i] = False
        for key, value in enumerate(columnsShow[:]):
            self.qPerformanceReport_table.setRowHidden(key, not value)

After clicking on the header of the first column (the QTableWidget is called self.qPerformanceReport_table), the self.keywords is initialized correctly (after checking the desired boxes from self.menu). In the filterdata function, j=0 (first loop) works fine but then I am being thrown:

if self.keywords[j]: KeyError: 1

not matter which checkbox is checked (or not) Did anyone run into an issue with this code?

Edit: here is a reproducible example. The data is coming a database (not a csv file)

class MyQtApp(main.Ui_MainWindow, QtWidgets.QMainWindow):
    def __init__(self):
        super(MyQtApp, self).__init__()
        self.setupUi(self)

        self.qPerformanceReport_refresh.clicked.connect(self.refresh_performance_report)
        self.horizontalHeader=self.qPerformanceReport_table.horizontalHeader()
        self.horizontalHeader.sectionClicked.connect(self.on_view_horizontalHeader_sectionClicked)
        self.keywords = dict([(i, []) for i in range(self.qPerformanceReport_table.columnCount())])
        self.checkBoxs = []
        self.col = None

    def refresh_performance_report(self):
        #df_agg = pd.read_sql("...")
        df_agg = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
                                       columns=['a', 'b', 'c'])
        nRows, nColumns = df_agg.shape
        self.qPerformanceReport_table.setColumnCount(nColumns)
        self.qPerformanceReport_table.setRowCount(nRows)
    
        self.qPerformanceReport_table.setHorizontalHeaderLabels( df_agg.columns)

        for i in range(self.qPerformanceReport_table.rowCount()):
            for j in range(self.qPerformanceReport_table.columnCount()):
                self.qPerformanceReport_table.setItem(i, j, QtWidgets.QTableWidgetItem(str(df_agg1.iloc[i, j])))

        for j in range(self.qPerformanceReport_table.columnCount()):
            self.qPerformanceReport_table.resizeColumnToContents(j)

    def slotSelect(self, state):

        for checkbox in self.checkBoxs:
            checkbox.setChecked(Qt.Qt.Checked == state)

    def on_view_horizontalHeader_sectionClicked(self, index):
        # self.clearFilter()
        self.menu = QtWidgets.QMenu(self)
        self.col = index

        data_unique = []

        self.checkBoxs = []

        checkBox = QtWidgets.QCheckBox("Select all", self.menu)
        checkableAction = QtWidgets.QWidgetAction(self.menu)
        checkableAction.setDefaultWidget(checkBox)
        self.menu.addAction(checkableAction)
        checkBox.setChecked(True)
        checkBox.stateChanged.connect(self.slotSelect)

        for i in range(self.qPerformanceReport_table.rowCount()):
            if not self.qPerformanceReport_table.isRowHidden(i):
                item = self.qPerformanceReport_table.item(i, index)
                if item.text() not in data_unique:
                    data_unique.append(item.text())
                    checkBox = QtWidgets.QCheckBox(item.text(), self.menu)
                    checkBox.setChecked(True)
                    checkableAction = QtWidgets.QWidgetAction(self.menu)
                    checkableAction.setDefaultWidget(checkBox)
                    self.menu.addAction(checkableAction)
                    self.checkBoxs.append(checkBox)

        btn = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel, Qt.Qt.Horizontal, self.menu)
        btn.accepted.connect(self.menuClose)
        btn.rejected.connect(self.menu.close)
        checkableAction = QtWidgets.QWidgetAction(self.menu)
        checkableAction.setDefaultWidget(btn)
        self.menu.addAction(checkableAction)

        headerPos = self.qPerformanceReport_table.mapToGlobal(self.horizontalHeader.pos())

        posY = headerPos.y() + self.horizontalHeader.height()
        posX = headerPos.x() + self.horizontalHeader.sectionPosition(index)
        self.menu.exec_(QtCore.QPoint(posX, posY))

    def menuClose(self):
        self.keywords[self.col] = []
        for element in self.checkBoxs:
        if element.isChecked():
            self.keywords[self.col].append(element.text())
        self.filterdata()
        self.menu.close()

    def clearFilter(self):
        for i in range(self.qPerformanceReport_table.rowCount()):
            self.qPerformanceReport_table.setRowHidden(i, False)

    def filterdata(self):

        columnsShow = dict([(i, True) for i in range(self.qPerformanceReport_table.rowCount())])

        for i in range(self.qPerformanceReport_table.rowCount()):
            for j in range(self.qPerformanceReport_table.columnCount()):
                item = self.qPerformanceReport_table.item(i, j)
                if self.keywords[j]:
                    if item.text() not in self.keywords[j]:
                        columnsShow[i] = False
                        for key, value in enumerate(columnsShow[:]):
                            self.qPerformanceReport_table.setRowHidden( key, not value)
0

There are 0 best solutions below