source: trunk/gtk/icons.c @ 9550

Last change on this file since 9550 was 9550, checked in by charles, 12 years ago

(trunk) #2096: Magnet, BEP #9 support

File size: 7.3 KB
Line 
1/*
2 * icons.[ch] written by Paolo Bacchilega, who writes:
3 * "There is no problem for me, you can license my code under whatever licence you wish :)"
4 */
5
6#include <string.h> /* strcmp */
7#include <glib.h>
8#include <gtk/gtk.h>
9#include "icons.h"
10
11#ifdef HAVE_GIO
12 #if GTK_CHECK_VERSION( 2, 12, 0 )
13   #define USE_GIO_ICONS
14 #endif
15#endif
16
17#ifdef USE_GIO_ICONS
18 #include <gio/gio.h>
19#endif
20
21#define VOID_PIXBUF_KEY "void-pixbuf"
22
23#ifdef USE_GIO_ICONS
24static const char *
25get_static_string( const char *s )
26{
27    static GStringChunk * static_strings = NULL;
28
29     if( s == NULL )
30         return NULL;
31
32     if( static_strings == NULL )
33         static_strings = g_string_chunk_new( 1024 );
34
35    return g_string_chunk_insert_const( static_strings, s );
36}
37#endif
38
39
40typedef struct {
41    GtkIconTheme * icon_theme;
42    int            icon_size;
43    GHashTable   * cache;
44} IconCache;
45
46
47static IconCache *icon_cache[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
48
49
50static GdkPixbuf*
51create_void_pixbuf (int width,
52                    int height)
53{
54    GdkPixbuf *p;
55
56    p = gdk_pixbuf_new( GDK_COLORSPACE_RGB,
57                        TRUE,
58                        8,
59                        width,
60                        height);
61    gdk_pixbuf_fill( p, 0xFFFFFF00 );
62
63    return p;
64}
65
66
67static int
68get_size_in_pixels( GtkWidget   * widget,
69                    GtkIconSize   icon_size )
70{
71    int width, height;
72
73    gtk_icon_size_lookup_for_settings( gtk_widget_get_settings( widget ),
74                                       icon_size,
75                                       &width, 
76                                       &height );
77    return MAX( width, height );
78}
79
80
81static IconCache * 
82icon_cache_new (GtkWidget * for_widget,
83                int         icon_size)
84{
85    IconCache * icon_cache;
86       
87    g_return_val_if_fail( for_widget != NULL, NULL );
88       
89    icon_cache = g_new0( IconCache, 1 );
90    icon_cache->icon_theme = gtk_icon_theme_get_for_screen( gtk_widget_get_screen( for_widget )); 
91    icon_cache->icon_size = get_size_in_pixels( for_widget, icon_size );
92    icon_cache->cache = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
93       
94    g_hash_table_insert( icon_cache->cache, (void*)VOID_PIXBUF_KEY, create_void_pixbuf( icon_cache->icon_size, icon_cache->icon_size ));
95       
96    return icon_cache;
97}
98
99#ifdef USE_GIO_ICONS
100static const char *
101_icon_cache_get_icon_key( GIcon * icon )
102{
103    const char * key = NULL;
104       
105    if ( G_IS_THEMED_ICON( icon )) {
106        char ** icon_names;
107        char  * name;
108       
109        g_object_get( icon, "names", &icon_names, NULL );
110        name = g_strjoinv( ",", icon_names );
111               
112        key = get_static_string( name );
113               
114        g_free( name );
115        g_strfreev( icon_names );       
116    }
117    else if ( G_IS_FILE_ICON( icon )) {
118        GFile * file;
119        char  * filename;
120
121        file = g_file_icon_get_file( G_FILE_ICON( icon ));
122        filename = g_file_get_path( file );
123               
124        key = get_static_string( filename );
125               
126        g_free( filename );
127        g_object_unref( file );
128    }
129       
130    return key;
131}
132
133
134static GdkPixbuf *
135get_themed_icon_pixbuf( GThemedIcon  *icon,
136                        int           size,
137                        GtkIconTheme *icon_theme )
138{
139    char        ** icon_names = NULL;
140    GtkIconInfo  * icon_info;
141    GdkPixbuf    * pixbuf;
142    GError       * error = NULL;
143
144    g_object_get( icon, "names", &icon_names, NULL );
145
146    icon_info = gtk_icon_theme_choose_icon( icon_theme, (const char **)icon_names, size, 0 );
147    if ( icon_info == NULL )
148        icon_info = gtk_icon_theme_lookup_icon( icon_theme, "text-x-generic", size, GTK_ICON_LOOKUP_USE_BUILTIN );
149
150    pixbuf = gtk_icon_info_load_icon( icon_info, &error );
151    if ( pixbuf == NULL ) {
152        if( error && error->message )
153            g_warning( "could not load icon pixbuf: %s\n", error->message );
154        g_clear_error( &error );
155    }
156
157    gtk_icon_info_free( icon_info );
158    g_strfreev( icon_names );
159
160    return pixbuf;
161}
162
163
164static GdkPixbuf *
165get_file_icon_pixbuf( GFileIcon *icon,
166                      int        size )
167{
168    GFile     * file;
169    char      * filename;
170    GdkPixbuf * pixbuf;
171       
172    file = g_file_icon_get_file( icon );
173    filename = g_file_get_path( file );
174    pixbuf = gdk_pixbuf_new_from_file_at_size( filename, size, -1, NULL );
175    g_free( filename );
176    g_object_unref( file );
177       
178    return pixbuf;
179}
180
181
182static GdkPixbuf *
183_get_icon_pixbuf( GIcon        *icon,
184                  int           size,
185                  GtkIconTheme *theme )
186{
187    if ( icon == NULL )
188        return NULL;
189    if ( G_IS_THEMED_ICON (icon) )
190        return get_themed_icon_pixbuf( G_THEMED_ICON( icon ), size, theme );
191    if ( G_IS_FILE_ICON (icon) )
192        return get_file_icon_pixbuf( G_FILE_ICON( icon ), size );
193    return NULL;
194}
195
196                 
197static GdkPixbuf *
198icon_cache_get_mime_type_icon( IconCache  * icon_cache,
199                               const char * mime_type )
200{
201    GIcon      * icon;
202    const char * key = NULL;
203    GdkPixbuf  * pixbuf;
204
205    icon = g_content_type_get_icon( mime_type );
206    key = _icon_cache_get_icon_key( icon );
207       
208    if (key == NULL)
209        key = VOID_PIXBUF_KEY;
210
211    pixbuf = g_hash_table_lookup( icon_cache->cache, key );
212    if (pixbuf != NULL) {
213        g_object_ref( pixbuf );
214        return pixbuf;
215    }
216
217    pixbuf = _get_icon_pixbuf( icon, icon_cache->icon_size, icon_cache->icon_theme );
218    if( pixbuf != NULL )
219        g_hash_table_insert( icon_cache->cache, (gpointer) key, g_object_ref( pixbuf ) );
220       
221    return pixbuf;
222}
223
224#else /* USE_GIO_ICONS */
225
226static GdkPixbuf *
227icon_cache_get_mime_type_icon( IconCache  * icon_cache,
228                               const char * mime_type )
229{
230    GdkPixbuf  * pixbuf;
231    const char * stock_name;
232
233    if( !strcmp( mime_type, UNKNOWN_MIME_TYPE ) )
234        stock_name = GTK_STOCK_MISSING_IMAGE;
235    else if( !strcmp( mime_type, DIRECTORY_MIME_TYPE ) )
236        stock_name = GTK_STOCK_DIRECTORY;
237    else
238        stock_name = GTK_STOCK_FILE;
239
240    pixbuf = g_hash_table_lookup( icon_cache->cache, stock_name );
241
242    if( pixbuf != NULL )
243    {
244        g_object_ref( pixbuf );
245        return pixbuf;
246    }
247
248    pixbuf = gtk_icon_theme_load_icon( icon_cache->icon_theme,
249                                       stock_name,
250                                       icon_cache->icon_size,
251                                       0, NULL );
252    g_hash_table_insert( icon_cache->cache, (gpointer) stock_name, g_object_ref( pixbuf ));
253    return pixbuf;
254}
255
256#endif
257
258
259GdkPixbuf * 
260get_mime_type_icon( const char   * mime_type,
261                    GtkIconSize    icon_size,
262                    GtkWidget    * for_widget )
263{
264    int n;
265   
266    switch ( icon_size ) {
267        case GTK_ICON_SIZE_MENU:            n = 1; break;
268        case GTK_ICON_SIZE_SMALL_TOOLBAR:   n = 2; break;
269        case GTK_ICON_SIZE_LARGE_TOOLBAR:   n = 3; break;
270        case GTK_ICON_SIZE_BUTTON:          n = 4; break;
271        case GTK_ICON_SIZE_DND:             n = 5; break;
272        case GTK_ICON_SIZE_DIALOG:          n = 6; break; 
273        default /*GTK_ICON_SIZE_INVALID*/:  n = 0; break;
274    }   
275
276    if( icon_cache[n] == NULL )
277        icon_cache[n] = icon_cache_new( for_widget, icon_size );
278
279    return icon_cache_get_mime_type_icon( icon_cache[n], mime_type );
280}                   
281
282
283const char * 
284get_mime_type_from_filename( const char * file G_GNUC_UNUSED )
285{
286#ifdef USE_GIO_ICONS
287    char * tmp = g_content_type_guess( file, NULL, 0, NULL );
288    const char * ret = get_static_string( tmp );
289    g_free( tmp );
290    return ret;
291#else
292    return "uncertain";
293#endif
294}
Note: See TracBrowser for help on using the repository browser.