changeset 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 3a269007711e
children 640551a3e75a
files doc/account-signals.dox libpurple/account.c libpurple/account.h
diffstat 3 files changed, 113 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/doc/account-signals.dox	Sat Oct 27 12:14:15 2007 +0000
+++ b/doc/account-signals.dox	Sat Oct 27 17:26:17 2007 +0000
@@ -12,6 +12,7 @@
   @signal account-authorization-requested
   @signal account-authorization-denied
   @signal account-authorization-granted
+  @signal account-error-changed
  @endsignals
 
  @see account.h
@@ -141,5 +142,17 @@
   @since 2.3.0
  @endsignaldef
 
+ @signaldef account-error-changed
+  @signalproto
+void (*account_error_changed)(PurpleAccount *account, const PurpleAccountCurrentError *current_error);
+  @endsignalproto
+  @signaldesc
+   Emitted when @a account's error changes.
+  @param account       The account whose error has changed.
+  @param current_error The account's current error, or @c NULL if it has no error.
+  @see purple_account_get_current_error()
+  @since 2.3.0
+ @endsignaldef
+
  */
 // vim: syntax=c.doxygen tw=75 et
--- 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);
 }
--- a/libpurple/account.h	Sat Oct 27 12:14:15 2007 +0000
+++ b/libpurple/account.h	Sat Oct 27 17:26:17 2007 +0000
@@ -140,8 +140,19 @@
 	void *ui_data;              /**< The UI can put data here.              */
 	PurpleAccountRegistrationCb registration_cb;
 	void *registration_cb_user_data;
+
+	gpointer priv;              /**< Pointer to opaque private data. */
 };
 
+/** The error most recently encountered on an account. */
+typedef struct
+{
+	/** The type of error. */
+	PurpleConnectionError reason;
+	/** A localised, human-readable description of the error. */
+	const char *description;
+} PurpleAccountCurrentError;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -893,6 +904,16 @@
  */
 gboolean purple_account_supports_offline_message(PurpleAccount *account, PurpleBuddy *buddy);
 
+/**
+ * Get the error that caused the account to be disconnected, or @c NULL if the
+ * account is happily connected or disconnected without an error.
+ *
+ * @param account The account whose error should be retrieved.
+ * @constreturn   The type of error and a human-readable description of the
+ *                current error, or @c NULL if there is no current error.
+ */
+const PurpleAccountCurrentError *purple_account_get_current_error(PurpleAccount *account);
+
 /*@}*/
 
 /**************************************************************************/