292 lines
7.3 KiB
C
292 lines
7.3 KiB
C
/*
|
|
* icons.[ch] written by Paolo Bacchilega, who writes:
|
|
* "There is no problem for me, you can license my code under whatever licence you wish :)"
|
|
*/
|
|
|
|
#include <string.h> /* strcmp */
|
|
#include <glib.h>
|
|
#include <gtk/gtk.h>
|
|
#include "icons.h"
|
|
|
|
#ifdef HAVE_GIO
|
|
#if GTK_CHECK_VERSION( 2, 12, 0 )
|
|
#define USE_GIO_ICONS
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef USE_GIO_ICONS
|
|
#include <gio/gio.h>
|
|
#endif
|
|
|
|
#define VOID_PIXBUF_KEY "void-pixbuf"
|
|
|
|
#ifdef USE_GIO_ICONS
|
|
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 );
|
|
}
|
|
#endif
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
#ifdef USE_GIO_ICONS
|
|
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;
|
|
}
|
|
|
|
#else /* USE_GIO_ICONS */
|
|
|
|
static GdkPixbuf *
|
|
icon_cache_get_mime_type_icon( IconCache * icon_cache, const char * mime_type )
|
|
{
|
|
GdkPixbuf * pixbuf;
|
|
const char * stock_name;
|
|
|
|
if( !strcmp( mime_type, UNKNOWN_MIME_TYPE ) )
|
|
stock_name = GTK_STOCK_MISSING_IMAGE;
|
|
else if( !strcmp( mime_type, DIRECTORY_MIME_TYPE ) )
|
|
stock_name = GTK_STOCK_DIRECTORY;
|
|
else
|
|
stock_name = GTK_STOCK_FILE;
|
|
|
|
pixbuf = g_hash_table_lookup( icon_cache->cache, stock_name );
|
|
|
|
if( pixbuf != NULL )
|
|
{
|
|
g_object_ref( pixbuf );
|
|
return pixbuf;
|
|
}
|
|
|
|
pixbuf = gtk_icon_theme_load_icon( icon_cache->icon_theme,
|
|
stock_name,
|
|
icon_cache->icon_size,
|
|
0, NULL );
|
|
g_hash_table_insert( icon_cache->cache, (gpointer) stock_name, g_object_ref( pixbuf ));
|
|
return pixbuf;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
GdkPixbuf *
|
|
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 *
|
|
get_mime_type_from_filename( const char * file G_GNUC_UNUSED )
|
|
{
|
|
#ifdef USE_GIO_ICONS
|
|
char * tmp = g_content_type_guess( file, NULL, 0, NULL );
|
|
const char * ret = get_static_string( tmp );
|
|
g_free( tmp );
|
|
return ret;
|
|
#else
|
|
return "uncertain";
|
|
#endif
|
|
}
|