いくつかのカスタムデザインファイル用にqtでファイルブラウザを作成しています。プレビューをサムネイルとしてロードしたいのでQIconProvider
、アイコンをに戻すために使用していQFileSystemModel
ます。
問題は、作成するアルゴリズムにQIcon
いくつかのリソースが必要であり、その結果、すべてのサムネイルの読み込みが完了するまでアプリケーションが応答しないことです。
QIconProvider
アプリケーションをレスポンシブにするために、バックグラウンドスレッドに自分を置く方法があるかどうか疑問に思っています。
残念ながら、QFileIconProvider
APIとモデルAPIの間にはインピーダンスの不一致があります。はQFileSystemModel
、状況が変化したときにビューに非同期通知を提供しますが、アイコンプロバイダーは、アイコンが変更されたとき、または認識されたときにモデルに非同期的に通知することはできません。
ファイルシステムモデルとビューの間にIDプロキシをインストールできます。そのプロキシのdata
メソッドは、アイコンを非同期的にクエリします。その場合、モデルの同期アイコンプロバイダーは未使用で不要です。
// https://github.com/KubaO/stackoverflown/tree/master/questions/icon-proxy-39144638
#include <QtWidgets>
#include <QtConcurrent>
/// A thread-safe function that returns an icon for an item with a given path.
/// If the icon is not known, a null icon is returned.
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);
}
};
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加