changeset 10006:9baedaca25c7

[gaim-migrate @ 10923] This is a patch from Dave West. He says it makes people show up as online/offline for him. It crashes for me. I've changed some things from his patch, so I'm gonna commit it and let people work from there. I feel it's a step in the right direction. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Fri, 10 Sep 2004 04:09:36 +0000
parents c892b6dbc341
children 267a2b69e36e
files src/gtkblist.c src/prpl.c src/prpl.h src/status.c src/status.h
diffstat 5 files changed, 158 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/src/gtkblist.c	Fri Sep 10 02:51:22 2004 +0000
+++ b/src/gtkblist.c	Fri Sep 10 04:09:36 2004 +0000
@@ -3476,13 +3476,13 @@
 	/* XXX: why do we assume we have a buddy here? */
 	if (!gtknode) {
 #if 0
-		gaim_debug(GAIM_DEBUG_ERROR, "gtkblist", "buddy %s has no ui_data\n", ((GaimBuddy *)node)->name);
+		gaim_debug_error("gtkblist", "buddy %s has no ui_data\n", ((GaimBuddy *)node)->name);
 #endif
 		return FALSE;
 	}
 
 	if (!gtkblist) {
-		gaim_debug(GAIM_DEBUG_ERROR, "gtkblist", "get_iter_from_node was called, but we don't seem to have a blist\n");
+		gaim_debug_error("gtkblist", "get_iter_from_node was called, but we don't seem to have a blist\n");
 		return FALSE;
 	}
 
@@ -3766,10 +3766,11 @@
 	contact = (GaimContact*)node;
 	buddy = gaim_contact_get_priority_buddy(contact);
 
