summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorSergio Martins <sergio.martins@kdab.com>2013-05-29 12:04:55 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-09 15:29:47 +0200
commit5bb495c9b8f64bc2cb435d62674f2b0fdfa5d764 (patch)
tree16a139b350ec7ded9e5ab8af5b0cbe8e06bab7c7 /src/gui
parent8d120435d7fce0e29b33900b7ddf81c4e9f0b50e (diff)
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. Unlike in Qt5, here we didn't add new methods to QFileIconProvider do avoid introducing new symbols. Change-Id: I0b98a180e53c9ee7d583f19b3917fcc9166cb3eb Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> (cherry picked from qtbase/46685f755b01288fd53c4483cb97a22c426a57f0) (cherry picked from qtbase/149f3efc39bebbe8fceacf2553836f90d2e1c383) Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/dialogs/qfiledialog.cpp8
-rw-r--r--src/gui/dialogs/qfiledialog.h15
-rw-r--r--src/gui/itemviews/qfileiconprovider.cpp37
-rw-r--r--src/gui/itemviews/qfileiconprovider.h1
-rw-r--r--src/gui/itemviews/qfileiconprovider_p.h2
5 files changed, 52 insertions, 11 deletions
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index 7df8197d8f..3518780c01 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -58,6 +58,7 @@
#include <qdebug.h>
#include <qapplication.h>
#include <qstylepainter.h>
+#include <itemviews/qfileiconprovider_p.h>
#if !defined(Q_WS_WINCE) && !defined(Q_OS_SYMBIAN)
#include "ui_qfiledialog.h"
#else
@@ -240,6 +241,10 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook
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 affect the behavior of the icon provider. This enum value was added in Qt 4.8.6.
*/
/*!
@@ -685,6 +690,9 @@ void QFileDialog::setOptions(Options options)
if (changed & ShowDirsOnly)
setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);
+
+ if (changed & DontUseCustomDirectoryIcons)
+ iconProvider()->d_ptr->setUseCustomDirectoryIcons(!(options & DontUseCustomDirectoryIcons));
}
QFileDialog::Options QFileDialog::options() const
diff --git a/src/gui/dialogs/qfiledialog.h b/src/gui/dialogs/qfiledialog.h
index 66c02c4613..817ee8da00 100644
--- a/src/gui/dialogs/qfiledialog.h
+++ b/src/gui/dialogs/qfiledialog.h
@@ -88,13 +88,14 @@ public:
// ### Rename to FileDialogOption and FileDialogOptions for Qt 5.0
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)
diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp
index f1ad7e0fc6..9fd9e9987d 100644
--- a/src/gui/itemviews/qfileiconprovider.cpp
+++ b/src/gui/itemviews/qfileiconprovider.cpp
@@ -89,10 +89,15 @@ QT_BEGIN_NAMESPACE
*/
QFileIconProviderPrivate::QFileIconProviderPrivate() :
- homePath(QDir::home().absolutePath())
+ homePath(QDir::home().absolutePath()), useCustomDirectoryIcons(true)
{
}
+void QFileIconProviderPrivate::setUseCustomDirectoryIcons(bool enable)
+{
+ useCustomDirectoryIcons = enable;
+}
+
QIcon QFileIconProviderPrivate::getIcon(QStyle::StandardPixmap name) const
{
switch (name) {
@@ -213,6 +218,8 @@ static bool isCacheable(const QFileInfo &fi)
QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
{
QIcon retIcon;
+ static int defaultFolderIIcon = -1;
+
QString key;
QPixmap pixmap;
// If it's a file, non-{exe,lnk,ico} then we might have it cached already
@@ -228,6 +235,19 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
}
}
+ const bool cacheableDirIcon = fileInfo.isDir() && !fileInfo.isRoot();
+ if (!useCustomDirectoryIcons && defaultFolderIIcon >= 0 && cacheableDirIcon) {
+ // We already have the default folder icon, just return it
+ key = QString::fromLatin1("qt_dir_%1").arg(defaultFolderIIcon);
+ QPixmapCache::find(key, pixmap);
+ if (!pixmap.isNull()) {
+ retIcon.addPixmap(pixmap);
+ if (QPixmapCache::find(key + QLatin1Char('l'), pixmap))
+ retIcon.addPixmap(pixmap);
+ return retIcon;
+ }
+ }
+
/* We don't use the variable, but by storing it statically, we
* ensure CoInitialize is only called once. */
static HRESULT comInit = CoInitialize(NULL);
@@ -237,19 +257,28 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
unsigned long val = 0;
//Get the small icon
- const unsigned int flags =
+ unsigned int flags =
#ifndef Q_OS_WINCE
SHGFI_ICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX;
#else
SHGFI_SYSICONINDEX;
#endif
- val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(),
- 0, &info, sizeof(SHFILEINFO), flags | SHGFI_SMALLICON);
+ if (cacheableDirIcon && !useCustomDirectoryIcons) {
+ flags |= SHGFI_USEFILEATTRIBUTES;
+ val = SHGetFileInfo(L"dummy",
+ FILE_ATTRIBUTE_DIRECTORY, &info,
+ sizeof(SHFILEINFO), flags | SHGFI_SMALLICON);
+ } else {
+ val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(),
+ 0, &info, sizeof(SHFILEINFO), flags | SHGFI_SMALLICON);
+ }
// Even if GetFileInfo returns a valid result, hIcon can be empty in some cases
if (val && info.hIcon) {
if (fileInfo.isDir() && !fileInfo.isRoot()) {
+ if (!useCustomDirectoryIcons && defaultFolderIIcon < 0)
+ defaultFolderIIcon = info.iIcon;
//using the unique icon index provided by windows save us from duplicate keys
key = QString::fromLatin1("qt_dir_%1").arg(info.iIcon);
QPixmapCache::find(key, pixmap);
diff --git a/src/gui/itemviews/qfileiconprovider.h b/src/gui/itemviews/qfileiconprovider.h
index 2ae4e81e86..3c98562313 100644
--- a/src/gui/itemviews/qfileiconprovider.h
+++ b/src/gui/itemviews/qfileiconprovider.h
@@ -70,6 +70,7 @@ private:
Q_DECLARE_PRIVATE(QFileIconProvider)
QScopedPointer<QFileIconProviderPrivate> d_ptr;
Q_DISABLE_COPY(QFileIconProvider)
+ friend class QFileDialog;
};
#endif // QT_NO_FILEICONPROVIDER
diff --git a/src/gui/itemviews/qfileiconprovider_p.h b/src/gui/itemviews/qfileiconprovider_p.h
index 704418b589..a44ae51180 100644
--- a/src/gui/itemviews/qfileiconprovider_p.h
+++ b/src/gui/itemviews/qfileiconprovider_p.h
@@ -57,6 +57,7 @@ class QFileIconProviderPrivate
public:
QFileIconProviderPrivate();
+ void setUseCustomDirectoryIcons(bool enable);
QIcon getIcon(QStyle::StandardPixmap name) const;
#ifdef Q_WS_WIN
QIcon getWinIcon(const QFileInfo &fi) const;
@@ -67,6 +68,7 @@ public:
const QString homePath;
private:
+ bool useCustomDirectoryIcons;
mutable QIcon file;
mutable QIcon fileLink;
mutable QIcon directory;