247 lines
6.1 KiB
C
247 lines
6.1 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 :)"
|
|
*
|
|
* $Id$
|
|
*/
|
|
|
|
#include <glib.h>
|
|
#include <gtk/gtk.h>
|
|
#include <gio/gio.h>
|
|
#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);
|
|
}
|
|
|
|
#if GTK_CHECK_VERSION(3,8,0)
|
|
g_object_unref (icon_info);
|
|
#else
|
|
gtk_icon_info_free (icon_info);
|
|
#endif
|
|
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)
|
|
{
|
|
char * tmp = g_content_type_guess (file, NULL, 0, NULL);
|
|
const char * ret = get_static_string (tmp);
|
|
g_free (tmp);
|
|
return ret;
|
|
}
|