In Python PyQt6, Why is my QTreeView displaying white icons instead of folder icons from QStandardItemModel?

Question:

I am attempting to add a folder icon for the folder items in my directory, along with the icons for the associated file type.

iconProvider = QFileIconProvider()

        for item in os.listdir(path):
            QItem = QStandardItem(item)
            file_item_icon = iconProvider.icon(QFileInfo(item))
            QItem.setIcon(file_item_icon)
            root_item.appendRow(QItem)

QTreeView Where folders show up with a White Icon

QTreeView Where folders show up with a White Icon

I have tried using the QFileSystemModel which does correctly show the icons, However, I need the control the QStandardItemModel offers…

QTreeView where icons are working

QTreeView where icons are working

Asked By: Devin Miller

||

Answers:

If the path used to construct the QFileInfo instance is not absolute, it can only use relative paths. As the documentation explains:

A QFileInfo can point to a file with either a relative or an absolute file path. Absolute file paths begin with the directory separator "/" (or with a drive specification on Windows). Relative file names begin with a directory name or a file name and specify a path relative to the current working directory.

[emphasis mine]

os.listdir() returns only the names:

Return a list containing the names of the entries in the directory given by path.

This means that QFileInfo will only have a "relative" name of each entry based on the working directory.

This is clearly an issue in your case:

  • since you’re probably using a path that is not directly relative to the working directory, it will be an invalid path, so the icon provider will use the default (usually, "new document") icon;
  • coincidentally, if the path returned by os.listdir() coincides with an existing name of the working directory, it could even provide the wrong icon: suppose you have a something.doc file in the working dir and the name returned by os.listdir() also is something.doc, it will have the icon of the former file, even if the latter is actually a directory;

So, the solution is to use absolute paths or the proper icon type.

For simple cases (when the icon type is known), you can use the icon(IconType) override using the provided enum. For instance, if you do know that the path refers to a directory (i.e. os.path.isdir()):

file_item_icon = iconProvider.icon(iconProvider.IconType.Folder)

Otherwise, you should use the full path, so that QFileInfo will use the real file reference:

baseDir = QDir(path)
for fileName in os.listdir(path):
    info = QFileInfo(baseDir.absoluteFilePath(fileName))
    icon = iconProvider.icon(info)
    root_item.appendRow(QStandardItem(icon, fileName))
Answered By: musicamante