Issue
I found this code here in the forum and just changed it for PySide2 but sometimes it doesn't work, I implemented this search in my own tool and it was the same there, in some entries in first letter or number when it doesn't exist listview resets to root folder '' :(
from PySide2 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
le = QtWidgets.QLineEdit()
le.textChanged.connect(self.on_textChanged)
self.lv = QtWidgets.QListView()
self._dirpath = "d:/"
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.Slot(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_())
Solution
The problem is caused by the recursive search itself.
That kind of search ensures that any top level item that has at least a matching item within its children tree.
Now, while this approach is normally fine for standard searches shown within a tree view, it can be a problem when dealing with a mapped view that sets as root an index that is not the model root.
In your case, you can see the C: drive because the search algorithm finds some child within the whole file system, specifically within that C: drive.
In the meantime, you're trying to set the root index based on D:, but that search returns no results within that tree node, and since that returned index is, in fact, invalid, it will reset the root index: remember that an invalid QModelIndex always refers to the root of the model. And since, at that point, the filter shows that something in C: matches the search, that's what you can see.
If you had another drive with a file or folder containing an "x", you'd have probably seen that drive too.
QSortFilterProxyModel doesn't allow to set the "depth" of a recursive filter, and the search filter is also required in order to show the root index of the view (which is not a top level item).
The only solution I can suggest is to always check for the validity of the mapped index: if it's valid, then proceed with setRootIndex()
, otherwise completely disable the recursive feature.
You then need to restore it again whenever the search changes.
def on_textChanged(self, text):
self.proxy_model.setFilterWildcard("*{}*".format(text))
self.proxy_model.setRecursiveFilteringEnabled(True)
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)
if not proxy_index.isValid():
self.proxy_model.setRecursiveFilteringEnabled(False)
else:
self.lv.setRootIndex(proxy_index)
Another possibility is to not directly use the sort filter in the view, but create a standalone QStandardItemModel and always repopulate it whenever the proxy changes its filter, by iterating through the mapped source index of the parent: if the parent is valid, try to append its children.
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.