Core: Clean up FileIconProvider interface

Change-Id: I98c3c8796cb887f5bb3c5184854562ff36727836
Reviewed-by: Christian Kandeler <christian.kandeler@digia.com>
This commit is contained in:
hjk
2013-09-12 16:06:33 +02:00
parent 3bb7339fd4
commit 65cc8ae4c2
22 changed files with 118 additions and 173 deletions

View File

@@ -49,94 +49,91 @@ using namespace Utils;
\class Core::FileIconProvider
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.
icons for specific subtypes. The underlying QFileIconProvider
can 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 overlay icons via registerIconOverlayForSuffix(), and
retrieve icons via the icon() method.
The instance is explicitly deleted by the core plugin for destruction order reasons.
*/
// Cache icons in a list of pairs suffix/icon which should be faster than
// hashes for small lists.
namespace Core {
namespace FileIconProvider {
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)
class FileIconProviderImplementation : public QFileIconProvider
{
for (; iter != end; ++iter)
if ((*iter).first == suffix)
return iter;
return end;
}
public:
FileIconProviderImplementation()
: m_unknownFileIcon(qApp->style()->standardIcon(QStyle::SP_FileIcon))
{}
namespace Core {
QIcon icon(const QFileInfo &info) const;
using QFileIconProvider::icon;
struct FileIconProviderPrivate {
FileIconProviderPrivate();
void registerIconOverlayForSuffix(const QIcon &icon, const QString &suffix)
{
if (debug)
qDebug() << "FileIconProvider::registerIconOverlayForSuffix" << suffix;
QTC_ASSERT(!icon.isNull() && !suffix.isEmpty(), return);
const QPixmap fileIconPixmap = FileIconProvider::overlayIcon(QStyle::SP_FileIcon, icon, QSize(16, 16));
// replace old icon, if it exists
for (int i = 0, n = m_cache.size(); i != n; ++i) {
if (m_cache.at(i).first == suffix) {
m_cache[i].second = fileIconPixmap;
return;
}
}
m_cache.append(StringIconPair(suffix, fileIconPixmap));
}
void registerIconOverlayForMimeType(const QIcon &icon, const MimeType &mimeType)
{
foreach (const QString &suffix, mimeType.suffixes())
registerIconOverlayForSuffix(icon, suffix);
}
// Mapping of file suffix to icon.
StringIconPairList m_cache;
QIcon m_unknownFileIcon;
// singleton pattern
static FileIconProvider *m_instance;
};
FileIconProviderPrivate::FileIconProviderPrivate() :
m_unknownFileIcon(qApp->style()->standardIcon(QStyle::SP_FileIcon))
FileIconProviderImplementation *instance()
{
static FileIconProviderImplementation theInstance;
return &theInstance;
}
FileIconProvider *FileIconProviderPrivate::m_instance = 0;
// FileIconProvider
FileIconProvider::FileIconProvider() :
d(new FileIconProviderPrivate)
QFileIconProvider *iconProvider()
{
FileIconProviderPrivate::m_instance = this;
return instance();
}
FileIconProvider::~FileIconProvider()
QIcon FileIconProviderImplementation::icon(const QFileInfo &fileInfo) const
{
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
{
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()) {
if (!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;
for (int i = 0, n = m_cache.size(); i != n; ++i)
if (m_cache.at(i).first == suffix)
return m_cache[i].second;
}
}
// Get icon from OS.
@@ -144,16 +141,32 @@ QIcon FileIconProvider::icon(const QFileInfo &fileInfo) const
return QFileIconProvider::icon(fileInfo);
// File icons are unknown on linux systems.
return (fileInfo.isDir()) ?
QFileIconProvider::icon(fileInfo) :
d->m_unknownFileIcon;
return fileInfo.isDir() ? QFileIconProvider::icon(fileInfo) : m_unknownFileIcon;
}
/*!
Returns the icon associated with the file suffix in fileInfo. If there is none,
the default icon of the operating system is returned.
*/
QIcon icon(const QFileInfo &info)
{
return instance()->icon(info);
}
/*!
* \overload
*/
QIcon icon(QFileIconProvider::IconType type)
{
return instance()->icon(type);
}
/*!
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)
QPixmap overlayIcon(QStyle::StandardPixmap baseIcon, const QIcon &overlayIcon, const QSize &size)
{
QPixmap iconPixmap = qApp->style()->standardIcon(baseIcon).pixmap(size);
QPainter painter(&iconPixmap);
@@ -166,43 +179,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 registerIconOverlayForSuffix(const char *path, const char *suffix)
{
typedef StringIconPairList::iterator CacheIterator;
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;
instance()->registerIconOverlayForSuffix(QIcon(QLatin1String(path)), QLatin1String(suffix));
}
/*!
Registers an icon for all the suffixes of a given mime type, overlaying the system file icon.
*/
void FileIconProvider::registerIconOverlayForMimeType(const QIcon &icon, const MimeType &mimeType)
void registerIconOverlayForMimeType(const QIcon &icon, const char *mimeType)
{
foreach (const QString &suffix, mimeType.suffixes())
registerIconOverlayForSuffix(icon, suffix);
instance()->registerIconOverlayForMimeType(icon, MimeDatabase::findByType(QString::fromLatin1(mimeType)));
}
/*!
Returns the sole instance of FileIconProvider.
*/
FileIconProvider *FileIconProvider::instance()
* \overload
*/
void registerIconOverlayForMimeType(const char *path, const char *mimeType)
{
if (!FileIconProviderPrivate::m_instance)
FileIconProviderPrivate::m_instance = new FileIconProvider;
return FileIconProviderPrivate::m_instance;
instance()->registerIconOverlayForMimeType(QIcon(QLatin1String(path)), MimeDatabase::findByType(QString::fromLatin1(mimeType)));
}
} // namespace core
} // namespace FileIconProvider
} // namespace Core