comparison src/gtkblist.c @ 13889:085b15c33ca4

[gaim-migrate @ 16370] Merging r16220 through 16367 from blist-efficiency branch into trunk. committer: Tailor Script <tailor@pidgin.im>
author Aaron Sheldon <aaronsheldon>
date Wed, 28 Jun 2006 19:42:20 +0000
parents b869ab32cccc
children 73cd68ae7c43
comparison
equal deleted inserted replaced
13888:9d66969a2e32 13889:085b15c33ca4
116 static void sort_method_status(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); 116 static void sort_method_status(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
117 static void sort_method_log(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); 117 static void sort_method_log(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
118 #endif 118 #endif
119 static GaimGtkBuddyList *gtkblist = NULL; 119 static GaimGtkBuddyList *gtkblist = NULL;
120 120
121 static gboolean gaim_gtk_blist_refresh_timer(GaimBuddyList *list);
121 static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node); 122 static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node);
122 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data); 123 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data);
123 static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node); 124 static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node);
125 static void gaim_gtk_blist_update_contact(GaimBuddyList *list, GaimBlistNode *node);
124 static char *gaim_get_tooltip_text(GaimBlistNode *node, gboolean full); 126 static char *gaim_get_tooltip_text(GaimBlistNode *node, gboolean full);
125 static const char *item_factory_translate_func (const char *path, gpointer func_data); 127 static const char *item_factory_translate_func (const char *path, gpointer func_data);
126 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter); 128 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter);
127 static void redo_buddy_list(GaimBuddyList *list, gboolean remove); 129 static void redo_buddy_list(GaimBuddyList *list, gboolean remove);
128 static void gaim_gtk_blist_collapse_contact_cb(GtkWidget *w, GaimBlistNode *node); 130 static void gaim_gtk_blist_collapse_contact_cb(GtkWidget *w, GaimBlistNode *node);
157 ***************************************************/ 159 ***************************************************/
158 static gboolean gtk_blist_visibility_cb(GtkWidget *w, GdkEventVisibility *event, gpointer data) 160 static gboolean gtk_blist_visibility_cb(GtkWidget *w, GdkEventVisibility *event, gpointer data)
159 { 161 {
160 if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) 162 if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
161 gtk_blist_obscured = TRUE; 163 gtk_blist_obscured = TRUE;
162 else 164 else if (gtk_blist_obscured) {
163 gtk_blist_obscured = FALSE; 165 gtk_blist_obscured = FALSE;
166 gaim_gtk_blist_refresh_timer(gaim_get_blist());
167 }
164 168
165 /* continue to handle event normally */ 169 /* continue to handle event normally */
166 return FALSE; 170 return FALSE;
167 } 171 }
168 172
169 static gboolean gtk_blist_window_state_cb(GtkWidget *w, GdkEventWindowState *event, gpointer data) 173 static gboolean gtk_blist_window_state_cb(GtkWidget *w, GdkEventWindowState *event, gpointer data)
170 { 174 {
171 if(event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) { 175 if(event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) {
172 if(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) 176 if(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN)
173 gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", FALSE); 177 gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", FALSE);
174 else 178 else {
175 gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", TRUE); 179 gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", TRUE);
180 gaim_gtk_blist_refresh_timer(gaim_get_blist());
181 }
176 } 182 }
177 183
178 if(event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) { 184 if(event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
179 if(event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) 185 if(event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
180 gaim_prefs_set_bool("/gaim/gtk/blist/list_maximized", TRUE); 186 gaim_prefs_set_bool("/gaim/gtk/blist/list_maximized", TRUE);
181 else 187 else
182 gaim_prefs_set_bool("/gaim/gtk/blist/list_maximized", FALSE); 188 gaim_prefs_set_bool("/gaim/gtk/blist/list_maximized", FALSE);
183 } 189 }
184 190
191 /* Refresh gtkblist if un-iconifying */
192 if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED){
193 if (!(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED))
194 gaim_gtk_blist_refresh_timer(gaim_get_blist());
195 }
196
185 return FALSE; 197 return FALSE;
186 } 198 }
187 199
188 static gboolean gtk_blist_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data) 200 static gboolean gtk_blist_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data)
189 { 201 {
875 /* Let the treeview draw so it knows where to scroll */ 887 /* Let the treeview draw so it knows where to scroll */
876 while (gtk_events_pending()) 888 while (gtk_events_pending())
877 gtk_main_iteration(); 889 gtk_main_iteration();
878 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(gtkblist->treeview), path, NULL, FALSE, 0, 0); 890 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(gtkblist->treeview), path, NULL, FALSE, 0, 0);
879 891
880 892 gaim_gtk_blist_update_contact(NULL, node->child);
881 gaim_gtk_blist_update(NULL, node);
882 gtk_tree_path_free(path); 893 gtk_tree_path_free(path);
883 } 894 }
884 895
885 static void 896 static void
886 gaim_gtk_blist_collapse_contact_cb(GtkWidget *w, GaimBlistNode *node) 897 gaim_gtk_blist_collapse_contact_cb(GtkWidget *w, GaimBlistNode *node)
2867 GaimContact *contact; 2878 GaimContact *contact;
2868 GaimPresence *presence; 2879 GaimPresence *presence;
2869 struct _gaim_gtk_blist_node *gtkcontactnode = NULL; 2880 struct _gaim_gtk_blist_node *gtkcontactnode = NULL;
2870 char *idletime = NULL, *statustext = NULL; 2881 char *idletime = NULL, *statustext = NULL;
2871 time_t t; 2882 time_t t;
2872 /* XXX Clean up this crap */ 2883 /* XXX Good luck cleaning up this crap */
2873 2884
2874 contact = (GaimContact*)((GaimBlistNode*)b)->parent; 2885 contact = (GaimContact*)((GaimBlistNode*)b)->parent;
2875 if(contact) 2886 if(contact)
2876 gtkcontactnode = ((GaimBlistNode*)contact)->ui_data; 2887 gtkcontactnode = ((GaimBlistNode*)contact)->ui_data;
2877 2888
2878 if(gtkcontactnode && !gtkcontactnode->contact_expanded && contact->alias) 2889 if(gtkcontactnode && !gtkcontactnode->contact_expanded && contact->alias)
2879 name = contact->alias; 2890 name = contact->alias;
2880 else 2891 else
2881 name = gaim_buddy_get_alias(b); 2892 name = gaim_buddy_get_alias(b);
2882 esc = g_markup_escape_text(name, strlen(name)); 2893 esc = g_markup_escape_text(name, strlen(name));
2883
2884 prpl = gaim_find_prpl(gaim_account_get_protocol_id(b->account));
2885
2886 if (prpl != NULL)
2887 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
2888 2894
2889 presence = gaim_buddy_get_presence(b); 2895 presence = gaim_buddy_get_presence(b);
2890 2896
2891 if (!gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) 2897 if (!gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons"))
2892 { 2898 {
2898 return text; 2904 return text;
2899 } 2905 }
2900 else 2906 else
2901 return esc; 2907 return esc;
2902 } 2908 }
2909
2910 prpl = gaim_find_prpl(gaim_account_get_protocol_id(b->account));
2911
2912 if (prpl != NULL)
2913 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
2903 2914
2904 if (prpl_info && prpl_info->status_text && b->account->gc) { 2915 if (prpl_info && prpl_info->status_text && b->account->gc) {
2905 char *tmp = prpl_info->status_text(b); 2916 char *tmp = prpl_info->status_text(b);
2906 const char *end; 2917 const char *end;
2907 2918
2949 } 2960 }
2950 statustext = tmp; 2961 statustext = tmp;
2951 #endif 2962 #endif
2952 } 2963 }
2953 2964
2954 if (gaim_prefs_get_bool("/gaim/gtk/blist/show_idle_time") &&
2955 gaim_presence_is_idle(presence))
2956 {
2957 time_t idle_secs = gaim_presence_get_idle_time(presence);
2958
2959 if (idle_secs > 0) {
2960 int ihrs, imin;
2961
2962 time(&t);
2963 ihrs = (t - idle_secs) / 3600;
2964 imin = ((t - idle_secs) / 60) % 60;
2965
2966 if (ihrs)
2967 idletime = g_strdup_printf(_("Idle %dh %02dm"), ihrs, imin);
2968 else
2969 idletime = g_strdup_printf(_("Idle %dm"), imin);
2970 }
2971 else
2972 idletime = g_strdup(_("Idle"));
2973 }
2974
2975 if(!gaim_presence_is_online(presence) && !statustext) 2965 if(!gaim_presence_is_online(presence) && !statustext)
2976 statustext = g_strdup(_("Offline")); 2966 statustext = g_strdup(_("Offline"));
2977 2967 else if (!statustext)
2978 if (statustext == NULL && idletime == NULL) 2968 text = g_strdup(esc);
2969
2970 if (gaim_presence_is_idle(presence)) {
2971 if (gaim_prefs_get_bool("/gaim/gtk/blist/show_idle_time")) {
2972 time_t idle_secs = gaim_presence_get_idle_time(presence);
2973
2974 if (idle_secs > 0) {
2975 int ihrs, imin;
2976
2977 time(&t);
2978 ihrs = (t - idle_secs) / 3600;
2979 imin = ((t - idle_secs) / 60) % 60;
2980
2981 if (ihrs)
2982 idletime = g_strdup_printf(_("Idle %dh %02dm"), ihrs, imin);
2983 else
2984 idletime = g_strdup_printf(_("Idle %dm"), imin);
2985 }
2986 else
2987 idletime = g_strdup(_("Idle"));
2988
2989 if (!selected)
2990 text = g_strdup_printf("<span color='%s'>%s</span>\n"
2991 "<span color='%s' size='smaller'>%s%s%s</span>",
2992 dim_grey(), esc, dim_grey(),
2993 idletime != NULL ? idletime : "",
2994 (idletime != NULL && statustext != NULL) ? " - " : "",
2995 statustext != NULL ? statustext : "");
2996 }
2997 else if (!selected && !statustext) /* We handle selected text later */
2998 text = g_strdup_printf("<span color='%s'>%s</span>", dim_grey(), esc);
2999 else if (!selected && !text)
3000 text = g_strdup_printf("<span color='%s'>%s</span>\n"
3001 "<span color='%s' size='smaller'>%s%s%s</span>",
3002 dim_grey(), esc, dim_grey(),
3003 idletime != NULL ? idletime : "",
3004 (idletime != NULL && statustext != NULL) ? " - " : "",
3005 statustext != NULL ? statustext : "");
3006 }
3007
3008 /* Not idle and not selected */
3009 else if (!selected && !text)
2979 { 3010 {
2980 if (!selected && gaim_presence_is_idle(presence))
2981 text = g_strdup_printf("<span color='%s'>%s</span>", dim_grey(), esc);
2982 else
2983 text = g_strdup(esc);
2984 }
2985 else if (!selected)
2986 {
2987 if (gaim_presence_is_idle(presence))
2988 {
2989 text = g_strdup_printf("<span color='%s'>%s</span>\n"
2990 "<span color='%s' size='smaller'>%s%s%s</span>",
2991 dim_grey(), esc, dim_grey(),
2992 idletime != NULL ? idletime : "",
2993 (idletime != NULL && statustext != NULL) ? " - " : "",
2994 statustext != NULL ? statustext : "");
2995 }
2996 else
2997 {
2998 text = g_strdup_printf("%s\n"
2999 "<span color='%s' size='smaller'>%s%s%s</span>",
3000 esc, dim_grey(),
3001 idletime != NULL ? idletime : "",
3002 (idletime != NULL && statustext != NULL) ? " - " : "",
3003 statustext != NULL ? statustext : "");
3004 }
3005 }
3006 else
3007 text = g_strdup_printf("%s\n" 3011 text = g_strdup_printf("%s\n"
3008 "<span size='smaller'>%s%s%s</span>", 3012 "<span color='%s' size='smaller'>%s%s%s</span>",
3009 esc, 3013 esc, dim_grey(),
3010 idletime != NULL ? idletime : "", 3014 idletime != NULL ? idletime : "",
3011 (idletime != NULL && statustext != NULL) ? " - " : "", 3015 (idletime != NULL && statustext != NULL) ? " - " : "",
3012 statustext != NULL ? statustext : ""); 3016 statustext != NULL ? statustext : "");
3013 3017 }
3018
3019 /* It is selected. */
3020 if ((selected && !text) || (selected && idletime))
3021 text = g_strdup_printf("%s\n"
3022 "<span size='smaller'>%s%s%s</span>",
3023 esc,
3024 idletime != NULL ? idletime : "",
3025 (idletime != NULL && statustext != NULL) ? " - " : "",
3026 statustext != NULL ? statustext : "");
3014 3027
3015 g_free(idletime); 3028 g_free(idletime);
3016 g_free(statustext); 3029 g_free(statustext);
3017 g_free(esc); 3030 g_free(esc);
3018 3031
3055 3068
3056 static gboolean gaim_gtk_blist_refresh_timer(GaimBuddyList *list) 3069 static gboolean gaim_gtk_blist_refresh_timer(GaimBuddyList *list)
3057 { 3070 {
3058 GaimBlistNode *gnode, *cnode; 3071 GaimBlistNode *gnode, *cnode;
3059 3072
3073 if (gtk_blist_obscured || !GTK_WIDGET_VISIBLE(gtkblist->window))
3074 return TRUE;
3075
3060 for(gnode = list->root; gnode; gnode = gnode->next) { 3076 for(gnode = list->root; gnode; gnode = gnode->next) {
3061 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) 3077 if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
3062 continue; 3078 continue;
3063 for(cnode = gnode->child; cnode; cnode = cnode->next) { 3079 for(cnode = gnode->child; cnode; cnode = cnode->next) {
3064 if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) { 3080 if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
3066 3082
3067 buddy = gaim_contact_get_priority_buddy((GaimContact*)cnode); 3083 buddy = gaim_contact_get_priority_buddy((GaimContact*)cnode);
3068 3084
3069 if (buddy && 3085 if (buddy &&
3070 gaim_presence_is_idle(gaim_buddy_get_presence(buddy))) 3086 gaim_presence_is_idle(gaim_buddy_get_presence(buddy)))
3071 gaim_gtk_blist_update(list, cnode); 3087 gaim_gtk_blist_update_contact(list, (GaimBlistNode*)buddy);
3072 } 3088 }
3073 } 3089 }
3074 } 3090 }
3075 3091
3076 /* keep on going */ 3092 /* keep on going */
3906 { 3922 {
3907 GaimBlistNode *node = list->root; 3923 GaimBlistNode *node = list->root;
3908 3924
3909 while (node) 3925 while (node)
3910 { 3926 {
3911 if (!GAIM_BLIST_NODE_IS_GROUP(node) && remove) 3927 if (remove && !GAIM_BLIST_NODE_IS_GROUP(node))
3912 gaim_gtk_blist_hide_node(list, node); 3928 gaim_gtk_blist_hide_node(list, node);
3913 3929
3914 gaim_gtk_blist_update(list, node); 3930 gaim_gtk_blist_update(list, node);
3915 node = gaim_blist_node_next(node, FALSE); 3931 node = gaim_blist_node_next(node, FALSE);
3916 } 3932 }
4079 } 4095 }
4080 4096
4081 return TRUE; 4097 return TRUE;
4082 } 4098 }
4083 4099
4100 /*This version of gaim_gtk_blist_update_group can take the original buddy
4101 or a group, but has much better algorithmic performance with a pre-known buddy*/
4084 static void gaim_gtk_blist_update_group(GaimBuddyList *list, GaimBlistNode *node) 4102 static void gaim_gtk_blist_update_group(GaimBuddyList *list, GaimBlistNode *node)
4085 { 4103 {
4086 GaimGroup *group; 4104 GaimGroup *group;
4087 int count; 4105 int count;
4088 gboolean show = FALSE; 4106 gboolean show = FALSE;
4089 4107 GaimBlistNode* gnode;
4090 g_return_if_fail(GAIM_BLIST_NODE_IS_GROUP(node)); 4108
4091 4109
4092 group = (GaimGroup*)node; 4110 if (GAIM_BLIST_NODE_IS_GROUP(node))
4111 gnode = node;
4112 else if (GAIM_BLIST_NODE_IS_BUDDY(node)) /* maybe OR'ed with IS_CHAT? */
4113 gnode = node->parent->parent;
4114 else if (GAIM_BLIST_NODE_IS_CONTACT(node))
4115 gnode = node->parent;
4116 g_return_if_fail(GAIM_BLIST_NODE_IS_GROUP(gnode));
4117
4118 group = (GaimGroup*)gnode;
4093 4119
4094 if(gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")) 4120 if(gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies"))
4095 count = gaim_blist_get_group_size(group, FALSE); 4121 count = gaim_blist_get_group_size(group, FALSE);
4096 else 4122 else
4097 count = gaim_blist_get_group_online_count(group); 4123 count = gaim_blist_get_group_online_count(group);
4098 4124
4099 if (count > 0 || gaim_prefs_get_bool("/gaim/gtk/blist/show_empty_groups")) 4125 if (count > 0 || gaim_prefs_get_bool("/gaim/gtk/blist/show_empty_groups"))
4100 show = TRUE; 4126 show = TRUE;
4101 else { 4127 else if (GAIM_BLIST_NODE_IS_BUDDY(node)){ /* Or chat? */
4102 GaimBlistNode *n; 4128 if (buddy_is_displayable((GaimBuddy*)node))
4103 n = node->child; 4129 show = TRUE;}
4104 while (n && !GAIM_BLIST_NODE_IS_GROUP(n)) {
4105 if (GAIM_BLIST_NODE_IS_BUDDY(n)) {
4106 if (buddy_is_displayable((GaimBuddy*)n)) {
4107 show = TRUE;
4108 break;
4109 }
4110 }
4111 n = gaim_blist_node_next(n, FALSE);
4112 }
4113 }
4114 4130
4115 if (show) { 4131 if (show) {
4116 char *mark, *esc; 4132 char *mark, *esc;
4117 GtkTreeIter iter; 4133 GtkTreeIter iter;
4118 4134
4119 if(!insert_node(list, node, &iter)) 4135 if(!insert_node(list, gnode, &iter))
4120 return; 4136 return;
4121 4137
4122 esc = g_markup_escape_text(group->name, -1); 4138 esc = g_markup_escape_text(group->name, -1);
4123 mark = g_strdup_printf("<span weight='bold'>%s</span> (%d/%d)", 4139 mark = g_strdup_printf("<span weight='bold'>%s</span> (%d/%d)",
4124 esc, gaim_blist_get_group_online_count(group), 4140 esc, gaim_blist_get_group_online_count(group),
4127 4143
4128 gtk_tree_store_set(gtkblist->treemodel, &iter, 4144 gtk_tree_store_set(gtkblist->treemodel, &iter,
4129 STATUS_ICON_COLUMN, NULL, 4145 STATUS_ICON_COLUMN, NULL,
4130 STATUS_ICON_VISIBLE_COLUMN, FALSE, 4146 STATUS_ICON_VISIBLE_COLUMN, FALSE,
4131 NAME_COLUMN, mark, 4147 NAME_COLUMN, mark,
4132 NODE_COLUMN, node, 4148 NODE_COLUMN, gnode,
4133 -1); 4149 -1);
4134 g_free(mark); 4150 g_free(mark);
4135 } else { 4151 } else {
4136 gaim_gtk_blist_hide_node(list, node); 4152 gaim_gtk_blist_hide_node(list, gnode);
4137 } 4153 }
4138 } 4154 }
4139 4155
4140 static void buddy_node(GaimBuddy *buddy, GtkTreeIter *iter, GaimBlistNode *node) 4156 static void buddy_node(GaimBuddy *buddy, GtkTreeIter *iter, GaimBlistNode *node)
4141 { 4157 {
4153 4169
4154 avatar = gaim_gtk_blist_get_buddy_icon((GaimBlistNode *)buddy, TRUE, TRUE); 4170 avatar = gaim_gtk_blist_get_buddy_icon((GaimBlistNode *)buddy, TRUE, TRUE);
4155 mark = gaim_gtk_blist_get_name_markup(buddy, selected); 4171 mark = gaim_gtk_blist_get_name_markup(buddy, selected);
4156 4172
4157 if (gaim_prefs_get_bool("/gaim/gtk/blist/show_idle_time") && 4173 if (gaim_prefs_get_bool("/gaim/gtk/blist/show_idle_time") &&
4158 gaim_presence_is_idle(presence)) 4174 gaim_presence_is_idle(presence) &&
4175 !gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons"))
4159 { 4176 {
4160 time_t idle_secs = gaim_presence_get_idle_time(presence); 4177 time_t idle_secs = gaim_presence_get_idle_time(presence);
4161 4178
4162 if (idle_secs > 0) 4179 if (idle_secs > 0)
4163 { 4180 {
4164 time_t t; 4181 time_t t;
4165 int ihrs, imin; 4182 int ihrs, imin;
4166 time(&t); 4183 time(&t);
4167 ihrs = (t - idle_secs) / 3600; 4184 ihrs = (t - idle_secs) / 3600;
4168 imin = ((t - idle_secs) / 60) % 60; 4185 imin = ((t - idle_secs) / 60) % 60;
4169
4170 idle = g_strdup_printf("%d:%02d", ihrs, imin); 4186 idle = g_strdup_printf("%d:%02d", ihrs, imin);
4171 } 4187 }
4172 } 4188 }
4173 4189
4174 if (gaim_presence_is_idle(presence)) 4190 if (gaim_presence_is_idle(presence))
4195 g_object_unref(status); 4211 g_object_unref(status);
4196 if(avatar) 4212 if(avatar)
4197 g_object_unref(avatar); 4213 g_object_unref(avatar);
4198 } 4214 }
4199 4215
4200 4216 /* This is a variation on the original gtk_blist_update_contact. Here we
4217 can know in advance which buddy has changed so we can just update that */
4201 static void gaim_gtk_blist_update_contact(GaimBuddyList *list, GaimBlistNode *node) 4218 static void gaim_gtk_blist_update_contact(GaimBuddyList *list, GaimBlistNode *node)
4202 { 4219 {
4220 GaimBlistNode *cnode;
4203 GaimContact *contact; 4221 GaimContact *contact;
4204 GaimBuddy *buddy; 4222 GaimBuddy *buddy;
4205 struct _gaim_gtk_blist_node *gtknode; 4223 struct _gaim_gtk_blist_node *gtknode;
4206 4224
4207 g_return_if_fail(GAIM_BLIST_NODE_IS_CONTACT(node)); 4225 if (GAIM_BLIST_NODE_IS_BUDDY(node))
4226 cnode = node->parent;
4227 else
4228 cnode = node;
4229
4230 g_return_if_fail(GAIM_BLIST_NODE_IS_CONTACT(cnode));
4208 4231
4209 /* First things first, update the group */ 4232 /* First things first, update the group */
4210 gaim_gtk_blist_update_group(list, node->parent); 4233 if (GAIM_BLIST_NODE_IS_BUDDY(node))
4211 4234 gaim_gtk_blist_update_group(list, node);
4212 contact = (GaimContact*)node; 4235 else
4236 gaim_gtk_blist_update_group(list, cnode->parent);
4237
4238 contact = (GaimContact*)cnode;
4213 buddy = gaim_contact_get_priority_buddy(contact); 4239 buddy = gaim_contact_get_priority_buddy(contact);
4214 4240
4215 if (buddy_is_displayable(buddy)) 4241 if (buddy_is_displayable(buddy))
4216 { 4242 {
4217 GtkTreeIter iter; 4243 GtkTreeIter iter;
4218 4244
4219 if(!insert_node(list, node, &iter)) 4245 if(!insert_node(list, cnode, &iter))
4220 return; 4246 return;
4221 4247
4222 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; 4248 gtknode = (struct _gaim_gtk_blist_node *)cnode->ui_data;
4223 4249
4224 if(gtknode->contact_expanded) { 4250 if(gtknode->contact_expanded) {
4225 GdkPixbuf *status; 4251 GdkPixbuf *status;
4226 char *mark; 4252 char *mark;
4227 4253
4228 status = gaim_gtk_blist_get_status_icon(node, 4254 status = gaim_gtk_blist_get_status_icon(cnode,
4229 (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons") ? 4255 (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons") ?
4230 GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL)); 4256 GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL));
4231 4257
4232 mark = g_markup_escape_text(gaim_contact_get_alias(contact), -1); 4258 mark = g_markup_escape_text(gaim_contact_get_alias(contact), -1);
4233 4259
4240 -1); 4266 -1);
4241 g_free(mark); 4267 g_free(mark);
4242 if(status) 4268 if(status)
4243 g_object_unref(status); 4269 g_object_unref(status);
4244 } else { 4270 } else {
4245 buddy_node(buddy, &iter, node); 4271 buddy_node(buddy, &iter, cnode);
4246 } 4272 }
4247 } else { 4273 } else {
4248 gaim_gtk_blist_hide_node(list, node); 4274 gaim_gtk_blist_hide_node(list, cnode);
4249 } 4275 }
4250 } 4276 }
4277
4278
4251 4279
4252 static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node) 4280 static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node)
4253 { 4281 {
4254 GaimContact *contact;
4255 GaimBuddy *buddy; 4282 GaimBuddy *buddy;
4256 struct _gaim_gtk_blist_node *gtkparentnode; 4283 struct _gaim_gtk_blist_node *gtkparentnode;
4257 4284
4258 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); 4285 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node));
4259 4286
4287 if (node->parent == NULL)
4288 return;
4289
4260 buddy = (GaimBuddy*)node; 4290 buddy = (GaimBuddy*)node;
4261 contact = (GaimContact*)node->parent; 4291
4262
4263 if (contact == NULL)
4264 return;
4265
4266 /* First things first, update the contact */ 4292 /* First things first, update the contact */
4267 gaim_gtk_blist_update_contact(list, node->parent); 4293 gaim_gtk_blist_update_contact(list, node);
4268 4294
4269 gtkparentnode = (struct _gaim_gtk_blist_node *)node->parent->ui_data; 4295 gtkparentnode = (struct _gaim_gtk_blist_node *)node->parent->ui_data;
4270 4296
4271 if (gtkparentnode->contact_expanded && buddy_is_displayable(buddy)) 4297 if (gtkparentnode->contact_expanded && buddy_is_displayable(buddy))
4272 { 4298 {