source: trunk/gtk/icons.c @ 7996

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

(gtk trunk) #628: Show thumbnails next to torrents

File size: 6.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 <glib.h>
7#include <glib/gi18n.h>
8#include <gio/gio.h>
9#include <gtk/gtk.h>
10#include "icons.h"
11
12
13#define VOID_PIXBUF_KEY "void-pixbuf"
14
15
16static GHashTable *static_strings = NULL;
17
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
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;
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        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,
165                      int        size )
166{
167    GFile     * file;
168    char      * filename;
169    GdkPixbuf * pixbuf;
170       
171    file = g_file_icon_get_file( icon );
172    filename = g_file_get_path( file );
173    pixbuf = gdk_pixbuf_new_from_file_at_size( filename, size, -1, NULL );
174    g_free( filename );
175    g_object_unref( file );
176       
177    return pixbuf;
178}
179
180
181static GdkPixbuf *
182_get_icon_pixbuf( GIcon        *icon,
183                  int           size,
184                  GtkIconTheme *theme )
185{
186    if ( icon == NULL )
187        return NULL;
188    if ( G_IS_THEMED_ICON (icon) )
189        return get_themed_icon_pixbuf( G_THEMED_ICON( icon ), size, theme );
190    if ( G_IS_FILE_ICON (icon) )
191        return get_file_icon_pixbuf( G_FILE_ICON( icon ), size );
192    return NULL;
193}
194
195                 
196static GdkPixbuf *
197icon_cache_get_mime_type_icon( IconCache  * icon_cache,
198                               const char * mime_type )
199{
200    GIcon      * icon;
201    const char * key = NULL;
202    GdkPixbuf  * pixbuf;
203
204    icon = g_content_type_get_icon( mime_type );
205    key = _icon_cache_get_icon_key( icon );
206       
207    if (key == NULL)
208        key = VOID_PIXBUF_KEY;
209
210    pixbuf = g_hash_table_lookup( icon_cache->cache, key );
211    if (pixbuf != NULL) {
212        g_object_ref( pixbuf );
213        return pixbuf;
214    }
215       
216    pixbuf = _get_icon_pixbuf( icon, icon_cache->icon_size, icon_cache->icon_theme );
217    g_hash_table_insert( icon_cache->cache, (gpointer) key, g_object_ref( pixbuf ));
218       
219    return pixbuf;
220}
221
222
223GdkPixbuf * 
224get_mime_type_icon( const char   * mime_type,
225                    GtkIconSize    icon_size,
226                    GtkWidget    * for_widget )
227{
228    int n;
229   
230    switch ( icon_size ) {
231        case GTK_ICON_SIZE_INVALID:       n = 0; break;
232        case GTK_ICON_SIZE_MENU:          n = 1; break;
233        case GTK_ICON_SIZE_SMALL_TOOLBAR: n = 2; break;
234        case GTK_ICON_SIZE_LARGE_TOOLBAR: n = 3; break;
235        case GTK_ICON_SIZE_BUTTON:        n = 4; break;
236        case GTK_ICON_SIZE_DND:           n = 5; break;
237        case GTK_ICON_SIZE_DIALOG:        n = 6; break; 
238    }   
239
240    if( icon_cache[n] == NULL )
241        icon_cache[n] = icon_cache_new( for_widget, icon_size );
242
243    return icon_cache_get_mime_type_icon( icon_cache[n], mime_type );
244}                   
245
246
247const char * 
248get_mime_type_from_filename( const char *file )
249{
250    return get_static_string( g_content_type_guess( file, NULL, 0, NULL ));
251}
Note: See TracBrowser for help on using the repository browser.