/* Screem: screem-icon-cache.c * * Copyright (C) 2004 David A Knight * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * * For contact information with the author of this source code please see * the AUTHORS file. If there is no AUTHORS file present then check the * about box under the help menu for a contact address */ #include #include #include #include #include #include "screem-icon-cache.h" struct ScreemIconCachePrivate { GtkIconTheme *theme; GnomeThumbnailFactory *small_thumbs; GnomeThumbnailFactory *large_thumbs; GHashTable *hash; }; enum { ARG_0 }; enum { CHANGED, LAST_SIGNAL }; static guint screem_icon_cache_signals[ LAST_SIGNAL ] = { 0 }; static void screem_icon_cache_theme_changed( GtkIconTheme *theme, ScreemIconCache *cache ); static gchar *screem_icon_cache_get_name( ScreemIconCache *cache, const gchar *uri, const gchar *mime_type, gboolean thumbnail, GnomeThumbnailSize thumb_size ); static GdkPixbuf *screem_icon_cache_get_icon( ScreemIconCache *cache, const gchar *uri, const gchar *mime_type, gboolean thumbnail, GnomeThumbnailSize thumb_size, gint size ); /* G Object stuff */ G_DEFINE_TYPE( ScreemIconCache, screem_icon_cache, G_TYPE_OBJECT ) static void screem_icon_cache_finalize( GObject *object ); static void screem_icon_cache_set_prop( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec ); static void screem_icon_cache_get_prop( GObject *object, guint property_id, GValue *value, GParamSpec *pspec ); static void screem_icon_cache_class_init( ScreemIconCacheClass *klass ) { GObjectClass *object_class; object_class = G_OBJECT_CLASS( klass ); object_class->finalize = screem_icon_cache_finalize; screem_icon_cache_parent_class = g_type_class_peek_parent( klass ); object_class->get_property = screem_icon_cache_get_prop; object_class->set_property = screem_icon_cache_set_prop; screem_icon_cache_signals[ CHANGED ] = g_signal_new( "changed", G_OBJECT_CLASS_TYPE( object_class ), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET( ScreemIconCacheClass, changed ), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 ); } static void screem_icon_cache_init( ScreemIconCache *icon_cache ) { ScreemIconCachePrivate *priv; GtkIconTheme *theme; priv = icon_cache->priv = g_new0( ScreemIconCachePrivate, 1 ); theme = priv->theme = gtk_icon_theme_get_default(); g_signal_connect( G_OBJECT( theme ), "changed", G_CALLBACK( screem_icon_cache_theme_changed ), icon_cache ); priv->small_thumbs = gnome_thumbnail_factory_new( GNOME_THUMBNAIL_SIZE_NORMAL ); priv->large_thumbs = gnome_thumbnail_factory_new( GNOME_THUMBNAIL_SIZE_LARGE ); priv->hash = g_hash_table_new_full( g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_object_unref ); } static void screem_icon_cache_finalize( GObject *object ) { ScreemIconCache *icon_cache; ScreemIconCachePrivate *priv; icon_cache = SCREEM_ICON_CACHE( object ); priv = icon_cache->priv; if( priv->theme ) { g_object_unref( priv->theme ); } if( priv->small_thumbs ) { g_object_unref( priv->small_thumbs ); } if( priv->large_thumbs ) { g_object_unref( priv->large_thumbs ); } if( priv->hash ) { g_hash_table_destroy( priv->hash ); } g_free( priv ); G_OBJECT_CLASS( screem_icon_cache_parent_class )->finalize( object ); } static void screem_icon_cache_set_prop( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec ) { ScreemIconCache *icon_cache; ScreemIconCachePrivate *priv; icon_cache = SCREEM_ICON_CACHE( object ); priv = icon_cache->priv; switch( property_id ) { default: break; } } static void screem_icon_cache_get_prop( GObject *object, guint property_id, GValue *value, GParamSpec *pspec ) { ScreemIconCache *icon_cache; ScreemIconCachePrivate *priv; icon_cache = SCREEM_ICON_CACHE( object ); priv = icon_cache->priv; switch( property_id ) { default: break; } } /* Private API */ static void screem_icon_cache_theme_changed( GtkIconTheme *theme, ScreemIconCache *cache ) { ScreemIconCachePrivate *priv; priv = cache->priv; g_hash_table_destroy( priv->hash ); priv->hash = g_hash_table_new_full( g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_object_unref ); g_signal_emit( G_OBJECT( cache ), screem_icon_cache_signals[ CHANGED ], 0 ); } static gchar *screem_icon_cache_get_name( ScreemIconCache *cache, const gchar *uri, const gchar *mime_type, gboolean thumbnail, GnomeThumbnailSize thumb_size ) { ScreemIconCachePrivate *priv; GtkIconTheme *theme; GnomeThumbnailFactory *thumbs; const gchar *custom_icon; GnomeIconLookupFlags flags; GnomeIconLookupResultFlags result; gchar *icon; g_return_val_if_fail( SCREEM_IS_ICON_CACHE( cache ), NULL ); priv = cache->priv; theme = priv->theme; if( ! thumbnail ) { thumbs = NULL; } else if( thumb_size == GNOME_THUMBNAIL_SIZE_LARGE ) { thumbs = priv->large_thumbs; } else { thumbs = priv->small_thumbs; } custom_icon = NULL; flags = GNOME_ICON_LOOKUP_FLAGS_NONE; icon = gnome_icon_lookup( theme, thumbs, uri, custom_icon, NULL /*GnomeVFSFileInfo*/, mime_type, flags, &result ); return icon; } static GdkPixbuf *screem_icon_cache_get_icon( ScreemIconCache *cache, const gchar *uri, const gchar *mime_type, gboolean thumbnail, GnomeThumbnailSize thumb_size, gint size ) { ScreemIconCachePrivate *priv; gchar *icon; gchar *lookup; GtkIconLookupFlags flags; GError *error; GdkPixbuf *pixbuf; guint width; guint height; guint max; gdouble factor; GdkPixbuf *scale; g_return_val_if_fail( SCREEM_IS_ICON_CACHE( cache ), NULL ); priv = cache->priv; icon = screem_icon_cache_get_name( cache, uri, mime_type, thumbnail, thumb_size ); pixbuf = NULL; if( icon ) { if( ! thumbnail ) { lookup = g_strdup_printf( "%s-%i", icon, size ); } else { lookup = g_strdup_printf( "%s-%i-thumb-%i", icon, size, (gint)thumb_size ); } pixbuf = g_hash_table_lookup( priv->hash, lookup ); if( ! pixbuf ) { flags = GTK_ICON_LOOKUP_USE_BUILTIN; error = NULL; pixbuf = gtk_icon_theme_load_icon( priv->theme, icon, size, flags, &error ); if( pixbuf ) { width = gdk_pixbuf_get_width( pixbuf ); height = gdk_pixbuf_get_height( pixbuf ); max = MAX( width, height ); factor = ( size / (gdouble) max ); if( factor != 1.0 ) { width = (guint)width * factor; height = (guint)height * factor; scale = gdk_pixbuf_scale_simple( pixbuf, width, height, GDK_INTERP_HYPER ); if( scale ) { g_object_unref( pixbuf ); pixbuf = scale; } } g_hash_table_insert( priv->hash, g_strdup( lookup ), pixbuf ); } else if( error ) { g_error_free( error ); } } if( pixbuf ) { g_object_ref( pixbuf ); } g_free( lookup ); g_free( icon ); } return pixbuf; } /* Public API */ ScreemIconCache *screem_icon_cache_new( void ) { ScreemIconCache *icon_cache; icon_cache = SCREEM_ICON_CACHE( g_object_new( SCREEM_TYPE_ICON_CACHE, NULL ) ); return icon_cache; } GdkPixbuf *screem_icon_cache_get_pixbuf( ScreemIconCache *cache, const gchar *uri, const gchar *mime_type, gint size ) { GdkPixbuf *ret; g_return_val_if_fail( SCREEM_IS_ICON_CACHE( cache ), NULL ); g_return_val_if_fail( ( uri != NULL || mime_type != NULL ), NULL ); ret = screem_icon_cache_get_icon( cache, uri, mime_type, FALSE, GNOME_THUMBNAIL_SIZE_NORMAL, size ); return ret; } GdkPixbuf *screem_icon_cache_get_thumbnail( ScreemIconCache *cache, const gchar *uri, const gchar *mime_type, gint size ) { GdkPixbuf *ret; g_return_val_if_fail( SCREEM_IS_ICON_CACHE( cache ), NULL ); g_return_val_if_fail( ( uri != NULL || mime_type != NULL ), NULL ); ret = screem_icon_cache_get_icon( cache, uri, mime_type, FALSE, GNOME_THUMBNAIL_SIZE_NORMAL, size ); return ret; } GdkPixbuf *screem_icon_cache_get_large_thumbnail( ScreemIconCache *cache, const gchar *uri, const gchar *mime_type, gint size ) { GdkPixbuf *ret; g_return_val_if_fail( SCREEM_IS_ICON_CACHE( cache ), NULL ); g_return_val_if_fail( ( uri != NULL || mime_type != NULL ), NULL ); ret = screem_icon_cache_get_icon( cache, uri, mime_type, FALSE, GNOME_THUMBNAIL_SIZE_LARGE, size ); return ret; }