source: trunk/gtk/icons.c @ 8003

Last change on this file since 8003 was 8003, checked in by charles, 13 years ago

(trunk gtk) #628: tweak r7996 a little bit to play nicer on older versions of gtk+

File size: 7.2 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 #include <gio/gio.h>
13#endif
14
15#define VOID_PIXBUF_KEY "void-pixbuf"
16
17static GHashTable *static_strings = NULL;
18
19static const char *
20get_static_string( const char *s )
21{
22    const char *result;
23
24    if ( s == NULL )
25        return NULL;
26
27    if ( static_strings == NULL )
28        static_strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
29
30    if ( ! g_hash_table_lookup_extended( static_strings, s, (gpointer) &result, NULL )) {
31        result = g_strdup( s );
32        g_hash_table_insert( static_strings,
33                             (gpointer) result,
34                             GINT_TO_POINTER( 1 ));
35    }
36
37    return result;
38}
39
40
41typedef struct {
42    GtkIconTheme * icon_theme;
43    int            icon_size;
44    GHashTable   * cache;
45} IconCache;
46
47
48static IconCache *icon_cache[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
49
50
51static GdkPixbuf*
52create_void_pixbuf (int width,
53                    int height)
54{
55    GdkPixbuf *p;
56
57    p = gdk_pixbuf_new( GDK_COLORSPACE_RGB,
58                        TRUE,
59                        8,
60                        width,
61                        height);
62    gdk_pixbuf_fill( p, 0xFFFFFF00 );
63
64    return p;
65}
66
67
68static int
69get_size_in_pixels( GtkWidget   * widget,
70                    GtkIconSize   icon_size )
71{
72    int width, height;
73
74    gtk_icon_size_lookup_for_settings( gtk_widget_get_settings( widget ),
75                                       icon_size,
76                                       &width, 
77                                       &height );
78    return MAX( width, height );
79}
80
81
82static IconCache * 
83icon_cache_new (GtkWidget * for_widget,
84                int         icon_size)
85{
86    IconCache * icon_cache;
87       
88    g_return_val_if_fail( for_widget != NULL, NULL );
89       
90    icon_cache = g_new0( IconCache, 1 );
91    icon_cache->icon_theme = gtk_icon_theme_get_for_screen( gtk_widget_get_screen( for_widget )); 
92    icon_cache->icon_size = get_size_in_pixels( for_widget, icon_size );
93    icon_cache->cache = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
94       
95    g_hash_table_insert( icon_cache->cache, (void*)VOID_PIXBUF_KEY, create_void_pixbuf( icon_cache->icon_size, icon_cache->icon_size ));
96       
97    return icon_cache;
98}
99
100#ifdef HAVE_GIO
101static const char *
102_icon_cache_get_icon_key( GIcon * icon )
103{
104    const char * key = NULL;
105       
106    if ( G_IS_THEMED_ICON( icon )) {
107        char ** icon_names;
108        char  * name;
109       
110        g_object_get( icon, "names", &icon_names, NULL );
111        name = g_strjoinv( ",", icon_names );
112               
113        key = get_static_string( name );
114               
115        g_free( name );
116        g_strfreev( icon_names );       
117    }
118    else if ( G_IS_FILE_ICON( icon )) {
119        GFile * file;
120        char  * filename;
121
122        file = g_file_icon_get_file( G_FILE_ICON( icon ));
123        filename = g_file_get_path( file );
124               
125        key = get_static_string( filename );
126               
127        g_free( filename );
128        g_object_unref( file );
129    }
130       
131    return key;
132}
133
134
135static GdkPixbuf *
136get_themed_icon_pixbuf( GThemedIcon  *icon,
137                        int           size,
138                        GtkIconTheme *icon_theme )
139{
140    char        ** icon_names;
141    GtkIconInfo  * icon_info;
142    GdkPixbuf    * pixbuf;
143    GError       * error = NULL;
144
145    g_object_get( icon, "names", &icon_names, NULL );
146
147    icon_info = gtk_icon_theme_choose_icon( icon_theme, (const char **)icon_names, size, 0 );
148    if ( icon_info == NULL )
149        icon_info = gtk_icon_theme_lookup_icon( icon_theme, "text-x-generic", size, GTK_ICON_LOOKUP_USE_BUILTIN );
150
151    pixbuf = gtk_icon_info_load_icon( icon_info, &error );
152    if ( pixbuf == NULL ) {
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    g_hash_table_insert( icon_cache->cache, (gpointer) key, g_object_ref( pixbuf ));
219       
220    return pixbuf;
221}
222
223#else /* HAVE_GIO */
224
225static GdkPixbuf *
226icon_cache_get_mime_type_icon( IconCache  * icon_cache,
227                               const char * mime_type )
228{
229    GdkPixbuf  * pixbuf;
230    const char * stock_name;
231
232    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_INVALID:       n = 0; break;
265        case GTK_ICON_SIZE_MENU:          n = 1; break;
266        case GTK_ICON_SIZE_SMALL_TOOLBAR: n = 2; break;
267        case GTK_ICON_SIZE_LARGE_TOOLBAR: n = 3; break;
268        case GTK_ICON_SIZE_BUTTON:        n = 4; break;
269        case GTK_ICON_SIZE_DND:           n = 5; break;
270        case GTK_ICON_SIZE_DIALOG:        n = 6; 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 HAVE_GIO
284    return get_static_string( g_content_type_guess( file, NULL, 0, NULL ));
285#else
286    return "uncertain";
287#endif
288}
Note: See TracBrowser for help on using the repository browser.