# HG changeset patch # User Daniel Atallah # Date 1196745349 0 # Node ID abd0cd2b712a736dba3cf96f15c7dfd9ad6e230d # Parent 5b0d9e08992d558a6e9fd53445e8850ded47c7b1 Add rudimentary caching for buddy list emblems. This avoids all the icons being duplicated in memory and constantly loaded. A more complete solution would be preferable, but I think this is better than nothing. diff -r 5b0d9e08992d -r abd0cd2b712a pidgin/gtkblist.c --- a/pidgin/gtkblist.c Tue Dec 04 05:03:49 2007 +0000 +++ b/pidgin/gtkblist.c Tue Dec 04 05:15:49 2007 +0000 @@ -3371,6 +3371,34 @@ return g_string_free(str, FALSE); } +static GHashTable *cached_emblems; + +static void _cleanup_cached_emblem(gpointer data, GObject *obj) { + g_hash_table_remove(cached_emblems, data); +} + +static GdkPixbuf * _pidgin_blist_get_cached_emblem(gchar *path) { + GdkPixbuf *pb = g_hash_table_lookup(cached_emblems, path); + + if (pb != NULL) { + /* The caller gets a reference */ + g_object_ref(pb); + g_free(path); + } else { + pb = gdk_pixbuf_new_from_file(path, NULL); + if (pb != NULL) { + /* We don't want to own a ref to the pixbuf, but we need to keep clean up. */ + /* I'm not sure if it would be better to just keep our ref and not let the emblem ever be destroyed */ + g_object_weak_ref(G_OBJECT(pb), _cleanup_cached_emblem, path); + g_hash_table_insert(cached_emblems, path, pb); + } else + g_free(path); + } + + return pb; +} + + GdkPixbuf * pidgin_blist_get_emblem(PurpleBlistNode *node) { @@ -3381,7 +3409,6 @@ PurplePluginProtocolInfo *prpl_info; const char *name = NULL; char *filename, *path; - GdkPixbuf *ret; PurplePresence *p; if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { @@ -3394,11 +3421,9 @@ gtkbuddynode = node->ui_data; p = purple_buddy_get_presence(buddy); if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) { - path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", + path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "mobile.png", NULL); - ret = gdk_pixbuf_new_from_file(path, NULL); - g_free(path); - return ret; + return _pidgin_blist_get_cached_emblem(path); } if (((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded) { @@ -3410,26 +3435,22 @@ return NULL; } + g_return_val_if_fail(buddy != NULL, NULL); + if (!purple_privacy_check(buddy->account, purple_buddy_get_name(buddy))) { path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "blocked.png", NULL); - ret = gdk_pixbuf_new_from_file(path, NULL); - g_free(path); - return ret; + return _pidgin_blist_get_cached_emblem(path); } p = purple_buddy_get_presence(buddy); if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) { path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "mobile.png", NULL); - ret = gdk_pixbuf_new_from_file(path, NULL); - g_free(path); - return ret; + return _pidgin_blist_get_cached_emblem(path); } if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_TUNE)) { path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "music.png", NULL); - ret = gdk_pixbuf_new_from_file(path, NULL); - g_free(path); - return ret; + return _pidgin_blist_get_cached_emblem(path); } prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); @@ -3446,12 +3467,10 @@ filename = g_strdup_printf("%s.png", name); path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", filename, NULL); - ret = gdk_pixbuf_new_from_file(path, NULL); - g_free(filename); - g_free(path); - - return ret; + + /* _pidgin_blist_get_cached_emblem() assumes ownership of path */ + return _pidgin_blist_get_cached_emblem(path); } @@ -6897,6 +6916,8 @@ { void *gtk_blist_handle = pidgin_blist_get_handle(); + cached_emblems = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + purple_signal_connect(purple_connections_get_handle(), "signed-on", gtk_blist_handle, PURPLE_CALLBACK(account_signon_cb), NULL); @@ -6948,6 +6969,8 @@ void pidgin_blist_uninit(void) { + g_hash_table_destroy(cached_emblems); + purple_signals_unregister_by_instance(pidgin_blist_get_handle()); purple_signals_disconnect_by_handle(pidgin_blist_get_handle()); }