Mercurial > pidgin.yaz
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 } |