/* * icons.[ch] written by Paolo Bacchilega, who writes: * "There is no problem for me, you can license my code * under whatever licence you wish :)" * * $Id$ */ #include /* strcmp */ #include #include #include #include "icons.h" #define VOID_PIXBUF_KEY "void-pixbuf" static const char * get_static_string( const char *s ) { static GStringChunk * static_strings = NULL; if( s == NULL ) return NULL; if( static_strings == NULL ) static_strings = g_string_chunk_new( 1024 ); return g_string_chunk_insert_const( static_strings, s ); } typedef struct { GtkIconTheme * icon_theme; int icon_size; GHashTable * cache; } IconCache; static IconCache *icon_cache[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static GdkPixbuf* create_void_pixbuf (int width, int height) { GdkPixbuf *p; p = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE, 8, width, height); gdk_pixbuf_fill( p, 0xFFFFFF00 ); return p; } static int get_size_in_pixels( GtkWidget * widget, GtkIconSize icon_size ) { int width, height; gtk_icon_size_lookup_for_settings( gtk_widget_get_settings( widget ), icon_size, &width, &height ); return MAX( width, height ); } static IconCache * icon_cache_new (GtkWidget * for_widget, int icon_size) { IconCache * icon_cache; g_return_val_if_fail( for_widget != NULL, NULL ); icon_cache = g_new0( IconCache, 1 ); icon_cache->icon_theme = gtk_icon_theme_get_for_screen( gtk_widget_get_screen( for_widget )); icon_cache->icon_size = get_size_in_pixels( for_widget, icon_size ); icon_cache->cache = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); g_hash_table_insert( icon_cache->cache, (void*)VOID_PIXBUF_KEY, create_void_pixbuf( icon_cache->icon_size, icon_cache->icon_size )); return icon_cache; } static const char * _icon_cache_get_icon_key( GIcon * icon ) { const char * key = NULL; if ( G_IS_THEMED_ICON( icon )) { char ** icon_names; char * name; g_object_get( icon, "names", &icon_names, NULL ); name = g_strjoinv( ",", icon_names ); key = get_static_string( name ); g_free( name ); g_strfreev( icon_names ); } else if ( G_IS_FILE_ICON( icon )) { GFile * file; char * filename; file = g_file_icon_get_file( G_FILE_ICON( icon )); filename = g_file_get_path( file ); key = get_static_string( filename ); g_free( filename ); g_object_unref( file ); } return key; } static GdkPixbuf * get_themed_icon_pixbuf( GThemedIcon * icon, int size, GtkIconTheme * icon_theme ) { char ** icon_names = NULL; GtkIconInfo * icon_info; GdkPixbuf * pixbuf; GError * error = NULL; g_object_get( icon, "names", &icon_names, NULL ); icon_info = gtk_icon_theme_choose_icon( icon_theme, (const char **)icon_names, size, 0 ); if ( icon_info == NULL ) icon_info = gtk_icon_theme_lookup_icon( icon_theme, "text-x-generic", size, GTK_ICON_LOOKUP_USE_BUILTIN ); pixbuf = gtk_icon_info_load_icon( icon_info, &error ); if ( pixbuf == NULL ) { if( error && error->message ) g_warning( "could not load icon pixbuf: %s\n", error->message ); g_clear_error( &error ); } gtk_icon_info_free( icon_info ); g_strfreev( icon_names ); return pixbuf; } static GdkPixbuf * get_file_icon_pixbuf( GFileIcon * icon, int size ) { GFile * file; char * filename; GdkPixbuf * pixbuf; file = g_file_icon_get_file( icon ); filename = g_file_get_path( file ); pixbuf = gdk_pixbuf_new_from_file_at_size( filename, size, -1, NULL ); g_free( filename ); g_object_unref( file ); return pixbuf; } static GdkPixbuf * _get_icon_pixbuf( GIcon * icon, int size, GtkIconTheme * theme ) { if ( icon == NULL ) return NULL; if ( G_IS_THEMED_ICON (icon) ) return get_themed_icon_pixbuf( G_THEMED_ICON( icon ), size, theme ); if ( G_IS_FILE_ICON (icon) ) return get_file_icon_pixbuf( G_FILE_ICON( icon ), size ); return NULL; } static GdkPixbuf * icon_cache_get_mime_type_icon( IconCache * icon_cache, const char * mime_type ) { GIcon * icon; const char * key = NULL; GdkPixbuf * pixbuf; icon = g_content_type_get_icon( mime_type ); key = _icon_cache_get_icon_key( icon ); if (key == NULL) key = VOID_PIXBUF_KEY; pixbuf = g_hash_table_lookup( icon_cache->cache, key ); if (pixbuf != NULL) { g_object_ref( pixbuf ); g_object_unref( G_OBJECT( icon ) ); return pixbuf; } pixbuf = _get_icon_pixbuf( icon, icon_cache->icon_size, icon_cache->icon_theme ); if( pixbuf != NULL ) g_hash_table_insert( icon_cache->cache, (gpointer) key, g_object_ref( pixbuf ) ); g_object_unref( G_OBJECT( icon ) ); return pixbuf; } GdkPixbuf * gtr_get_mime_type_icon( const char * mime_type, GtkIconSize icon_size, GtkWidget * for_widget ) { int n; switch ( icon_size ) { case GTK_ICON_SIZE_MENU: n = 1; break; case GTK_ICON_SIZE_SMALL_TOOLBAR: n = 2; break; case GTK_ICON_SIZE_LARGE_TOOLBAR: n = 3; break; case GTK_ICON_SIZE_BUTTON: n = 4; break; case GTK_ICON_SIZE_DND: n = 5; break; case GTK_ICON_SIZE_DIALOG: n = 6; break; default /*GTK_ICON_SIZE_INVALID*/: n = 0; break; } if( icon_cache[n] == NULL ) icon_cache[n] = icon_cache_new( for_widget, icon_size ); return icon_cache_get_mime_type_icon( icon_cache[n], mime_type ); } const char * gtr_get_mime_type_from_filename( const char * file G_GNUC_UNUSED ) { char * tmp = g_content_type_guess( file, NULL, 0, NULL ); const char * ret = get_static_string( tmp ); g_free( tmp ); return ret; }