Ticket #9401: 0001-Get-file-icons-on-linux.2.patch

File 0001-Get-file-icons-on-linux.2.patch, 9.0 KB (added by Francois Ferrand, 10 years ago)

patch v2

  • src/interface/LocalListView.cpp

    From 81b4a0bdbf6a80b0b58a8814ec03db7f37e0e9f4 Mon Sep 17 00:00:00 2001
    From: Francois Ferrand <thetypz@gmail.com>
    Date: Mon, 3 Mar 2014 18:04:33 +0100
    Subject: [PATCH] Get file icons on linux.
    
    * Try to use Gnome VFS/mime database if available, otherwise fall back to
    g_file_query_info (which does not work for remote files).
    * Fallback to wxTheMimeTypesManager if no icon could be found through.
    * Properly display local symlinks.
    Gnome/Gtk.
    ---
     src/interface/LocalListView.cpp   |   4 +-
     src/interface/systemimagelist.cpp | 176 +++++++++++++++++++++++++++++++-------
     2 files changed, 149 insertions(+), 31 deletions(-)
    
    diff --git a/src/interface/LocalListView.cpp b/src/interface/LocalListView.cpp
    index 2f4796f..d4b971e 100644
    a b int CLocalListView::OnGetItemImage(long item) const  
    487487                path = m_dir + data->name;
    488488        }
    489489
    490         icon = pThis->GetIconIndex(data->dir ? dir : file, path);
     490        bool isSymLink = false;
     491        CLocalFileSystem::GetFileInfo(path, isSymLink, NULL, NULL, NULL);
     492        icon = pThis->GetIconIndex(data->dir ? dir : file, path, true, isSymLink);
    491493    }
    492494    return icon;
    493495}
  • src/interface/systemimagelist.cpp

    diff --git a/src/interface/systemimagelist.cpp b/src/interface/systemimagelist.cpp
    index 2480ac3..af94585 100644
    a b  
    1717#include "themeprovider.h"
    1818#include <wx/rawbmp.h>
    1919#endif
     20#ifdef __WXGTK__
     21#include <gio/gio.h>
     22#include <gtk/gtk.h>
     23#include <wx/dynlib.h>
     24#endif
    2025
    2126wxImageListEx::wxImageListEx()
    2227    : wxImageList()
    static void OverlaySymlink(wxBitmap& bmp)  
    6368{
    6469    // This is ugly, but apparently needed so that the data is _really_ in the right internal format
    6570    bmp = bmp.ConvertToImage();
    66     wxBitmap symlink = wxArtProvider::GetBitmap(_T("ART_SYMLINK"),  wxART_OTHER, wxSize(bmp.GetWidth(), bmp.GetHeight())).ConvertToImage();
     71
     72    wxBitmap symlink;
     73#ifdef __WXGTK__
     74    symlink = wxArtProvider::GetBitmap(_T("emblem-symbolic-link"), wxART_OTHER, wxSize(bmp.GetWidth(), bmp.GetHeight()));
     75#endif
     76    if (!symlink.IsOk())
     77        symlink = wxArtProvider::GetBitmap(_T("ART_SYMLINK"), wxART_OTHER, wxSize(bmp.GetWidth(), bmp.GetHeight()));
     78    symlink = symlink.ConvertToImage();
    6779
    6880    wxAlphaPixelData target(bmp);
    6981    wxAlphaPixelData source(symlink);
    bool CSystemImageList::CreateSystemImageList(int size)  
    119131#else
    120132    m_pImageList = new wxImageListEx(size, size);
    121133
    122     wxBitmap file = wxArtProvider::GetBitmap(_T("ART_FILE"),  wxART_OTHER, wxSize(size, size));
    123     wxBitmap folderclosed = wxArtProvider::GetBitmap(_T("ART_FOLDERCLOSED"),  wxART_OTHER, wxSize(size, size));
    124     wxBitmap folder = wxArtProvider::GetBitmap(_T("ART_FOLDER"),  wxART_OTHER, wxSize(size, size));
     134    wxBitmap file;
     135    wxBitmap folderclosed;
     136    wxBitmap folder;
     137#ifdef __WXGTK__
     138    file = wxArtProvider::GetBitmap(_T("unknown"),  wxART_OTHER, wxSize(size, size));
     139    folderclosed = wxArtProvider::GetBitmap(_T("folder"),  wxART_OTHER, wxSize(size, size));
     140    folder = wxArtProvider::GetBitmap(_T("folder-open"),  wxART_OTHER, wxSize(size, size));
     141#endif
     142    if (!file.IsOk())
     143        file = wxArtProvider::GetBitmap(_T("ART_FILE"),  wxART_OTHER, wxSize(size, size));
     144    if (!folderclosed.IsOk())
     145        folderclosed = wxArtProvider::GetBitmap(_T("ART_FOLDERCLOSED"),  wxART_OTHER, wxSize(size, size));
     146    if (!folder.IsOk())
     147        folder = wxArtProvider::GetBitmap(_T("ART_FOLDER"),  wxART_OTHER, wxSize(size, size));
     148
    125149    m_pImageList->Add(file);
    126150    m_pImageList->Add(folderclosed);
    127151    m_pImageList->Add(folder);
    CSystemImageList::~CSystemImageList()  
    150174    m_pImageList = 0;
    151175}
    152176
    153 #ifndef __WXMSW__
     177#ifdef __WXGTK__
     178
     179typedef enum {
     180    GNOME_ICON_LOOKUP_FLAGS_NONE = 0,
     181    GNOME_ICON_LOOKUP_FLAGS_EMBEDDING_TEXT = 1<<0,
     182    GNOME_ICON_LOOKUP_FLAGS_SHOW_SMALL_IMAGES_AS_THEMSELVES = 1<<1,
     183    GNOME_ICON_LOOKUP_FLAGS_ALLOW_SVG_AS_THEMSELVES = 1<<2
     184} GnomeIconLookupFlags;
     185
     186typedef enum {
     187    GNOME_ICON_LOOKUP_RESULT_FLAGS_NONE = 0,
     188    GNOME_ICON_LOOKUP_RESULT_FLAGS_THUMBNAIL = 1<<0
     189} GnomeIconLookupResultFlags;
     190
     191struct Gnome {
     192    Gnome():
     193        libGnomeVfs(_T("libgnomevfs-2.so.0"), wxDL_QUIET),
     194        libGnomeUi(_T("libgnomeui-2.so.0"), wxDL_QUIET),
     195        gnome_vfs_init((Gnome_Vfs_Init)libGnomeVfs.GetSymbol(_T("gnome_vfs_init"))),
     196        vfs_get_mime_type_for_name((Gnome_Vfs_Get_Mime_Type_For_Name)libGnomeVfs.GetSymbol(_T("gnome_vfs_get_mime_type_for_name"))),
     197        icon_lookup((Gnome_Icon_Lookup)libGnomeUi.GetSymbol(_T("gnome_icon_lookup")))
     198    {
     199        if (!gnome_vfs_init || !gnome_vfs_init())
     200            icon_lookup = NULL;
     201    }
     202
     203    typedef int (*Gnome_Vfs_Init)(void);
     204    typedef const char * (*Gnome_Vfs_Get_Mime_Type_For_Name)(const char *filename);
     205    typedef char * (*Gnome_Icon_Lookup)(GtkIconTheme *icon_theme,
     206                                        const char *file_uri,
     207                                        void/*GnomeThumbnailFactory*/ *thumbnail_factory,
     208                                        const char *custom_icon,
     209                                        void/*GnomeVFSFileInfo*/ *file_info,
     210                                        const char *mime_type,
     211                                        GnomeIconLookupFlags flags,
     212                                        GnomeIconLookupResultFlags *result);
     213    wxDynamicLibrary libGnomeVfs;
     214    wxDynamicLibrary libGnomeUi;
     215    Gnome_Vfs_Init gnome_vfs_init;
     216    Gnome_Vfs_Get_Mime_Type_For_Name vfs_get_mime_type_for_name;
     217    Gnome_Icon_Lookup icon_lookup;
     218} static gnome;
     219
     220static wxBitmap GetNativeFileIcon(const wxString & fileName, const wxString & ext)
     221{
     222    wxString iconName;
     223    if (gnome.icon_lookup)
     224    {
     225        GtkIconTheme *theme = gtk_icon_theme_get_default();
     226        const wxCharBuffer name = fileName.ToUTF8();
     227        const char * mimetype = gnome.vfs_get_mime_type_for_name(name.data());
     228        char * res = gnome.icon_lookup(theme, name.data(), NULL, NULL, NULL, mimetype, GNOME_ICON_LOOKUP_FLAGS_NONE, NULL);
     229        if (res)
     230            iconName = wxString::FromUTF8(res);
     231        g_free(res);
     232    }
     233    else
     234    {
     235        GFile * file = g_file_new_for_path(fileName.ToUTF8().data());
     236        GFileInfo * fileInfo = file ? g_file_query_info(file, G_FILE_ATTRIBUTE_STANDARD_ICON, G_FILE_QUERY_INFO_NONE, NULL, NULL) : NULL;
     237        GIcon * fileIcon = fileInfo ? g_file_info_get_icon(fileInfo) : NULL;
     238        const gchar * const * iconNames = fileIcon ? g_themed_icon_get_names(G_THEMED_ICON(fileIcon)) : NULL;
     239        if (iconNames)
     240            iconName = wxString::FromUTF8(iconNames[0]);
     241        if (fileInfo)
     242            g_object_unref(fileInfo);
     243        if (file)
     244            g_object_unref(file);
     245    }
     246
     247    wxSize iconSize = CThemeProvider::GetIconSize(iconSizeSmall);
     248    if (iconName.IsEmpty())
     249        return wxBitmap();
     250    if (iconName.GetChar(0) == '/')
     251        return wxImage(iconName).Rescale(iconSize.GetWidth(), iconSize.GetHeight());
     252    return wxArtProvider::GetBitmap(iconName, wxART_OTHER, CThemeProvider::GetIconSize(iconSizeSmall));
     253}
     254
     255#else
     256
     257static wxBitmap GetNativeFileIcon(const wxString & /*fileName*/, const wxString & /*ext*/)
     258{
     259    return wxBitmap();
     260}
     261
     262#endif
     263
    154264// This function converts to the right size with the given background colour
    155 wxBitmap PrepareIcon(wxIcon icon, wxSize size)
     265static wxBitmap PrepareIcon(wxIcon icon, wxSize size)
    156266{
    157267    if (icon.GetWidth() == size.GetWidth() && icon.GetHeight() == size.GetHeight())
    158268        return icon;
    wxBitmap PrepareIcon(wxIcon icon, wxSize size)  
    160270    bmp.CopyFromIcon(icon);
    161271    return bmp.ConvertToImage().Rescale(size.GetWidth(), size.GetHeight());
    162272}
    163 #endif
     273
     274static wxBitmap GetFileIcon(const wxString & /*fileName*/, const wxString & ext)
     275{
     276    wxFileType *pType = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
     277    if (!pType)
     278        return wxBitmap();
     279
     280    wxBitmap bmp;
     281    wxIconLocation loc;
     282    if (pType->GetIcon(&loc) && loc.IsOk())
     283    {
     284        wxLogNull nul;
     285        wxIcon newIcon(loc);
     286
     287        if (newIcon.Ok())
     288            bmp = PrepareIcon(newIcon, CThemeProvider::GetIconSize(iconSizeSmall));
     289    }
     290    delete pType;
     291
     292    return bmp;
     293}
    164294
    165295int CSystemImageList::GetIconIndex(enum filetype type, const wxString& fileName /*=_T("")*/, bool physical /*=true*/, bool symlink /*=false*/)
    166296{
    int CSystemImageList::GetIconIndex(enum filetype type, const wxString& fileName  
    216346            return cacheIter->second;
    217347    }
    218348
    219     wxFileType *pType = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
    220     if (!pType)
    221     {
    222         m_iconCache[ext] = icon;
    223         return icon;
     349    wxBitmap bmp = GetNativeFileIcon(fileName, ext);
     350    if (!bmp.IsOk())
     351        bmp = GetFileIcon(fileName, ext);
     352    if (bmp.IsOk()) {
     353        if (symlink)
     354            OverlaySymlink(bmp);
     355        int index = m_pImageList->Add(bmp);
     356        if (index > 0)
     357            icon = index;
    224358    }
    225359
    226     wxIconLocation loc;
    227     if (pType->GetIcon(&loc) && loc.IsOk())
    228     {
    229         wxLogNull nul;
    230         wxIcon newIcon(loc);
    231 
    232         if (newIcon.Ok())
    233         {
    234             wxBitmap bmp = PrepareIcon(newIcon, CThemeProvider::GetIconSize(iconSizeSmall));
    235             if (symlink)
    236                 OverlaySymlink(bmp);
    237             int index = m_pImageList->Add(bmp);
    238             if (index > 0)
    239                 icon = index;
    240         }
    241     }
    242     delete pType;
    243 
    244360    if (symlink)
    245361        m_iconCache[ext] = icon;
    246362    else