How can I change the Qtreeview directory(folder) icon for different folders?
-
@sandip-nandwana
Then subclassQFileSystemModel
, overridedata()
virtual method and do what you want forQt::DecorationRole
orQFileSystemModel::FileIconRole
role, takingindex
of individual item into account. This is illustrated in https://stackoverflow.com/questions/27587035/qfilesystemmodel-custom-icons. -
@sandip-nandwana
So what did you do abouttaking
index
of individual item into account.? If you do not use the
index
to look at the filename and decide from that which icon you want --- assuming you want to distinguish by filename, you don't say what your actual criteria for different icons are --- it won't work by magic, how do you expect it to know? So show the code you have to decide/produce which icon for which item? -
@JonB everything works fine but the subfolder icon changes slowly (first it shows the file icon after 500ms it shows my new icon), below is the code.
QVariant MyFileSystemModel::data(const QModelIndex& index, int role) const
{
QFileInfo info = MyFileSystemModel::fileInfo(index);
QString dirName = info.absoluteFilePath().split("/").last();
QStringList tem = info.absolutePath().split( "/" );if( role == Qt::DecorationRole ) { if( ( dirName.contains("Case") == true ) && ( index.column() == 0 ) ) { return QPixmap( ":/images/YellowFolderIcon.png" ); } else if( ( dirName.contains("Log") == true ) && ( index.column() == 0 ) ) { return QPixmap( ":/images/BlueFolderIcon.png" ); } else if( ( dirName.contains("Screen") == true ) && ( index.column() == 0 ) ) { if( ( tem.length() >= 4 ) && QString(tem.at(4)).contains("Case") ) { return QPixmap( ":/images/YellowFolderIcon.png" ); } else { return QPixmap( ":/images/BlueFolderIcon.png" ); } } } return QFileSystemModel::data(index, role);
}
and the filter is not working when I changed the "setNameFilters" input StringList.
-
@sandip-nandwana
OK, at least this code approach looks right.For the "slowness": your code reads a
.png
file from your resources to create aQPixmap
for it each time that is wanted for an individual folder's icon. I imagine that might be "slow". Also (I think) a separate in-memoryQPixmap
copy is kept for each folder it applies to, they do not share one created pixmap for each re-use of the same icon. I imagine that it is eating memory.Store a single instance of each unique
QPixmap
as member variables in your class. Create/read them in the constructor, or when first wanted, as you please. Re-use those variables in yourreturn
statements. Does that increase speed?and the filter is not working when I changed the "setNameFilters" input StringList.
Not sure what you mean. This is not to do with the icon? I would first test that
setNameFilters()
works as you expect if you set it to something initially. Then maybe you are saying if you change it once theQFileSystemModel
has been populated it does not update to reflect the change? Maybe just try callingsetRootPath()
aftersetNameFilters()
to see whether that causes it to refresh itself? Or, what are you expecting to see when a filename does not pass a name filter? Have you looked atsetNameFilterDisables(bool enable)
? -
@JonB said in How can I change the Qtreeview directory(folder) icon for different folders?:
Store a single instance of each unique QPixmap as member variables in your class. Create/read them in the constructor, or when first wanted, as you please. Re-use those variables in your return statements. Does that increase speed?
I tried before, but it had no impact.
-
@sandip-nandwana
Then I have no idea why anything would take 500ms, does not sound right.... -
@JonB said in How can I change the Qtreeview directory(folder) icon for different folders?:
Not sure what you mean. This is not to do with the icon? I would first test that setNameFilters() works as you expect if you set it to something initially. Then maybe you are saying if you change it once the QFileSystemModel has been populated it does not update to reflect the change? Maybe just try calling setRootPath() after setNameFilters() to see whether that causes it to refresh itself? Or, what are you expecting to see when a filename does not pass a name filter? Have you looked at setNameFilterDisables(bool enable)?
I have set the filter to include both the "Case" and "Log" directories, and then I'll set the filter to only include the "Case" directory, but it can't filter that it also shows the "Log" directory.
"Shows" how? What is your setNameFilterDisables() setting? -> is false
-
@sandip-nandwana
"Shows" how? What is yoursetNameFilterDisables()
setting?Did you at least try resetting
setRootPath()
to see whether it is a caching/updating issue? -
@JonB said in How can I change the Qtreeview directory(folder) icon for different folders?:
"Shows" how? What is your setNameFilterDisables() setting?
Is false.
@JonB said in How can I change the Qtreeview directory(folder) icon for different folders?:
Did you at least try resetting setRootPath() to see whether it is a caching/updating issue?
I tried but it did not work.
below is the code.
m_fileSystemModel->setNameFilterDisables( false ); m_fileSystemModel->setFilter( QDir::Dirs | QDir::Files ); filesFilter.append( "*.csv" ); filesFilter.append( "ScreenCapture" ); filesFilter.append( "*.png" ); if( m_isCaseStarted == true ) { /** @note: * info - 1793: * invoking non-const member function symbol of class symbol on a temporary */ filesFilter.append( m_logDirectory.split("/").last() );//lint !e1793 } else { filesFilter.append( "Log*" ); filesFilter.append( "Case*" ); } m_fileSystemModel->setNameFilterDisables( false ); m_fileSystemModel->setNameFilters( filesFilter ); ui->logDirectoryListView->setModel( m_fileSystemModel ); m_fileSystemModel->setRootPath( m_logDirectory.left( m_logDirectoryPosition ) );//lint !e534 ui->logDirectoryListView->setRootIndex( m_fileSystemModel->index( m_logDirectory.left( m_logDirectoryPosition ) ) );
-
@sandip-nandwana
You are trying to usesetNameFilters()
to filter the directories/folders shown, is that right? I would not expect that to work in any situation, whether you set it initially or change it? The name filters are intended to be like*.txt
to filter the files being shown within each directory, but not for the directory names themselves (else e.g.*.txt
would never be useful). Is that your situation?If so, I think you need to find another approach, writing your own filter for directory names. You might interpose a
QSortFilterProxyModel
for this. There is an example in the accepted solutuon at e.g. https://stackoverflow.com/a/56627595/489865. It's a bit old but looks OK, usesetFilterRegularExpression()
instead ofsetFilterRegExp()
.I am not sure whether that example will mean that your your whole tree will only display the (filtered) directories now, and nothing else. If you have to be smarter I think you will need to: subclass
QSortFilterProxyModel
, overrideQSortFilterProxyModel::filterAcceptsRow()
, implement your logic there. Use that instead of setting a regular expression filter on the proxy so that you can implement logic to test for the item type to see whether it is a directory or a file, since you want these to behave differently.