diff libpurple/account.c @ 21366:8858a42ca237

Make PurpleAccount keep track of the last connection error suffered (or not, if the account is happily connected or is disconnected without error). Add a signal which fires when the current error changes, and an accessor to get the current error. The error itself is stored inside a private struct.
author Will Thompson <will.thompson@collabora.co.uk>
date Sat, 27 Oct 2007 17:26:17 +0000
parents a20ef7180680
children 0aa18e21a595
line wrap: on
line diff
--- a/libpurple/account.c	Sat Oct 27 12:14:15 2007 +0000
+++ b/libpurple/account.c	Sat Oct 27 17:26:17 2007 +0000
@@ -41,6 +41,14 @@
 #include "util.h"
 #include "xmlnode.h"
 
+typedef struct
+{
+	PurpleAccountCurrentError *current_error;
+} PurpleAccountPrivate;
+
+#define PURPLE_ACCOUNT_GET_PRIVATE(account) \
+	((PurpleAccountPrivate *) (account->priv))
+
 /* TODO: Should use PurpleValue instead of this?  What about "ui"? */
 typedef struct
 {
@@ -77,6 +85,8 @@
 
 static GList *handles = NULL;
 
+static void clear_current_error(PurpleAccount *account);
+
 /*********************************************************************
  * Writing to disk                                                   *
  *********************************************************************/
@@ -827,6 +837,7 @@
 purple_account_new(const char *username, const char *protocol_id)
 {
 	PurpleAccount *account = NULL;
+	PurpleAccountPrivate *priv = NULL;
 	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleStatusType *status_type;
@@ -841,6 +852,8 @@
 
 	account = g_new0(PurpleAccount, 1);
 	PURPLE_DBUS_REGISTER_POINTER(account, PurpleAccount);
+	priv = g_new0(PurpleAccountPrivate, 1);
+	account->priv = priv;
 
 	purple_account_set_username(account, username);
 
@@ -881,6 +894,7 @@
 void
 purple_account_destroy(PurpleAccount *account)
 {
+	PurpleAccountPrivate *priv = NULL;
 	GList *l;
 
 	g_return_if_fail(account != NULL);
@@ -912,6 +926,10 @@
 	if(account->system_log)
 		purple_log_free(account->system_log);
 
+	priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
+	g_free(priv->current_error);
+	g_free(priv);
+
 	PURPLE_DBUS_UNREGISTER_POINTER(account);
 	g_free(account);
 }
@@ -2214,6 +2232,53 @@
 	return prpl_info->offline_message(buddy);
 }
 
+static void
+clear_current_error(PurpleAccount *account)
+{
+	PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
+	if (priv->current_error)
+	{
+		g_free (priv->current_error);
+		priv->current_error = NULL;
+	}
+
+	purple_signal_emit(purple_accounts_get_handle(), "account-error-changed",
+	                   account, priv->current_error);
+}
+
+static void
+signed_on_cb(PurpleConnection *gc,
+             gpointer unused)
+{
+	PurpleAccount *account = purple_connection_get_account(gc);
+	clear_current_error(account);
+}
+
+static void
+connection_error_cb(PurpleConnection *gc,
+                    PurpleConnectionError err,
+                    const gchar *desc,
+                    gpointer unused)
+{
+	PurpleAccount *account = purple_connection_get_account(gc);
+	PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
+
+	if (!priv->current_error)
+		priv->current_error = g_new0(PurpleAccountCurrentError, 1);
+	priv->current_error->reason = err;
+	priv->current_error->description = desc;
+
+	purple_signal_emit(purple_accounts_get_handle(), "account-error-changed",
+	                   account, priv->current_error);
+}
+
+const PurpleAccountCurrentError *
+purple_account_get_current_error(PurpleAccount *account)
+{
+	PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
+	return priv->current_error;
+}
+
 void
 purple_accounts_add(PurpleAccount *account)
 {
@@ -2238,6 +2303,7 @@
 
 	schedule_accounts_save();
 
+	clear_current_error(account);
 	purple_signal_emit(purple_accounts_get_handle(), "account-removed", account);
 }
 
@@ -2443,6 +2509,7 @@
 purple_accounts_init(void)
 {
 	void *handle = purple_accounts_get_handle();
+	void *conn_handle = purple_connections_get_handle();
 
 	purple_signal_register(handle, "account-connecting",
 						 purple_marshal_VOID__POINTER, NULL, 1,
@@ -2513,6 +2580,15 @@
 										PURPLE_SUBTYPE_ACCOUNT),
 						purple_value_new(PURPLE_TYPE_STRING));
 
+	purple_signal_register(handle, "account-error-changed",
+	                       purple_marshal_VOID__POINTER_POINTER, NULL, 2,
+	                       purple_value_new(PURPLE_TYPE_SUBTYPE,
+	                                        PURPLE_SUBTYPE_ACCOUNT),
+	                       purple_value_new(PURPLE_TYPE_POINTER));
+
+	purple_signal_connect(conn_handle, "signed-on", handle,
+	                      PURPLE_CALLBACK(signed_on_cb), NULL);
+
 	load_accounts();
 
 }
@@ -2520,6 +2596,7 @@
 void
 purple_accounts_uninit(void)
 {
+	gpointer handle = purple_accounts_get_handle();
 	if (save_timer != 0)
 	{
 		purple_timeout_remove(save_timer);
@@ -2527,5 +2604,6 @@
 		sync_accounts();
 	}
 
-	purple_signals_unregister_by_instance(purple_accounts_get_handle());
+	purple_signals_disconnect_by_handle(handle);
+	purple_signals_unregister_by_instance(handle);
 }