Tue, 22 Apr 2025 00:09:40 -0500
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/
--- 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;