QFileSystemModel: don't crash with setIconProvider(nullptr)
The method takes a pointer, so the code shouldn't crash when passed a nullptr. QFileInfoGatherer::getInfo() still needs to generate a descriptive string for the file, so we refactor QAbstractFileIconProvider::type() to put the implementation into a reusable static function QAbstractFileIconProviderPrivate::getFileType(const QFileInfo &info). This unfortunately involves constructing a QMimeDatabase on the fly, but the docs say that is fine. Drive-by change: use nullptr instead of `0` for pointers. Pick-to: 6.6 6.5 Fixes: QTBUG-99178 Change-Id: Ia32ea0a26701d593e74fbecced7be8d9e0aa0f52 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> (cherry picked from commit 2a8b27bf6c523de6f3f466f8062279c093940a60) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
8543be7355
commit
1753af3841
@ -229,21 +229,16 @@ QIcon QAbstractFileIconProvider::icon(const QFileInfo &info) const
|
||||
return result.isNull() ? d->getPlatformThemeIcon(info) : result;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the type of the file described by \a info.
|
||||
*/
|
||||
|
||||
QString QAbstractFileIconProvider::type(const QFileInfo &info) const
|
||||
QString QAbstractFileIconProviderPrivate::getFileType(const QFileInfo &info)
|
||||
{
|
||||
Q_D(const QAbstractFileIconProvider);
|
||||
if (QFileSystemEntry::isRootPath(info.absoluteFilePath()))
|
||||
return QGuiApplication::translate("QAbstractFileIconProvider", "Drive");
|
||||
if (info.isFile()) {
|
||||
#if QT_CONFIG(mimetype)
|
||||
const QMimeType mimeType = d->mimeDatabase.mimeTypeForFile(info);
|
||||
const QMimeType mimeType = QMimeDatabase().mimeTypeForFile(info);
|
||||
return mimeType.comment().isEmpty() ? mimeType.name() : mimeType.comment();
|
||||
#else
|
||||
Q_UNUSED(d);
|
||||
return QGuiApplication::translate("QAbstractFileIconProvider", "File");
|
||||
#endif
|
||||
}
|
||||
@ -273,4 +268,13 @@ QString QAbstractFileIconProvider::type(const QFileInfo &info) const
|
||||
return QGuiApplication::translate("QAbstractFileIconProvider", "Unknown");
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the type of the file described by \a info.
|
||||
*/
|
||||
|
||||
QString QAbstractFileIconProvider::type(const QFileInfo &info) const
|
||||
{
|
||||
return QAbstractFileIconProviderPrivate::getFileType(info);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -37,6 +37,7 @@ public:
|
||||
QIcon getIconThemeIcon(const QFileInfo &info) const;
|
||||
|
||||
static void clearIconTypeCache();
|
||||
static QString getFileType(const QFileInfo &info);
|
||||
|
||||
QAbstractFileIconProvider *q_ptr = nullptr;
|
||||
QAbstractFileIconProvider::Options options = {};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <qcoreapplication.h>
|
||||
#include <qdebug.h>
|
||||
#include <qdiriterator.h>
|
||||
#include <private/qabstractfileiconprovider_p.h>
|
||||
#include <private/qfileinfo_p.h>
|
||||
#ifndef Q_OS_WIN
|
||||
# include <unistd.h>
|
||||
@ -344,8 +345,12 @@ void QFileInfoGatherer::run()
|
||||
QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const
|
||||
{
|
||||
QExtendedInformation info(fileInfo);
|
||||
info.icon = m_iconProvider->icon(fileInfo);
|
||||
info.displayType = m_iconProvider->type(fileInfo);
|
||||
if (m_iconProvider) {
|
||||
info.icon = m_iconProvider->icon(fileInfo);
|
||||
info.displayType = m_iconProvider->type(fileInfo);
|
||||
} else {
|
||||
info.displayType = QAbstractFileIconProviderPrivate::getFileType(fileInfo);
|
||||
}
|
||||
#if QT_CONFIG(filesystemwatcher)
|
||||
// ### Not ready to listen all modifications by default
|
||||
static const bool watchFiles = qEnvironmentVariableIsSet("QT_FILESYSTEMMODEL_WATCH_FILES");
|
||||
|
@ -693,7 +693,9 @@ QVariant QFileSystemModel::myComputer(int role) const
|
||||
return QFileSystemModelPrivate::myComputer();
|
||||
#if QT_CONFIG(filesystemwatcher)
|
||||
case Qt::DecorationRole:
|
||||
return d->fileInfoGatherer->iconProvider()->icon(QAbstractFileIconProvider::Computer);
|
||||
if (auto *provider = d->fileInfoGatherer->iconProvider())
|
||||
return provider->icon(QAbstractFileIconProvider::Computer);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return QVariant();
|
||||
@ -733,10 +735,9 @@ QVariant QFileSystemModel::data(const QModelIndex &index, int role) const
|
||||
QIcon icon = d->icon(index);
|
||||
#if QT_CONFIG(filesystemwatcher)
|
||||
if (icon.isNull()) {
|
||||
if (d->node(index)->isDir())
|
||||
icon = d->fileInfoGatherer->iconProvider()->icon(QAbstractFileIconProvider::Folder);
|
||||
else
|
||||
icon = d->fileInfoGatherer->iconProvider()->icon(QAbstractFileIconProvider::File);
|
||||
using P = QAbstractFileIconProvider;
|
||||
if (auto *provider = d->fileInfoGatherer->iconProvider())
|
||||
icon = provider->icon(d->node(index)->isDir() ? P::Folder: P::File);
|
||||
}
|
||||
#endif // filesystemwatcher
|
||||
return icon;
|
||||
@ -1569,7 +1570,7 @@ QAbstractFileIconProvider *QFileSystemModel::iconProvider() const
|
||||
Q_D(const QFileSystemModel);
|
||||
return d->fileInfoGatherer->iconProvider();
|
||||
#else
|
||||
return 0;
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -150,8 +150,12 @@ public:
|
||||
return visibleChildren.indexOf(childName);
|
||||
}
|
||||
void updateIcon(QAbstractFileIconProvider *iconProvider, const QString &path) {
|
||||
if (!iconProvider)
|
||||
return;
|
||||
|
||||
if (info)
|
||||
info->icon = iconProvider->icon(QFileInfo(path));
|
||||
|
||||
for (QFileSystemNode *child : std::as_const(children)) {
|
||||
//On windows the root (My computer) has no path so we don't want to add a / for nothing (e.g. /C:/)
|
||||
if (!path.isEmpty()) {
|
||||
@ -165,6 +169,9 @@ public:
|
||||
}
|
||||
|
||||
void retranslateStrings(QAbstractFileIconProvider *iconProvider, const QString &path) {
|
||||
if (!iconProvider)
|
||||
return;
|
||||
|
||||
if (info)
|
||||
info->displayType = iconProvider->type(QFileInfo(path));
|
||||
for (QFileSystemNode *child : std::as_const(children)) {
|
||||
|
@ -183,11 +183,14 @@ void QUrlModel::setUrl(const QModelIndex &index, const QUrl &url, const QModelIn
|
||||
setData(index, true, EnabledRole);
|
||||
}
|
||||
|
||||
// newIcon could be null if fileSystemModel->iconProvider() returns null
|
||||
if (!newIcon.isNull()) {
|
||||
// Make sure that we have at least 32x32 images
|
||||
const QSize size = newIcon.actualSize(QSize(32,32));
|
||||
if (size.width() < 32) {
|
||||
QPixmap smallPixmap = newIcon.pixmap(QSize(32, 32));
|
||||
newIcon.addPixmap(smallPixmap.scaledToWidth(32, Qt::SmoothTransformation));
|
||||
const QSize size = newIcon.actualSize(QSize(32,32));
|
||||
if (size.width() < 32) {
|
||||
QPixmap smallPixmap = newIcon.pixmap(QSize(32, 32));
|
||||
newIcon.addPixmap(smallPixmap.scaledToWidth(32, Qt::SmoothTransformation));
|
||||
}
|
||||
}
|
||||
|
||||
if (index.data().toString() != newName)
|
||||
|
@ -65,6 +65,7 @@ private slots:
|
||||
void rootPath();
|
||||
void readOnly();
|
||||
void iconProvider();
|
||||
void nullIconProvider();
|
||||
|
||||
void rowCount();
|
||||
|
||||
@ -311,6 +312,19 @@ void tst_QFileSystemModel::iconProvider()
|
||||
QCOMPARE(myModel->fileIcon(myModel->index(QDir::homePath())).pixmap(50, 50), mb);
|
||||
}
|
||||
|
||||
void tst_QFileSystemModel::nullIconProvider()
|
||||
{
|
||||
QFileSystemModel model;
|
||||
QAbstractItemModelTester tester(&model);
|
||||
tester.setUseFetchMore(false);
|
||||
QVERIFY(model.iconProvider());
|
||||
// No crash when setIconProvider(nullptr) is used
|
||||
model.setIconProvider(nullptr);
|
||||
const auto documentPaths = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
|
||||
QVERIFY(!documentPaths.isEmpty());
|
||||
model.setRootPath(documentPaths.constFirst());
|
||||
}
|
||||
|
||||
bool tst_QFileSystemModel::createFiles(QFileSystemModel *model, const QString &test_path,
|
||||
const QStringList &initial_files, int existingFileCount,
|
||||
const QStringList &initial_dirs)
|
||||
|
@ -86,6 +86,7 @@ FileDialogPanel::FileDialogPanel(QWidget *parent)
|
||||
, m_resolveSymLinks(new QCheckBox(tr("Resolve symlinks")))
|
||||
, m_native(new QCheckBox(tr("Use native dialog")))
|
||||
, m_customDirIcons(new QCheckBox(tr("Don't use custom directory icons")))
|
||||
, m_noIconProvider(new QCheckBox(tr("Null icon provider")))
|
||||
, m_acceptMode(createCombo(this, acceptModeComboData, sizeof(acceptModeComboData)/sizeof(FlagData)))
|
||||
, m_fileMode(createCombo(this, fileModeComboData, sizeof(fileModeComboData)/sizeof(FlagData)))
|
||||
, m_viewMode(createCombo(this, viewModeComboData, sizeof(viewModeComboData)/sizeof(FlagData)))
|
||||
@ -113,6 +114,7 @@ FileDialogPanel::FileDialogPanel(QWidget *parent)
|
||||
optionsLayout->addRow(m_resolveSymLinks);
|
||||
optionsLayout->addRow(m_readOnly);
|
||||
optionsLayout->addRow(m_customDirIcons);
|
||||
optionsLayout->addRow(m_noIconProvider);
|
||||
|
||||
// Files
|
||||
QGroupBox *filesGroupBox = new QGroupBox(tr("Files / Filters"));
|
||||
@ -417,12 +419,19 @@ void FileDialogPanel::restoreDefaults()
|
||||
l->restoreDefault(&d);
|
||||
}
|
||||
|
||||
void FileDialogPanel::applySettings(QFileDialog *d) const
|
||||
void FileDialogPanel::applySettings(QFileDialog *d)
|
||||
{
|
||||
d->setAcceptMode(comboBoxValue<QFileDialog::AcceptMode>(m_acceptMode));
|
||||
d->setViewMode(comboBoxValue<QFileDialog::ViewMode>(m_viewMode));
|
||||
d->setFileMode(comboBoxValue<QFileDialog::FileMode>(m_fileMode));
|
||||
d->setOptions(options());
|
||||
if (m_noIconProvider->isChecked()) {
|
||||
m_origIconProvider = d->iconProvider();
|
||||
d->setIconProvider(nullptr);
|
||||
} else if (m_origIconProvider) {
|
||||
d->setIconProvider(m_origIconProvider);
|
||||
}
|
||||
|
||||
d->setDefaultSuffix(m_defaultSuffix->text().trimmed());
|
||||
const QString directory = m_directory->text().trimmed();
|
||||
if (!directory.isEmpty())
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <QPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAbstractFileIconProvider;
|
||||
class QPushButton;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
@ -52,7 +54,7 @@ private:
|
||||
QString filterString() const;
|
||||
QFileDialog::Options options() const;
|
||||
QStringList allowedSchemes() const;
|
||||
void applySettings(QFileDialog *d) const;
|
||||
void applySettings(QFileDialog *d);
|
||||
|
||||
QFormLayout *filesLayout;
|
||||
QCheckBox *m_showDirsOnly;
|
||||
@ -62,6 +64,9 @@ private:
|
||||
QCheckBox *m_resolveSymLinks;
|
||||
QCheckBox *m_native;
|
||||
QCheckBox *m_customDirIcons;
|
||||
QCheckBox *m_noIconProvider = nullptr;
|
||||
QAbstractFileIconProvider *m_origIconProvider = nullptr;
|
||||
|
||||
QComboBox *m_acceptMode;
|
||||
QComboBox *m_fileMode;
|
||||
QComboBox *m_viewMode;
|
||||
|
Loading…
x
Reference in New Issue
Block a user