很遗憾,QFileIconProvider
API 和模型 API 之间存在阻抗不匹配:当事物发生变化时,QFileSystemModel
向视图提供异步通知,但是图标提供程序无法异步通知模型图标何时更改或变为已知。
您可以在文件系统模型和视图之间安装身份代理。该代理的 data
方法将异步查询图标。模型的同步图标提供程序将不再使用和不必要。
#include <QtWidgets>
#include <QtConcurrent>
QIcon getIcon(const QString & path);
class IconProxy : public QIdentityProxyModel {
Q_OBJECT
QMap<QString, QIcon> m_icons;
Q_SIGNAL void hasIcon(const QString&, const QIcon&, const QPersistentModelIndex& index) const;
void onIcon(const QString& path, const QIcon& icon, const QPersistentModelIndex& index) {
m_icons.insert(path, icon);
emit dataChanged(index, index, QVector<int>{QFileSystemModel::FileIconRole});
}
public:
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override {
if (role == QFileSystemModel::FileIconRole) {
auto path = index.data(QFileSystemModel::FilePathRole).toString();
auto it = m_icons.find(path);
if (it != m_icons.end()) {
if (! it->isNull()) return *it;
return QIdentityProxyModel::data(index, role);
}
QPersistentModelIndex pIndex{index};
QtConcurrent::run([this,path,pIndex]{
emit hasIcon(path, getIcon(path), pIndex);
});
return QVariant{};
}
return QIdentityProxyModel::data(index, role);
}
IconProxy(QObject * parent = nullptr) : QIdentityProxyModel{parent} {
connect(this, &IconProxy::hasIcon, this, &IconProxy::onIcon);
}
};
QtConcurrent::run
进行后台执行,然后使用排队信号进行通知。 - G.M.