Python Forum
How to filter a table view using SortFilterProxyModel
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to filter a table view using SortFilterProxyModel
#5
Thank you Alex and Deanhystad, I appreciate your help

I can understand how the findInTable method will allow me to hide the data I do not want to see, but I am still curious as to why my implementation is not working. I tried Deanhystads suggestion of using the QSortFilterProxyModel, but still could not get something to work using the subclassing approach.

I then tried a non-sub classed approach based on https://raw.githubusercontent.com/PyQt5/...ermodel.py

This is still not working for me, so I think I have some logic error or other flaw in the code that is probably preventing both implementations from working. I am going to use the findInTable approach for now, but I would love to understand where I am going wrong in the proxy model approach.

from PyQt5.QtWidgets import (QApplication, QMainWindow,
                             QTableWidget, QTableWidgetItem, QMenu, QAction, QDialog,
                             QInputDialog, QTableView,  QHeaderView, QLineEdit, QLabel, QVBoxLayout)
from PyQt5.QtGui import QIcon, QStandardItemModel

import sys

from PyQt5.QtCore import Qt, QSortFilterProxyModel, QModelIndex, QRegExp
from typing import Callable

headers = ["Word", "Meaning", ""]


NUMBER_OF_COLUMNS = 2
NUMBER_OF_ROWS = 3


class SortFilterProxyModel(QSortFilterProxyModel):
    def __init__(self):
        super().__init__()

    def filterAcceptsRow(self, sourceRow, sourceParent):
        result = False
        if self.filterKeyColumn() == 0:

            index = self.sourceModel().index(sourceRow, 0, sourceParent)
            data = self.sourceModel().data(index)
            if data:
                print("Soft Filter checking " + data)
            # we could additionally filter here on the data
            return True

        # Otherwise ignore
        return super(SortFilterProxyModel, self).filterAcceptsRow(sourceRow, sourceParent)

# Reference: https://doc.qt.io/archives/qtjambi-4.5.2_01/com/trolltech/qt/qtjambi-customfilter.html


class WordSelector(QDialog):
    def __init__(self,  title,  parent=None):
        QDialog.__init__(self,  parent)
        self.parent = parent
        self.lastStart = 0

        self.proxyModel = SortFilterProxyModel()
        # This property holds whether the proxy model is dynamically sorted and filtered whenever the contents of the source model change
        self.proxyModel.setDynamicSortFilter(True)

        self.sourceView = QTableView()
        self.sourceView.setAlternatingRowColors(True)

        self.proxyView = QTableView()
        self.proxyView.setAlternatingRowColors(True)
        self.proxyView.setModel(self.proxyModel)
        self.proxyView.setSortingEnabled(True)

        self.setWindowTitle(title)
        self.proxyView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.proxyView.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.proxyView.setAlternatingRowColors(True)
        self.proxyView.setSortingEnabled(True)
        self.proxyView.verticalHeader().hide()
        self.proxyView.setSelectionMode(QTableView.SingleSelection)
        self.proxyView.setSelectionBehavior(QTableView.SelectRows)
        self.proxyView.clicked.connect(self.getItem)
        self.filterSTring = ""
        self.initUI()

    def initUI(self):

        layout = QVBoxLayout()
        self.filterLabel = QLabel("  Filter")
        layout.addWidget(self.filterLabel)
        self.filter = QLineEdit(self)
        self.filter.setStyleSheet(
            "background-color: #FFFFFF; padding:1px 1px 1px 1px")
        self.filter.setFixedWidth(120)
        self.filter.returnPressed.connect(self.lookupWord)
        layout.addWidget(self.filter)
        layout.addWidget(self.proxyView)
        self.setGeometry(300, 300, 500, 300)
        self.setWindowTitle("Find and Replace")
        self.setLayout(layout)

    def setFilterString(self, string):
        self.filterString = "^" + string

    def getItem(self, index):

        mapped_index = self.proxyModel.mapToSource(index)
        item = self.model.itemFromIndex(mapped_index)
        print(item.text() + "  ")
        item = self.model.data(mapped_index)
        row = mapped_index.row()
        column = mapped_index.column()
        data = mapped_index.data()
        item = self.model.itemFromIndex(mapped_index)
        print(item.text() + "  " + str(row) + "  " + str(column) + "  " + data)

    def lookupWord(self):
        self.setFilterString(self.filter.text())
        self.filterRegExpChanged()

    def setSourceModel(self, model):
        self.proxyModel.setSourceModel(model)
        self.sourceView.setModel(model)

    def filterRegExpChanged(self):

        syntax = QRegExp.RegExp  # can be one of QRegExp.RegExp2, QRegExp.WildCard, QRegExp.RegExp2 etc, see https://doc.qt.io/qt-5/qregexp.html#PatternSyntax-enum
        caseSensitivity = Qt.CaseInsensitive
        regExp = QRegExp(self.filterString,
                         caseSensitivity, syntax)
        # This property holds the QRegExp used to filter the contents of the source model
        self.proxyModel.setFilterRegExp(regExp)


def addWord(model, word, meaning):
    model.insertRow(0)
    model.setData(model.index(0, 0), word)
    model.setData(model.index(0, 1), meaning)


def createModel(parent):

    model = QStandardItemModel(3, 2, parent)
    model.setHeaderData(0, Qt.Horizontal, "Word")
    model.setHeaderData(1, Qt.Horizontal, "Meaning")
    addWord(model, "Abundance", "A very large quantity of something.")
    addWord(model, "Belonging", "An affinity for a place or situation.")
    addWord(model, "Candor",
            "The quality of being open and honest in expression; frankness")
    return model


def main(args):
    app = QApplication(args)
    wordSelector = WordSelector("words")
    wordSelector.setSourceModel(createModel(wordSelector))
    wordSelector.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main(sys.argv)
Reply


Messages In This Thread
RE: How to filter a table view using SortFilterProxyModel - by DrakeSoft - May-28-2022, 10:08 AM

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020