# HG changeset patch
# Node ID 1553a0ca5e36
# Parent  72178a341eb8
diff --git a/ChangeLog.API b/ChangeLog.API
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -342,6 +342,7 @@
 		* purple_accounts_get_ui_ops
 		* purple_accounts_remove
 		* purple_accounts_reorder
+		* purple_accounts_restore_current_statuses
 		* purple_accounts_set_ui_ops
 		* PurpleAttentionType
 		* purple_attention_type_set_name
diff --git a/finch/libfinch.c b/finch/libfinch.c
--- a/finch/libfinch.c
+++ b/finch/libfinch.c
@@ -181,8 +181,7 @@
 	/* load plugins we had when we quit */
 	purple_plugins_load_saved("/finch/plugins/loaded");
 
-	if (opt_nologin)
-	{
+	if(opt_nologin) {
 		/* Set all accounts to "offline" */
 		PurpleSavedStatus *saved_status;
 
@@ -196,13 +195,16 @@
 
 		/* Set the status for each account */
 		purple_savedstatus_activate(saved_status);
-	}
-	else
-	{
+	} else {
+		PurpleAccountManager *manager = NULL;
+
 		/* Everything is good to go--sign on already */
-		if (!purple_prefs_get_bool("/purple/savedstatus/startup_current_status"))
+		if(!purple_prefs_get_bool("/purple/savedstatus/startup_current_status")) {
 			purple_savedstatus_activate(purple_savedstatus_get_startup());
-		purple_accounts_restore_current_statuses();
+		}
+
+		manager = purple_account_manager_get_default();
+		purple_account_manager_set_online(manager, TRUE);
 	}
 
 	return 1;
diff --git a/libpurple/accounts.h b/libpurple/accounts.h
--- a/libpurple/accounts.h
+++ b/libpurple/accounts.h
@@ -51,22 +51,6 @@
 PURPLE_AVAILABLE_IN_ALL
 void purple_accounts_delete(PurpleAccount *account);
 
-/**
- * purple_accounts_restore_current_statuses:
- *
- * This is called by the core after all subsystems and what
- * not have been initialized.  It sets all enabled accounts
- * to their startup status by signing them on, setting them
- * away, etc.
- *
- * You probably shouldn't call this unless you really know
- * what you're doing.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_accounts_restore_current_statuses(void);
-
 /**************************************************************************/
 /* Accounts Subsystem                                                     */
 /**************************************************************************/
diff --git a/libpurple/accounts.c b/libpurple/accounts.c
--- a/libpurple/accounts.c
+++ b/libpurple/accounts.c
@@ -43,7 +43,10 @@
                                    G_GNUC_UNUSED gpointer data)
 {
 	if(available) {
-		purple_accounts_restore_current_statuses();
+		PurpleAccountManager *manager = NULL;
+
+		manager = purple_account_manager_get_default();
+		purple_account_manager_set_online(manager, TRUE);
 	}
 }
 
@@ -573,36 +576,6 @@
 	                                               g_object_ref(account));
 }
 
-static void
-purple_accounts_restore_current_status(PurpleAccount *account,
-                                       G_GNUC_UNUSED gpointer data) {
-	gboolean enabled = FALSE, online = FALSE;
-
-	enabled = purple_account_get_enabled(account);
-	online = purple_presence_is_online(purple_account_get_presence(account));
-
-	if(enabled && online) {
-		purple_account_connect(account);
-	}
-}
-
-void
-purple_accounts_restore_current_statuses(void) {
-	PurpleAccountManager *manager = NULL;
-
-	/* If we're not connected to the Internet right now, we bail on this */
-	if (!purple_network_is_available()) {
-		g_warning("Network not connected; skipping reconnect");
-
-		return;
-	}
-
-	manager = purple_account_manager_get_default();
-	purple_account_manager_foreach(manager,
-	                               purple_accounts_restore_current_status,
-	                               NULL);
-}
-
 void *
 purple_accounts_get_handle(void)
 {
diff --git a/libpurple/purpleaccountmanager.h b/libpurple/purpleaccountmanager.h
--- a/libpurple/purpleaccountmanager.h
+++ b/libpurple/purpleaccountmanager.h
@@ -222,6 +222,32 @@
 PURPLE_AVAILABLE_IN_3_0
 void purple_account_manager_foreach(PurpleAccountManager *manager, PurpleAccountManagerForeachFunc callback, gpointer data);
 
+/**
+ * purple_account_manager_get_online:
+ * @manager: The instance.
+ *
+ * Gets whether or not new accounts should automatically have
+ * [method@Account.connect] called for them.
+ *
+ * Returns: %TRUE if @manager is online, otherwise %FALSE.
+ *
+ * Since: 3.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+gboolean purple_account_manager_get_online(PurpleAccountManager *manager);
+
+/**
+ * purple_account_manager_set_online:
+ * @manager: The instance.
+ *
+ * Sets whether or not new accounts should automatically have
+ * [method@Account.connect] called for them.
+ *
+ * Since: 3.0.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+void purple_account_manager_set_online(PurpleAccountManager *manager, gboolean online);
+
 G_END_DECLS
 
 #endif /* PURPLE_ACCOUNT_MANAGER_H */
diff --git a/libpurple/purpleaccountmanager.c b/libpurple/purpleaccountmanager.c
--- a/libpurple/purpleaccountmanager.c
+++ b/libpurple/purpleaccountmanager.c
@@ -28,6 +28,13 @@
 #include "purpleaccount.h"
 
 enum {
+	PROP_0,
+	PROP_ONLINE,
+	N_PROPERTIES,
+};
+static GParamSpec *properties[N_PROPERTIES] = {NULL, };
+
+enum {
 	SIG_ADDED,
 	SIG_REMOVED,
 	SIG_ACCOUNT_CHANGED,
@@ -41,6 +48,7 @@
 struct _PurpleAccountManager {
 	GObject parent;
 
+	gboolean online;
 	GPtrArray *accounts;
 };
 
@@ -142,7 +150,41 @@
 }
 
 static void
+purple_account_manager_get_property(GObject *obj, guint param_id,
+                                    GValue *value, GParamSpec *pspec)
+{
+	PurpleAccountManager *manager = PURPLE_ACCOUNT_MANAGER(obj);
+
+	switch(param_id) {
+	case PROP_ONLINE:
+		g_value_set_boolean(value, purple_account_manager_get_online(manager));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+		break;
+	}
+}
+
+static void
+purple_account_manager_set_property(GObject *obj, guint param_id,
+                                    const GValue *value, GParamSpec *pspec)
+{
+	PurpleAccountManager *manager = PURPLE_ACCOUNT_MANAGER(obj);
+
+	switch(param_id) {
+	case PROP_ONLINE:
+		purple_account_manager_set_online(manager, g_value_get_boolean(value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+		break;
+	}
+}
+
+static void
 purple_account_manager_init(PurpleAccountManager *manager) {
+	manager->online = FALSE;
+
 	manager->accounts = g_ptr_array_new_full(0, (GDestroyNotify)g_object_unref);
 }
 
@@ -151,6 +193,33 @@
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
 	obj_class->finalize = purple_account_manager_finalize;
+	obj_class->get_property = purple_account_manager_get_property;
+	obj_class->set_property = purple_account_manager_set_property;
+
+	/**
+	 * PurpleAccountManager:online:
+	 *
+	 * Controls whether or not accounts that the manager knows about should be
+	 * online of offline.
+	 *
+	 * While this is set to %TRUE, any account added via
+	 * [method@AccountManager.add] that has [property@Account:enabled] set to
+	 * %TRUE, will automatically have [method@Account.connect] called on it.
+	 *
+	 * When this property changes, all accounts that the manager knows about
+	 * with [property@Account:enabled] set to %TRUE will have
+	 * [method@Account.connect] or [method@Account.disconnect] called on them
+	 * to keep their state synchronized.
+	 *
+	 * Since: 3.0
+	 */
+	properties[PROP_ONLINE] = g_param_spec_boolean(
+		"online", "online",
+		"Whether or not known accounts are online or offline.",
+		FALSE,
+		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
 
 	/**
 	 * PurpleAccountManager::added:
@@ -370,6 +439,10 @@
 
 	g_signal_emit(manager, signals[SIG_ADDED], 0, account);
 	g_list_model_items_changed(G_LIST_MODEL(manager), 0, 0, 1);
+
+	if(manager->online) {
+		purple_account_connect(account);
+	}
 }
 
 void
@@ -596,3 +669,56 @@
 		callback(account, data);
 	}
 }
+
+gboolean
+purple_account_manager_get_online(PurpleAccountManager *manager) {
+	g_return_val_if_fail(PURPLE_IS_ACCOUNT_MANAGER(manager), FALSE);
+
+	return manager->online;
+}
+
+void
+purple_account_manager_set_online(PurpleAccountManager *manager,
+                                  gboolean online)
+{
+	g_return_if_fail(PURPLE_IS_ACCOUNT_MANAGER(manager));
+
+	if(manager->online == online) {
+		return;
+	}
+
+	manager->online = online;
+
+	for(guint index = 0; index < manager->accounts->len; index++) {
+		PurpleAccount *account = g_ptr_array_index(manager->accounts, index);
+		PurplePresence *presence = NULL;
+		gboolean enabled = FALSE;
+		gboolean online = FALSE;
+
+		enabled = purple_account_get_enabled(account);
+		if(!enabled) {
+			continue;
+		}
+
+		if(manager->online) {
+			if(!purple_account_is_connected(account) &&
+			   !purple_account_is_connecting(account))
+			{
+				presence = purple_account_get_presence(account);
+				online = purple_presence_is_online(presence);
+
+				if(online) {
+					purple_account_connect(account);
+				}
+			}
+		} else if (!manager->online) {
+			if(!purple_account_is_disconnected(account) &&
+			   !purple_account_is_disconnecting(account))
+			{
+				purple_account_disconnect(account);
+			}
+		}
+	}
+
+	g_object_notify_by_pspec(G_OBJECT(manager), properties[PROP_ONLINE]);
+}
diff --git a/pidgin/pidginapplication.c b/pidgin/pidginapplication.c
--- a/pidgin/pidginapplication.c
+++ b/pidgin/pidginapplication.c
@@ -863,6 +863,8 @@
 		pidgin_debug_window_show();
 	}
 
+	manager = purple_account_manager_get_default();
+
 	if(opt_nologin) {
 		/* Set all accounts to "offline" */
 		PurpleSavedStatus *saved_status;
@@ -884,10 +886,9 @@
 			purple_savedstatus_activate(purple_savedstatus_get_startup());
 		}
 
-		purple_accounts_restore_current_statuses();
+		purple_account_manager_set_online(manager, TRUE);
 	}
 
-	manager = purple_account_manager_get_default();
 	active_accounts = purple_account_manager_get_enabled(manager);
 	if(active_accounts == NULL) {
 		g_action_group_activate_action(G_ACTION_GROUP(application),
