mirror of
https://github.com/transmission/transmission
synced 2024-12-27 01:57:52 +00:00
260 lines
5.7 KiB
C
260 lines
5.7 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 <glib.h>
|
|
#include <gtk/gtk.h>
|
|
#include <gio/gio.h>
|
|
#include "icons.h"
|
|
|
|
#define VOID_PIXBUF_KEY "void-pixbuf"
|
|
|
|
static char const* get_static_string(char const* 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(GtkIconSize icon_size)
|
|
{
|
|
int width = 0;
|
|
int height = 0;
|
|
gtk_icon_size_lookup(icon_size, &width, &height);
|
|
return MAX(width, height);
|
|
}
|
|
|
|
static IconCache* icon_cache_new(GtkWidget* for_widget, int icon_size)
|
|
{
|
|
g_return_val_if_fail(for_widget != NULL, NULL);
|
|
|
|
IconCache* icons = g_new0(IconCache, 1);
|
|
icons->icon_theme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(for_widget));
|
|
icons->icon_size = get_size_in_pixels(icon_size);
|
|
icons->cache = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_object_unref);
|
|
|
|
g_hash_table_insert(icons->cache, (void*)VOID_PIXBUF_KEY, create_void_pixbuf(icons->icon_size, icons->icon_size));
|
|
|
|
return icons;
|
|
}
|
|
|
|
static char const* _icon_cache_get_icon_key(GIcon* icon)
|
|
{
|
|
char const* 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, (char const**)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 != NULL && error->message != NULL)
|
|
{
|
|
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* icons, char const* mime_type)
|
|
{
|
|
GIcon* icon = g_content_type_get_icon(mime_type);
|
|
char const* key = _icon_cache_get_icon_key(icon);
|
|
if (key == NULL)
|
|
{
|
|
key = VOID_PIXBUF_KEY;
|
|
}
|
|
|
|
g_return_val_if_fail(icons != NULL, NULL);
|
|
GdkPixbuf* pixbuf = g_hash_table_lookup(icons->cache, key);
|
|
if (pixbuf != NULL)
|
|
{
|
|
g_object_ref(pixbuf);
|
|
g_object_unref(G_OBJECT(icon));
|
|
return pixbuf;
|
|
}
|
|
|
|
pixbuf = _get_icon_pixbuf(icon, icons->icon_size, icons->icon_theme);
|
|
|
|
if (pixbuf != NULL)
|
|
{
|
|
g_hash_table_insert(icons->cache, (gpointer)key, g_object_ref(pixbuf));
|
|
}
|
|
|
|
g_object_unref(G_OBJECT(icon));
|
|
|
|
return pixbuf;
|
|
}
|
|
|
|
GdkPixbuf* gtr_get_mime_type_icon(char const* 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);
|
|
}
|
|
|
|
char const* gtr_get_mime_type_from_filename(char const* file)
|
|
{
|
|
char* tmp = g_content_type_guess(file, NULL, 0, NULL);
|
|
char const* ret = get_static_string(tmp);
|
|
g_free(tmp);
|
|
return ret;
|
|
}
|