nautilus/libnautilus-private/nautilus-icon-info.c
Cosimo Cecchi 17d2a02449 Remove more unused methods
Found with cppcheck.
2015-05-23 13:45:39 -07:00

581 lines
13 KiB
C

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* nautilus-icon-info.c
* Copyright (C) 2007 Red Hat, Inc., Alexander Larsson <alexl@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <string.h>
#include "nautilus-icon-info.h"
#include "nautilus-icon-names.h"
#include "nautilus-default-file-icon.h"
#include <gtk/gtk.h>
#include <gio/gio.h>
struct _NautilusIconInfo
{
GObject parent;
gboolean sole_owner;
gint64 last_use_time;
GdkPixbuf *pixbuf;
char *icon_name;
gint orig_scale;
};
struct _NautilusIconInfoClass
{
GObjectClass parent_class;
};
static void schedule_reap_cache (void);
G_DEFINE_TYPE (NautilusIconInfo,
nautilus_icon_info,
G_TYPE_OBJECT);
static void
nautilus_icon_info_init (NautilusIconInfo *icon)
{
icon->last_use_time = g_get_monotonic_time ();
icon->sole_owner = TRUE;
}
gboolean
nautilus_icon_info_is_fallback (NautilusIconInfo *icon)
{
return icon->pixbuf == NULL;
}
static void
pixbuf_toggle_notify (gpointer info,
GObject *object,
gboolean is_last_ref)
{
NautilusIconInfo *icon = info;
if (is_last_ref) {
icon->sole_owner = TRUE;
g_object_remove_toggle_ref (object,
pixbuf_toggle_notify,
info);
icon->last_use_time = g_get_monotonic_time ();
schedule_reap_cache ();
}
}
static void
nautilus_icon_info_finalize (GObject *object)
{
NautilusIconInfo *icon;
icon = NAUTILUS_ICON_INFO (object);
if (!icon->sole_owner && icon->pixbuf) {
g_object_remove_toggle_ref (G_OBJECT (icon->pixbuf),
pixbuf_toggle_notify,
icon);
}
if (icon->pixbuf) {
g_object_unref (icon->pixbuf);
}
g_free (icon->icon_name);
G_OBJECT_CLASS (nautilus_icon_info_parent_class)->finalize (object);
}
static void
nautilus_icon_info_class_init (NautilusIconInfoClass *icon_info_class)
{
GObjectClass *gobject_class;
gobject_class = (GObjectClass *) icon_info_class;
gobject_class->finalize = nautilus_icon_info_finalize;
}
NautilusIconInfo *
nautilus_icon_info_new_for_pixbuf (GdkPixbuf *pixbuf,
gint scale)
{
NautilusIconInfo *icon;
icon = g_object_new (NAUTILUS_TYPE_ICON_INFO, NULL);
if (pixbuf) {
icon->pixbuf = g_object_ref (pixbuf);
}
icon->orig_scale = scale;
return icon;
}
static NautilusIconInfo *
nautilus_icon_info_new_for_icon_info (GtkIconInfo *icon_info,
gint scale)
{
NautilusIconInfo *icon;
const char *filename;
char *basename, *p;
icon = g_object_new (NAUTILUS_TYPE_ICON_INFO, NULL);
icon->pixbuf = gtk_icon_info_load_icon (icon_info, NULL);
filename = gtk_icon_info_get_filename (icon_info);
if (filename != NULL) {
basename = g_path_get_basename (filename);
p = strrchr (basename, '.');
if (p) {
*p = 0;
}
icon->icon_name = basename;
}
icon->orig_scale = scale;
return icon;
}
typedef struct {
GIcon *icon;
int size;
} LoadableIconKey;
typedef struct {
char *filename;
int size;
} ThemedIconKey;
static GHashTable *loadable_icon_cache = NULL;
static GHashTable *themed_icon_cache = NULL;
static guint reap_cache_timeout = 0;
#define MICROSEC_PER_SEC ((guint64)1000000L)
static guint time_now;
static gboolean
reap_old_icon (gpointer key,
gpointer value,
gpointer user_info)
{
NautilusIconInfo *icon = value;
gboolean *reapable_icons_left = user_info;
if (icon->sole_owner) {
if (time_now - icon->last_use_time > 30 * MICROSEC_PER_SEC) {
/* This went unused 30 secs ago. reap */
return TRUE;
} else {
/* We can reap this soon */
*reapable_icons_left = TRUE;
}
}
return FALSE;
}
static gboolean
reap_cache (gpointer data)
{
gboolean reapable_icons_left;
reapable_icons_left = TRUE;
time_now = g_get_monotonic_time ();
if (loadable_icon_cache) {
g_hash_table_foreach_remove (loadable_icon_cache,
reap_old_icon,
&reapable_icons_left);
}
if (themed_icon_cache) {
g_hash_table_foreach_remove (themed_icon_cache,
reap_old_icon,
&reapable_icons_left);
}
if (reapable_icons_left) {
return TRUE;
} else {
reap_cache_timeout = 0;
return FALSE;
}
}
static void
schedule_reap_cache (void)
{
if (reap_cache_timeout == 0) {
reap_cache_timeout = g_timeout_add_seconds_full (0, 5,
reap_cache,
NULL, NULL);
}
}
void
nautilus_icon_info_clear_caches (void)
{
if (loadable_icon_cache) {
g_hash_table_remove_all (loadable_icon_cache);
}
if (themed_icon_cache) {
g_hash_table_remove_all (themed_icon_cache);
}
}
static guint
loadable_icon_key_hash (LoadableIconKey *key)
{
return g_icon_hash (key->icon) ^ key->size;
}
static gboolean
loadable_icon_key_equal (const LoadableIconKey *a,
const LoadableIconKey *b)
{
return a->size == b->size &&
g_icon_equal (a->icon, b->icon);
}
static LoadableIconKey *
loadable_icon_key_new (GIcon *icon, int size)
{
LoadableIconKey *key;
key = g_slice_new (LoadableIconKey);
key->icon = g_object_ref (icon);
key->size = size;
return key;
}
static void
loadable_icon_key_free (LoadableIconKey *key)
{
g_object_unref (key->icon);
g_slice_free (LoadableIconKey, key);
}
static guint
themed_icon_key_hash (ThemedIconKey *key)
{
return g_str_hash (key->filename) ^ key->size;
}
static gboolean
themed_icon_key_equal (const ThemedIconKey *a,
const ThemedIconKey *b)
{
return a->size == b->size &&
g_str_equal (a->filename, b->filename);
}
static ThemedIconKey *
themed_icon_key_new (const char *filename, int size)
{
ThemedIconKey *key;
key = g_slice_new (ThemedIconKey);
key->filename = g_strdup (filename);
key->size = size;
return key;
}
static void
themed_icon_key_free (ThemedIconKey *key)
{
g_free (key->filename);
g_slice_free (ThemedIconKey, key);
}
NautilusIconInfo *
nautilus_icon_info_lookup (GIcon *icon,
int size,
int scale)
{
NautilusIconInfo *icon_info;
GdkPixbuf *pixbuf;
if (G_IS_LOADABLE_ICON (icon)) {
LoadableIconKey lookup_key;
LoadableIconKey *key;
GInputStream *stream;
if (loadable_icon_cache == NULL) {
loadable_icon_cache =
g_hash_table_new_full ((GHashFunc)loadable_icon_key_hash,
(GEqualFunc)loadable_icon_key_equal,
(GDestroyNotify) loadable_icon_key_free,
(GDestroyNotify) g_object_unref);
}
lookup_key.icon = icon;
lookup_key.size = size;
icon_info = g_hash_table_lookup (loadable_icon_cache, &lookup_key);
if (icon_info) {
return g_object_ref (icon_info);
}
pixbuf = NULL;
stream = g_loadable_icon_load (G_LOADABLE_ICON (icon),
size * scale,
NULL, NULL, NULL);
if (stream) {
pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream,
size * scale, size * scale,
TRUE,
NULL, NULL);
g_input_stream_close (stream, NULL, NULL);
g_object_unref (stream);
}
icon_info = nautilus_icon_info_new_for_pixbuf (pixbuf, scale);
key = loadable_icon_key_new (icon, size);
g_hash_table_insert (loadable_icon_cache, key, icon_info);
return g_object_ref (icon_info);
} else if (G_IS_THEMED_ICON (icon)) {
const char * const *names;
ThemedIconKey lookup_key;
ThemedIconKey *key;
GtkIconTheme *icon_theme;
GtkIconInfo *gtkicon_info;
const char *filename;
if (themed_icon_cache == NULL) {
themed_icon_cache =
g_hash_table_new_full ((GHashFunc)themed_icon_key_hash,
(GEqualFunc)themed_icon_key_equal,
(GDestroyNotify) themed_icon_key_free,
(GDestroyNotify) g_object_unref);
}
names = g_themed_icon_get_names (G_THEMED_ICON (icon));
icon_theme = gtk_icon_theme_get_default ();
gtkicon_info = gtk_icon_theme_choose_icon_for_scale (icon_theme, (const char **)names,
size, scale, 0);
if (gtkicon_info == NULL) {
return nautilus_icon_info_new_for_pixbuf (NULL, scale);
}
filename = gtk_icon_info_get_filename (gtkicon_info);
if (filename == NULL) {
g_object_unref (gtkicon_info);
return nautilus_icon_info_new_for_pixbuf (NULL, scale);
}
lookup_key.filename = (char *)filename;
lookup_key.size = size;
icon_info = g_hash_table_lookup (themed_icon_cache, &lookup_key);
if (icon_info) {
g_object_unref (gtkicon_info);
return g_object_ref (icon_info);
}
icon_info = nautilus_icon_info_new_for_icon_info (gtkicon_info, scale);
key = themed_icon_key_new (filename, size);
g_hash_table_insert (themed_icon_cache, key, icon_info);
g_object_unref (gtkicon_info);
return g_object_ref (icon_info);
} else {
GdkPixbuf *pixbuf;
GtkIconInfo *gtk_icon_info;
gtk_icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (gtk_icon_theme_get_default (),
icon,
size,
scale,
GTK_ICON_LOOKUP_GENERIC_FALLBACK);
if (gtk_icon_info != NULL) {
pixbuf = gtk_icon_info_load_icon (gtk_icon_info, NULL);
g_object_unref (gtk_icon_info);
} else {
pixbuf = NULL;
}
icon_info = nautilus_icon_info_new_for_pixbuf (pixbuf, scale);
if (pixbuf != NULL) {
g_object_unref (pixbuf);
}
return icon_info;
}
}
NautilusIconInfo *
nautilus_icon_info_lookup_from_name (const char *name,
int size,
int scale)
{
GIcon *icon;
NautilusIconInfo *info;
icon = g_themed_icon_new (name);
info = nautilus_icon_info_lookup (icon, size, scale);
g_object_unref (icon);
return info;
}
NautilusIconInfo *
nautilus_icon_info_lookup_from_path (const char *path,
int size,
int scale)
{
GFile *icon_file;
GIcon *icon;
NautilusIconInfo *info;
icon_file = g_file_new_for_path (path);
icon = g_file_icon_new (icon_file);
info = nautilus_icon_info_lookup (icon, size, scale);
g_object_unref (icon);
g_object_unref (icon_file);
return info;
}
GdkPixbuf *
nautilus_icon_info_get_pixbuf_nodefault (NautilusIconInfo *icon)
{
GdkPixbuf *res;
if (icon->pixbuf == NULL) {
res = NULL;
} else {
res = g_object_ref (icon->pixbuf);
if (icon->sole_owner) {
icon->sole_owner = FALSE;
g_object_add_toggle_ref (G_OBJECT (res),
pixbuf_toggle_notify,
icon);
}
}
return res;
}
GdkPixbuf *
nautilus_icon_info_get_pixbuf (NautilusIconInfo *icon)
{
GdkPixbuf *res;
res = nautilus_icon_info_get_pixbuf_nodefault (icon);
if (res == NULL) {
res = gdk_pixbuf_new_from_data (nautilus_default_file_icon,
GDK_COLORSPACE_RGB,
TRUE,
8,
nautilus_default_file_icon_width,
nautilus_default_file_icon_height,
nautilus_default_file_icon_width * 4, /* stride */
NULL, /* don't destroy info */
NULL);
}
return res;
}
GdkPixbuf *
nautilus_icon_info_get_pixbuf_nodefault_at_size (NautilusIconInfo *icon,
gsize forced_size)
{
GdkPixbuf *pixbuf, *scaled_pixbuf;
int w, h, s;
double scale;
pixbuf = nautilus_icon_info_get_pixbuf_nodefault (icon);
if (pixbuf == NULL)
return NULL;
w = gdk_pixbuf_get_width (pixbuf) / icon->orig_scale;
h = gdk_pixbuf_get_height (pixbuf) / icon->orig_scale;
s = MAX (w, h);
if (s == forced_size) {
return pixbuf;
}
scale = (double)forced_size / s;
scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
w * scale, h * scale,
GDK_INTERP_BILINEAR);
g_object_unref (pixbuf);
return scaled_pixbuf;
}
GdkPixbuf *
nautilus_icon_info_get_pixbuf_at_size (NautilusIconInfo *icon,
gsize forced_size)
{
GdkPixbuf *pixbuf, *scaled_pixbuf;
int w, h, s;
double scale;
pixbuf = nautilus_icon_info_get_pixbuf (icon);
w = gdk_pixbuf_get_width (pixbuf) / icon->orig_scale;
h = gdk_pixbuf_get_height (pixbuf) / icon->orig_scale;
s = MAX (w, h);
if (s == forced_size) {
return pixbuf;
}
scale = (double)forced_size / s;
scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
w * scale, h * scale,
GDK_INTERP_BILINEAR);
g_object_unref (pixbuf);
return scaled_pixbuf;
}
const char *
nautilus_icon_info_get_used_name (NautilusIconInfo *icon)
{
return icon->icon_name;
}
gint
nautilus_get_icon_size_for_stock_size (GtkIconSize size)
{
gint w, h;
if (gtk_icon_size_lookup (size, &w, &h)) {
return MAX (w, h);
}
return NAUTILUS_CANVAS_ICON_SIZE_SMALL;
}