/* * 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; }