Qt 4.8 - QFileIconProvider,获取不存在文件的图标(根据扩展名)

4

我正在尝试根据文件扩展名获取图标,但似乎QFileIconProvider只会在它可以读取现有文件时返回一个图标。有没有办法基于文件扩展名获取QIcon?一种替代方法是写一个具有所需扩展名的临时文件,但这非常低效,因此我正在寻找一种解决方法。

任何帮助将不胜感激!

1个回答

3
以下是关于Windows的解决方案:
iconprovider.h:
class IconProvider
{
public:
    static IconProvider * instance();
    static QIcon fileIcon(const QString &filename);
    static QIcon dirIcon();

private:
    IconProvider() {}

private:
    static IconProvider *self;
    QPixmapCache iconCache;
    QFileIconProvider iconProvider;
};

iconprovider.cpp:

IconProvider *IconProvider::self = 0;

IconProvider *IconProvider::instance()
{
    if(!self)
        self = new IconProvider();
    return self;
}

QIcon IconProvider::fileIcon(const QString &filename)
{
    QFileInfo fileInfo(filename);
    QPixmap pixmap;

#ifdef Q_OS_WIN32

    if (fileInfo.suffix().isEmpty() || fileInfo.suffix() == "exe" && fileInfo.exists())
    {
        return instance()->iconProvider.icon(fileInfo);
    }

    if (!instance()->iconCache.find(fileInfo.suffix(), &pixmap))
    {
        // Support for nonexistent file type icons, will reimplement it as custom icon provider later
        /* We don't use the variable, but by storing it statically, we
         * ensure CoInitialize is only called once. */
        static HRESULT comInit = CoInitialize(NULL);
        Q_UNUSED(comInit);

        SHFILEINFO shFileInfo;
        unsigned long val = 0;

        val = SHGetFileInfo((const wchar_t *)("foo." + fileInfo.suffix()).utf16(), 0, &shFileInfo,
                            sizeof(SHFILEINFO), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES);

        // Even if GetFileInfo returns a valid result, hIcon can be empty in some cases
        if (val && shFileInfo.hIcon)
        {
            pixmap = QPixmap::fromWinHICON(shFileInfo.hIcon);
            if (!pixmap.isNull())
            {
                instance()->iconCache.insert(fileInfo.suffix(), pixmap);
            }
            DestroyIcon(shFileInfo.hIcon);
        }
        else
        {
            // TODO: Return default icon if nothing else found
        }
    }

#else
    // Default icon for Linux and Mac OS X for now
    return instance()->iconProvider.icon(fileInfo);
#endif

    return QIcon(pixmap);
}

QIcon IconProvider::dirIcon()
{
    return instance()->iconProvider.icon(QFileIconProvider::Folder);
}

如果你有Qt,为什么要使用WinApi函数? - Blood
@Blood Qt没有API可以获取不存在文件(即文件类型)的图标。 - Oleg Shparber
1
我刚刚使用了QTemporaryFile,然后在临时文件上使用了QFileIconProvider。这样可以保持平台无关性。有点低效,但可能是唯一的方法。 - Brad
@Brad 是的,这是一个可能的解决方案,但要注意在大数据集的情况下可能会出现性能问题。 - Oleg Shparber
@Brad,Oleg:如何保留一个文件扩展名到QIcons的哈希映射,这样你只需要为应用程序关心的每个扩展名创建一个临时文件? - nullstellensatz
@nullstellensatz,显然这是一个可能的优化选项,适用于需要经常检索文件类型图标的应用程序。 - Oleg Shparber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接