How To Install Custom Icon in QFileDialog
-
In order to make my project folders distinguishable I have added a ".PjtsZr" suffix to their name. When I call QFileDialog to select one of these folders, I want them to have a different folder icon within the dialog. I use the following to use the QFileDialog:
QFileDialog dialog(this, "Select Project Directory", "~/"); dialog.setFileMode(QFileDialog::DirectoryOnly); dialog.setOption(QFileDialog::DontUseNativeDialog, true); dialog.setWindowFlags(Qt::Dialog); dialog.setViewMode(QFileDialog::List); QString dirPath; if (dialog.exec() == QDialog::Accepted) { dirPath = dialog.selectedFiles().value(0); } QDir dir(dirPath);
It has been suggested on the internet to use the QSortFilterProxyModel Class to see the items of the QFileDialog, and this seems to work. But, once I detect a directory with the ".PjtsZr" extension, how do I change its icon?
//---------- filterAcceptsRow ---------- bool PjtFileFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent); QFileSystemModel* fileModel = qobject_cast<QFileSystemModel*>(sourceModel()); QString p = QDir::homePath(); QString homeName = gLastNameOfPath(p); //---------- if (fileModel!=NULL && fileModel->isDir(index0)) { QString modelStr = fileModel->fileName(index0); if (modelStr.compare(homeName) == 0){ qDebug() << "HELLO PROXY home: "<<modelStr; return true; }//if //---------- if (modelStr.endsWith("PjtsZr")){ qDebug()<<"GOT ONE!!! "<<fileModel->filePath(index0); QString pjtDirPath = fileModel->filePath(index0); QDir pjtDir(pjtDirPath); return true; }//if return true; }//if else{ return false; }//else // uncomment below to execute default implementation //return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); }
-
You can set your proxy model with http://doc.qt.io/qt-5/qfiledialog.html#setProxyModel
-
Thanks, Christian Ehrlicher, your suggestion was essential.
I finally solved the problem. Notice that globals.h contains all of the nic-nak Qt "#include"'s necessary to make it work.
pjticonprovider.h:
#ifndef GLOBALS_H #include "globals.h" #endif const static int PV_FILE_FOLDER = 0; const static int PV_PINK_FOLDER = 1; const static int PV_OOPS = 2; class PjtIconProvider : public QFileIconProvider { public: PjtIconProvider(); ~PjtIconProvider(); //QIcon icon( const QFileInfo & info ) const; QIcon icon(const QFileInfo & info) const; private: QIcon pinkFolder; QIcon defaultFolder; QIcon oopsIcon; };
pjticonprovider.cpp:
#include "pjticonprovider.h" //---------- CONSTRUCTOR PjtIconProvider ----------- PjtIconProvider :: PjtIconProvider() { qDebug()<<"CONSTRUCTOR PjtIconProvider"; defaultFolder = QIcon(":/Icons/FolderIcon.svg"); pinkFolder = QIcon(":/Icons/PinkIcon.png"); oopsIcon = QIcon(":/Icons/OopsIcon.png"); } //---------- DESTRUCTOR ~PjtIconProvider ----------- PjtIconProvider :: ~PjtIconProvider() { qDebug()<<"DESTRUCTOR PjtIconProvider"; } //---------- icon ----------- QIcon PjtIconProvider :: icon( const QFileInfo & info) const { QString name = info.fileName(); if (name.endsWith("PjtsZr")){ return pinkFolder; }//if else if(( ! name.isEmpty()) and ( ! name.isNull())){ return defaultFolder; }//elseif return oopsIcon;
pjtfilefilterproxymodel.h:
#ifndef PJTICONPROVIDER_H #include "pjticonprovider.h" #endif #ifndef GLOBALS_H #include "globals.h" #endif class PjtFileFilterProxyModel : public QSortFilterProxyModel { Q_OBJECT public: PjtFileFilterProxyModel(); ~PjtFileFilterProxyModel(); PjtIconProvider *provider; protected: virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; };
pjtfilefilterproxymodel.cpp:
#include "pjtfilefilterproxymodel.h" //---------- CONSTRUCTOR PjtFileFilterProxyModel ---------- PjtFileFilterProxyModel :: PjtFileFilterProxyModel() { qDebug()<<"CONSTRUCTOR PjtFileFilterProxyModel"; provider = new PjtIconProvider(); } //---------- DESTRUCTOR PjtFileFilterProxyModel ---------- PjtFileFilterProxyModel :: ~PjtFileFilterProxyModel() { qDebug()<<"DESTRUCTOR PjtFileFilterProxyModel"; delete provider; } //---------- filterAcceptsRow ---------- bool PjtFileFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent); QFileSystemModel* fileModel = qobject_cast<QFileSystemModel*>(sourceModel()); fileModel->setIconProvider(provider); QFileInfo info = fileModel->fileInfo(index0); qDebug()<<info.fileName(); return true; // uncomment below to execute default implementation //return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); }
Notice that the UI of the QFileDialog still is awkward, but will be fixed soon. Here is the slot within MainWindow which handles the dialog:
//---------- SLOT openProject ---------- void MainWindow :: SlotOpenProject() { qDebug()<<" openProject"; statusMessageKey = S_OPEN_A_PROJECT; doFreshStatusMessage = true; QString dirPath; QFileDialog dialog(this, "Select Project Directory", "/home" ); dialog.setNameFilter("*/PjtsZr"); dialog.setOption( QFileDialog::DontUseNativeDialog ); dialog.setOption( QFileDialog::ShowDirsOnly ); dialog.setOption( QFileDialog::DontResolveSymlinks ); PjtFileFilterProxyModel* proxyModel = new PjtFileFilterProxyModel(); dialog.setProxyModel(proxyModel); QDialogButtonBox *button_box = findChild<QDialogButtonBox *>(); button_box->addButton("Select", QDialogButtonBox::AcceptRole); dialog.exec(); QStringList sList = dialog.selectedFiles(); QString selectedPjt( sList.at(0) ); qDebug()<<"<<<<<<<<<<<<<<<<<<<<<<<<<<< selected: "<<selectedPjt; }//openProject