简体   繁体   中英

PyQt - QTableView search by hiding rows

Here's my problem. I have a QTableView displaying some data (set up in a model) and a QLineEdit Widget that i want to use for searching text in all displayed rows. The expected behavior should be: i type some text in the QLineEdit and the QTableView update itself hiding all rows that not contain that data.

The question is, how should i implement that? I have found a QTableView member function named hideRows() that seems the right choice, but i can't figure out how should i iterate through all the data and where to put that method. It should be contained inside the model or the dialog? (this is actually my first time using models, so i just grasped how they work)

Plus i need to implement an export function (csv, html or whatever) but just with the currently displayed rows (those who are not hiding). Is this possible?

Thank you for any advice.

Here is my code till now:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import Android_extractor
import ui_android_dialog



class recordsTableModel(QAbstractTableModel):

    def __init__(self, records, parent = None):
        QAbstractTableModel.__init__(self, parent)
        self.__records = records

    def rowCount(self, parent):
        return len(self.__records)

    def columnCount(self, parent):
        return len(self.__records[0])

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable

    def data(self, index, role):
        if role == Qt.EditRole:
            row = index.row()
            column = index.column()
            return self.__colors[row][column].name()

        if role == Qt.DisplayRole:
            row = index.row()
            column = index.column()
            value = self.__records[row][column]

            return value

    def headerData(self, section, orientation, role):
        if role == Qt.DisplayRole:
            if orientation == Qt.Horizontal:
                return self.__records[0]._fields[section]




class AndroidDialog(QDialog, ui_android_dialog.Ui_androidDialog):

    def __init__(self, parent=None):
        super(AndroidDialog, self).__init__(parent)
        self.setupUi(self)

        self.buttonMapper = QSignalMapper(self)

        self.buttonMapper.setMapping(self.contactsToolButton, 0)
        self.buttonMapper.setMapping(self.groupsToolButton, 1)
        self.buttonMapper.setMapping(self.chatsessionToolButton, 2)
        self.buttonMapper.setMapping(self.messageToolButton, 3)

        self.contactsToolButton.clicked.connect(self.buttonMapper.map)
        self.groupsToolButton.clicked.connect(self.buttonMapper.map)
        self.chatsessionToolButton.clicked.connect(self.buttonMapper.map)
        self.messageToolButton.clicked.connect(self.buttonMapper.map)

        self.buttonMapper.mapped.connect(self.dataStackedWidget.setCurrentIndex)


        self.newQuery = Android_extractor.AndroidQuery(sys.argv[1])
        self.contacts = self.newQuery.getContacts()
        self.groups = self.newQuery.getGroups()
        self.chats = self.newQuery.getChats()

        self.contactsTableView.setModel(recordsTableModel(self.contacts))
        self.contactsTableView.resizeColumnsToContents()
        self.contactsTableView.resizeRowsToContents()
        self.groupsTableView.setModel(recordsTableModel(self.groups))
        self.groupsTableView.resizeColumnsToContents()
        self.groupsTableView.resizeRowsToContents()
        self.chatsessionTableView.setModel(recordsTableModel(self.chats))
        self.chatsessionTableView.resizeColumnsToContents()
        self.chatsessionTableView.resizeRowsToContents()



app = QApplication(sys.argv)
form = AndroidDialog()
form.show()
app.exec_()

You should have a look at QSortFilterProxyModel

Instead of setting your custom model directly on your tableview, set in as Source model on the proxy, then set the proxy model on your view.

    self.proxyModelContact = QSortFilterProxyModel(self)
    self.proxyModelContact.setSourceModel(recordsTableModel(self.contacts))
    self.contactsTableView.setModel(self.proxyModelContact)

QSortFilterProxyModel provides two methods:

  • setFilterRegExp(pattern) allows you to set a regex filter on your view (ie only the items that match the pattern will be displayed)

  • setFilterKeyColumn(index) allows you to define which column will be used to do the filtering (if index = -1, all columns will be looked at).

You just have to link the textChanged signal of your linedit to a slot which will update the filter eg:

def onTextChanged(self, text):
    self.proxyModelContact.setFilterRegExp(str(text))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM