2009-03-02 23:31:01 +00:00
|
|
|
/*
|
|
|
|
* icons.[ch] written by Paolo Bacchilega, who writes:
|
2011-01-19 13:48:47 +00:00
|
|
|
* "There is no problem for me, you can license my code
|
|
|
|
* under whatever licence you wish :)"
|
2010-10-01 20:22:51 +00:00
|
|
|
*
|
2009-03-02 23:31:01 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <gtk/gtk.h>
|
2011-08-07 18:41:13 +00:00
|
|
|
#include <gio/gio.h>
|
2009-03-02 23:31:01 +00:00
|
|
|
#include "icons.h"
|
|
|
|
|
2009-03-03 00:55:03 +00:00
|
|
|
#define VOID_PIXBUF_KEY "void-pixbuf"
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
static char const* get_static_string(char const* s)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
static GStringChunk* static_strings = nullptr;
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
if (s == nullptr)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
return nullptr;
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
if (static_strings == nullptr)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
static_strings = g_string_chunk_new(1024);
|
|
|
|
}
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
return g_string_chunk_insert_const(static_strings, s);
|
2009-03-02 23:31:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
GtkIconTheme* icon_theme;
|
|
|
|
int icon_size;
|
|
|
|
GHashTable* cache;
|
2021-08-15 09:41:48 +00:00
|
|
|
} IconCache;
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
static IconCache* icon_cache[7] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static GdkPixbuf* create_void_pixbuf(int width, int height)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
GdkPixbuf* p;
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
p = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
|
|
|
|
gdk_pixbuf_fill(p, 0xFFFFFF00);
|
2009-03-02 23:31:01 +00:00
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2020-11-09 03:31:02 +00:00
|
|
|
static int get_size_in_pixels(GtkIconSize icon_size)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
2020-11-09 03:31:02 +00:00
|
|
|
int width = 0;
|
|
|
|
int height = 0;
|
|
|
|
gtk_icon_size_lookup(icon_size, &width, &height);
|
2017-04-19 12:04:45 +00:00
|
|
|
return MAX(width, height);
|
2009-03-02 23:31:01 +00:00
|
|
|
}
|
|
|
|
|
2021-09-25 10:47:09 +00:00
|
|
|
static IconCache* icon_cache_new(GtkWidget* for_widget, GtkIconSize icon_size)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
g_return_val_if_fail(for_widget != nullptr, nullptr);
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2020-08-11 18:11:55 +00:00
|
|
|
IconCache* icons = g_new0(IconCache, 1);
|
|
|
|
icons->icon_theme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(for_widget));
|
2020-11-09 03:31:02 +00:00
|
|
|
icons->icon_size = get_size_in_pixels(icon_size);
|
2021-10-06 16:32:17 +00:00
|
|
|
icons->cache = g_hash_table_new_full(g_str_hash, g_str_equal, nullptr, g_object_unref);
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2021-08-15 09:41:48 +00:00
|
|
|
g_hash_table_insert(icons->cache, (void*)VOID_PIXBUF_KEY, create_void_pixbuf(icons->icon_size, icons->icon_size));
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2020-08-11 18:11:55 +00:00
|
|
|
return icons;
|
2009-03-02 23:31:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
static char const* _icon_cache_get_icon_key(GIcon* icon)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
char const* key = nullptr;
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (G_IS_THEMED_ICON(icon))
|
|
|
|
{
|
|
|
|
char** icon_names;
|
2017-04-21 07:40:57 +00:00
|
|
|
char* name;
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
g_object_get(icon, "names", &icon_names, nullptr);
|
2017-04-19 12:04:45 +00:00
|
|
|
name = g_strjoinv(",", icon_names);
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
key = get_static_string(name);
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
g_free(name);
|
|
|
|
g_strfreev(icon_names);
|
2009-03-02 23:31:01 +00:00
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
else if (G_IS_FILE_ICON(icon))
|
|
|
|
{
|
|
|
|
GFile* file;
|
2017-04-21 07:40:57 +00:00
|
|
|
char* filename;
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
file = g_file_icon_get_file(G_FILE_ICON(icon));
|
|
|
|
filename = g_file_get_path(file);
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
key = get_static_string(filename);
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
g_free(filename);
|
|
|
|
g_object_unref(file);
|
2009-03-02 23:31:01 +00:00
|
|
|
}
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2009-03-02 23:31:01 +00:00
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static GdkPixbuf* get_themed_icon_pixbuf(GThemedIcon* icon, int size, GtkIconTheme* icon_theme)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
char** icon_names = nullptr;
|
2017-04-19 12:04:45 +00:00
|
|
|
GtkIconInfo* icon_info;
|
|
|
|
GdkPixbuf* pixbuf;
|
2021-10-06 16:32:17 +00:00
|
|
|
GError* error = nullptr;
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
g_object_get(icon, "names", &icon_names, nullptr);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2021-09-25 10:47:09 +00:00
|
|
|
icon_info = gtk_icon_theme_choose_icon(icon_theme, (char const**)icon_names, size, {});
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
if (icon_info == nullptr)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
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);
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
if (pixbuf == nullptr)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
if (error != nullptr && error->message != nullptr)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
g_warning("could not load icon pixbuf: %s\n", error->message);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_clear_error(&error);
|
2009-03-02 23:31:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-21 07:40:57 +00:00
|
|
|
#if GTK_CHECK_VERSION(3, 8, 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
g_object_unref(icon_info);
|
2013-07-08 16:25:18 +00:00
|
|
|
#else
|
2017-04-19 12:04:45 +00:00
|
|
|
gtk_icon_info_free(icon_info);
|
2013-07-08 16:25:18 +00:00
|
|
|
#endif
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
g_strfreev(icon_names);
|
2009-03-02 23:31:01 +00:00
|
|
|
|
|
|
|
return pixbuf;
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static GdkPixbuf* get_file_icon_pixbuf(GFileIcon* icon, int size)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
GFile* file;
|
|
|
|
char* filename;
|
|
|
|
GdkPixbuf* pixbuf;
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
file = g_file_icon_get_file(icon);
|
|
|
|
filename = g_file_get_path(file);
|
2021-10-06 16:32:17 +00:00
|
|
|
pixbuf = gdk_pixbuf_new_from_file_at_size(filename, size, -1, nullptr);
|
2017-04-19 12:04:45 +00:00
|
|
|
g_free(filename);
|
|
|
|
g_object_unref(file);
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2009-03-02 23:31:01 +00:00
|
|
|
return pixbuf;
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static GdkPixbuf* _get_icon_pixbuf(GIcon* icon, int size, GtkIconTheme* theme)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
if (icon == nullptr)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
return nullptr;
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
return nullptr;
|
2009-03-02 23:31:01 +00:00
|
|
|
}
|
|
|
|
|
2020-08-11 18:11:55 +00:00
|
|
|
static GdkPixbuf* icon_cache_get_mime_type_icon(IconCache* icons, char const* mime_type)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
2020-10-31 21:23:43 +00:00
|
|
|
GIcon* icon = g_content_type_get_icon(mime_type);
|
|
|
|
char const* key = _icon_cache_get_icon_key(icon);
|
2021-10-06 16:32:17 +00:00
|
|
|
if (key == nullptr)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2009-03-02 23:31:01 +00:00
|
|
|
key = VOID_PIXBUF_KEY;
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
g_return_val_if_fail(icons != nullptr, nullptr);
|
2021-09-25 10:47:09 +00:00
|
|
|
auto* pixbuf = static_cast<GdkPixbuf*>(g_hash_table_lookup(icons->cache, key));
|
2021-10-06 16:32:17 +00:00
|
|
|
if (pixbuf != nullptr)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
g_object_ref(pixbuf);
|
|
|
|
g_object_unref(G_OBJECT(icon));
|
2009-03-02 23:31:01 +00:00
|
|
|
return pixbuf;
|
|
|
|
}
|
2009-07-27 18:48:21 +00:00
|
|
|
|
2020-08-11 18:11:55 +00:00
|
|
|
pixbuf = _get_icon_pixbuf(icon, icons->icon_size, icons->icon_theme);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
if (pixbuf != nullptr)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2020-08-11 18:11:55 +00:00
|
|
|
g_hash_table_insert(icons->cache, (gpointer)key, g_object_ref(pixbuf));
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2009-11-25 04:42:42 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
g_object_unref(G_OBJECT(icon));
|
2010-05-18 20:55:14 +00:00
|
|
|
|
2009-03-02 23:31:01 +00:00
|
|
|
return pixbuf;
|
|
|
|
}
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
GdkPixbuf* gtr_get_mime_type_icon(char const* mime_type, GtkIconSize icon_size, GtkWidget* for_widget)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
|
|
|
int n;
|
2010-01-05 23:47:50 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
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;
|
2010-05-18 20:55:14 +00:00
|
|
|
}
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2021-10-06 16:32:17 +00:00
|
|
|
if (icon_cache[n] == nullptr)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
icon_cache[n] = icon_cache_new(for_widget, icon_size);
|
|
|
|
}
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
return icon_cache_get_mime_type_icon(icon_cache[n], mime_type);
|
2010-01-05 23:47:50 +00:00
|
|
|
}
|
2009-03-02 23:31:01 +00:00
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* gtr_get_mime_type_from_filename(char const* file)
|
2009-03-02 23:31:01 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
char* tmp = g_content_type_guess(file, nullptr, 0, nullptr);
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* ret = get_static_string(tmp);
|
2017-04-19 12:04:45 +00:00
|
|
|
g_free(tmp);
|
2009-04-23 15:45:30 +00:00
|
|
|
return ret;
|
2009-03-03 17:58:25 +00:00
|
|
|
}
|