From fd6f3356d27d3e3b6f0506b76e0a381efed7e3ef Mon Sep 17 00:00:00 2001 From: Alan Fitton Date: Thu, 23 Aug 2012 08:30:02 +0100 Subject: adapt the cell renderer from Transmission to sort of work. possibly an alternative style, but lots of work to be done here. --- src/icons.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 src/icons.c (limited to 'src/icons.c') diff --git a/src/icons.c b/src/icons.c new file mode 100644 index 0000000..0c0e07e --- /dev/null +++ b/src/icons.c @@ -0,0 +1,243 @@ +/* + * 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: icons.c 12639 2011-08-07 18:41:13Z jordan $ + */ + +#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; +} -- cgit v1.2.3