# HG changeset patch # User Richard Laager # Date 1132533800 0 # Node ID a655bdeb561dfd2e5052dd8b081a51259e3c1144 # Parent c7652a9103082bac5f64eb89cec94c8fd43ab330 [gaim-migrate @ 14477] SF Patch #1360582 from Casey Harkins (charkins) "This patch adds an unseen_count field to gtkconvs which obviously counts the number of unseen messages. It is handled entirely within ...set_unseen() in gtkconv.c. The code for filling the gtkblist menutray context menu with unseen conversations is moved into gtkconv.c because it will also be used by the docklet (avoiding code duplication). I documented it in ChangeLog.API. The context menu items and the tooltips faceprint added now will show the message count as well." committer: Tailor Script diff -r c7652a910308 -r a655bdeb561d plugins/ChangeLog.API --- a/plugins/ChangeLog.API Sun Nov 20 22:09:24 2005 +0000 +++ b/plugins/ChangeLog.API Mon Nov 21 00:43:20 2005 +0000 @@ -150,6 +150,8 @@ a visibility manager - see the docs for more information * gaim_gtk_conversations_get_first_unseen() to find the first conv with an "unseen" state >= to the specified state + * gaim_gtk_conversations_fill_unseen_menu() to fill a menu with a list of + conversations with an "unseen" state >= to the specified state * gaim_gtk_create_prpl_icon() * gaim_gtk_create_prpl_icon_with_status() * gaim_gtk_pounces_manager_show() diff -r c7652a910308 -r a655bdeb561d src/gtkblist.c --- a/src/gtkblist.c Sun Nov 20 22:09:24 2005 +0000 +++ b/src/gtkblist.c Mon Nov 21 00:43:20 2005 +0000 @@ -3127,46 +3127,19 @@ } static void -unseen_conv_menu_cb(GtkMenuItem *item, GaimConversation *conv) -{ - g_return_if_fail(conv != NULL); - gaim_gtkconv_present_conversation(conv); -} - -static void unseen_conv_menu() { static GtkWidget *menu = NULL; - GList *convs; if (menu) gtk_widget_destroy(menu); - if (!gaim_gtk_conversations_get_first_unseen(GAIM_CONV_TYPE_IM, GAIM_UNSEEN_TEXT)) + menu = gtk_menu_new(); + if (!gaim_gtk_conversations_fill_unseen_menu(menu, GAIM_CONV_TYPE_IM, GAIM_UNSEEN_TEXT)) { + /* no conversations added, don't show the menu */ + gtk_widget_destroy(menu); return; - - menu = gtk_menu_new(); - - for (convs = gaim_get_ims(); convs != NULL ; convs = convs->next) { - GaimConversation *conv = convs->data; - GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); - - if (gtkconv->unseen_state >= GAIM_UNSEEN_TEXT) { - GtkWidget *icon = gtk_image_new(); - GdkPixbuf *pbuf = gaim_gtkconv_get_tab_icon(conv, TRUE); - GtkWidget *item; - - gtk_image_set_from_pixbuf(GTK_IMAGE(icon), pbuf); - g_object_unref(pbuf); - - item = gtk_image_menu_item_new_with_label( - gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon); - g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(unseen_conv_menu_cb), conv); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - } } - gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time()); @@ -3194,22 +3167,24 @@ GtkWidget *img = NULL; GString *tooltip_text = NULL; - if(gtkblist->menutrayicon) { + if (type != GAIM_CONV_UPDATE_UNSEEN) + return; + + if (gtkblist->menutrayicon) { gtk_widget_destroy(gtkblist->menutrayicon); gtkblist->menutrayicon = NULL; } - if(gaim_gtk_conversations_get_first_unseen(GAIM_CONV_TYPE_IM, GAIM_UNSEEN_TEXT)) { + if (gaim_gtk_conversations_get_first_unseen(GAIM_CONV_TYPE_IM, GAIM_UNSEEN_TEXT)) { GList *convs = gaim_get_ims(); tooltip_text = g_string_new(""); - while(convs) { - conv = convs->data; - if(GAIM_IS_GTK_CONVERSATION(conv)) { - GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); - if(gtkconv->unseen_state >= GAIM_UNSEEN_TEXT) { - g_string_append_printf(tooltip_text, - _("Unread messages from %s\n"), gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); - } + while (convs) { + GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION((GaimConversation *)convs->data); + + if (gtkconv->unseen_state >= GAIM_UNSEEN_TEXT) { + g_string_append_printf(tooltip_text, + _("%d unread message(s) from %s\n"), gtkconv->unseen_count, + gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); } convs = convs->next; } diff -r c7652a910308 -r a655bdeb561d src/gtkconv.c --- a/src/gtkconv.c Sun Nov 20 22:09:24 2005 +0000 +++ b/src/gtkconv.c Mon Nov 21 00:43:20 2005 +0000 @@ -2392,16 +2392,65 @@ for(; l!=NULL; l=l->next) { GaimConversation *conv = (GaimConversation*)l->data; - if(GAIM_IS_GTK_CONVERSATION(conv)) { - if(GAIM_GTK_CONVERSATION(conv)->unseen_state>=min_state) { - return conv; - } - } + if (GAIM_GTK_CONVERSATION(conv)->unseen_state >= min_state) + return conv; } return NULL; } +static void +unseen_conv_menu_cb(GtkMenuItem *item, GaimConversation *conv) +{ + g_return_if_fail(conv != NULL); + gaim_gtkconv_present_conversation(conv); +} + +guint +gaim_gtk_conversations_fill_unseen_menu(GtkWidget *menu, + GaimConversationType type, + GaimUnseenState min_state) +{ + GList *l; + guint ret = 0; + + g_return_val_if_fail(menu != NULL, 0); + + if (type == GAIM_CONV_TYPE_IM) { + l = gaim_get_ims(); + } else if (type == GAIM_CONV_TYPE_CHAT) { + l = gaim_get_chats(); + } else { + l = gaim_get_conversations(); + } + + for (; l != NULL ; l = l->next) { + GaimConversation *conv = (GaimConversation*)l->data; + GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); + + if (gtkconv->unseen_state >= min_state) { + GtkWidget *icon = gtk_image_new(); + GdkPixbuf *pbuf = gaim_gtkconv_get_tab_icon(conv, TRUE); + GtkWidget *item; + gchar *text = g_strdup_printf("%s (%d)", + gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)), + gtkconv->unseen_count); + + gtk_image_set_from_pixbuf(GTK_IMAGE(icon), pbuf); + g_object_unref(pbuf); + + item = gtk_image_menu_item_new_with_label(text); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon); + g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(unseen_conv_menu_cb), conv); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + g_free(text); + ret++; + } + } + + return ret; +} + GaimGtkWindow * gaim_gtkconv_get_window(GaimGtkConversation *gtkconv) { @@ -3907,6 +3956,8 @@ /* Setup some initial variables. */ gtkconv->sg = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); gtkconv->tooltips = gtk_tooltips_new(); + gtkconv->unseen_state = GAIM_UNSEEN_NONE; + gtkconv->unseen_count = 0; if (conv_type == GAIM_CONV_TYPE_IM) { gtkconv->u.im = g_malloc0(sizeof(GaimGtkImPane)); @@ -5982,7 +6033,7 @@ { GaimGtkConversation *gtkconv = l->data; if (gaim_conversation_get_type(gtkconv->active_conv) == GAIM_CONV_TYPE_IM && - gtkconv->unseen_state == GAIM_UNSEEN_TEXT) + gtkconv->unseen_state >= GAIM_UNSEEN_TEXT) { build_warn_close_dialog(win); gtk_widget_show_all(warn_close_dialog); @@ -5999,12 +6050,21 @@ static void gtkconv_set_unseen(GaimGtkConversation *gtkconv, GaimUnseenState state) { - /* only allow NONE or higher priority unseen state */ - if((state==GAIM_UNSEEN_NONE && gtkconv->unseen_state!=GAIM_UNSEEN_NONE) - || state > gtkconv->unseen_state) { - gtkconv->unseen_state = state; - gaim_conversation_update(gtkconv->active_conv, GAIM_CONV_UPDATE_UNSEEN); - } + if (state == GAIM_UNSEEN_NONE) + { + gtkconv->unseen_count = 0; + gtkconv->unseen_state = GAIM_UNSEEN_NONE; + } + else + { + gtkconv->unseen_count++; + + if (state > gtkconv->unseen_state) + gtkconv->unseen_state = state; + } + + /* emit update signal to notify of count and possible unseen state change */ + gaim_conversation_update(gtkconv->active_conv, GAIM_CONV_UPDATE_UNSEEN); } /* diff -r c7652a910308 -r a655bdeb561d src/gtkconv.h --- a/src/gtkconv.h Sun Nov 20 22:09:24 2005 +0000 +++ b/src/gtkconv.h Mon Nov 21 00:43:20 2005 +0000 @@ -143,6 +143,7 @@ GtkWidget *toolbar; GaimUnseenState unseen_state; + guint unseen_count; struct { @@ -211,6 +212,21 @@ GaimConversation * gaim_gtk_conversations_get_first_unseen(GaimConversationType type, GaimUnseenState min_state); +/** + * Adds an item to a menu for each conversation of the given type + * with an unseen state greater than or equal to the specified minimum + * state. The menu item will present the conversation to the user + * when activated. + * + * @param menu Menu widget to add items to. + * @param type The type of conversation. + * @param min_state The minimum unseen state. + * @return Number of conversations added to menu. + */ +guint +gaim_gtk_conversations_fill_unseen_menu(GtkWidget *menu, + GaimConversationType type, + GaimUnseenState min_state); /** * Presents a gaim conversation to the user.