source: trunk/gtk/icons.c @ 10657

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

(trunk gtk) and while we're on the subject, fix more tab damage

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, int icon_size)
83{
84    IconCache * icon_cache;
85
86    g_return_val_if_fail( for_widget != NULL, NULL );
87
88    icon_cache = g_new0( IconCache, 1 );
89    icon_cache->icon_theme = gtk_icon_theme_get_for_screen( gtk_widget_get_screen( for_widget ));
90    icon_cache->icon_size = get_size_in_pixels( for_widget, icon_size );
91    icon_cache->cache = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
92
93    g_hash_table_insert( icon_cache->cache, (void*)VOID_PIXBUF_KEY, create_void_pixbuf( icon_cache->icon_size, icon_cache->icon_size ));
94
95    return icon_cache;
96}
97
98#ifdef USE_GIO_ICONS
99static const char *
100_icon_cache_get_icon_key( GIcon * icon )
101{
102    const char * key = NULL;
103
104    if ( G_IS_THEMED_ICON( icon )) {
105        char ** icon_names;
106        char  * name;
107
108        g_object_get( icon, "names", &icon_names, NULL );
109        name = g_strjoinv( ",", icon_names );
110
111        key = get_static_string( name );
112
113        g_free( name );
114        g_strfreev( icon_names );
115    }
116    else if ( G_IS_FILE_ICON( icon )) {
117        GFile * file;
118        char  * filename;
119
120        file = g_file_icon_get_file( G_FILE_ICON( icon ));
121        filename = g_file_get_path( file );
122
123        key = get_static_string( filename );
124
125        g_free( filename );
126        g_object_unref( file );
127    }
128
129    return key;
130}
131
132
133static GdkPixbuf *
134get_themed_icon_pixbuf( GThemedIcon   * icon,
135                        int             size,
136                        GtkIconTheme  * icon_theme )
137{
138    char        ** icon_names = NULL;
139    GtkIconInfo  * icon_info;
140    GdkPixbuf    * pixbuf;
141    GError       * error = NULL;
142
143    g_object_get( icon, "names", &icon_names, NULL );
144
145    icon_info = gtk_icon_theme_choose_icon( icon_theme, (const char **)icon_names, size, 0 );
146    if ( icon_info == NULL )
147        icon_info = gtk_icon_theme_lookup_icon( icon_theme, "text-x-generic", size, GTK_ICON_LOOKUP_USE_BUILTIN );
148
149    pixbuf = gtk_icon_info_load_icon( icon_info, &error );
150    if ( pixbuf == NULL ) {
151        if( error && error->message )
152            g_warning( "could not load icon pixbuf: %s\n", error->message );
153        g_clear_error( &error );
154    }
155
156    gtk_icon_info_free( icon_info );
157    g_strfreev( icon_names );
158
159    return pixbuf;
160}
161
162
163static GdkPixbuf *
164get_file_icon_pixbuf( GFileIcon * icon, int size )
165{
166    GFile     * file;
167    char      * filename;
168    GdkPixbuf * pixbuf;
169
170    file = g_file_icon_get_file( icon );
171    filename = g_file_get_path( file );
172    pixbuf = gdk_pixbuf_new_from_file_at_size( filename, size, -1, NULL );
173    g_free( filename );
174    g_object_unref( file );
175
176    return pixbuf;
177}
178
179
180static GdkPixbuf *
181_get_icon_pixbuf( GIcon * icon, int size, GtkIconTheme * theme )
182{
183    if ( icon == NULL )
184        return NULL;
185    if ( G_IS_THEMED_ICON (icon) )
186        return get_themed_icon_pixbuf( G_THEMED_ICON( icon ), size, theme );
187    if ( G_IS_FILE_ICON (icon) )
188        return get_file_icon_pixbuf( G_FILE_ICON( icon ), size );
189    return NULL;
190}
191
192
193static GdkPixbuf *
194icon_cache_get_mime_type_icon( IconCache * icon_cache, const char * mime_type )
195{
196    GIcon      * icon;
197    const char * key = NULL;
198    GdkPixbuf  * pixbuf;
199
200    icon = g_content_type_get_icon( mime_type );
201    key = _icon_cache_get_icon_key( icon );
202
203    if (key == NULL)
204        key = VOID_PIXBUF_KEY;
205
206    pixbuf = g_hash_table_lookup( icon_cache->cache, key );
207    if (pixbuf != NULL) {
208        g_object_ref( pixbuf );
209        g_object_unref( G_OBJECT( icon ) );
210        return pixbuf;
211    }
212
213    pixbuf = _get_icon_pixbuf( icon, icon_cache->icon_size, icon_cache->icon_theme );
214    if( pixbuf != NULL )
215        g_hash_table_insert( icon_cache->cache, (gpointer) key, g_object_ref( pixbuf ) );
216
217    g_object_unref( G_OBJECT( icon ) );
218
219    return pixbuf;
220}
221
222#else /* USE_GIO_ICONS */
223
224static GdkPixbuf *
225icon_cache_get_mime_type_icon( IconCache * icon_cache, const char * mime_type )
226{
227    GdkPixbuf  * pixbuf;
228    const char * stock_name;
229
230    if( !strcmp( mime_type, UNKNOWN_MIME_TYPE ) )
231        stock_name = GTK_STOCK_MISSING_IMAGE;
232    else if( !strcmp( mime_type, DIRECTORY_MIME_TYPE ) )
233        stock_name = GTK_STOCK_DIRECTORY;
234    else
235        stock_name = GTK_STOCK_FILE;
236
237    pixbuf = g_hash_table_lookup( icon_cache->cache, stock_name );
238
239    if( pixbuf != NULL )
240    {
241        g_object_ref( pixbuf );
242        return pixbuf;
243    }
244
245    pixbuf = gtk_icon_theme_load_icon( icon_cache->icon_theme,
246                                       stock_name,
247                                       icon_cache->icon_size,
248                                       0, NULL );
249    g_hash_table_insert( icon_cache->cache, (gpointer) stock_name, g_object_ref( pixbuf ));
250    return pixbuf;
251}
252
253#endif
254
255
256GdkPixbuf *
257get_mime_type_icon( const char   * mime_type,
258                    GtkIconSize    icon_size,
259                    GtkWidget    * for_widget )
260{
261    int n;
262
263    switch ( icon_size ) {
264        case GTK_ICON_SIZE_MENU:            n = 1; break;
265        case GTK_ICON_SIZE_SMALL_TOOLBAR:   n = 2; break;
266        case GTK_ICON_SIZE_LARGE_TOOLBAR:   n = 3; break;
267        case GTK_ICON_SIZE_BUTTON:          n = 4; break;
268        case GTK_ICON_SIZE_DND:             n = 5; break;
269        case GTK_ICON_SIZE_DIALOG:          n = 6; break;
270        default /*GTK_ICON_SIZE_INVALID*/:  n = 0; break;
271    }
272
273    if( icon_cache[n] == NULL )
274        icon_cache[n] = icon_cache_new( for_widget, icon_size );
275
276    return icon_cache_get_mime_type_icon( icon_cache[n], mime_type );
277}
278
279
280const char *
281get_mime_type_from_filename( const char * file G_GNUC_UNUSED )
282{
283#ifdef USE_GIO_ICONS
284    char * tmp = g_content_type_guess( file, NULL, 0, NULL );
285    const char * ret = get_static_string( tmp );
286    g_free( tmp );
287    return ret;
288#else
289    return "uncertain";
290#endif
291}
Note: See TracBrowser for help on using the repository browser.