Mercurial > pidgin
changeset 19939:0ac0e112a0fa
Add some stuff so that we don't have to traverse over a list to determine
whether a node in the buddylist has a conversation for it or not. Instead,
maintain the information about conversations with the blist-node's ui-data.
Looking at the ui-data can thus quickly tell us whether there's any hidden
conversation with the node. We can also use this for other purposes later.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Tue, 04 Sep 2007 07:56:10 +0000 |
parents | 0b8740878f9e |
children | 1fe1ac03e1fe |
files | pidgin/gtkblist.c |
diffstat | 1 files changed, 126 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/pidgin/gtkblist.c Tue Sep 04 05:44:21 2007 +0000 +++ b/pidgin/gtkblist.c Tue Sep 04 07:56:10 2007 +0000 @@ -137,12 +137,21 @@ static void pidgin_blist_collapse_contact_cb(GtkWidget *w, PurpleBlistNode *node); static char *pidgin_get_group_title(PurpleBlistNode *gnode, gboolean expanded); -struct _pidgin_blist_node { +typedef enum { + PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE = 1 << 0, /* Whether there's pending message in a conversation */ +} PidginBlistNodeFlags; + +typedef struct _pidgin_blist_node { GtkTreeRowReference *row; gboolean contact_expanded; gboolean recent_signonoff; gint recent_signonoff_timer; -}; + struct { + PurpleConversation *conv; + time_t last_message; /* timestamp for last displayed message */ + PidginBlistNodeFlags flags; + } conv; +} PidginBlistNode; static char dim_grey_string[8] = ""; static char *dim_grey() @@ -310,6 +319,17 @@ gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); } +static PurpleConversation * +find_conversation_with_buddy(PurpleBuddy *buddy) +{ + PidginBlistNode *ui = buddy->node.ui_data; + if (ui) + return ui->conv.conv; + return purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + purple_buddy_get_name(buddy), + purple_buddy_get_account(buddy)); +} + static void gtk_blist_join_chat(PurpleChat *chat) { PurpleConversation *conv; @@ -3257,9 +3277,7 @@ } if(buddy) { - PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - purple_buddy_get_name(buddy), - purple_buddy_get_account(buddy)); + PurpleConversation *conv = find_conversation_with_buddy(buddy); PurplePresence *p; gboolean trans; @@ -3323,16 +3341,17 @@ struct _pidgin_blist_node *gtkcontactnode = NULL; char *idletime = NULL, *statustext = NULL; time_t t; - PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - purple_buddy_get_name(b), - purple_buddy_get_account(b)); - PidginConversation *gtkconv; + PurpleConversation *conv = find_conversation_with_buddy(b); gboolean hidden_conv = FALSE; - if(conv != NULL) { - gtkconv = PIDGIN_CONVERSATION(conv); - if(gtkconv == NULL || pidgin_conv_is_hidden(gtkconv)) { - hidden_conv = TRUE; + if (conv != NULL) { + PidginBlistNode *ui = b->node.ui_data; + if (ui) { + if (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE) + hidden_conv = TRUE; + } else { + if (PIDGIN_CONVERSATION(conv) == NULL) + hidden_conv = TRUE; } } @@ -3766,6 +3785,87 @@ conversation_updated_cb(conv, PURPLE_CONV_UPDATE_UNSEEN, gtkblist); } +static void +conversation_deleted_update_ui_cb(PurpleConversation *conv, struct _pidgin_blist_node *ui) +{ + if (ui->conv.conv != conv) + return; + ui->conv.conv = NULL; + ui->conv.flags = 0; + ui->conv.last_message = 0; +} + +static void +written_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message, + PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node) +{ + PidginBlistNode *ui = node->ui_data; + if (ui->conv.conv != conv || PIDGIN_CONVERSATION(conv)) + return; + ui->conv.flags |= PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE; + ui->conv.last_message = time(NULL); /* XXX: for lack of better data */ + pidgin_blist_update(purple_get_blist(), node); +} + +static void +displayed_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message, + PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node) +{ + PidginBlistNode *ui = node->ui_data; + if (ui->conv.conv != conv) + return; + ui->conv.flags &= ~PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE; + pidgin_blist_update(purple_get_blist(), node); +} + +static void +conversation_created_cb(PurpleConversation *conv, PidginBuddyList *gtkblist) +{ + switch (conv->type) { + case PURPLE_CONV_TYPE_IM: + { + GSList *buddies = purple_find_buddies(conv->account, conv->name); + while (buddies) { + PurpleBlistNode *buddy = buddies->data; + struct _pidgin_blist_node *ui = buddy->ui_data; + buddies = g_slist_delete_link(buddies, buddies); + if (!ui) + continue; + ui->conv.conv = conv; + ui->conv.flags = 0; + ui->conv.last_message = 0; + purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", + ui, PURPLE_CALLBACK(conversation_deleted_update_ui_cb), ui); + purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", + ui, PURPLE_CALLBACK(written_msg_update_ui_cb), buddy); + purple_signal_connect(pidgin_conversations_get_handle(), "displayed-im-msg", + ui, PURPLE_CALLBACK(displayed_msg_update_ui_cb), buddy); + } + } + case PURPLE_CONV_TYPE_CHAT: + { + PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); + struct _pidgin_blist_node *ui; + if (!chat) + break; + ui = chat->node.ui_data; + if (!ui) + break; + ui->conv.conv = conv; + ui->conv.flags = 0; + ui->conv.last_message = 0; + purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", + ui, PURPLE_CALLBACK(conversation_deleted_update_ui_cb), ui); + purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", + ui, PURPLE_CALLBACK(written_msg_update_ui_cb), chat); + purple_signal_connect(pidgin_conversations_get_handle(), "displayed-chat-msg", + ui, PURPLE_CALLBACK(displayed_msg_update_ui_cb), chat); + } + default: + break; + } +} + /********************************************************************************** * Public API Functions * **********************************************************************************/ @@ -4679,6 +4779,9 @@ purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", gtkblist, PURPLE_CALLBACK(conversation_deleting_cb), gtkblist); + purple_signal_connect(purple_conversations_get_handle(), "conversation-created", + gtkblist, PURPLE_CALLBACK(conversation_created_cb), + gtkblist); gtk_widget_hide(gtkblist->headline_hbox); gtk_widget_hide(gtkblist->error_buttons); @@ -4785,6 +4888,7 @@ if(gtknode->recent_signonoff_timer > 0) purple_timeout_remove(gtknode->recent_signonoff_timer); + purple_signals_disconnect_by_handle(node->ui_data); g_free(node->ui_data); node->ui_data = NULL; } @@ -5209,14 +5313,17 @@ GdkPixbuf *emblem; char *mark; gboolean showicons = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); - const char *name = purple_chat_get_name(chat); - PurpleConversation *conv = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name, chat->account); - gboolean hidden = (conv && !PIDGIN_CONVERSATION(conv)); - - if(!insert_node(list, node, &iter)) + PidginBlistNode *ui; + PurpleConversation *conv; + gboolean hidden; + + if (!insert_node(list, node, &iter)) return; + ui = node->ui_data; + conv = ui->conv.conv; + hidden = (conv && (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE)); + status = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_SMALL); emblem = pidgin_blist_get_emblem(node);