Issue
from PySide2 import QtCore, QtWidgets
class AssetBrowser(QtWidgets.QWidget):
def __init__(self):
super(AssetBrowser, self).__init__()
self.setWindowTitle("Tree and List View Example")
self.setGeometry(100, 100, 400, 500)
self.treeView = QtWidgets.QTreeView(self)
self.mainListView = QtWidgets.QListView(self)
self.search_line_edit = QtWidgets.QLineEdit(self)
# Create the layout
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.treeView)
layout.addWidget(self.mainListView)
layout.addWidget(self.search_line_edit)
# Create a central widget and set the layout
central_widget = QtWidgets.QWidget(self)
central_widget.setLayout(layout)
### treeViewViewStart
self.treeViewModel = QtWidgets.QFileSystemModel()
self.treeViewModel.setRootPath('')
self.treeViewModel.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.AllDirs)
self.treeViewProxyModel = QtCore.QSortFilterProxyModel()
self.treeViewProxyModel.setSourceModel(self.treeViewModel)
self.treeView.setModel(self.treeViewProxyModel)
self.treeView.setRootIndex(self.treeViewProxyModel.mapFromSource(self.treeViewModel.index("D:/")))
self.treeView.setColumnHidden(1, True)
self.treeView.setColumnHidden(2, True)
self.treeView.setColumnHidden(3, True)
self.treeView.setHeaderHidden(True)
self.treeView.clicked.connect(self.update_main_list_view)
### treeViewViewEnd
### listViewStart
self.mainListViewModel = QtWidgets.QFileSystemModel()
self.mainListViewModel.setRootPath('')
############### when i add this line after update_main_list_view list view reset to root '' ######################################
#self.mainListViewModel.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.Files)
self.mainListView.setIconSize(QtCore.QSize(100, 100))
self.mainListView.setViewMode(QtWidgets.QListView.IconMode)
self.mainListView.setResizeMode(QtWidgets.QListView.Adjust)
self.mainListView.setMovement(QtWidgets.QListView.Static)
### listViewEnd
self.mainListView.setModel(self.mainListViewModel)
self.mainListView.setRootIndex(self.mainListViewModel.index("D:/"))
def update_main_list_view(self, index):
selected_index = self.treeViewProxyModel.mapToSource(index)
new_path = self.treeViewModel.filePath(selected_index)
print(new_path)
self.mainListView.setRootIndex(self.mainListViewModel.index(new_path))
if __name__ == "__main__":
app = QtWidgets.QApplication([])
window = AssetBrowser()
window.show()
app.exec_()
Hi, when I add filter folders, after update_main_list_view call list view resets to root ''. qtreeview and qlistview each one have it's own qfilesystemmodel, I read the index from treeview and pass it to listview, I just want to see files and not the folders
Solution
The setFilter()
documentation explains it:
Note that the filter you set should always include the QDir::AllDirs enum value, otherwise QFileSystemModel won't be able to read the directory structure.
In fact, if you check the new index, it will not be valid as long as it refers to any directory that is a level beyond the root path.
new_index = self.mainListViewModel.index(new_path)
print(new_index.isValid())
That's because without providing the AllDirs
enum, QFileSystemModel will always see the top level items as empty, even if their related directories are not.
The solution could be to always call setRootPath()
before setting the root index of the view, so that the model will at least load the contents of that path.
Unfortunately, this won't be enough.
Due to a still unresolved bug in QFileSystemModel, when you navigate into a directory, going to the parent directory will also list the previously browsed directories in it even if the Dirs
or AllDirs
flags are not used.
The only solution to this is to use a further proxy model.
The trick is to always update the rootPath()
as suggested above, but also filter out any directory whenever the filter checks for children of the root path.
class FileOnlyModel(QtCore.QSortFilterProxyModel):
def __init__(self):
super().__init__()
self.fsmodel = QtWidgets.QFileSystemModel(self)
self.setSourceModel(self.fsmodel)
self.fsmodel.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.Files)
self.setRootPath('')
def rootIndex(self):
return self.mapFromSource(self.parentIndex)
def setRootPath(self, path):
self.fsmodel.setRootPath(path)
self.parentIndex = self.fsmodel.index(path)
self.invalidateFilter()
def filterAcceptsRow(self, row, parent):
if parent == self.parentIndex:
return not self.fsmodel.isDir(self.fsmodel.index(row, 0, parent))
return True
Then you can use it like this:
class AssetBrowser(QtWidgets.QWidget):
def __init__(self):
...
self.mainListViewModel = FileOnlyModel()
self.mainListView.setModel(self.mainListViewModel)
...
def update_main_list_view(self, index):
new_path = self.treeViewModel.filePath(
self.treeViewProxyModel.mapToSource(index))
self.mainListViewModel.setRootPath(new_path)
self.mainListView.setRootIndex(self.mainListViewModel.rootIndex())
Note that you created a "central widget", but a QWidget doesn't need any; in fact, if the AssetBrowser
window is resized, the layout will be unchanged, possibly hiding the widgets. Just remove that central widget, since it's useless, and create the layout for the window itself: layout = QtWidgets.QVBoxLayout(self)
.
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.