Фильтруйте / ищите QFileSystemModel в QListFiew (возможно, QSortFilterProxyModel) - PullRequest
0 голосов
/ 14 декабря 2018

То, что я пытаюсь сделать, это Filter / Search QListView, который использует QFileSystemModel, чтобы заполнить его: это часть окна, которое я сейчас использую, используя папку test / dummy, которую я создал

(я работаю над созданием массового файла 'renamer', просто проекта, который я решил изучить по ходу работы)

Я хочу иметь возможность искать / фильтровать представление списка, печатаячто-то в строке 'getOut' edit.Примерно такова моя цель (это из старого случайного видео на YouTube , но оно использует QListWidget

Я прочитал, что QSortFilterProxyModel, вероятно, то, что яхочу использовать, но когда я устанавливаю представления списка "setRootIndex" с помощью прокси - он выдает ошибку.

TypeError: index(self, int, int, parent: QModelIndex = QModelIndex()): argument 1 has unexpected type 'str'

Так что мои вопросы сводятся к этому:

  1. Возможно ли даже отфильтровать QListView, как то, что я собираюсь описать выше в gif?
  2. Можно ли фильтровать / искать QFileSystemModel таким образом?
  3. Является ли QSortFilterProxyModel подходящим инструментом для работы, если 2 приведенных выше в порядке?
  4. Должен ли я использовать другую модель или сделать другую (я думаю, что вы можете) более простой и открытой для фильтрации?

Я могу сделать то, что пытаюсь, используя только "setNameFilters" и "setNameFilterDisables (False)" QFileSystemModel, но я должен сделать это таким странным способом, который вы можете увидеть ниже.

def listPopulate(self):
    print('\ninside the listPopulate method now')
    getOut = self.getOutInputBox.text()
    gList = []
    gList.insert(0, getOut)
    if self.homes:
        if os.path.exists(self.homes):
            listModel = QtWidgets.QFileSystemModel()
            listModel.setFilter(QDir.NoDotAndDotDot | QDir.AllEntries | QDir.Dirs | QDir.Files)
            listModel.setRootPath(self.homes)

            # proxyModel = QtCore.QSortFilterProxyModel()
            # proxyModel.setSourceModel(listModel)

            self.mainListView.setModel(listModel)
            self.mainListView.setRootIndex(listModel.index(self.homes))
            if not getOut:
                print('\ngetOut empty')
            else:
                print(getOut)
                listModel.setNameFilters(gList)
                listModel.setNameFilterDisables(False)

_All "gList"Это происходит потому, что setNameFilters принимает только список (я предполагаю, что это обычно используется для фильтрации расширений файлов), поэтому я беру фильтр getOut и выбрасываю его в список.и я МОГУ заставить его что-то фильтровать так, как я хочу, но я должен напечатать такие вещи, как " q ", чтобы получить фильтр к вещам с 'Q' в них.А «self.homes» - это просто мой путь / каталог, который выбирает пользователь.

1 Ответ

0 голосов
/ 14 декабря 2018

Ответы на все ваши вопросы, если фильтрация QFileSystemModel правильно реализована с использованием QSortFilterProxyModel.

Следующее решение возможно только для Qt> = 5.10, поскольку в этой версии мы добавили свойство recursiveFilteringEnabled, которое позволяет выполнятьрекурсивная фильтрация в древовидных моделях, как в этом случае.

С другой стороны, вы указываете, что у вас были проблемы, когда вы хотели использовать QSortFilterProxyModel, прежде чем указать, в чем заключалась проблема, вы должны понять, что представление незнать и вас не интересует, знаете ли вы, что модель является прокси или нет, просто подождите модель и QModelIndex от имени rootIndex, который принадлежит этой модели.В вашем случае вы должны преобразовать индекс QFileSystemModel в индекс QSortFilterProxyModel, используя метод mapFromSource().

И, наконец, кажется, что есть ошибка, потому что, когда данные фильтруются и они становятся пустыми,rootIndex изменяется внутренне, поэтому его необходимо восстановить, как я сделал в своем ответе.

from PyQt5 import QtCore, QtGui, QtWidgets

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        le = QtWidgets.QLineEdit(textChanged=self.on_textChanged)
        self.lv = QtWidgets.QListView()

        self._dirpath = QtCore.QDir.homePath()

        self.file_model = QtWidgets.QFileSystemModel()
        self.file_model.setRootPath(QtCore.QDir.rootPath())
        self.file_model.setFilter(QtCore.QDir.NoDotAndDotDot 
            | QtCore.QDir.AllEntries 
            | QtCore.QDir.Dirs 
            | QtCore.QDir.Files)
        self.proxy_model = QtCore.QSortFilterProxyModel(
            recursiveFilteringEnabled=True,
            filterRole=QtWidgets.QFileSystemModel.FileNameRole)
        self.proxy_model.setSourceModel(self.file_model)
        self.lv.setModel(self.proxy_model)
        self.adjust_root_index()

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(le)
        lay.addWidget(self.lv)

    @QtCore.pyqtSlot(str)
    def on_textChanged(self, text):
        self.proxy_model.setFilterWildcard("*{}*".format(text))
        self.adjust_root_index()

    def adjust_root_index(self):
        root_index = self.file_model.index(self._dirpath)
        proxy_index = self.proxy_model.mapFromSource(root_index)
        self.lv.setRootIndex(proxy_index)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...