From: <aar...@us...> - 2006-07-23 21:25:19
|
Revision: 16553 Author: aaronsheldon Date: 2006-07-23 14:25:09 -0700 (Sun, 23 Jul 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16553&view=rev Log Message: ----------- Caching lookup keys until something changes. Still has some bugs though. Modified Paths: -------------- branches/soc-2006-blist-efficiency/src/gtkblist.c branches/soc-2006-blist-efficiency/src/gtkblist.h Modified: branches/soc-2006-blist-efficiency/src/gtkblist.c =================================================================== --- branches/soc-2006-blist-efficiency/src/gtkblist.c 2006-07-23 20:38:07 UTC (rev 16552) +++ branches/soc-2006-blist-efficiency/src/gtkblist.c 2006-07-23 21:25:09 UTC (rev 16553) @@ -120,7 +120,8 @@ static GaimGtkBuddyList *gtkblist = NULL; static gboolean gaim_gtk_blist_refresh_timer(GaimBuddyList *list); -static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node); +static void gaim_gtk_blist_update_buddy_status_icon_key(GaimBlistNode *node, GaimStatusIconSize size); +static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node, gboolean statusChange); static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data); static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node); static void gaim_gtk_blist_update_contact(GaimBuddyList *list, GaimBlistNode *node); @@ -137,6 +138,7 @@ gboolean contact_expanded; gboolean recent_signonoff; gint recent_signonoff_timer; + GString *status_icon_key; }; @@ -2706,6 +2708,98 @@ return; } +static void +gaim_gtk_blist_update_buddy_status_icon_key(GaimBlistNode *node, GaimStatusIconSize size) +{ + int i; + GaimAccount *account; + GaimPlugin *prpl; + GaimPluginProtocolInfo *prpl_info; + GString *key = g_string_sized_new(16); + GaimBuddy *buddy; + const char *protoname = NULL; + struct _gaim_gtk_blist_node *gtknode = node->ui_data; + struct _gaim_gtk_blist_node *gtkbuddynode = NULL; + struct _emblem_data emblems[4] = {{NULL, 15, 15}, {NULL, 0, 15}, + {NULL, 0, 0}, {NULL, 15, 0}}; + + buddy = (GaimBuddy*)node; + gtkbuddynode = node->ui_data; + + if (gtkbuddynode && gtkbuddynode->recent_signonoff) { + if (GAIM_BUDDY_IS_ONLINE(buddy)) + g_string_printf(key, "%s/login", protoname); + else + g_string_printf(key, "%s/logout", protoname); + } else { + GaimConversation *conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, + gaim_buddy_get_name(buddy), + gaim_buddy_get_account(buddy)); + if(conv != NULL) { + GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); + if(gtkconv != NULL && gaim_gtkconv_is_hidden(gtkconv)) { + /* add pending emblem */ + if(size == GAIM_STATUS_ICON_SMALL) { + emblems[0].filename="pending"; + } + else { + emblems[3].filename=emblems[2].filename; + emblems[2].filename="pending"; + } + } + } + + account = buddy->account; + prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); + + if(!prpl) + return; + + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); + + if(prpl_info && prpl_info->list_icon) { + protoname = prpl_info->list_icon(account, buddy); + } + if(prpl_info && prpl_info->list_emblems && buddy) { + if(gtknode && !gtknode->recent_signonoff) + prpl_info->list_emblems(buddy, &emblems[0].filename, + &emblems[1].filename, &emblems[2].filename, + &emblems[3].filename); + } + + if(size == GAIM_STATUS_ICON_SMALL) { + /* So that only the se icon will composite */ + emblems[1].filename = emblems[2].filename = emblems[3].filename = NULL; + } + + g_string_assign(key, protoname); + + for(i=0; i<4; i++) { + if(emblems[i].filename) { + g_string_append_printf(key, "/%s", emblems[i].filename); + } + } + } + + if (!GAIM_BUDDY_IS_ONLINE(buddy)) { + key = g_string_append(key, "/off"); + } else if (gaim_presence_is_idle(gaim_buddy_get_presence(buddy))) { + key = g_string_append(key, "/idle"); + } + if (!gaim_privacy_check(buddy->account, gaim_buddy_get_name(buddy))) { + key = g_string_append(key, "/priv"); + } + + if (gtkbuddynode) { + if (gtkbuddynode->status_icon_key) + g_string_free(gtkbuddynode->status_icon_key, TRUE); + gtkbuddynode->status_icon_key = g_string_new(key->str); + } + + g_string_free(key, TRUE); + return; +} + GdkPixbuf * gaim_gtk_blist_get_status_icon(GaimBlistNode *node, GaimStatusIconSize size) { @@ -2722,12 +2816,6 @@ GaimBuddy *buddy = NULL; GaimChat *chat = NULL; - if (!status_icon_hash_table) - status_icon_hash_table = g_hash_table_new_full((GHashFunc)g_string_hash, - (GEqualFunc)g_string_equal, - (GDestroyNotify)g_string_destroy, - (GDestroyNotify)gdk_pixbuf_unref); - if(GAIM_BLIST_NODE_IS_CONTACT(node)) { if(!gtknode->contact_expanded) { buddy = gaim_contact_get_priority_buddy((GaimContact*)node); @@ -2742,6 +2830,28 @@ return NULL; } + if (!status_icon_hash_table) { + status_icon_hash_table = g_hash_table_new_full((GHashFunc)g_string_hash, + (GEqualFunc)g_string_equal, + (GDestroyNotify)g_string_destroy, + (GDestroyNotify)gdk_pixbuf_unref); + + } else if (buddy && gtkbuddynode->status_icon_key && gtkbuddynode->status_icon_key->str) { + key = g_string_new(gtkbuddynode->status_icon_key->str); + + /* Respect the size request given */ + if (size == GAIM_STATUS_ICON_SMALL) { + key = g_string_append(key, "/tiny"); + } + + scale = g_hash_table_lookup(status_icon_hash_table, key); + if (scale) { + gdk_pixbuf_ref(scale); + g_string_free(key, TRUE); + return scale; + } + } + if(buddy || chat) { GaimAccount *account; GaimPlugin *prpl; @@ -2769,75 +2879,43 @@ } } - if(buddy) { - GaimConversation *conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, - gaim_buddy_get_name(buddy), - gaim_buddy_get_account(buddy)); - if(conv != NULL) { - GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); - if(gtkconv != NULL && gaim_gtkconv_is_hidden(gtkconv)) { - /* add pending emblem */ - if(size == GAIM_STATUS_ICON_SMALL) { - emblems[0].filename="pending"; - } - else { - emblems[3].filename=emblems[2].filename; - emblems[2].filename="pending"; - } - } - } - } - - if(size == GAIM_STATUS_ICON_SMALL) { - scalesize = 15; - /* So that only the se icon will composite */ - emblems[1].filename = emblems[2].filename = emblems[3].filename = NULL; - } - /* Begin Generating Lookup Key */ if (buddy) { + gaim_gtk_blist_update_buddy_status_icon_key(node, size); + g_string_printf(key, "%s", strdup(gtkbuddynode->status_icon_key->str)); + } + /* There are only two options for chat or gaimdude - big or small */ + else if (chat) { + GaimAccount *account; + GaimPlugin *prpl; + GaimPluginProtocolInfo *prpl_info; - if (GAIM_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) - g_string_append_printf(key, "%s/login", protoname); - else if (!GAIM_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) - g_string_append_printf(key, "%s/logout", protoname); - else - key = g_string_append(key, protoname); + account = chat->account; - presence = gaim_buddy_get_presence(buddy); - if (!GAIM_BUDDY_IS_ONLINE(buddy)) { - key = g_string_append(key, "/off"); - } else if (gaim_presence_is_idle(presence)) { - key = g_string_append(key, "/idle"); - } + prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); + if(!prpl) + return NULL; - if (!gaim_privacy_check(buddy->account, gaim_buddy_get_name(buddy))) { - key = g_string_append(key, "/priv"); - } + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); - if (size == GAIM_STATUS_ICON_SMALL) { - key = g_string_append(key, "/tiny"); + if(prpl_info && prpl_info->list_icon) { + protoname = prpl_info->list_icon(account, NULL); } - - for(i=0; i<4; i++) { - if(emblems[i].filename) { - g_string_append_printf(key, "/%s", emblems[i].filename); - } - } + g_string_append_printf(key, "%s-chat", protoname); } - /* There are only two options for chat or gaimdude - big or small */ - else if (chat && size == GAIM_STATUS_ICON_SMALL) - g_string_append_printf(key, "%s-chat-s", protoname); - else if (chat) - g_string_append_printf(key, "%s-chat", protoname); - else if (size == GAIM_STATUS_ICON_SMALL) - key = g_string_append(key, "gaimdude-s"); else key = g_string_append(key, "gaimdude"); + /* If the icon is small, we do not store this into the status_icon_key + * in the gtkbuddynode. This way we can respect the size value on cache + * lookup. Otherwise, different sized icons could not be stored easily. + */ + if (size == GAIM_STATUS_ICON_SMALL) { + key = g_string_append(key, "/tiny"); + } + /* End Generating Lookup Key */ - /* If we already know this icon, just return it */ scale = g_hash_table_lookup(status_icon_hash_table, key); if (scale) { @@ -2848,6 +2926,54 @@ /* Create a new composite icon */ + if(buddy) { + GaimAccount *account; + GaimPlugin *prpl; + GaimPluginProtocolInfo *prpl_info; + GaimConversation *conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, + gaim_buddy_get_name(buddy), + gaim_buddy_get_account(buddy)); + + if(conv != NULL) { + GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); + if(gtkconv != NULL && gaim_gtkconv_is_hidden(gtkconv)) { + /* add pending emblem */ + if(size == GAIM_STATUS_ICON_SMALL) { + emblems[0].filename="pending"; + } + else { + emblems[3].filename=emblems[2].filename; + emblems[2].filename="pending"; + } + } + } + account = buddy->account; + + prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); + if(!prpl) + return NULL; + + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); + + if(prpl_info && prpl_info->list_icon) { + protoname = prpl_info->list_icon(account, buddy); + } + if(prpl_info && prpl_info->list_emblems) { + if(gtknode && !gtknode->recent_signonoff) + prpl_info->list_emblems(buddy, &emblems[0].filename, + &emblems[1].filename, &emblems[2].filename, + &emblems[3].filename); + } + } + + if(size == GAIM_STATUS_ICON_SMALL) { + scalesize = 15; + /* So that only the se icon will composite */ + emblems[1].filename = emblems[2].filename = emblems[3].filename = NULL; + } + + + if(buddy && GAIM_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) { filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "login.png", NULL); } else if(buddy && !GAIM_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) { @@ -2903,7 +3029,7 @@ } if(buddy) { - + presence = gaim_buddy_get_presence(buddy); if (!GAIM_BUDDY_IS_ONLINE(buddy)) gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); else if (gaim_presence_is_idle(presence)) @@ -3309,7 +3435,7 @@ if(conv->account != NULL && conv->name != NULL) { GaimBuddy *buddy = gaim_find_buddy(conv->account, conv->name); if(buddy != NULL) - gaim_gtk_blist_update_buddy(NULL, (GaimBlistNode *)buddy); + gaim_gtk_blist_update_buddy(NULL, (GaimBlistNode *)buddy, TRUE); } if (gtkblist->menutrayicon) { @@ -3997,12 +4123,11 @@ /* This is only needed when we're reverting to a non-GTK+ sorted * status. We shouldn't need to remove otherwise. */ - if (remove && !GAIM_BLIST_NODE_IS_GROUP(node)) gaim_gtk_blist_hide_node(list, node, FALSE); if (GAIM_BLIST_NODE_IS_BUDDY(node)) - gaim_gtk_blist_update_buddy(list, node); + gaim_gtk_blist_update_buddy(list, node, FALSE); else if (GAIM_BLIST_NODE_IS_CHAT(node)) gaim_gtk_blist_update(list, node); node = gaim_blist_node_next(node, FALSE); @@ -4363,7 +4488,7 @@ -static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node) +static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node, gboolean statusChange) { GaimBuddy *buddy; struct _gaim_gtk_blist_node *gtkparentnode; @@ -4374,7 +4499,10 @@ return; buddy = (GaimBuddy*)node; - + if (statusChange) + gaim_gtk_blist_update_buddy_status_icon_key(node, (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons") + ? GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL)); + /* First things first, update the contact */ gaim_gtk_blist_update_contact(list, node); @@ -4450,7 +4578,7 @@ gaim_gtk_blist_update_contact(list, node); break; case GAIM_BLIST_BUDDY_NODE: - gaim_gtk_blist_update_buddy(list, node); + gaim_gtk_blist_update_buddy(list, node, TRUE); break; case GAIM_BLIST_CHAT_NODE: gaim_gtk_blist_update_chat(list, node); Modified: branches/soc-2006-blist-efficiency/src/gtkblist.h =================================================================== --- branches/soc-2006-blist-efficiency/src/gtkblist.h 2006-07-23 20:38:07 UTC (rev 16552) +++ branches/soc-2006-blist-efficiency/src/gtkblist.h 2006-07-23 21:25:09 UTC (rev 16553) @@ -143,7 +143,7 @@ * Populates a menu with the items shown on the buddy list for a buddy. * * @param menu The menu to populate - * @param buddy The buddy who's menu to get + * @param buddy The buddy whose menu to get * @param sub TRUE if this is a sub-menu, FALSE otherwise */ void gaim_gtk_blist_make_buddy_menu(GtkWidget *menu, GaimBuddy *buddy, gboolean sub); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |