Move the connection-state implementation to Purple.Account

Tue, 22 Apr 2025 00:09:40 -0500

author
Gary Kramlich <grim@reaperworld.com>
date
Tue, 22 Apr 2025 00:09:40 -0500
changeset 43237
c641f6bea7dd
parent 43236
ce4987105a4e
child 43238
58bca4467196

Move the connection-state implementation to Purple.Account

This removes the connection-state implementation from Purple.Connection to
Purple.Account.

Testing Done:
Connected a demo and ircv3 account without issues.

Bugs closed: PIDGIN-17988

Reviewed at https://reviews.imfreedom.org/r/3964/

libpurple/purpleaccount.c file | annotate | diff | comparison | revisions
libpurple/purpleaccountmanager.c file | annotate | diff | comparison | revisions
libpurple/purpleconnection.c file | annotate | diff | comparison | revisions
libpurple/purpleconnection.h file | annotate | diff | comparison | revisions
libpurple/purplepresence.h file | annotate | diff | comparison | revisions
pidgin/pidginaccountmanagerrow.c file | annotate | diff | comparison | revisions
pidgin/pidgincontactlist.c file | annotate | diff | comparison | revisions
--- a/libpurple/purpleaccount.c	Mon Apr 21 23:41:59 2025 -0500
+++ b/libpurple/purpleaccount.c	Tue Apr 22 00:09:40 2025 -0500
@@ -69,6 +69,7 @@
 	char *protocol_id;
 	PurpleProtocol *protocol;
 
+	PurpleConnectionState connection_state;
 	PurpleConnection *gc;
 	gboolean disconnecting;
 
@@ -127,13 +128,29 @@
 {
 	g_return_if_fail(PURPLE_IS_ACCOUNT(account));
 
-	if(PURPLE_IS_CONNECTION(account->gc)) {
-		G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-		purple_connection_set_state(account->gc, connection_state);
-		G_GNUC_END_IGNORE_DEPRECATIONS
-
+	if(account->connection_state != connection_state) {
+		/* We set the property and notify right away so that the signal
+		 * handlers below will see the correct state.
+		 */
+		account->connection_state = connection_state;
 		g_object_notify_by_pspec(G_OBJECT(account),
 		                         properties[PROP_CONNECTION_STATE]);
+
+		if(connection_state == PURPLE_CONNECTION_STATE_CONNECTED) {
+			GDateTime *timestamp = NULL;
+
+			/* Set the time the account came online */
+			timestamp = g_date_time_new_now_utc();
+			purple_presence_set_login_time(account->presence, timestamp);
+			g_date_time_unref(timestamp);
+
+			g_signal_emit(account, signals[SIG_CONNECTED], 0);
+		} else if(connection_state == PURPLE_CONNECTION_STATE_DISCONNECTED) {
+			/* The user is no longer online, so clear their login time. */
+			purple_presence_set_login_time(account->presence, NULL);
+
+			g_signal_emit(account, signals[SIG_DISCONNECTED], 0);
+		}
 	}
 }
 
@@ -367,38 +384,6 @@
 	g_free(setting);
 }
 
-static PurpleConnectionState
-purple_account_get_state(PurpleAccount *account) {
-	PurpleConnection *gc;
-
-	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account),
-	                     PURPLE_CONNECTION_STATE_DISCONNECTED);
-
-	gc = purple_account_get_connection(account);
-	if(!gc) {
-		return PURPLE_CONNECTION_STATE_DISCONNECTED;
-	}
-
-	return purple_connection_get_state(gc);
-}
-
-static void
-purple_account_connection_state_cb(GObject *obj,
-                                   G_GNUC_UNUSED GParamSpec *pspec,
-                                   gpointer data)
-{
-	PurpleAccount *account = data;
-	PurpleConnection *connection = PURPLE_CONNECTION(obj);
-	PurpleConnectionState state = PURPLE_CONNECTION_STATE_DISCONNECTED;
-
-	state = purple_connection_get_state(connection);
-	if(state == PURPLE_CONNECTION_STATE_CONNECTED) {
-		g_signal_emit(account, signals[SIG_CONNECTED], 0);
-	} else if(state == PURPLE_CONNECTION_STATE_DISCONNECTED) {
-		g_signal_emit(account, signals[SIG_DISCONNECTED], 0);
-	}
-}
-
 static void
 purple_account_can_connect_cb(GObject *source, GAsyncResult *result,
                               gpointer data)
@@ -1017,8 +1002,7 @@
 	 * @account: The account whose setting changed.
 	 * @name: The name of the setting that changed.
 	 *
-	 * The ::setting-changed signal is emitted whenever an account setting is
-	 * changed.
+	 * This signal is emitted whenever an account setting is changed.
 	 *
 	 * This signal supports details, so you can be notified when a single
 	 * setting changes. For example, say there's a setting named `foo`,
@@ -1043,9 +1027,8 @@
 	 * PurpleAccount::connected:
 	 * @account: The account instance.
 	 *
-	 * This is emitted when the [property@Account:connection]'s
-	 * [property@Connection:state] has changed to
-	 * %PURPLE_CONNECTION_STATE_CONNECTED.
+	 * This signal is emitted when the [property@Account:connection-state] has
+	 * changed to %PURPLE_CONNECTION_STATE_CONNECTED.
 	 *
 	 * Since: 3.0
 	 */
@@ -1064,9 +1047,8 @@
 	 * PurpleAccount::disconnected:
 	 * @account: The account instance.
 	 *
-	 * This is emitted when the [property@Account:connection]'s
-	 * [property@Connection:state] has changed to
-	 * %PURPLE_CONNECTION_STATE_DISCONNECTED.
+	 * This signal is emitted when the [property@Account:connection-state] has
+	 * changed to %PURPLE_CONNECTION_STATE_DISCONNECTED.
 	 *
 	 * Since: 3.0
 	 */
@@ -1250,7 +1232,7 @@
 purple_account_is_disconnecting(PurpleAccount *account) {
 	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), TRUE);
 
-	return (purple_account_get_state(account) == PURPLE_CONNECTION_STATE_DISCONNECTING);
+	return (account->connection_state == PURPLE_CONNECTION_STATE_DISCONNECTING);
 }
 
 void
@@ -1352,38 +1334,9 @@
 purple_account_set_connection(PurpleAccount *account, PurpleConnection *gc) {
 	g_return_if_fail(PURPLE_IS_ACCOUNT(account));
 
-	/* If we got the same pointer, bail. */
-	if(account->gc == gc) {
-		return;
-	}
-
-	/* Remove our old signal handler. */
-	if(PURPLE_IS_CONNECTION(account->gc)) {
-		g_signal_handlers_disconnect_by_func(account->gc,
-		                                     purple_account_connection_state_cb,
-		                                     account);
-	}
-
 	if(g_set_object(&account->gc, gc)) {
-		GObject *obj = G_OBJECT(account);
-
-		if(PURPLE_IS_CONNECTION(account->gc)) {
-			g_signal_connect(account->gc, "notify::state",
-			                 G_CALLBACK(purple_account_connection_state_cb),
-			                 account);
-		}
-
-		g_object_freeze_notify(obj);
-		g_object_notify_by_pspec(obj, properties[PROP_CONNECTION]);
-		g_object_notify_by_pspec(obj, properties[PROP_CONNECTED]);
-		g_object_thaw_notify(obj);
-	} else {
-		/* If the set didn't work, restore our old signal. */
-		if(PURPLE_IS_CONNECTION(account->gc)) {
-			g_signal_connect(account->gc, "notify::state",
-			                 G_CALLBACK(purple_account_connection_state_cb),
-			                 account);
-		}
+		g_object_notify_by_pspec(G_OBJECT(account),
+		                         properties[PROP_CONNECTION]);
 	}
 }
 
@@ -1497,21 +1450,21 @@
 purple_account_is_connected(PurpleAccount *account) {
 	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
 
-	return (purple_account_get_state(account) == PURPLE_CONNECTION_STATE_CONNECTED);
+	return (account->connection_state == PURPLE_CONNECTION_STATE_CONNECTED);
 }
 
 gboolean
 purple_account_is_connecting(PurpleAccount *account) {
 	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
 
-	return (purple_account_get_state(account) == PURPLE_CONNECTION_STATE_CONNECTING);
+	return (account->connection_state == PURPLE_CONNECTION_STATE_CONNECTING);
 }
 
 gboolean
 purple_account_is_disconnected(PurpleAccount *account) {
 	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
 
-	return (purple_account_get_state(account) == PURPLE_CONNECTION_STATE_DISCONNECTED);
+	return (account->connection_state == PURPLE_CONNECTION_STATE_DISCONNECTED);
 }
 
 const char *
@@ -1561,11 +1514,7 @@
 	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account),
 	                     PURPLE_CONNECTION_STATE_DISCONNECTED);
 
-	if(PURPLE_IS_CONNECTION(account->gc)) {
-		return purple_connection_get_state(account->gc);
-	}
-
-	return PURPLE_CONNECTION_STATE_DISCONNECTED;
+	return account->connection_state;
 }
 
 PurpleConnection *
--- a/libpurple/purpleaccountmanager.c	Mon Apr 21 23:41:59 2025 -0500
+++ b/libpurple/purpleaccountmanager.c	Tue Apr 22 00:09:40 2025 -0500
@@ -607,12 +607,8 @@
 
 	for(guint index = 0; index < manager->accounts->len; index++) {
 		PurpleAccount *account = g_ptr_array_index(manager->accounts, index);
-		PurpleConnection *connection = NULL;
 
-		connection = purple_account_get_connection(account);
-		if(PURPLE_IS_CONNECTION(connection) &&
-		   PURPLE_CONNECTION_IS_CONNECTED(connection))
-		{
+		if(purple_account_is_connected(account)) {
 			connected = g_list_append(connected, account);
 		}
 	}
--- a/libpurple/purpleconnection.c	Mon Apr 21 23:41:59 2025 -0500
+++ b/libpurple/purpleconnection.c	Tue Apr 22 00:09:40 2025 -0500
@@ -41,8 +41,6 @@
 
 	PurpleProtocol *protocol;     /* The protocol.                     */
 
-	PurpleConnectionState state;  /* The connection state.             */
-
 	PurpleAccount *account;       /* The account being connected to.   */
 	char *password;               /* The password used.                */
 } PurpleConnectionPrivate;
@@ -52,7 +50,6 @@
 	PROP_ID,
 	PROP_CANCELLABLE,
 	PROP_PROTOCOL,
-	PROP_STATE,
 	PROP_ACCOUNT,
 	PROP_PASSWORD,
 	N_PROPERTIES,
@@ -76,49 +73,6 @@
  * d8D->-< DANCE!
  */
 
-void
-purple_connection_set_state(PurpleConnection *connection,
-                            PurpleConnectionState state)
-{
-	PurpleConnectionPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_CONNECTION(connection));
-
-	priv = purple_connection_get_instance_private(connection);
-
-	if(priv->state == state) {
-		return;
-	}
-
-	priv->state = state;
-
-	if(priv->state == PURPLE_CONNECTION_STATE_CONNECTED) {
-		PurplePresence *presence;
-		GDateTime *timestamp = NULL;
-
-		presence = purple_account_get_presence(priv->account);
-
-		/* Set the time the account came online */
-		timestamp = g_date_time_new_now_utc();
-		purple_presence_set_login_time(presence, timestamp);
-		g_date_time_unref(timestamp);
-	}
-
-	g_object_notify_by_pspec(G_OBJECT(connection), properties[PROP_STATE]);
-}
-
-PurpleConnectionState
-purple_connection_get_state(PurpleConnection *connection) {
-	PurpleConnectionPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_CONNECTION(connection),
-	                     PURPLE_CONNECTION_STATE_DISCONNECTED);
-
-	priv = purple_connection_get_instance_private(connection);
-
-	return priv->state;
-}
-
 PurpleAccount *
 purple_connection_get_account(PurpleConnection *connection) {
 	PurpleConnectionPrivate *priv = NULL;
@@ -255,11 +209,6 @@
 	case PROP_PROTOCOL:
 		priv->protocol = g_value_get_object(value);
 		break;
-	case PROP_STATE:
-		G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-		purple_connection_set_state(connection, g_value_get_enum(value));
-		G_GNUC_END_IGNORE_DEPRECATIONS
-		break;
 	case PROP_ACCOUNT:
 		purple_connection_set_account(connection, g_value_get_object(value));
 		break;
@@ -289,9 +238,6 @@
 	case PROP_PROTOCOL:
 		g_value_set_object(value, purple_connection_get_protocol(connection));
 		break;
-	case PROP_STATE:
-		g_value_set_enum(value, purple_connection_get_state(connection));
-		break;
 	case PROP_ACCOUNT:
 		g_value_set_object(value, purple_connection_get_account(connection));
 		break;
@@ -311,10 +257,6 @@
 	priv = purple_connection_get_instance_private(connection);
 
 	priv->cancellable = g_cancellable_new();
-
-	G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-	purple_connection_set_state(connection, PURPLE_CONNECTION_STATE_CONNECTING);
-	G_GNUC_END_IGNORE_DEPRECATIONS
 }
 
 static void
@@ -412,18 +354,6 @@
 		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
 
 	/**
-	 * PurpleConnection:state:
-	 *
-	 * The state of the connection.
-	 *
-	 * Since: 3.0
-	 */
-	properties[PROP_STATE] = g_param_spec_enum(
-		"state", NULL, NULL,
-		PURPLE_TYPE_CONNECTION_STATE, PURPLE_CONNECTION_STATE_DISCONNECTED,
-		G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
-
-	/**
 	 * PurpleConnection:account:
 	 *
 	 * The account this connection belongs to.
@@ -461,9 +391,9 @@
 
 	priv = purple_connection_get_instance_private(connection);
 
-	if(!purple_account_is_disconnected(priv->account)) {
+	if(!purple_account_is_connecting(priv->account)) {
 		g_set_error(error, PURPLE_CONNECTION_ERROR, 0,
-		            "account %s is not disconnected",
+		            "account %s is not in a connecting state",
 		            purple_account_get_username(priv->account));
 
 		return TRUE;
@@ -510,10 +440,6 @@
 	priv = purple_connection_get_instance_private(connection);
 
 	purple_debug_info("connection", "Disconnecting connection %p", connection);
-	G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-	purple_connection_set_state(connection,
-	                            PURPLE_CONNECTION_STATE_DISCONNECTING);
-	G_GNUC_END_IGNORE_DEPRECATIONS
 
 	/* Dispatch to the connection's disconnect method. */
 	klass = PURPLE_CONNECTION_GET_CLASS(connection);
@@ -521,11 +447,6 @@
 		ret = klass->disconnect(connection, error);
 	}
 
-	G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-	purple_connection_set_state(connection,
-	                            PURPLE_CONNECTION_STATE_DISCONNECTED);
-	G_GNUC_END_IGNORE_DEPRECATIONS
-
 	purple_account_request_close_with_account(priv->account);
 	purple_request_close_with_handle(connection);
 
--- a/libpurple/purpleconnection.h	Mon Apr 21 23:41:59 2025 -0500
+++ b/libpurple/purpleconnection.h	Tue Apr 22 00:09:40 2025 -0500
@@ -178,8 +178,7 @@
  * @error: Return address for a #GError, or %NULL.
  *
  * Tells the connection to connect. This is done by calling the
- * [vfunc@Purple.Connection.connect] function. State is managed by this
- * function.
+ * [vfunc@Purple.Connection.connect] function.
  *
  * Due to the asynchronous nature of network connections, the return value and
  * @error are to be used to do some initial validation before a connection is
@@ -211,47 +210,6 @@
 gboolean purple_connection_disconnect(PurpleConnection *connection, GError **error);
 
 /**
- * purple_connection_set_state:
- * @connection: The connection.
- * @state: The connection state.
- *
- * Sets the connection state.  Protocols should call this and pass in
- * the state #PURPLE_CONNECTION_CONNECTED when the account is completely
- * signed on.  What does it mean to be completely signed on?  If
- * the core can call protocol's set_status, and it successfully changes
- * your status, then the account is online.
- *
- * Since: 2.0
- */
-PURPLE_DEPRECATED_FOR(purple_account_connected)
-void purple_connection_set_state(PurpleConnection *connection, PurpleConnectionState state);
-
-/**
- * purple_connection_get_state:
- * @connection: The connection.
- *
- * Gets the connection state.
- *
- * Returns: The connection state.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleConnectionState purple_connection_get_state(PurpleConnection *connection);
-
-/**
- * PURPLE_CONNECTION_IS_CONNECTED:
- *
- * Returns TRUE if the account is connected, otherwise returns FALSE.
- *
- * Returns: TRUE if the account is connected, otherwise returns FALSE.
- *
- * Since: 2.0
- */
-#define PURPLE_CONNECTION_IS_CONNECTED(connection) \
-	(purple_connection_get_state(connection) == PURPLE_CONNECTION_STATE_CONNECTED)
-
-/**
  * purple_connection_get_id:
  * @connection: The connection.
  *
--- a/libpurple/purplepresence.h	Mon Apr 21 23:41:59 2025 -0500
+++ b/libpurple/purplepresence.h	Tue Apr 22 00:09:40 2025 -0500
@@ -133,7 +133,7 @@
 /**
  * purple_presence_set_login_time:
  * @presence: The #PurplePresence instance.
- * @login_time: (transfer none): The login time.
+ * @login_time: (transfer none) (nullable): The login time.
  *
  * Sets the login time on a presence.
  *
--- a/pidgin/pidginaccountmanagerrow.c	Mon Apr 21 23:41:59 2025 -0500
+++ b/pidgin/pidginaccountmanagerrow.c	Tue Apr 22 00:09:40 2025 -0500
@@ -69,25 +69,20 @@
 				status = error->message;
 				errored = TRUE;
 			} else {
-				PurpleConnection *connection = NULL;
-
-				connection = purple_account_get_connection(row->account);
-				if(PURPLE_IS_CONNECTION(connection)) {
-					switch(purple_connection_get_state(connection)) {
-						case PURPLE_CONNECTION_STATE_DISCONNECTED:
-							status = _("Disconnected");
-							break;
-						case PURPLE_CONNECTION_STATE_DISCONNECTING:
-							status = _("Disconnecting...");
-							break;
-						case PURPLE_CONNECTION_STATE_CONNECTED:
-							status = _("Connected");
-							connected = TRUE;
-							break;
-						case PURPLE_CONNECTION_STATE_CONNECTING:
-							status = _("Connecting...");
-							break;
-					}
+				switch(purple_account_get_connection_state(row->account)) {
+				case PURPLE_CONNECTION_STATE_DISCONNECTED:
+					status = _("Disconnected");
+					break;
+				case PURPLE_CONNECTION_STATE_DISCONNECTING:
+					status = _("Disconnecting...");
+					break;
+				case PURPLE_CONNECTION_STATE_CONNECTED:
+					status = _("Connected");
+					connected = TRUE;
+					break;
+				case PURPLE_CONNECTION_STATE_CONNECTING:
+					status = _("Connecting...");
+					break;
 				}
 			}
 		}
--- a/pidgin/pidgincontactlist.c	Mon Apr 21 23:41:59 2025 -0500
+++ b/pidgin/pidgincontactlist.c	Tue Apr 22 00:09:40 2025 -0500
@@ -61,21 +61,13 @@
 	 * but it doesn't hurt to check.
 	 */
 	if(PURPLE_IS_CONTACT(info)) {
-		PurpleConnection *connection = NULL;
 		PurpleContact *contact = PURPLE_CONTACT(info);
 		PurpleAccount *account = NULL;
 
 		account = purple_contact_get_account(contact);
-		connection = purple_account_get_connection(account);
-
-		if(PURPLE_IS_CONNECTION(connection)) {
-			PurpleConnectionState state = PURPLE_CONNECTION_STATE_DISCONNECTED;
-
-			state = purple_connection_get_state(connection);
-
-			return (state == PURPLE_CONNECTION_STATE_CONNECTED);
+		if(purple_account_is_connected(account)) {
+			return TRUE;
 		}
-
 	}
 
 	return FALSE;

mercurial