changeset 12175:a655bdeb561d

[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 <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Mon, 21 Nov 2005 00:43:20 +0000
parents c7652a910308
children 6f41d8d33989
files plugins/ChangeLog.API src/gtkblist.c src/gtkconv.c src/gtkconv.h
diffstat 4 files changed, 106 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- 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()
--- 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;
 		}
--- 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);
 }
 
 /*
--- 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.