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 |
---|
24 | static const char * |
---|
25 | get_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 | |
---|
40 | typedef struct { |
---|
41 | GtkIconTheme * icon_theme; |
---|
42 | int icon_size; |
---|
43 | GHashTable * cache; |
---|
44 | } IconCache; |
---|
45 | |
---|
46 | |
---|
47 | static IconCache *icon_cache[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; |
---|
48 | |
---|
49 | |
---|
50 | static GdkPixbuf* |
---|
51 | create_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 | |
---|
67 | static int |
---|
68 | get_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 | |
---|
81 | static IconCache * |
---|
82 | icon_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 |
---|
99 | static 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 | |
---|
133 | static GdkPixbuf * |
---|
134 | get_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 | |
---|
163 | static GdkPixbuf * |
---|
164 | get_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 | |
---|
180 | static 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 | |
---|
193 | static GdkPixbuf * |
---|
194 | icon_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 | |
---|
224 | static GdkPixbuf * |
---|
225 | icon_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 | |
---|
256 | GdkPixbuf * |
---|
257 | get_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 | |
---|
280 | const char * |
---|
281 | get_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 | } |
---|