comparison src/gtkblist.c @ 14138:7f276f375789

[gaim-migrate @ 16780] Merges r16472-16568 from blist-efficiency into trunk. committer: Tailor Script <tailor@pidgin.im>
author Aaron Sheldon <aaronsheldon>
date Wed, 16 Aug 2006 04:50:27 +0000
parents 7a763d1d1df6
children f96ff06f6dcc
comparison
equal deleted inserted replaced
14137:7a763d1d1df6 14138:7f276f375789
102 102
103 static GtkWidget *accountmenu = NULL; 103 static GtkWidget *accountmenu = NULL;
104 104
105 static guint visibility_manager_count = 0; 105 static guint visibility_manager_count = 0;
106 static gboolean gtk_blist_obscured = FALSE; 106 static gboolean gtk_blist_obscured = FALSE;
107 GHashTable* status_icon_hash_table = NULL;
107 108
108 static GList *gaim_gtk_blist_sort_methods = NULL; 109 static GList *gaim_gtk_blist_sort_methods = NULL;
109 static struct gaim_gtk_blist_sort_method *current_sort_method = NULL; 110 static struct gaim_gtk_blist_sort_method *current_sort_method = NULL;
110 static void sort_method_none(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); 111 static void sort_method_none(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
111 112
117 static void sort_method_log(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); 118 static void sort_method_log(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
118 #endif 119 #endif
119 static GaimGtkBuddyList *gtkblist = NULL; 120 static GaimGtkBuddyList *gtkblist = NULL;
120 121
121 static gboolean gaim_gtk_blist_refresh_timer(GaimBuddyList *list); 122 static gboolean gaim_gtk_blist_refresh_timer(GaimBuddyList *list);
122 static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node); 123 static void gaim_gtk_blist_update_buddy_status_icon_key(GaimBlistNode *node, GaimStatusIconSize size);
124 static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node, gboolean statusChange);
123 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data); 125 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data);
124 static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node); 126 static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node);
125 static void gaim_gtk_blist_update_contact(GaimBuddyList *list, GaimBlistNode *node); 127 static void gaim_gtk_blist_update_contact(GaimBuddyList *list, GaimBlistNode *node);
126 static char *gaim_get_tooltip_text(GaimBlistNode *node, gboolean full); 128 static char *gaim_get_tooltip_text(GaimBlistNode *node, gboolean full);
127 static const char *item_factory_translate_func (const char *path, gpointer func_data); 129 static const char *item_factory_translate_func (const char *path, gpointer func_data);
128 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter); 130 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter);
129 static void redo_buddy_list(GaimBuddyList *list, gboolean remove); 131 static void redo_buddy_list(GaimBuddyList *list, gboolean remove, gboolean rerender);
130 static void gaim_gtk_blist_collapse_contact_cb(GtkWidget *w, GaimBlistNode *node); 132 static void gaim_gtk_blist_collapse_contact_cb(GtkWidget *w, GaimBlistNode *node);
131 133
132 static void gaim_gtk_blist_tooltip_destroy(void); 134 static void gaim_gtk_blist_tooltip_destroy(void);
133 135
134 struct _gaim_gtk_blist_node { 136 struct _gaim_gtk_blist_node {
135 GtkTreeRowReference *row; 137 GtkTreeRowReference *row;
136 gboolean contact_expanded; 138 gboolean contact_expanded;
137 gboolean recent_signonoff; 139 gboolean recent_signonoff;
138 gint recent_signonoff_timer; 140 gint recent_signonoff_timer;
141 GString *status_icon_key;
139 }; 142 };
140 143
141 144
142 static char dim_grey_string[8] = ""; 145 static char dim_grey_string[8] = "";
143 static char *dim_grey() 146 static char *dim_grey()
530 sensitive = FALSE; 533 sensitive = FALSE;
531 } 534 }
532 } 535 }
533 536
534 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), GTK_RESPONSE_OK, sensitive); 537 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), GTK_RESPONSE_OK, sensitive);
538 }
539
540 static void
541 gaim_gtk_blist_update_privacy_cb(GaimBuddy *buddy)
542 {
543 gaim_gtk_blist_update_buddy(gaim_get_blist(), (GaimBlistNode*)(buddy), TRUE);
535 } 544 }
536 545
537 static void 546 static void
538 rebuild_joinchat_entries(GaimGtkJoinChatData *data) 547 rebuild_joinchat_entries(GaimGtkJoinChatData *data)
539 { 548 {
2690 const char *filename; 2699 const char *filename;
2691 int x; 2700 int x;
2692 int y; 2701 int y;
2693 }; 2702 };
2694 2703
2695 GdkPixbuf * 2704 static void g_string_destroy(GString *destroyable)
2696 gaim_gtk_blist_get_status_icon(GaimBlistNode *node, GaimStatusIconSize size) 2705 {
2697 { 2706 g_string_free(destroyable, TRUE);
2698 GdkPixbuf *scale, *status = NULL; 2707 return;
2699 int i, scalesize = 30; 2708 }
2700 char *filename; 2709
2710 static void
2711 gaim_gtk_blist_update_buddy_status_icon_key(GaimBlistNode *node, GaimStatusIconSize size)
2712 {
2713 int i;
2714 GaimAccount *account;
2715 GaimPlugin *prpl;
2716 GaimPluginProtocolInfo *prpl_info;
2717 GString *key = g_string_sized_new(16);
2718 GaimBuddy *buddy;
2701 const char *protoname = NULL; 2719 const char *protoname = NULL;
2702 struct _gaim_gtk_blist_node *gtknode = node->ui_data; 2720 struct _gaim_gtk_blist_node *gtknode = node->ui_data;
2703 struct _gaim_gtk_blist_node *gtkbuddynode = NULL; 2721 struct _gaim_gtk_blist_node *gtkbuddynode = NULL;
2704 struct _emblem_data emblems[4] = {{NULL, 15, 15}, {NULL, 0, 15}, 2722 struct _emblem_data emblems[4] = {{NULL, 15, 15}, {NULL, 0, 15},
2705 {NULL, 0, 0}, {NULL, 15, 0}}; 2723 {NULL, 0, 0}, {NULL, 15, 0}};
2706 GaimPresence *presence = NULL; 2724
2707 GaimBuddy *buddy = NULL; 2725 buddy = (GaimBuddy*)node;
2708 GaimChat *chat = NULL; 2726 gtkbuddynode = node->ui_data;
2709 2727
2710 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { 2728 if (gtkbuddynode && gtkbuddynode->recent_signonoff) {
2711 if(!gtknode->contact_expanded) { 2729 if (GAIM_BUDDY_IS_ONLINE(buddy))
2712 buddy = gaim_contact_get_priority_buddy((GaimContact*)node); 2730 g_string_printf(key, "login");
2713 gtkbuddynode = ((GaimBlistNode*)buddy)->ui_data; 2731 else
2714 } 2732 g_string_printf(key, "logout");
2715 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) {
2716 buddy = (GaimBuddy*)node;
2717 gtkbuddynode = node->ui_data;
2718 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) {
2719 chat = (GaimChat*)node;
2720 } else { 2733 } else {
2721 return NULL; 2734 GaimConversation *conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM,
2722 } 2735 gaim_buddy_get_name(buddy),
2723 2736 gaim_buddy_get_account(buddy));
2724 if(buddy || chat) { 2737
2725 GaimAccount *account; 2738 account = buddy->account;
2726 GaimPlugin *prpl;
2727 GaimPluginProtocolInfo *prpl_info;
2728
2729 if(buddy)
2730 account = buddy->account;
2731 else
2732 account = chat->account;
2733
2734 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); 2739 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account));
2740
2735 if(!prpl) 2741 if(!prpl)
2736 return NULL; 2742 return;
2737 2743
2738 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); 2744 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
2739 2745
2740 if(prpl_info && prpl_info->list_icon) { 2746 if(prpl_info && prpl_info->list_icon) {
2741 protoname = prpl_info->list_icon(account, buddy); 2747 protoname = prpl_info->list_icon(account, buddy);
2742 } 2748 }
2743 if(prpl_info && prpl_info->list_emblems && buddy) { 2749 if(prpl_info && prpl_info->list_emblems) {
2744 if(gtknode && !gtknode->recent_signonoff) 2750 if(gtknode)
2745 prpl_info->list_emblems(buddy, &emblems[0].filename, 2751 prpl_info->list_emblems(buddy, &emblems[0].filename,
2746 &emblems[1].filename, &emblems[2].filename, 2752 &emblems[1].filename, &emblems[2].filename,
2747 &emblems[3].filename); 2753 &emblems[3].filename);
2748 } 2754 }
2749 } 2755
2750 2756 g_string_assign(key, protoname);
2751 if(buddy) { 2757
2752 GaimConversation *conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM,
2753 gaim_buddy_get_name(buddy),
2754 gaim_buddy_get_account(buddy));
2755 if(conv != NULL) { 2758 if(conv != NULL) {
2756 GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); 2759 GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv);
2757 if(gtkconv != NULL && gaim_gtkconv_is_hidden(gtkconv)) { 2760 if(gtkconv != NULL && gaim_gtkconv_is_hidden(gtkconv)) {
2758 /* add pending emblem */ 2761 /* add pending emblem */
2759 if(size == GAIM_STATUS_ICON_SMALL) { 2762 if(size == GAIM_STATUS_ICON_SMALL) {
2763 emblems[3].filename=emblems[2].filename; 2766 emblems[3].filename=emblems[2].filename;
2764 emblems[2].filename="pending"; 2767 emblems[2].filename="pending";
2765 } 2768 }
2766 } 2769 }
2767 } 2770 }
2768 } 2771
2772 if(size == GAIM_STATUS_ICON_SMALL) {
2773 /* So that only the se icon will composite */
2774 emblems[1].filename = emblems[2].filename = emblems[3].filename = NULL;
2775 }
2776
2777 for(i=0; i<4; i++) {
2778 if(emblems[i].filename) {
2779 g_string_append_printf(key, "/%s", emblems[i].filename);
2780 }
2781 }
2782 }
2783
2784 if (!GAIM_BUDDY_IS_ONLINE(buddy)) {
2785 key = g_string_append(key, "/off");
2786 } else if (gaim_presence_is_idle(gaim_buddy_get_presence(buddy))) {
2787 key = g_string_append(key, "/idle");
2788 }
2789 if (!gaim_privacy_check(buddy->account, gaim_buddy_get_name(buddy))) {
2790 key = g_string_append(key, "/priv");
2791 }
2792
2793 if (gtkbuddynode) {
2794 if (gtkbuddynode->status_icon_key)
2795 g_string_free(gtkbuddynode->status_icon_key, TRUE);
2796 gtkbuddynode->status_icon_key = g_string_new(key->str);
2797 }
2798
2799 g_string_free(key, TRUE);
2800 return;
2801 }
2802
2803 GdkPixbuf *
2804 gaim_gtk_blist_get_status_icon(GaimBlistNode *node, GaimStatusIconSize size)
2805 {
2806 GdkPixbuf *scale, *status = NULL;
2807 int i, scalesize = 30;
2808 char *filename;
2809 GString *key = g_string_sized_new(16);
2810 const char *protoname = NULL;
2811 struct _gaim_gtk_blist_node *gtknode = node->ui_data;
2812 struct _gaim_gtk_blist_node *gtkbuddynode = NULL;
2813 struct _emblem_data emblems[4] = {{NULL, 15, 15}, {NULL, 0, 15},
2814 {NULL, 0, 0}, {NULL, 15, 0}};
2815 GaimPresence *presence = NULL;
2816 GaimBuddy *buddy = NULL;
2817 GaimChat *chat = NULL;
2818
2819 if(GAIM_BLIST_NODE_IS_CONTACT(node)) {
2820 if(!gtknode->contact_expanded) {
2821 buddy = gaim_contact_get_priority_buddy((GaimContact*)node);
2822 gtkbuddynode = ((GaimBlistNode*)buddy)->ui_data;
2823 }
2824 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) {
2825 buddy = (GaimBuddy*)node;
2826 gtkbuddynode = node->ui_data;
2827 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) {
2828 chat = (GaimChat*)node;
2829 } else {
2830 return NULL;
2831 }
2832
2833 if (!status_icon_hash_table) {
2834 status_icon_hash_table = g_hash_table_new_full((GHashFunc)g_string_hash,
2835 (GEqualFunc)g_string_equal,
2836 (GDestroyNotify)g_string_destroy,
2837 (GDestroyNotify)gdk_pixbuf_unref);
2838
2839 } else if (buddy && gtkbuddynode->status_icon_key && gtkbuddynode->status_icon_key->str) {
2840 key = g_string_new(gtkbuddynode->status_icon_key->str);
2841
2842 /* Respect the size request given */
2843 if (size == GAIM_STATUS_ICON_SMALL) {
2844 key = g_string_append(key, "/tiny");
2845 }
2846
2847 scale = g_hash_table_lookup(status_icon_hash_table, key);
2848 if (scale) {
2849 gdk_pixbuf_ref(scale);
2850 g_string_free(key, TRUE);
2851 return scale;
2852 }
2853 }
2854
2855 if(buddy || chat) {
2856 GaimAccount *account;
2857 GaimPlugin *prpl;
2858 GaimPluginProtocolInfo *prpl_info;
2859
2860 if(buddy)
2861 account = buddy->account;
2862 else
2863 account = chat->account;
2864
2865 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account));
2866 if(!prpl)
2867 return NULL;
2868
2869 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
2870
2871 if(prpl_info && prpl_info->list_icon) {
2872 protoname = prpl_info->list_icon(account, buddy);
2873 }
2874 if(prpl_info && prpl_info->list_emblems && buddy) {
2875 if(gtknode && !gtknode->recent_signonoff)
2876 prpl_info->list_emblems(buddy, &emblems[0].filename,
2877 &emblems[1].filename, &emblems[2].filename,
2878 &emblems[3].filename);
2879 }
2880 }
2881
2882 /* Begin Generating Lookup Key */
2883 if (buddy) {
2884 gaim_gtk_blist_update_buddy_status_icon_key(node, size);
2885 g_string_printf(key, "%s", strdup(gtkbuddynode->status_icon_key->str));
2886 }
2887 /* There are only two options for chat or gaimdude - big or small */
2888 else if (chat) {
2889 GaimAccount *account;
2890 GaimPlugin *prpl;
2891 GaimPluginProtocolInfo *prpl_info;
2892
2893 account = chat->account;
2894
2895 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account));
2896 if(!prpl)
2897 return NULL;
2898
2899 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
2900
2901 if(prpl_info && prpl_info->list_icon) {
2902 protoname = prpl_info->list_icon(account, NULL);
2903 }
2904 g_string_append_printf(key, "%s-chat", protoname);
2905 }
2906 else
2907 key = g_string_append(key, "gaimdude");
2908
2909 /* If the icon is small, we do not store this into the status_icon_key
2910 * in the gtkbuddynode. This way we can respect the size value on cache
2911 * lookup. Otherwise, different sized icons could not be stored easily.
2912 */
2913 if (size == GAIM_STATUS_ICON_SMALL) {
2914 key = g_string_append(key, "/tiny");
2915 }
2916
2917 /* End Generating Lookup Key */
2918
2919 /* If we already know this icon, just return it */
2920 scale = g_hash_table_lookup(status_icon_hash_table, key);
2921 if (scale) {
2922 gdk_pixbuf_ref(scale);
2923 g_string_free(key, TRUE);
2924 return scale;
2925 }
2926
2927 /* Create a new composite icon */
2928
2929 if(buddy) {
2930 GaimAccount *account;
2931 GaimPlugin *prpl;
2932 GaimPluginProtocolInfo *prpl_info;
2933 GaimConversation *conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM,
2934 gaim_buddy_get_name(buddy),
2935 gaim_buddy_get_account(buddy));
2936
2937 account = buddy->account;
2938
2939 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account));
2940 if(!prpl)
2941 return NULL;
2942
2943 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
2944
2945 if(prpl_info && prpl_info->list_icon) {
2946 protoname = prpl_info->list_icon(account, buddy);
2947 }
2948 if(prpl_info && prpl_info->list_emblems) {
2949 if(gtknode && !gtknode->recent_signonoff)
2950 prpl_info->list_emblems(buddy, &emblems[0].filename,
2951 &emblems[1].filename, &emblems[2].filename,
2952 &emblems[3].filename);
2953 }
2954
2955 if(conv != NULL) {
2956 GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv);
2957 if(gtkconv != NULL && gaim_gtkconv_is_hidden(gtkconv)) {
2958 /* add pending emblem */
2959 if(size == GAIM_STATUS_ICON_SMALL) {
2960 emblems[0].filename="pending";
2961 }
2962 else {
2963 emblems[3].filename=emblems[2].filename;
2964 emblems[2].filename="pending";
2965 }
2966 }
2967 }
2968 }
2769 2969
2770 if(size == GAIM_STATUS_ICON_SMALL) { 2970 if(size == GAIM_STATUS_ICON_SMALL) {
2771 scalesize = 15; 2971 scalesize = 15;
2772 /* So that only the se icon will composite */ 2972 /* So that only the se icon will composite */
2773 emblems[1].filename = emblems[2].filename = emblems[3].filename = NULL; 2973 emblems[1].filename = emblems[2].filename = emblems[3].filename = NULL;
2774 } 2974 }
2975
2976
2775 2977
2776 if(buddy && GAIM_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) { 2978 if(buddy && GAIM_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) {
2777 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "login.png", NULL); 2979 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "login.png", NULL);
2778 } else if(buddy && !GAIM_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) { 2980 } else if(buddy && !GAIM_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) {
2779 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "logout.png", NULL); 2981 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "logout.png", NULL);
2827 } 3029 }
2828 } 3030 }
2829 3031
2830 if(buddy) { 3032 if(buddy) {
2831 presence = gaim_buddy_get_presence(buddy); 3033 presence = gaim_buddy_get_presence(buddy);
2832
2833 if (!GAIM_BUDDY_IS_ONLINE(buddy)) 3034 if (!GAIM_BUDDY_IS_ONLINE(buddy))
2834 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); 3035 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE);
2835 else if (gaim_presence_is_idle(presence)) 3036 else if (gaim_presence_is_idle(presence))
2836 { 3037 {
2837 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.25, FALSE); 3038 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.25, FALSE);
2857 g_object_unref(emblem); 3058 g_object_unref(emblem);
2858 } 3059 }
2859 } 3060 }
2860 } 3061 }
2861 3062
3063 /* Insert the new icon into the status icon hash table */
3064 g_hash_table_insert (status_icon_hash_table, key, scale);
3065 gdk_pixbuf_ref(scale);
3066
2862 return scale; 3067 return scale;
2863 } 3068 }
2864 3069
2865 static gchar *gaim_gtk_blist_get_name_markup(GaimBuddy *b, gboolean selected) 3070 static gchar *gaim_gtk_blist_get_name_markup(GaimBuddy *b, gboolean selected)
2866 { 3071 {
3080 3285
3081 /* keep on going */ 3286 /* keep on going */
3082 return TRUE; 3287 return TRUE;
3083 } 3288 }
3084 3289
3085 static void gaim_gtk_blist_hide_node(GaimBuddyList *list, GaimBlistNode *node) 3290 static void gaim_gtk_blist_hide_node(GaimBuddyList *list, GaimBlistNode *node, gboolean update)
3086 { 3291 {
3087 struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; 3292 struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data;
3088 GtkTreeIter iter; 3293 GtkTreeIter iter;
3089 3294
3090 if (!gtknode || !gtknode->row || !gtkblist) 3295 if (!gtknode || !gtknode->row || !gtkblist)
3091 return; 3296 return;
3092 3297
3093 if(gtkblist->selected_node == node) 3298 if(gtkblist->selected_node == node)
3094 gtkblist->selected_node = NULL; 3299 gtkblist->selected_node = NULL;
3095
3096 if (get_iter_from_node(node, &iter)) { 3300 if (get_iter_from_node(node, &iter)) {
3097 gtk_tree_store_remove(gtkblist->treemodel, &iter); 3301 gtk_tree_store_remove(gtkblist->treemodel, &iter);
3098 if(GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_BUDDY(node) 3302 if(update && (GAIM_BLIST_NODE_IS_CONTACT(node) ||
3099 || GAIM_BLIST_NODE_IS_CHAT(node)) { 3303 GAIM_BLIST_NODE_IS_BUDDY(node) || GAIM_BLIST_NODE_IS_CHAT(node))) {
3100 gaim_gtk_blist_update(list, node->parent); 3304 gaim_gtk_blist_update(list, node->parent);
3101 } 3305 }
3102 } 3306 }
3103 gtk_tree_row_reference_free(gtknode->row); 3307 gtk_tree_row_reference_free(gtknode->row);
3104 gtknode->row = NULL; 3308 gtknode->row = NULL;
3226 return; 3430 return;
3227 3431
3228 if(conv->account != NULL && conv->name != NULL) { 3432 if(conv->account != NULL && conv->name != NULL) {
3229 GaimBuddy *buddy = gaim_find_buddy(conv->account, conv->name); 3433 GaimBuddy *buddy = gaim_find_buddy(conv->account, conv->name);
3230 if(buddy != NULL) 3434 if(buddy != NULL)
3231 gaim_gtk_blist_update_buddy(NULL, (GaimBlistNode *)buddy); 3435 gaim_gtk_blist_update_buddy(NULL, (GaimBlistNode *)buddy, TRUE);
3232 } 3436 }
3233 3437
3234 if (gtkblist->menutrayicon) { 3438 if (gtkblist->menutrayicon) {
3235 gtk_widget_destroy(gtkblist->menutrayicon); 3439 gtk_widget_destroy(gtkblist->menutrayicon);
3236 gtkblist->menutrayicon = NULL; 3440 gtkblist->menutrayicon = NULL;
3365 if (gtk_tree_selection_get_selected(sel, NULL, &iter)) 3569 if (gtk_tree_selection_get_selected(sel, NULL, &iter))
3366 { 3570 {
3367 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); 3571 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1);
3368 } 3572 }
3369 3573
3370 redo_buddy_list(gaim_get_blist(), TRUE); 3574 redo_buddy_list(gaim_get_blist(), FALSE, FALSE);
3371 #if GTK_CHECK_VERSION(2,6,0) 3575 #if GTK_CHECK_VERSION(2,6,0)
3372 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(gtkblist->treeview)); 3576 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(gtkblist->treeview));
3373 #endif 3577 #endif
3374 3578
3375 if (node) 3579 if (node)
3912 4116
3913 /* emit our created signal */ 4117 /* emit our created signal */
3914 gaim_signal_emit(handle, "gtkblist-created", list); 4118 gaim_signal_emit(handle, "gtkblist-created", list);
3915 } 4119 }
3916 4120
3917 static void redo_buddy_list(GaimBuddyList *list, gboolean remove) 4121 static void redo_buddy_list(GaimBuddyList *list, gboolean remove, gboolean rerender)
3918 { 4122 {
3919 GaimBlistNode *node = list->root; 4123 GaimBlistNode *node = list->root;
3920 4124
3921 while (node) 4125 while (node)
3922 { 4126 {
4127 /* This is only needed when we're reverting to a non-GTK+ sorted
4128 * status. We shouldn't need to remove otherwise.
4129 */
3923 if (remove && !GAIM_BLIST_NODE_IS_GROUP(node)) 4130 if (remove && !GAIM_BLIST_NODE_IS_GROUP(node))
3924 gaim_gtk_blist_hide_node(list, node); 4131 gaim_gtk_blist_hide_node(list, node, FALSE);
3925 4132
3926 gaim_gtk_blist_update(list, node); 4133 if (GAIM_BLIST_NODE_IS_BUDDY(node))
4134 gaim_gtk_blist_update_buddy(list, node, rerender);
4135 else if (GAIM_BLIST_NODE_IS_CHAT(node))
4136 gaim_gtk_blist_update(list, node);
3927 node = gaim_blist_node_next(node, FALSE); 4137 node = gaim_blist_node_next(node, FALSE);
3928 } 4138 }
4139
4140 /* There is no hash table if there is nothing in the buddy list to update */
4141 if (status_icon_hash_table) {
4142 g_hash_table_destroy(status_icon_hash_table);
4143 status_icon_hash_table = NULL;
4144 }
4145
3929 } 4146 }
3930 4147
3931 void gaim_gtk_blist_refresh(GaimBuddyList *list) 4148 void gaim_gtk_blist_refresh(GaimBuddyList *list)
3932 { 4149 {
3933 redo_buddy_list(list, FALSE); 4150 redo_buddy_list(list, FALSE, TRUE);
3934 } 4151 }
3935 4152
3936 void 4153 void
3937 gaim_gtk_blist_update_refresh_timeout() 4154 gaim_gtk_blist_update_refresh_timeout()
3938 { 4155 {
3977 { 4194 {
3978 struct _gaim_gtk_blist_node *gtknode = node->ui_data; 4195 struct _gaim_gtk_blist_node *gtknode = node->ui_data;
3979 4196
3980 gaim_request_close_with_handle(node); 4197 gaim_request_close_with_handle(node);
3981 4198
3982 gaim_gtk_blist_hide_node(list, node); 4199 gaim_gtk_blist_hide_node(list, node, TRUE);
3983 4200
3984 if(node->parent) 4201 if(node->parent)
3985 gaim_gtk_blist_update(list, node->parent); 4202 gaim_gtk_blist_update(list, node->parent);
3986 4203
3987 /* There's something I don't understand here - Ethan */ 4204 /* There's something I don't understand here - Ethan */
4145 NAME_COLUMN, mark, 4362 NAME_COLUMN, mark,
4146 NODE_COLUMN, gnode, 4363 NODE_COLUMN, gnode,
4147 -1); 4364 -1);
4148 g_free(mark); 4365 g_free(mark);
4149 } else { 4366 } else {
4150 gaim_gtk_blist_hide_node(list, gnode); 4367 gaim_gtk_blist_hide_node(list, gnode, TRUE);
4151 } 4368 }
4152 } 4369 }
4153 4370
4154 static void buddy_node(GaimBuddy *buddy, GtkTreeIter *iter, GaimBlistNode *node) 4371 static void buddy_node(GaimBuddy *buddy, GtkTreeIter *iter, GaimBlistNode *node)
4155 { 4372 {
4267 g_object_unref(status); 4484 g_object_unref(status);
4268 } else { 4485 } else {
4269 buddy_node(buddy, &iter, cnode); 4486 buddy_node(buddy, &iter, cnode);
4270 } 4487 }
4271 } else { 4488 } else {
4272 gaim_gtk_blist_hide_node(list, cnode); 4489 gaim_gtk_blist_hide_node(list, cnode, TRUE);
4273 } 4490 }
4274 } 4491 }
4275 4492
4276 4493
4277 4494
4278 static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node) 4495 static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node, gboolean statusChange)
4279 { 4496 {
4280 GaimBuddy *buddy; 4497 GaimBuddy *buddy;
4281 struct _gaim_gtk_blist_node *gtkparentnode; 4498 struct _gaim_gtk_blist_node *gtkparentnode;
4282 4499
4283 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); 4500 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node));
4284 4501
4285 if (node->parent == NULL) 4502 if (node->parent == NULL)
4286 return; 4503 return;
4287 4504
4288 buddy = (GaimBuddy*)node; 4505 buddy = (GaimBuddy*)node;
4506
4507 if (statusChange)
4508 gaim_gtk_blist_update_buddy_status_icon_key(node, (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")
4509 ? GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL));
4289 4510
4290 /* First things first, update the contact */ 4511 /* First things first, update the contact */
4291 gaim_gtk_blist_update_contact(list, node); 4512 gaim_gtk_blist_update_contact(list, node);
4292 4513
4293 gtkparentnode = (struct _gaim_gtk_blist_node *)node->parent->ui_data; 4514 gtkparentnode = (struct _gaim_gtk_blist_node *)node->parent->ui_data;
4300 return; 4521 return;
4301 4522
4302 buddy_node(buddy, &iter, node); 4523 buddy_node(buddy, &iter, node);
4303 4524
4304 } else { 4525 } else {
4305 gaim_gtk_blist_hide_node(list, node); 4526 gaim_gtk_blist_hide_node(list, node, TRUE);
4306 } 4527 }
4307 4528
4308 } 4529 }
4309 4530
4310 static void gaim_gtk_blist_update_chat(GaimBuddyList *list, GaimBlistNode *node) 4531 static void gaim_gtk_blist_update_chat(GaimBuddyList *list, GaimBlistNode *node)
4340 4561
4341 g_free(mark); 4562 g_free(mark);
4342 if(status) 4563 if(status)
4343 g_object_unref(status); 4564 g_object_unref(status);
4344 } else { 4565 } else {
4345 gaim_gtk_blist_hide_node(list, node); 4566 gaim_gtk_blist_hide_node(list, node, TRUE);
4346 } 4567 }
4347 } 4568 }
4348 4569
4349 static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node) 4570 static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node)
4350 { 4571 {
4360 break; 4581 break;
4361 case GAIM_BLIST_CONTACT_NODE: 4582 case GAIM_BLIST_CONTACT_NODE:
4362 gaim_gtk_blist_update_contact(list, node); 4583 gaim_gtk_blist_update_contact(list, node);
4363 break; 4584 break;
4364 case GAIM_BLIST_BUDDY_NODE: 4585 case GAIM_BLIST_BUDDY_NODE:
4365 gaim_gtk_blist_update_buddy(list, node); 4586 gaim_gtk_blist_update_buddy(list, node, TRUE);
4366 break; 4587 break;
4367 case GAIM_BLIST_CHAT_NODE: 4588 case GAIM_BLIST_CHAT_NODE:
4368 gaim_gtk_blist_update_chat(list, node); 4589 gaim_gtk_blist_update_chat(list, node);
4369 break; 4590 break;
4370 case GAIM_BLIST_OTHER_NODE: 4591 case GAIM_BLIST_OTHER_NODE:
5212 gaim_value_new(GAIM_TYPE_BOOLEAN)); 5433 gaim_value_new(GAIM_TYPE_BOOLEAN));
5213 5434
5214 5435
5215 gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-on", gtk_blist_handle, GAIM_CALLBACK(buddy_signonoff_cb), NULL); 5436 gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-on", gtk_blist_handle, GAIM_CALLBACK(buddy_signonoff_cb), NULL);
5216 gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-off", gtk_blist_handle, GAIM_CALLBACK(buddy_signonoff_cb), NULL); 5437 gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-off", gtk_blist_handle, GAIM_CALLBACK(buddy_signonoff_cb), NULL);
5438 gaim_signal_connect(gaim_blist_get_handle(), "buddy-privacy-changed", gtk_blist_handle, GAIM_CALLBACK(gaim_gtk_blist_update_privacy_cb), NULL);
5217 } 5439 }
5218 5440
5219 void 5441 void
5220 gaim_gtk_blist_uninit(void) { 5442 gaim_gtk_blist_uninit(void) {
5221 gaim_signals_unregister_by_instance(gaim_gtk_blist_get_handle()); 5443 gaim_signals_unregister_by_instance(gaim_gtk_blist_get_handle());
5269 current_sort_method = l->data; 5491 current_sort_method = l->data;
5270 } else if (!current_sort_method) { 5492 } else if (!current_sort_method) {
5271 gaim_gtk_blist_sort_method_set("none"); 5493 gaim_gtk_blist_sort_method_set("none");
5272 return; 5494 return;
5273 } 5495 }
5274 redo_buddy_list(gaim_get_blist(), TRUE); 5496 if (!strcmp(id, "none")) {
5275 5497 redo_buddy_list(gaim_get_blist(), TRUE, FALSE);
5498 } else {
5499 redo_buddy_list(gaim_get_blist(), FALSE, FALSE);
5500 }
5276 } 5501 }
5277 5502
5278 /****************************************** 5503 /******************************************
5279 ** Sort Methods 5504 ** Sort Methods
5280 ******************************************/ 5505 ******************************************/
5835 sortmethod_act(GtkCheckMenuItem *checkmenuitem, char *id) 6060 sortmethod_act(GtkCheckMenuItem *checkmenuitem, char *id)
5836 { 6061 {
5837 if (gtk_check_menu_item_get_active(checkmenuitem)) 6062 if (gtk_check_menu_item_get_active(checkmenuitem))
5838 { 6063 {
5839 gaim_gtk_set_cursor(gtkblist->window, GDK_WATCH); 6064 gaim_gtk_set_cursor(gtkblist->window, GDK_WATCH);
5840 6065 /* This is redundant. I think. */
5841 gaim_gtk_blist_sort_method_set(id); 6066 /* gaim_gtk_blist_sort_method_set(id); */
5842 gaim_prefs_set_string("/gaim/gtk/blist/sort_type", id); 6067 gaim_prefs_set_string("/gaim/gtk/blist/sort_type", id);
5843 6068
5844 gaim_gtk_clear_cursor(gtkblist->window); 6069 gaim_gtk_clear_cursor(gtkblist->window);
5845 } 6070 }
5846 } 6071 }