--- /dev/null
+#include "image-cache.h"
+
+ImageCache *
+image_cache_new(guint cache_max)
+{
+ImageCache *ic;
+ic=g_slice_new0(ImageCache);
+ic->cache=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
+ic->cache_max=cache_max;
+return ic;
+}
+
+void
+image_cache_free(ImageCache *ic)
+{
+g_assert(ic);
+g_assert(ic->cache);
+image_cache_clear(ic);
+g_hash_table_destroy(ic->cache);
+g_slice_free(ImageCache, ic);
+}
+
+static void
+image_cache_stats(ImageCache *ic)
+{
+g_assert(ic);
+g_assert(ic->cache);
+
+g_debug("ICC: %u/%u (E: %u, GC: %u S: %d)", ic->hit, ic->miss, ic->error, ic->gc, g_hash_table_size(ic->cache));
+}
+
+void
+image_cache_clear(ImageCache *ic)
+{
+g_assert(ic);
+g_assert(ic->cache);
+
+#if (GLIB_CHECK_VERSION (2, 12, 0))
+g_hash_table_remove_all(ic->cache);
+#else
+g_hash_table_foreach_remove(ic->cache, gtk_true, NULL);
+#endif
+}
+
+void
+image_cache_invalidate(ImageCache *ic, const gchar *key)
+{
+g_assert(ic);
+g_assert(ic->cache);
+g_assert(key);
+g_hash_table_remove(ic->cache, key);
+}
+
+static gboolean
+image_cache_is_same(gchar *key, GdkPixbuf *cpixbuf, GdkPixbuf *pixbuf)
+{
+return (pixbuf==cpixbuf) ? TRUE : FALSE;
+}
+
+void
+image_cache_invalidate_by_image(ImageCache *ic, GdkPixbuf *pixbuf)
+{
+g_assert(ic);
+g_assert(ic->cache);
+g_return_if_fail(GDK_IS_PIXBUF(pixbuf));
+g_hash_table_foreach_remove(ic->cache, image_cache_is_same, pixbuf);
+}
+
+void
+image_cache_replace(ImageCache *ic, const gchar *key, GdkPixbuf *pixbuf)
+{
+
+}
+
+static gboolean
+image_cache_gc_check(gchar *key, GdkPixbuf *pixbuf, ImageCache *ic)
+{
+g_assert(ic);
+/* For now just remove everything when over limit */
+return TRUE;
+}
+
+void
+image_cache_gc(ImageCache *ic, gint max)
+{
+gint m;
+
+g_assert(ic);
+g_assert(ic->cache);
+
+m=(max>0) ? max : ic->cache_max;
+if (g_hash_table_size(ic->cache)>m) {
+ g_hash_table_foreach_remove(ic->cache,(GHRFunc *)image_cache_gc_check, ic);
+ ic->gc++;
+}
+}
+
+GdkPixbuf *
+image_cache_get(ImageCache *ic, const gchar *key, const gchar *image)
+{
+GdkPixbuf *pixbuf;
+GError *error=NULL;
+
+g_assert(ic);
+g_assert(ic->cache);
+g_assert(key);
+g_assert(image);
+
+image_cache_stats(ic);
+
+pixbuf=g_hash_table_lookup(ic->cache, key);
+if (pixbuf) {
+ ic->hit++;
+ return pixbuf;
+}
+
+pixbuf=gdk_pixbuf_new_from_file(image, &error);
+if (error || !pixbuf) {
+ ic->error++;
+ return NULL;
+}
+g_return_val_if_fail(GDK_IS_PIXBUF(pixbuf), NULL);
+
+image_cache_gc(ic, 0);
+
+ic->miss++;
+g_hash_table_insert(ic->cache, g_strdup(key), pixbuf);
+return pixbuf;
+}
--- /dev/null
+#ifndef _MAPPER_IMAGE_CACHE_H
+#define _MAPPER_IMAGE_CACHE_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+typedef struct _image_cache_item ImageCacheItem;
+struct _image_cache_item {
+ GdkPixbuf *pixbuf;
+ time_t last_hit;
+};
+
+typedef struct _image_cache ImageCache;
+struct _image_cache {
+ GHashTable *cache;
+ guint hit;
+ guint miss;
+ guint error;
+ guint cache_max;
+ guint gc;
+};
+
+ImageCache *image_cache_new(guint cache_max);
+void image_cache_free(ImageCache *ic);
+void image_cache_clear(ImageCache *ic);
+void image_cache_gc(ImageCache *ic, gint max);
+void image_cache_invalidate(ImageCache *ic, const gchar *key);
+void image_cache_invalidate_by_image(ImageCache *ic, GdkPixbuf *pixbuf);
+GdkPixbuf *image_cache_get(ImageCache *ic, const gchar *key, const gchar *icon);
+
+#endif