Rao
Rao

Reputation: 2962

How to create combo filter for Qtables in pyqt

I have below code snippet from the help of stackoverflow followers.

I am able to filter the table now. but when i try to filter it sorts first as i enabled sort for the view.

I want to create the QTableview such a way that if i click on header it should sort. and should have a dropdown box (may be combox box style) at the right of every header. i am uploading a snap of how i want (which i made it in .NET)

Code Snippet

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from PyQt4 import QtCore, QtGui

class myWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(myWindow, self).__init__(parent)
        self.centralwidget  = QtGui.QWidget(self)
        self.view           = QtGui.QTableView(self.centralwidget)
        self.view.setSortingEnabled(True)
        self.gridLayout = QtGui.QGridLayout(self.centralwidget)
        self.gridLayout.addWidget(self.view, 1, 0, 1, 3)

        self.setCentralWidget(self.centralwidget)

        self.model = QtGui.QStandardItemModel(self)

        for rowName in range(3) * 5:
            self.model.invisibleRootItem().appendRow(
                [   QtGui.QStandardItem("row {0} col {1}".format(rowName, column))    
                    for column in range(3)
                    ]
                )
        self.proxy = QtGui.QSortFilterProxyModel(self)
        self.proxy.setSourceModel(self.model)
    
        self.view.setModel(self.proxy)

        self.horizontalHeader = self.view.horizontalHeader()
        self.horizontalHeader.sectionClicked.connect(self.horizontalHeader_Clicked)

    @QtCore.pyqtSlot(int)
    def horizontalHeader_Clicked(self, logicalIndex):
        self.logicalIndex   = logicalIndex
        # local variable, and no parent
        menuValues = QtGui.QMenu()
        # delete the previous one
        try:
            self.signalMapper.deleteLater()
        except:
            pass
    
        self.signalMapper = QtCore.QSignalMapper(self)  

        valuesUnique = [    
            self.proxy.index(row, self.logicalIndex).data().toString()
            for row in xrange(self.proxy.rowCount())
            ]

        print 'printing col %d values' % self.logicalIndex                            
        for row in range(self.proxy.rowCount()):
            print 'row %d Item %s' % (row,self.model.item(row,     self.logicalIndex).text())
        
        
        actionAll = QtGui.QAction("All", self)
        actionAll.triggered.connect(self.actionAll)
        menuValues.addAction(actionAll)
        menuValues.addSeparator()
    
        for actionNumber, actionName in enumerate(sorted(list(set(valuesUnique)))):              
        
            action = QtGui.QAction(actionName, self)
            self.signalMapper.setMapping(action, actionNumber)  
            action.triggered.connect(self.signalMapper.map)  
            menuValues.addAction(action)

        self.signalMapper.mapped.connect(self.signalMapper_mapped)  

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

        posY = headerPos.y() + self.horizontalHeader.height()
        posX = headerPos.x() + self.horizontalHeader.sectionPosition(self.logicalIndex)

        menuValues.exec_(QtCore.QPoint(posX, posY))

    @QtCore.pyqtSlot()
    def actionAll(self):
        filterColumn = self.logicalIndex
        filterString = QtCore.QRegExp(  "",
                                    QtCore.Qt.CaseInsensitive,
                                    QtCore.QRegExp.RegExp
                                    )

        self.proxy.setFilterRegExp(filterString)
        self.proxy.setFilterKeyColumn(filterColumn)

    @QtCore.pyqtSlot(int)
    def signalMapper_mapped(self, i):
        stringAction = self.signalMapper.mapping(i).text()
        filterColumn = self.logicalIndex
        filterString = QtCore.QRegExp(  stringAction,
                                    QtCore.Qt.CaseSensitive,
                                    QtCore.QRegExp.FixedString
                                    )

        self.proxy.setFilterRegExp(filterString)
        self.proxy.setFilterKeyColumn(filterColumn)
   
if __name__ == "__main__":
    import sys

    app  = QtGui.QApplication(sys.argv)
    main = myWindow()
    main.show()
    main.resize(400, 600)
    sys.exit(app.exec_())

This i how i am trying to get (Sort and filter)

enter image description here

If possible I need the ability to set the filter for selected columns only like in above image.

Upvotes: 0

Views: 1823

Answers (1)

jdi
jdi

Reputation: 92559

There is a discussion location here about the same topic: Quick way for QWidget in QHeaderView's columns?

They suggest that you would need to ditch the stock QHeaderView in your view, and provide your own custom widget for the header functionality, in order to place custom widgets into the header sections.

Upvotes: 1

Related Questions