summaryrefslogtreecommitdiff
path: root/src/plugins/coreplugin/fileiconprovider.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/coreplugin/fileiconprovider.cpp')
-rw-r--r--src/plugins/coreplugin/fileiconprovider.cpp185
1 files changed, 120 insertions, 65 deletions
diff --git a/src/plugins/coreplugin/fileiconprovider.cpp b/src/plugins/coreplugin/fileiconprovider.cpp
index 5615fb81d9..03bfb56cf4 100644
--- a/src/plugins/coreplugin/fileiconprovider.cpp
+++ b/src/plugins/coreplugin/fileiconprovider.cpp
@@ -30,68 +30,138 @@
#include "fileiconprovider.h"
#include "mimedatabase.h"
+#include <utils/qtcassert.h>
+
#include <QtGui/QApplication>
#include <QtGui/QStyle>
#include <QtGui/QPainter>
+#include <QtCore/QFileInfo>
+#include <QtCore/QPair>
+#include <QtCore/QDebug>
-using namespace Core;
+#include <QtGui/QFileIconProvider>
+#include <QtGui/QIcon>
+#include <QtGui/QStyle>
/*!
\class FileIconProvider
- Provides icons based on file suffixes.
+ Provides icons based on file suffixes with the ability to overwrite system
+ icons for specific subtypes. Implements the QFileIconProvider interface
+ and can therefore be used for QFileSystemModel.
+
+ Note: Registering overlay icons currently completely replaces the system
+ icon and is therefore not recommended on platforms that have their
+ own overlay icon handling (Mac/Windows).
The class is a singleton: It's instance can be accessed via the static instance() method.
Plugins can register custom icons via registerIconSuffix(), and retrieve icons via the icon()
method.
+ The instance is explicitly deleted by the core plugin for destruction order reasons.
*/
-FileIconProvider *FileIconProvider::m_instance = 0;
+// Cache icons in a list of pairs suffix/icon which should be faster than
+// hashes for small lists.
+
+enum { debug = 0 };
+
+typedef QPair<QString, QIcon> StringIconPair;
+typedef QList<StringIconPair> StringIconPairList;
+
+// Helper to find an icon by suffix in a list of pairs for const/non-const-iterators.
+
+template <class StringIconPairListIterator>
+inline StringIconPairListIterator
+findBySuffix(const QString &suffix,
+ StringIconPairListIterator iter,
+ const StringIconPairListIterator &end)
+{
+ for (; iter != end; ++iter)
+ if ((*iter).first == suffix)
+ return iter;
+ return end;
+}
+
+namespace Core {
+
+struct FileIconProviderPrivate {
+ FileIconProviderPrivate();
+
+ // Mapping of file suffix to icon.
+ StringIconPairList m_cache;
-FileIconProvider::FileIconProvider()
- : m_unknownFileIcon(qApp->style()->standardIcon(QStyle::SP_FileIcon))
+ QFileIconProvider m_systemIconProvider;
+ QIcon m_unknownFileIcon;
+
+ // singleton pattern
+ static FileIconProvider *m_instance;
+};
+
+FileIconProviderPrivate::FileIconProviderPrivate() :
+ m_unknownFileIcon(qApp->style()->standardIcon(QStyle::SP_FileIcon))
+{
+}
+
+FileIconProvider *FileIconProviderPrivate::m_instance = 0;
+
+// FileIconProvider
+
+FileIconProvider::FileIconProvider() :
+ d(new FileIconProviderPrivate)
{
+ FileIconProviderPrivate::m_instance = this;
}
FileIconProvider::~FileIconProvider()
{
- m_instance = 0;
+ FileIconProviderPrivate::m_instance = 0;
+ delete d;
}
/*!
Returns the icon associated with the file suffix in fileInfo. If there is none,
the default icon of the operating system is returned.
*/
-QIcon FileIconProvider::icon(const QFileInfo &fileInfo)
-{
- const QString suffix = fileInfo.suffix();
- QIcon icon = iconForSuffix(suffix);
-
- if (icon.isNull()) {
- // Get icon from OS and store it in the cache
- // Disabled since for now we'll make sure that all icons fit with our
- // own custom icons by returning an empty one if we don't know it.
+QIcon FileIconProvider::icon(const QFileInfo &fileInfo) const
+{
+ typedef StringIconPairList::const_iterator CacheConstIterator;
+
+ if (debug)
+ qDebug() << "FileIconProvider::icon" << fileInfo.absoluteFilePath();
+ // Check for cached overlay icons by file suffix.
+ if (!d->m_cache.isEmpty() && !fileInfo.isDir()) {
+ const QString suffix = fileInfo.suffix();
+ if (!suffix.isEmpty()) {
+ const CacheConstIterator it = findBySuffix(suffix, d->m_cache.constBegin(), d->m_cache.constEnd());
+ if (it != d->m_cache.constEnd())
+ return (*it).second;
+ }
+ }
+ // Get icon from OS.
#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
- // This is incorrect if the OS does not always return the same icon for the
- // same suffix (Mac OS X), but should speed up the retrieval a lot ...
- icon = m_systemIconProvider.icon(fileInfo);
- if (!suffix.isEmpty())
- registerIconOverlayForSuffix(icon, suffix);
+ return d->m_systemIconProvider.icon(fileInfo);
#else
- if (fileInfo.isDir()) {
- icon = m_systemIconProvider.icon(fileInfo);
- } else {
- icon = m_unknownFileIcon;
- }
+ // File icons are unknown on linux systems.
+ return (fileInfo.isDir()) ?
+ d->m_systemIconProvider.icon(fileInfo) :
+ d->m_unknownFileIcon;
#endif
- }
+}
+
+QIcon FileIconProvider::icon(IconType type) const
+{
+ return d->m_systemIconProvider.icon(type);
+}
- return icon;
+QString FileIconProvider::type(const QFileInfo &info) const
+{
+ return d->m_systemIconProvider.type(info);
}
/*!
Creates a pixmap with baseicon at size and overlays overlayIcon over it.
+ See platform note in class documentation about recommended usage.
*/
QPixmap FileIconProvider::overlayIcon(QStyle::StandardPixmap baseIcon, const QIcon &overlayIcon, const QSize &size) const
{
@@ -104,21 +174,26 @@ QPixmap FileIconProvider::overlayIcon(QStyle::StandardPixmap baseIcon, const QIc
/*!
Registers an icon for a given suffix, overlaying the system file icon.
+ See platform note in class documentation about recommended usage.
*/
-void FileIconProvider::registerIconOverlayForSuffix(const QIcon &icon, const QString &suffix)
+void FileIconProvider::registerIconOverlayForSuffix(const QIcon &icon,
+ const QString &suffix)
{
- QPixmap fileIconPixmap = overlayIcon(QStyle::SP_FileIcon, icon, QSize(16, 16));
- // delete old icon, if it exists
- QList<QPair<QString,QIcon> >::iterator iter = m_cache.begin();
- for (; iter != m_cache.end(); ++iter) {
- if ((*iter).first == suffix) {
- iter = m_cache.erase(iter);
- break;
- }
- }
+ typedef StringIconPairList::iterator CacheIterator;
- QPair<QString,QIcon> newEntry(suffix, fileIconPixmap);
- m_cache.append(newEntry);
+ if (debug)
+ qDebug() << "FileIconProvider::registerIconOverlayForSuffix" << suffix;
+
+ QTC_ASSERT(!icon.isNull() && !suffix.isEmpty(), return)
+
+ const QPixmap fileIconPixmap = overlayIcon(QStyle::SP_FileIcon, icon, QSize(16, 16));
+ // replace old icon, if it exists
+ const CacheIterator it = findBySuffix(suffix, d->m_cache.begin(), d->m_cache.end());
+ if (it == d->m_cache.end()) {
+ d->m_cache.append(StringIconPair(suffix, fileIconPixmap));
+ } else {
+ (*it).second = fileIconPixmap;
+ }
}
/*!
@@ -131,34 +206,14 @@ void FileIconProvider::registerIconOverlayForMimeType(const QIcon &icon, const M
}
/*!
- Returns an icon for the given suffix, or an empty one if none registered.
- */
-QIcon FileIconProvider::iconForSuffix(const QString &suffix) const
-{
- QIcon icon;
-#if defined(Q_WS_WIN) || defined(Q_WS_MAC) // On Windows and Mac we use the file system icons
- Q_UNUSED(suffix)
-#else
- if (suffix.isEmpty())
- return icon;
-
- QList<QPair<QString,QIcon> >::const_iterator iter = m_cache.constBegin();
- for (; iter != m_cache.constEnd(); ++iter) {
- if ((*iter).first == suffix) {
- icon = (*iter).second;
- break;
- }
- }
-#endif
- return icon;
-}
-
-/*!
Returns the sole instance of FileIconProvider.
*/
+
FileIconProvider *FileIconProvider::instance()
{
- if (!m_instance)
- m_instance = new FileIconProvider;
- return m_instance;
+ if (!FileIconProviderPrivate::m_instance)
+ FileIconProviderPrivate::m_instance = new FileIconProvider;
+ return FileIconProviderPrivate::m_instance;
}
+
+} // namespace core