-	if(buddy && (buddy->present != GAIM_BUDDY_OFFLINE ||
-			(gaim_account_is_connected(buddy->account) &&
-			 gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")) ||
-			gaim_blist_node_get_bool(node, "show_offline"))) {
+	if (buddy && (gaim_presence_is_online(buddy->presence) ||
+		(gaim_account_is_connected(buddy->account) &&
+			gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")) ||
+			gaim_blist_node_get_bool(node, "show_offline")))
+	{
 		GtkTreeIter iter;
 
 		if(!insert_node(list, node, &iter))
@@ -3819,14 +3820,15 @@
 	/* First things first, update the contact */
 	gaim_gtk_blist_update_contact(list, node->parent);
 
-	if(gtkparentnode->contact_expanded &&
-			(buddy->present != GAIM_BUDDY_OFFLINE ||
+	if (gtkparentnode->contact_expanded &&
+		(gaim_presence_is_online(buddy->presence) ||
 			(gaim_account_is_connected(buddy->account) &&
-			 gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")) ||
-			gaim_blist_node_get_bool(node->parent, "show_offline"))) {
+				gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")) ||
+			gaim_blist_node_get_bool(node->parent, "show_offline")))
+	{
 		GtkTreeIter iter;
 
-		if(!insert_node(list, node, &iter))
+		if (!insert_node(list, node, &iter))
 			return;
 
 		buddy_node(buddy, &iter, node);
@@ -4556,7 +4558,7 @@
 		} else {
 			/* we're logging in or something... do nothing */
 			/* or should I make the blist? */
-			gaim_debug(GAIM_DEBUG_WARNING, "blist",
+			gaim_debug_warning("gtkblist",
 					   "docklet_toggle called with gaim_connections_get_all() "
 					   "but no blist!\n");
 		}
@@ -4599,6 +4601,19 @@
 	}
 }
 
+void gaim_gtk_blist_status_changed(GaimBuddy *buddy, GaimStatus *status)
+{
+	g_return_if_fail(buddy != NULL);
+
+	/*
+	 * What do we do with status here?
+	 * g_return_if_fail(status != NULL);
+	 */
+
+	gaim_debug_info("gtkblist", "Updating buddy list\n");
+	gaim_gtk_blist_update(gaim_get_blist(), (GaimBlistNode*)buddy);	
+}
+
 static GaimBlistUiOps blist_ui_ops =
 {
 	gaim_gtk_blist_new_list,
@@ -4610,7 +4625,8 @@
 	gaim_gtk_blist_set_visible,
 	gaim_gtk_blist_request_add_buddy,
 	gaim_gtk_blist_request_add_chat,
-	gaim_gtk_blist_request_add_group
+	gaim_gtk_blist_request_add_group,
+	gaim_gtk_blist_status_changed
 };
 
 
--- a/src/prpl.c	Fri Sep 10 02:51:22 2004 +0000
+++ b/src/prpl.c	Fri Sep 10 04:09:36 2004 +0000
@@ -256,12 +256,7 @@
 
 	presence = gaim_buddy_get_presence(buddy);
 
-	/*
-	 * TODO: Set a presence's sign-on time. We don't support this yet.
-	 */
-	gaim_debug_warning("prpl",
-					   "Attempting to set a user's sign-on time, but we "
-					   "don't support this yet! FIX IT!\n");
+	gaim_presence_set_login_time(presence, login_time);
 }
 
 void
@@ -339,6 +334,36 @@
 		prpl_info->set_status(account, status);
 }
 
+GList *
+gaim_prpl_get_statuses(GaimAccount *account, GaimPresence *presence)
+{
+	GaimPlugin *prpl;
+	GaimPluginProtocolInfo *prpl_info;
+	GList *statuses = NULL;
+	GList *l;
+	GaimStatus *status;
+
+	g_return_val_if_fail(account != NULL, NULL);
+	g_return_val_if_fail(presence != NULL, NULL);
+
+	prpl = gaim_find_prpl(gaim_account_get_protocol_id(account));
+	
+	if (prpl == NULL)
+		return NULL;
+	
+	prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
+	if (prpl_info == NULL || prpl_info->status_types == NULL)
+		return NULL;
+
+	for (l = prpl_info->status_types(account); l != NULL; l = l->next)
+	{
+		status = gaim_status_new((GaimStatusType *)l->data, presence);
+		statuses = g_list_append(statuses, status);
+	}
+
+	return statuses;
+}
+
 
 /**************************************************************************
  * Protocol Plugin Subsystem API
--- a/src/prpl.h	Fri Sep 10 02:51:22 2004 +0000
+++ b/src/prpl.h	Fri Sep 10 04:09:36 2004 +0000
@@ -409,6 +409,16 @@
  */
 void gaim_prpl_set_account_status(GaimAccount *account, GaimStatus *status);
 
+/**
+ * Retrieves the list of stock status types from a prpl.
+ *
+ * @param account The account the user is on.
+ * @param presence The presence for which we're going to get statuses
+ *
+ * @return List of statuses
+ */
+GList *gaim_prpl_get_statuses(GaimAccount *account, GaimPresence *presence);
+
 /*@}*/
 
 /**************************************************************************/
--- a/src/status.c	Fri Sep 10 02:51:22 2004 +0000
+++ b/src/status.c	Fri Sep 10 04:09:36 2004 +0000
@@ -67,6 +67,7 @@
 
 	gboolean idle;
 	time_t idle_time;
+ 	time_t login_time;
 
 	unsigned int warning_level;
 
@@ -117,6 +118,7 @@
 {
 	GaimAccount *account;
 	char *name;
+	guint id;
 
 } GaimStatusBuddyKey;
 
@@ -216,6 +218,7 @@
 	g_return_val_if_fail(primitive  != GAIM_STATUS_UNSET, NULL);
 	g_return_val_if_fail(id         != NULL,              NULL);
 	g_return_val_if_fail(name       != NULL,              NULL);
+ 	g_return_val_if_fail(attr_id    != NULL,              NULL);
 	g_return_val_if_fail(attr_name  != NULL,              NULL);
 	g_return_val_if_fail(attr_value != NULL,              NULL);
 
@@ -567,6 +570,8 @@
 {
 	GaimPresenceContext context = gaim_presence_get_context(presence);
 
+	gaim_debug_info("notify_status_update", "Context is %d\n", context);
+
 	if (context == GAIM_PRESENCE_CONTEXT_ACCOUNT)
 	{
 		GaimAccountUiOps *ops = gaim_accounts_get_ui_ops();
@@ -613,11 +618,11 @@
 
 	status_type = gaim_status_get_type(status);
 
-	if (!active && gaim_status_type_is_independent(status_type))
+	if (!active && !gaim_status_type_is_independent(status_type))
 	{
 		gaim_debug(GAIM_DEBUG_ERROR, "status",
-				"Cannot deactivate an exclusive status (%s).\n",
-				gaim_status_type_get_id(status_type));
+				   "Cannot deactivate an exclusive status (%s).\n",
+				   gaim_status_type_get_id(status_type));
 		return;
 	}
 
@@ -628,14 +633,12 @@
 	{
 		const GList *l;
 
-		for (l = gaim_presence_get_statuses(presence);
-				l != NULL;
-				l = l->next)
+		for (l = gaim_presence_get_statuses(presence); l != NULL; l = l->next)
 		{
 			GaimStatus *temp_status = (GaimStatus *)l->data;
 			GaimStatusType *temp_type;
 
-			if (temp_status == status)
+			if  (!gaim_status_compare(temp_status, status))
 				continue;
 
 			temp_type = gaim_status_get_type(temp_status);
@@ -912,12 +915,11 @@
 gaim_presence_new_for_account(GaimAccount *account)
 {
 	GaimPresence *presence;
-
 	g_return_val_if_fail(account != NULL, NULL);
 
 	presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_ACCOUNT);
-
 	presence->u.account = account;
+	presence->statuses = gaim_prpl_get_statuses(account, presence);
 
 	return presence;
 }
@@ -930,8 +932,8 @@
 	g_return_val_if_fail(conv != NULL, NULL);
 
 	presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_CONV);
-
 	presence->u.chat.conv = conv;
+	/* presence->statuses = gaim_prpl_get_statuses(conv->account, presence); ? */
 
 	return presence;
 }
@@ -941,19 +943,31 @@
 {
 	GaimPresence *presence;
 	GaimStatusBuddyKey *key;
+	GaimAccount *account;
+	gchar *hash_seed;
 
 	g_return_val_if_fail(buddy != NULL, NULL);
 
+	account = buddy->account;
+	hash_seed = g_strdup_printf("%s:%s:%s", buddy->name, account->username,
+								account->protocol_id);
+
 	key = g_new0(GaimStatusBuddyKey, 1);
 	key->account = buddy->account;
 	key->name    = g_strdup(buddy->name);
+	key->id		 = g_str_hash(hash_seed);
 
-	if ((presence = g_hash_table_lookup(buddy_presences, key)) == NULL)
+	g_free(hash_seed);
+	hash_seed = NULL;
+
+	presence = g_hash_table_lookup(buddy_presences, key);
+	if (presence == NULL)
 	{
 		presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_BUDDY);
 
 		presence->u.buddy.name    = g_strdup(buddy->name);
 		presence->u.buddy.account = buddy->account;
+		presence->statuses = gaim_prpl_get_statuses(buddy->account, presence);
 
 		g_hash_table_insert(buddy_presences, key, presence);
 	}
@@ -997,6 +1011,9 @@
 			g_free(presence->u.chat.user);
 	}
 
+	if (buddy_presences != NULL)
+		g_hash_table_destroy(buddy_presences);
+
 	if (presence->statuses != NULL)
 		g_list_free(presence->statuses);
 
@@ -1174,6 +1191,17 @@
 }
 
 void
+gaim_presence_set_login_time(GaimPresence *presence, time_t login_time)
+{
+	g_return_if_fail(presence != NULL);
+
+	if (presence->login_time == login_time)
+		return;
+
+	presence->login_time = login_time;
+}
+
+void
 gaim_presence_set_warning_level(GaimPresence *presence, unsigned int level)
 {
 	g_return_if_fail(presence != NULL);
@@ -1267,12 +1295,29 @@
 gaim_presence_get_status(const GaimPresence *presence, const char *status_id)
 {
 	GaimStatus *status;
+	const GList *l = NULL;
 
 	g_return_val_if_fail(presence  != NULL, NULL);
 	g_return_val_if_fail(status_id != NULL, NULL);
 
-	status = (GaimStatus *)g_hash_table_lookup(presence->status_table,
-			status_id);
+	/* What's the purpose of this hash table? */
+  	status = (GaimStatus *)g_hash_table_lookup(presence->status_table,
+						   status_id);
+  
+	if (status == NULL) {
+		for (l = gaim_presence_get_statuses(presence); 
+			 l != NULL && status == NULL; l = l->next)
+		{
+			GaimStatus *temp_status = l->data;
+ 
+			if (!strcmp(status_id, gaim_status_get_id(temp_status)))
+				status = temp_status;
+		}
+
+		if (status != NULL)
+			g_hash_table_insert(presence->status_table,
+								g_strdup(gaim_status_get_id(status)), status);
+  	}
 
 	return status;
 }
@@ -1446,6 +1491,24 @@
 	primitive_scores[index] = GPOINTER_TO_INT(value);
 }
 
+guint 
+gaim_buddy_presences_hash(gconstpointer key)
+{
+	return ((GaimStatusBuddyKey *)key)->id;
+}
+
+gboolean 
+gaim_buddy_presences_equal(gconstpointer a, gconstpointer b)
+{
+	GaimStatusBuddyKey *key_a = (GaimStatusBuddyKey *)a;
+	GaimStatusBuddyKey *key_b = (GaimStatusBuddyKey *)b;
+
+	if (key_a->id == key_b->id)
+		return TRUE;
+	else
+		return FALSE;
+}
+
 void
 gaim_statuses_init(void)
 {
@@ -1483,6 +1546,10 @@
 	gaim_prefs_connect_callback("/core/status/scores/idle",
 			score_pref_changed_cb,
 			GINT_TO_POINTER(SCORE_IDLE));
+
+	/* XXX - I don't think this is destroyed correctly.  --Mark */
+	buddy_presences = g_hash_table_new(gaim_buddy_presences_hash,
+									   gaim_buddy_presences_equal);
 }
 
 void
--- a/src/status.h	Fri Sep 10 02:51:22 2004 +0000
+++ b/src/status.h	Fri Sep 10 04:09:36 2004 +0000
@@ -654,6 +654,14 @@
 							time_t idle_time);
 
 /**
+ * Sets the login time on a presence.
+ *
+ * @param presence The presence.
+ * @param level    The login time.
+ */
+void gaim_presence_set_login_time(GaimPresence *presence, time_t login_time);
+
+/**
  * Sets the warning level on a presence.
  *
  * @param presence The presence.