Windows: Introduce QFileDialog::DontUseCustomDirectoryIcons
Folders can have a custom icon, set by the user. Some system folders also have one, for example c:\windows\fonts. This option allows you to disable this behavior, you'll get the folder directory icon. As a side-effect, you'll get a very big performance improvement on removable/network media: 2 seconds vs 60 seconds on a SDCard with 10000 folders. Change-Id: Id55ea628186e0a6523585ec7a4ff622d6f5da505 Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
This commit is contained in:
parent
0e9ea64edc
commit
46685f755b
@ -217,13 +217,14 @@ public:
|
||||
|
||||
enum FileDialogOption
|
||||
{
|
||||
ShowDirsOnly = 0x00000001,
|
||||
DontResolveSymlinks = 0x00000002,
|
||||
DontConfirmOverwrite = 0x00000004,
|
||||
DontUseSheet = 0x00000008,
|
||||
DontUseNativeDialog = 0x00000010,
|
||||
ReadOnly = 0x00000020,
|
||||
HideNameFilterDetails = 0x00000040
|
||||
ShowDirsOnly = 0x00000001,
|
||||
DontResolveSymlinks = 0x00000002,
|
||||
DontConfirmOverwrite = 0x00000004,
|
||||
DontUseSheet = 0x00000008,
|
||||
DontUseNativeDialog = 0x00000010,
|
||||
ReadOnly = 0x00000020,
|
||||
HideNameFilterDetails = 0x00000040,
|
||||
DontUseCustomDirectoryIcons = 0x00000080
|
||||
};
|
||||
Q_DECLARE_FLAGS(FileDialogOptions, FileDialogOption)
|
||||
|
||||
|
@ -208,10 +208,12 @@ QPixmap QPlatformTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) co
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
QPixmap QPlatformTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const
|
||||
QPixmap QPlatformTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
|
||||
QPlatformTheme::IconOptions iconOptions) const
|
||||
{
|
||||
Q_UNUSED(fileInfo);
|
||||
Q_UNUSED(size);
|
||||
Q_UNUSED(iconOptions);
|
||||
// TODO Should return QCommonStyle pixmaps?
|
||||
return QPixmap();
|
||||
}
|
||||
|
@ -253,6 +253,11 @@ public:
|
||||
AnimateToolBoxUiEffect = 0x40
|
||||
};
|
||||
|
||||
enum IconOption {
|
||||
DontUseCustomDirectoryIcons = 0x01
|
||||
};
|
||||
Q_DECLARE_FLAGS(IconOptions, IconOption)
|
||||
|
||||
explicit QPlatformTheme();
|
||||
virtual ~QPlatformTheme();
|
||||
|
||||
@ -274,7 +279,8 @@ public:
|
||||
virtual QVariant themeHint(ThemeHint hint) const;
|
||||
|
||||
virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
|
||||
virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const;
|
||||
virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
|
||||
QPlatformTheme::IconOptions iconOptions = 0) const;
|
||||
|
||||
virtual QIconEngine *createIconEngine(const QString &iconName) const;
|
||||
|
||||
|
@ -68,7 +68,9 @@ public:
|
||||
const QPalette *palette(Palette type = SystemPalette) const;
|
||||
const QFont *font(Font type = SystemFont) const;
|
||||
QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
|
||||
QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const;
|
||||
QPixmap fileIconPixmap(const QFileInfo &fileInfo,
|
||||
const QSizeF &size,
|
||||
QPlatformTheme::IconOptions options = 0) const;
|
||||
|
||||
QVariant themeHint(ThemeHint hint) const;
|
||||
|
||||
|
@ -249,8 +249,10 @@ QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
|
||||
return QPlatformTheme::standardPixmap(sp, size);
|
||||
}
|
||||
|
||||
QPixmap QCocoaTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const
|
||||
QPixmap QCocoaTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
|
||||
QPlatformTheme::IconOptions iconOptions) const
|
||||
{
|
||||
Q_UNUSED(iconOptions);
|
||||
QCocoaAutoReleasePool pool;
|
||||
|
||||
NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFile:QCFString::toNSString(fileInfo.canonicalFilePath())];
|
||||
|
@ -595,7 +595,8 @@ public:
|
||||
void operator delete (void *) {}
|
||||
};
|
||||
|
||||
QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const
|
||||
QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
|
||||
QPlatformTheme::IconOptions iconOptions) const
|
||||
{
|
||||
/* We don't use the variable, but by storing it statically, we
|
||||
* ensure CoInitialize is only called once. */
|
||||
@ -604,6 +605,8 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
|
||||
|
||||
static QCache<QString, FakePointer<int> > dirIconEntryCache(1000);
|
||||
static QMutex mx;
|
||||
static int defaultFolderIIcon = 0;
|
||||
const bool useDefaultFolderIcon = iconOptions & QPlatformTheme::DontUseCustomDirectoryIcons;
|
||||
|
||||
QPixmap pixmap;
|
||||
const QString filePath = QDir::toNativeSeparators(fileInfo.filePath());
|
||||
@ -612,7 +615,8 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
|
||||
bool cacheableDirIcon = fileInfo.isDir() && !fileInfo.isRoot();
|
||||
if (cacheableDirIcon) {
|
||||
QMutexLocker locker(&mx);
|
||||
int iIcon = **dirIconEntryCache.object(filePath);
|
||||
int iIcon = (useDefaultFolderIcon && defaultFolderIIcon) ? defaultFolderIIcon
|
||||
: **dirIconEntryCache.object(filePath);
|
||||
if (iIcon) {
|
||||
QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize), pixmap);
|
||||
if (pixmap.isNull()) // Let's keep both caches in sync
|
||||
@ -629,13 +633,24 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
|
||||
#else
|
||||
iconSize|SHGFI_SYSICONINDEX;
|
||||
#endif // Q_OS_WINCE
|
||||
unsigned long val = SHGetFileInfo((const wchar_t *)filePath.utf16(), 0,
|
||||
&info, sizeof(SHFILEINFO), flags);
|
||||
unsigned long val = 0;
|
||||
if (cacheableDirIcon && useDefaultFolderIcon) {
|
||||
flags |= SHGFI_USEFILEATTRIBUTES;
|
||||
val = SHGetFileInfo(L"dummy",
|
||||
FILE_ATTRIBUTE_DIRECTORY,
|
||||
&info, sizeof(SHFILEINFO), flags);
|
||||
} else {
|
||||
val = SHGetFileInfo(reinterpret_cast<const wchar_t *>(filePath.utf16()), 0,
|
||||
&info, sizeof(SHFILEINFO), flags);
|
||||
}
|
||||
|
||||
// Even if GetFileInfo returns a valid result, hIcon can be empty in some cases
|
||||
if (val && info.hIcon) {
|
||||
QString key;
|
||||
if (cacheableDirIcon) {
|
||||
if (useDefaultFolderIcon && !defaultFolderIIcon)
|
||||
defaultFolderIIcon = info.iIcon;
|
||||
|
||||
//using the unique icon index provided by windows save us from duplicate keys
|
||||
key = dirIconPixmapCacheKey(info.iIcon, iconSize);
|
||||
QPixmapCache::find(key, pixmap);
|
||||
|
@ -68,7 +68,8 @@ public:
|
||||
{ return m_fonts[type]; }
|
||||
|
||||
virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
|
||||
virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const;
|
||||
virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
|
||||
QPlatformTheme::IconOptions iconOptions = 0) const;
|
||||
|
||||
void windowsThemeChanged(QWindow *window);
|
||||
|
||||
|
@ -255,6 +255,11 @@ Q_WIDGETS_EXPORT _qt_filedialog_save_file_url_hook qt_filedialog_save_file_url_h
|
||||
static functions will always be an application modal dialog. If
|
||||
you want to use sheets, use QFileDialog::open() instead.
|
||||
|
||||
\value DontUseCustomDirectoryIcons Always use the default directory icon.
|
||||
Some platforms allow the user to set a different icon. Custom icon lookup
|
||||
cause a big performance impact over network or removable drives.
|
||||
Setting this will enable the QFileIconProvider::DontUseCustomDirectoryIcons
|
||||
option in the icon provider. This enum value was added in Qt 5.2.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -754,6 +759,15 @@ void QFileDialog::setOptions(Options options)
|
||||
|
||||
if (changed & ShowDirsOnly)
|
||||
setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);
|
||||
|
||||
if (changed & DontUseCustomDirectoryIcons) {
|
||||
QFileIconProvider::Options providerOptions = iconProvider()->options();
|
||||
if (options & DontUseCustomDirectoryIcons)
|
||||
providerOptions |= QFileIconProvider::DontUseCustomDirectoryIcons;
|
||||
else
|
||||
providerOptions &= ~QFileIconProvider::DontUseCustomDirectoryIcons;
|
||||
iconProvider()->setOptions(providerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
QFileDialog::Options QFileDialog::options() const
|
||||
|
@ -84,13 +84,14 @@ public:
|
||||
|
||||
enum Option
|
||||
{
|
||||
ShowDirsOnly = 0x00000001,
|
||||
DontResolveSymlinks = 0x00000002,
|
||||
DontConfirmOverwrite = 0x00000004,
|
||||
DontUseSheet = 0x00000008,
|
||||
DontUseNativeDialog = 0x00000010,
|
||||
ReadOnly = 0x00000020,
|
||||
HideNameFilterDetails = 0x00000040
|
||||
ShowDirsOnly = 0x00000001,
|
||||
DontResolveSymlinks = 0x00000002,
|
||||
DontConfirmOverwrite = 0x00000004,
|
||||
DontUseSheet = 0x00000008,
|
||||
DontUseNativeDialog = 0x00000010,
|
||||
ReadOnly = 0x00000020,
|
||||
HideNameFilterDetails = 0x00000040,
|
||||
DontUseCustomDirectoryIcons = 0x00000080
|
||||
};
|
||||
Q_DECLARE_FLAGS(Options, Option)
|
||||
|
||||
|
@ -83,6 +83,16 @@ QT_BEGIN_NAMESPACE
|
||||
\value File
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\enum QFileIconProvider::Option
|
||||
\since 5.2
|
||||
|
||||
\value DontUseCustomDirectoryIcons Always use the default directory icon.
|
||||
Some platforms allow the user to set a different icon. Custom icon lookup
|
||||
cause a big performance impact over network or removable drives.
|
||||
*/
|
||||
|
||||
class QFileIconProviderPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QFileIconProvider)
|
||||
@ -94,6 +104,7 @@ public:
|
||||
|
||||
QFileIconProvider *q_ptr;
|
||||
const QString homePath;
|
||||
QFileIconProvider::Options options;
|
||||
|
||||
private:
|
||||
mutable QIcon file;
|
||||
@ -192,6 +203,31 @@ QFileIconProvider::~QFileIconProvider()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.2
|
||||
Sets \a options that affect the icon provider.
|
||||
\sa options()
|
||||
*/
|
||||
|
||||
void QFileIconProvider::setOptions(QFileIconProvider::Options options)
|
||||
{
|
||||
Q_D(QFileIconProvider);
|
||||
d->options = options;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.2
|
||||
Returns all the options that affect the icon provider.
|
||||
By default, all options are disabled.
|
||||
\sa setOptions()
|
||||
*/
|
||||
|
||||
QFileIconProvider::Options QFileIconProvider::options() const
|
||||
{
|
||||
Q_D(const QFileIconProvider);
|
||||
return d->options;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns an icon set for the given \a type.
|
||||
*/
|
||||
@ -228,6 +264,7 @@ static bool isCacheable(const QFileInfo &fi)
|
||||
#ifdef Q_OS_WIN
|
||||
// On windows it's faster to just look at the file extensions. QTBUG-13182
|
||||
const QString fileExtension = fi.suffix();
|
||||
// Will return false for .exe, .lnk and .ico extensions
|
||||
return fileExtension.compare(QLatin1String("exe"), Qt::CaseInsensitive) &&
|
||||
fileExtension.compare(QLatin1String("lnk"), Qt::CaseInsensitive) &&
|
||||
fileExtension.compare(QLatin1String("ico"), Qt::CaseInsensitive);
|
||||
@ -247,7 +284,6 @@ QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const
|
||||
if (sizes.isEmpty())
|
||||
return retIcon;
|
||||
|
||||
const QString fileExtension = fi.suffix().toUpper();
|
||||
const QString keyBase = QLatin1String("qt_.") + fi.suffix().toUpper();
|
||||
|
||||
bool cacheable = isCacheable(fi);
|
||||
@ -269,8 +305,12 @@ QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const
|
||||
}
|
||||
}
|
||||
|
||||
QPlatformTheme::IconOptions iconOptions;
|
||||
if (options & QFileIconProvider::DontUseCustomDirectoryIcons)
|
||||
iconOptions |= QPlatformTheme::DontUseCustomDirectoryIcons;
|
||||
|
||||
Q_FOREACH (int size, sizes) {
|
||||
QPixmap pixmap = theme->fileIconPixmap(fi, QSizeF(size, size));
|
||||
QPixmap pixmap = theme->fileIconPixmap(fi, QSizeF(size, size), iconOptions);
|
||||
if (!pixmap.isNull()) {
|
||||
retIcon.addPixmap(pixmap);
|
||||
if (cacheable)
|
||||
|
@ -59,10 +59,19 @@ public:
|
||||
QFileIconProvider();
|
||||
virtual ~QFileIconProvider();
|
||||
enum IconType { Computer, Desktop, Trashcan, Network, Drive, Folder, File };
|
||||
|
||||
enum Option {
|
||||
DontUseCustomDirectoryIcons = 0x00000001
|
||||
};
|
||||
Q_DECLARE_FLAGS(Options, Option)
|
||||
|
||||
virtual QIcon icon(IconType type) const;
|
||||
virtual QIcon icon(const QFileInfo &info) const;
|
||||
virtual QString type(const QFileInfo &info) const;
|
||||
|
||||
void setOptions(Options options);
|
||||
Options options() const;
|
||||
|
||||
private:
|
||||
Q_DECLARE_PRIVATE(QFileIconProvider)
|
||||
QScopedPointer<QFileIconProviderPrivate> d_ptr;
|
||||
@ -71,6 +80,8 @@ private:
|
||||
|
||||
#endif // QT_NO_FILEICONPROVIDER
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileIconProvider::Options)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QFILEICONPROVIDER_H
|
||||
|
@ -154,6 +154,7 @@ FileDialogPanel::FileDialogPanel(QWidget *parent)
|
||||
, m_nameFilterDetailsVisible(new QCheckBox(tr("Name filter details visible")))
|
||||
, 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_acceptMode(createCombo(this, acceptModeComboData, sizeof(acceptModeComboData)/sizeof(ComboData)))
|
||||
, m_fileMode(createCombo(this, fileModeComboData, sizeof(fileModeComboData)/sizeof(ComboData)))
|
||||
, m_viewMode(createCombo(this, viewModeComboData, sizeof(viewModeComboData)/sizeof(ComboData)))
|
||||
@ -178,6 +179,7 @@ FileDialogPanel::FileDialogPanel(QWidget *parent)
|
||||
optionsLayout->addRow(m_nameFilterDetailsVisible);
|
||||
optionsLayout->addRow(m_resolveSymLinks);
|
||||
optionsLayout->addRow(m_readOnly);
|
||||
optionsLayout->addRow(m_customDirIcons);
|
||||
|
||||
// Files
|
||||
QGroupBox *filesGroupBox = new QGroupBox(tr("Files / Filters"));
|
||||
@ -322,6 +324,8 @@ QFileDialog::Options FileDialogPanel::options() const
|
||||
result |= QFileDialog::DontConfirmOverwrite;
|
||||
if (!m_native->isChecked())
|
||||
result |= QFileDialog::DontUseNativeDialog;
|
||||
if (!m_customDirIcons->isChecked())
|
||||
result |= QFileDialog::DontUseCustomDirectoryIcons;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -454,6 +458,7 @@ void FileDialogPanel::restoreDefaults()
|
||||
m_resolveSymLinks->setChecked(d.resolveSymlinks());
|
||||
m_readOnly->setChecked(d.isReadOnly());
|
||||
m_native->setChecked(true);
|
||||
m_customDirIcons->setChecked(d.testOption(QFileDialog::DontUseCustomDirectoryIcons));
|
||||
m_directory->setText(QDir::homePath());
|
||||
m_defaultSuffix->setText(QLatin1String("txt"));
|
||||
m_nameFilters->setPlainText(QLatin1String("Any files (*)\nImage files (*.png *.xpm *.jpg)\nText files (*.txt)"));
|
||||
|
@ -92,6 +92,7 @@ private:
|
||||
QCheckBox *m_nameFilterDetailsVisible;
|
||||
QCheckBox *m_resolveSymLinks;
|
||||
QCheckBox *m_native;
|
||||
QCheckBox *m_customDirIcons;
|
||||
QComboBox *m_acceptMode;
|
||||
QComboBox *m_fileMode;
|
||||
QComboBox *m_viewMode;
|
||||
|
Loading…
Reference in New Issue
Block a user