gobjectification: 947b2f5f: Save accounts from the account-manager, ...
sadrul at pidgin.im
sadrul at pidgin.im
Sun Jun 22 14:42:00 EDT 2008
-----------------------------------------------------------------
Revision: 947b2f5f15d0fd8c782d89718d5c5e7d1b96cabd
Ancestor: 25a7956a58e2d73e89d4e5fb686847e93f8c993d
Author: sadrul at pidgin.im
Date: 2008-06-22T16:59:06
Branch: im.pidgin.gobjectification
URL: http://d.pidgin.im/viewmtn/revision/info/947b2f5f15d0fd8c782d89718d5c5e7d1b96cabd
Modified files:
libpurple/account.c libpurple/account.h
libpurple/accountmanager.c libpurple/accountmanager.h
ChangeLog:
Save accounts from the account-manager, and a 'settings-changed' detailed
signal for account settings.
Currently I am using the same signal for ui-settings too. Do we want a
new signal for that, or do we want to merge the two kind of settings?
-------------- next part --------------
============================================================
--- libpurple/account.c 193239c73aed0dc6179cc31f751654278eade88e
+++ libpurple/account.c d292477a5b8f3c09a4ba8e0d7947d853c3a49979
@@ -83,17 +83,16 @@ static PurpleAccountUiOps *account_ui_op
static PurpleAccountUiOps *account_ui_ops = NULL;
-static guint save_timer = 0;
-static gboolean accounts_loaded = FALSE;
-
static GList *handles = NULL;
static void set_current_error(PurpleAccount *account,
PurpleConnectionErrorInfo *new_err);
-/*********************************************************************
- * Writing to disk *
- *********************************************************************/
+static void
+schedule_accounts_save(void)
+{
+#warning Remove this when it's no longer needed
+}
static void
setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data)
@@ -356,129 +355,7 @@ current_error_to_xmlnode(PurpleConnectio
return node;
}
-static xmlnode *
-account_to_xmlnode(PurpleAccount *account)
-{
- PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
-
- xmlnode *node, *child;
- const char *tmp;
- PurplePresence *presence;
- PurpleProxyInfo *proxy_info;
-
- node = xmlnode_new("account");
-
- child = xmlnode_new_child(node, "protocol");
- xmlnode_insert_data(child, purple_account_get_protocol_id(account), -1);
-
- child = xmlnode_new_child(node, "name");
- xmlnode_insert_data(child, purple_account_get_username(account), -1);
-
- if (purple_account_get_remember_password(account) &&
- ((tmp = purple_account_get_password(account)) != NULL))
- {
- child = xmlnode_new_child(node, "password");
- xmlnode_insert_data(child, tmp, -1);
- }
-
- if ((tmp = purple_account_get_alias(account)) != NULL)
- {
- child = xmlnode_new_child(node, "alias");
- xmlnode_insert_data(child, tmp, -1);
- }
-
- if ((presence = purple_account_get_presence(account)) != NULL)
- {
- child = statuses_to_xmlnode(presence);
- xmlnode_insert_child(node, child);
- }
-
- if ((tmp = purple_account_get_user_info(account)) != NULL)
- {
- /* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */
- child = xmlnode_new_child(node, "userinfo");
- xmlnode_insert_data(child, tmp, -1);
- }
-
- if (g_hash_table_size(account->settings) > 0)
- {
- child = xmlnode_new_child(node, "settings");
- g_hash_table_foreach(account->settings, setting_to_xmlnode, child);
- }
-
- if (g_hash_table_size(account->ui_settings) > 0)
- {
- g_hash_table_foreach(account->ui_settings, ui_setting_to_xmlnode, node);
- }
-
- if ((proxy_info = purple_account_get_proxy_info(account)) != NULL)
- {
- child = proxy_settings_to_xmlnode(proxy_info);
- xmlnode_insert_child(node, child);
- }
-
- child = current_error_to_xmlnode(priv->current_error);
- xmlnode_insert_child(node, child);
-
- return node;
-}
-
-static xmlnode *
-accounts_to_xmlnode(void)
-{
- xmlnode *node, *child;
- GList *cur;
-
- node = xmlnode_new("account");
- xmlnode_set_attrib(node, "version", "1.0");
-
- for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next)
- {
- child = account_to_xmlnode(cur->data);
- xmlnode_insert_child(node, child);
- }
-
- return node;
-}
-
static void
-sync_accounts(void)
-{
- xmlnode *node;
- char *data;
-
- if (!accounts_loaded)
- {
- purple_debug_error("account", "Attempted to save accounts before "
- "they were read!\n");
- return;
- }
-
- node = accounts_to_xmlnode();
- data = xmlnode_to_formatted_str(node, NULL);
- purple_util_write_data_to_file("accounts.xml", data, -1);
- g_free(data);
- xmlnode_free(node);
-}
-
-static gboolean
-save_cb(gpointer data)
-{
- sync_accounts();
- save_timer = 0;
- return FALSE;
-}
-
-static void
-schedule_accounts_save(void)
-{
-#warning Saving should really be moved to the account manager
- if (save_timer == 0)
- save_timer = purple_timeout_add_seconds(5, save_cb, NULL);
-}
-
-
-static void
delete_setting(void *data)
{
PurpleAccountSetting *setting = (PurpleAccountSetting *)data;
@@ -523,6 +400,7 @@ enum
enum
{
SIG_SETTING_INFO,
+ SIG_SETTINGS_CHANGED,
SIG_LAST
};
static guint signals[SIG_LAST] = { 0, };
@@ -629,6 +507,12 @@ purple_account_finalize(GObject *object)
/* Make sure we disconnect first */
purple_account_set_connection(account, NULL);
+ /* Clearing the error ensures that account-error-changed is emitted,
+ * which is the end of the guarantee that the the error's pointer is
+ * valid.
+ */
+ purple_account_clear_current_error(account);
+
for (l = purple_get_conversations(); l != NULL; l = l->next) {
PurpleConversation *conv = (PurpleConversation *)l->data;
@@ -719,7 +603,12 @@ static void purple_account_class_init(Pu
);
/* Setup signals */
-#warning TODO: Setup signals
+ signals[SIG_SETTINGS_CHANGED] =
+ g_signal_new("settings-changed", G_OBJECT_CLASS_TYPE(klass),
+ G_SIGNAL_ACTION | G_SIGNAL_DETAILED, 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+#warning TODO: Setup more signals
}
GType purple_account_get_gtype(void)
@@ -1270,8 +1159,6 @@ purple_account_set_username(PurpleAccoun
account->username = g_strdup(username);
g_object_notify(G_OBJECT(account), PROP_USERNAME_S);
- schedule_accounts_save();
-
/* if the name changes, we should re-write the buddy list
* to disk with the new name */
purple_blist_schedule_save();
@@ -1288,8 +1175,6 @@ purple_account_set_password(PurpleAccoun
g_free(account->password);
account->password = g_strdup(password);
g_object_notify(G_OBJECT(account), PROP_PASSWORD_S);
-
- schedule_accounts_save();
}
void
@@ -1311,7 +1196,6 @@ purple_account_set_alias(PurpleAccount *
purple_signal_emit(purple_accounts_get_handle(), "account-alias-changed",
account, old);
#endif
- schedule_accounts_save();
}
void
@@ -1420,8 +1304,6 @@ purple_account_set_enabled(PurpleAccount
purple_account_connect(account);
else if (!value && !purple_account_is_disconnected(account))
purple_account_disconnect(account);
-
- schedule_accounts_save();
}
void
@@ -1511,9 +1393,43 @@ purple_account_clear_settings(PurpleAcco
g_hash_table_destroy(account->settings);
account->settings = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, delete_setting);
+ g_free, delete_setting);
}
+static gboolean
+account_setting_value_changed(PurpleAccount *account, const char *name,
+ GType type, ...)
+{
+ va_list args;
+ PurpleAccountSetting *setting;
+ gboolean changed = TRUE;
+
+ setting = g_hash_table_lookup(account->settings, name);
+ if (!setting)
+ return TRUE; /* This is a new setting */
+
+ va_start(args, type);
+ switch (type) {
+ case G_TYPE_STRING: {
+ const char *string = va_arg(args, const char *);
+ changed = (g_utf8_collate(string, setting->value.string) != 0);
+ break;
+ }
+ case G_TYPE_INT: {
+ int value = va_arg(args, int);
+ changed = (value != setting->value.integer);
+ break;
+ }
+ case G_TYPE_BOOLEAN: {
+ gboolean value = va_arg(args, gboolean);
+ changed = (value != setting->value.boolean);
+ break;
+ }
+ }
+ va_end(args);
+ return changed;
+}
+
void
purple_account_set_int(PurpleAccount *account, const char *name, int value)
{
@@ -1522,14 +1438,17 @@ purple_account_set_int(PurpleAccount *ac
g_return_if_fail(PURPLE_IS_ACCOUNT(account));
g_return_if_fail(name != NULL);
+ if (!account_setting_value_changed(account, name, G_TYPE_INT, value))
+ return;
+
setting = g_new0(PurpleAccountSetting, 1);
setting->type = PURPLE_PREF_INT;
setting->value.integer = value;
g_hash_table_insert(account->settings, g_strdup(name), setting);
-
- schedule_accounts_save();
+ g_signal_emit(G_OBJECT(account), signals[SIG_SETTINGS_CHANGED],
+ g_quark_from_string(name));
}
void
@@ -1541,6 +1460,9 @@ purple_account_set_string(PurpleAccount
g_return_if_fail(PURPLE_IS_ACCOUNT(account));
g_return_if_fail(name != NULL);
+ if (!account_setting_value_changed(account, name, G_TYPE_STRING, value))
+ return;
+
setting = g_new0(PurpleAccountSetting, 1);
setting->type = PURPLE_PREF_STRING;
@@ -1548,7 +1470,8 @@ purple_account_set_string(PurpleAccount
g_hash_table_insert(account->settings, g_strdup(name), setting);
- schedule_accounts_save();
+ g_signal_emit(G_OBJECT(account), signals[SIG_SETTINGS_CHANGED],
+ g_quark_from_string(name));
}
void
@@ -1559,6 +1482,9 @@ purple_account_set_bool(PurpleAccount *a
g_return_if_fail(PURPLE_IS_ACCOUNT(account));
g_return_if_fail(name != NULL);
+ if (!account_setting_value_changed(account, name, G_TYPE_BOOLEAN, value))
+ return;
+
setting = g_new0(PurpleAccountSetting, 1);
setting->type = PURPLE_PREF_BOOLEAN;
@@ -1566,7 +1492,8 @@ purple_account_set_bool(PurpleAccount *a
g_hash_table_insert(account->settings, g_strdup(name), setting);
- schedule_accounts_save();
+ g_signal_emit(G_OBJECT(account), signals[SIG_SETTINGS_CHANGED],
+ g_quark_from_string(name));
}
static GHashTable *
@@ -1585,17 +1512,57 @@ get_ui_settings_table(PurpleAccount *acc
return table;
}
+static gboolean
+account_ui_setting_value_changed(PurpleAccount *account, const char *ui,
+ const char *name, GType type, ...)
+{
+ va_list args;
+ PurpleAccountSetting *setting;
+ gboolean changed = TRUE;
+ GHashTable *table;
+
+ table = get_ui_settings_table(account, ui);
+ setting = table ? g_hash_table_lookup(table, name) : NULL;
+ if (!setting)
+ return TRUE; /* This is a new setting */
+
+ va_start(args, type);
+ switch (type) {
+ case G_TYPE_STRING: {
+ const char *string = va_arg(args, const char *);
+ changed = (g_utf8_collate(string, setting->value.string) != 0);
+ break;
+ }
+ case G_TYPE_INT: {
+ int value = va_arg(args, int);
+ changed = (value != setting->value.integer);
+ break;
+ }
+ case G_TYPE_BOOLEAN: {
+ gboolean value = va_arg(args, gboolean);
+ changed = (value != setting->value.boolean);
+ break;
+ }
+ }
+ va_end(args);
+ return changed;
+}
+
void
purple_account_set_ui_int(PurpleAccount *account, const char *ui,
const char *name, int value)
{
PurpleAccountSetting *setting;
GHashTable *table;
+ char *uiname;
g_return_if_fail(PURPLE_IS_ACCOUNT(account));
g_return_if_fail(ui != NULL);
g_return_if_fail(name != NULL);
+ if (!account_ui_setting_value_changed(account, ui, name, G_TYPE_INT, value))
+ return;
+
setting = g_new0(PurpleAccountSetting, 1);
setting->type = PURPLE_PREF_INT;
@@ -1606,7 +1573,11 @@ purple_account_set_ui_int(PurpleAccount
g_hash_table_insert(table, g_strdup(name), setting);
- schedule_accounts_save();
+ /* XXX: Or do want a seperate ui-settings-changed signal? */
+ uiname = g_strconcat("ui:", name, NULL);
+ g_signal_emit(G_OBJECT(account), signals[SIG_SETTINGS_CHANGED],
+ g_quark_from_string(uiname));
+ g_free(uiname);
}
void
@@ -1615,11 +1586,15 @@ purple_account_set_ui_string(PurpleAccou
{
PurpleAccountSetting *setting;
GHashTable *table;
+ char *uiname;
g_return_if_fail(PURPLE_IS_ACCOUNT(account));
g_return_if_fail(ui != NULL);
g_return_if_fail(name != NULL);
+ if (!account_ui_setting_value_changed(account, ui, name, G_TYPE_STRING, value))
+ return;
+
setting = g_new0(PurpleAccountSetting, 1);
setting->type = PURPLE_PREF_STRING;
@@ -1630,7 +1605,11 @@ purple_account_set_ui_string(PurpleAccou
g_hash_table_insert(table, g_strdup(name), setting);
- schedule_accounts_save();
+ /* XXX: Or do want a seperate ui-settings-changed signal? */
+ uiname = g_strconcat("ui:", name, NULL);
+ g_signal_emit(G_OBJECT(account), signals[SIG_SETTINGS_CHANGED],
+ g_quark_from_string(uiname));
+ g_free(uiname);
}
void
@@ -1639,11 +1618,15 @@ purple_account_set_ui_bool(PurpleAccount
{
PurpleAccountSetting *setting;
GHashTable *table;
+ char *uiname;
g_return_if_fail(PURPLE_IS_ACCOUNT(account));
g_return_if_fail(ui != NULL);
g_return_if_fail(name != NULL);
+ if (!account_ui_setting_value_changed(account, ui, name, G_TYPE_BOOLEAN, value))
+ return;
+
setting = g_new0(PurpleAccountSetting, 1);
setting->type = PURPLE_PREF_BOOLEAN;
@@ -1659,7 +1642,11 @@ purple_account_set_ui_bool(PurpleAccount
purple_account_set_enabled(account, value);
}
- schedule_accounts_save();
+ /* XXX: Or do want a seperate ui-settings-changed signal? */
+ uiname = g_strconcat("ui:", name, NULL);
+ g_signal_emit(G_OBJECT(account), signals[SIG_SETTINGS_CHANGED],
+ g_quark_from_string(uiname));
+ g_free(uiname);
}
static PurpleConnectionState
@@ -2260,14 +2247,81 @@ purple_account_clear_current_error(Purpl
set_current_error(account, NULL);
}
+xmlnode * purple_account_to_xmlnode(PurpleAccount *account)
+{
+ PurpleAccountPrivate *priv;
+ xmlnode *node, *child;
+ const char *tmp;
+ PurplePresence *presence;
+ PurpleProxyInfo *proxy_info;
+
+ g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
+
+ priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
+
+ node = xmlnode_new("account");
+
+ child = xmlnode_new_child(node, "protocol");
+ xmlnode_insert_data(child, purple_account_get_protocol_id(account), -1);
+
+ child = xmlnode_new_child(node, "name");
+ xmlnode_insert_data(child, purple_account_get_username(account), -1);
+
+ if (purple_account_get_remember_password(account) &&
+ ((tmp = purple_account_get_password(account)) != NULL))
+ {
+ child = xmlnode_new_child(node, "password");
+ xmlnode_insert_data(child, tmp, -1);
+ }
+
+ if ((tmp = purple_account_get_alias(account)) != NULL)
+ {
+ child = xmlnode_new_child(node, "alias");
+ xmlnode_insert_data(child, tmp, -1);
+ }
+
+ if ((presence = purple_account_get_presence(account)) != NULL)
+ {
+ child = statuses_to_xmlnode(presence);
+ xmlnode_insert_child(node, child);
+ }
+
+ if ((tmp = purple_account_get_user_info(account)) != NULL)
+ {
+ /* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */
+ child = xmlnode_new_child(node, "userinfo");
+ xmlnode_insert_data(child, tmp, -1);
+ }
+
+ if (g_hash_table_size(account->settings) > 0)
+ {
+ child = xmlnode_new_child(node, "settings");
+ g_hash_table_foreach(account->settings, setting_to_xmlnode, child);
+ }
+
+ if (g_hash_table_size(account->ui_settings) > 0)
+ {
+ g_hash_table_foreach(account->ui_settings, ui_setting_to_xmlnode, node);
+ }
+
+ if ((proxy_info = purple_account_get_proxy_info(account)) != NULL)
+ {
+ child = proxy_settings_to_xmlnode(proxy_info);
+ xmlnode_insert_child(node, child);
+ }
+
+ child = current_error_to_xmlnode(priv->current_error);
+ xmlnode_insert_child(node, child);
+
+ return node;
+}
+
void
purple_accounts_add(PurpleAccount *account)
{
g_return_if_fail(PURPLE_IS_ACCOUNT(account));
purple_account_manager_add_account(purple_account_manager_get(), account);
-
- schedule_accounts_save();
}
void
@@ -2276,15 +2330,6 @@ purple_accounts_remove(PurpleAccount *ac
g_return_if_fail(PURPLE_IS_ACCOUNT(account));
purple_account_manager_remove_account(purple_account_manager_get(), account);
-
- schedule_accounts_save();
-
-#warning TODO: This should be moved to the account destructor
- /* Clearing the error ensures that account-error-changed is emitted,
- * which is the end of the guarantee that the the error's pointer is
- * valid.
- */
- purple_account_clear_current_error(account);
}
void
@@ -2362,8 +2407,6 @@ purple_accounts_reorder(PurpleAccount *a
{
purple_account_manager_reorder_account(purple_account_manager_get(),
account, new_index);
-
- schedule_accounts_save();
}
GList *
@@ -2533,19 +2576,12 @@ purple_accounts_init(void)
purple_signal_connect(conn_handle, "connection-error", handle,
PURPLE_CALLBACK(connection_error_cb), NULL);
#endif
- accounts_loaded = TRUE;
}
void
purple_accounts_uninit(void)
{
gpointer handle = purple_accounts_get_handle();
- if (save_timer != 0)
- {
- purple_timeout_remove(save_timer);
- save_timer = 0;
- sync_accounts();
- }
purple_signals_disconnect_by_handle(handle);
purple_signals_unregister_by_instance(handle);
============================================================
--- libpurple/account.h bbbb68c958453100855fd9768340bda3daec27ec
+++ libpurple/account.h 56a7dd8c64e208f2cb70b2ec9b44ed2976f5cbb1
@@ -56,6 +56,7 @@ typedef void (*PurpleAccountUnregistrati
#include "proxy.h"
#include "prpl.h"
#include "status.h"
+#include "xmlnode.h"
/**
* Account request types.
@@ -930,6 +931,15 @@ void purple_account_clear_current_error(
*/
void purple_account_clear_current_error(PurpleAccount *account);
+/**
+ * Get an XML description of an account.
+ *
+ * @param account The account
+ *
+ * @return The XML description of the account.
+ */
+xmlnode * purple_account_to_xmlnode(PurpleAccount *account);
+
/*@}*/
/**************************************************************************/
============================================================
--- libpurple/accountmanager.c ee48caf65b8e5217d359fe387e49ac981feccb1d
+++ libpurple/accountmanager.c d76d501c5c7b99794ca0b12af2d205bf4b3e5905
@@ -29,6 +29,9 @@
#include <string.h>
+static void schedule_accounts_save(PurpleAccountManager *manager);
+static void sync_accounts(PurpleAccountManager *manager);
+
/******************************************************************************
* PurpleAccountManager API
*****************************************************************************/
@@ -44,6 +47,7 @@ struct _PurpleAccountManagerPrivate
{
GList *accounts;
gboolean accounts_loaded;
+ int save_timer;
};
#define PURPLE_ACCOUNT_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_ACCOUNT_MANAGER, PurpleAccountManagerPrivate))
@@ -60,19 +64,37 @@ static void
}
static void
+purple_account_manager_dispose(GObject *object)
+{
+ PurpleAccountManager *manager = PURPLE_ACCOUNT_MANAGER(object);
+ sync_accounts(manager);
+}
+
+static void
+purple_account_manager_finalize(GObject *object)
+{
+ PurpleAccountManagerPrivate *priv = PURPLE_ACCOUNT_MANAGER_GET_PRIVATE(object);
+ g_list_free(priv->accounts);
+}
+
+static void
purple_account_manager_class_init(PurpleAccountManagerClass *klass)
{
- G_OBJECT_CLASS(klass)->constructor = purple_account_manager_constructor;
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ obj_class->constructor = purple_account_manager_constructor;
+ obj_class->dispose = purple_account_manager_dispose;
+ obj_class->finalize = purple_account_manager_finalize;
+
account_manager_signals[ACCOUNT_ADDED] =
g_signal_new("account-added",
G_OBJECT_CLASS_TYPE(klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(PurpleAccountManagerClass, account_added),
NULL, NULL,
-#warning FIXME: Change this to __OBJECT when PurpleAccount is a GObject
- purple_smarshal_VOID__POINTER,
+ purple_smarshal_VOID__OBJECT,
G_TYPE_NONE,
- 1, G_TYPE_POINTER);//PURPLE_TYPE_ACCOUNT);
+ 1, PURPLE_TYPE_ACCOUNT);
account_manager_signals[ACCOUNT_REMOVED] =
g_signal_new("account-removed",
@@ -80,10 +102,9 @@ purple_account_manager_class_init(Purple
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(PurpleAccountManagerClass, account_removed),
NULL, NULL,
-#warning FIXME: Change this to __OBJECT when PurpleAccount is a GObject
- purple_smarshal_VOID__POINTER,
+ purple_smarshal_VOID__OBJECT,
G_TYPE_NONE,
- 1, G_TYPE_POINTER);//PURPLE_TYPE_ACCOUNT);
+ 1, PURPLE_TYPE_ACCOUNT);
g_type_class_add_private(klass, sizeof(PurpleAccountManagerPrivate));
}
@@ -111,6 +132,10 @@ void purple_account_manager_add_account(
manager->priv->accounts = g_list_append(manager->priv->accounts, account);
g_signal_emit(manager, account_manager_signals[ACCOUNT_ADDED], 0, account);
+
+ /* Make sure we save the accounts when something changes */
+ g_signal_connect_swapped(G_OBJECT(account), "notify", G_CALLBACK(schedule_accounts_save), manager);
+ g_signal_connect_swapped(G_OBJECT(account), "settings-changed", G_CALLBACK(schedule_accounts_save), manager);
}
void purple_account_manager_remove_account(PurpleAccountManager *manager, PurpleAccount *account)
@@ -120,6 +145,9 @@ void purple_account_manager_remove_accou
manager->priv->accounts = g_list_remove(manager->priv->accounts, account);
g_signal_emit(manager, account_manager_signals[ACCOUNT_REMOVED], 0, account);
+
+ g_signal_handlers_disconnect_by_func(G_OBJECT(account),
+ G_CALLBACK(schedule_accounts_save), manager);
}
void purple_account_manager_reorder_account(PurpleAccountManager *manager, PurpleAccount *account, int new_index)
@@ -151,6 +179,7 @@ void purple_account_manager_reorder_acco
/* Insert it where it should go. */
accounts = g_list_insert(accounts, account, new_index);
manager->priv->accounts = accounts;
+ schedule_accounts_save(manager);
}
GList *purple_account_manager_get_all_accounts(PurpleAccountManager *manager)
@@ -587,3 +616,67 @@ void purple_account_manager_load_account
_purple_buddy_icons_account_loaded_cb();
}
+/*********************************************************************
+ * Writing to disk *
+ *********************************************************************/
+
+static xmlnode *
+accounts_to_xmlnode(PurpleAccountManager *manager)
+{
+ xmlnode *node, *child;
+ GList *cur;
+
+ node = xmlnode_new("account");
+ xmlnode_set_attrib(node, "version", "1.0");
+
+ for (cur = purple_account_manager_get_all_accounts(manager);
+ cur != NULL; cur = cur->next)
+ {
+ child = purple_account_to_xmlnode(PURPLE_ACCOUNT(cur->data));
+ xmlnode_insert_child(node, child);
+ }
+
+ return node;
+}
+
+static void
+sync_accounts(PurpleAccountManager *manager)
+{
+ xmlnode *node;
+ char *data;
+ PurpleAccountManagerPrivate *priv = PURPLE_ACCOUNT_MANAGER_GET_PRIVATE(manager);
+
+ if (priv->save_timer == 0)
+ return;
+
+ if (!priv->accounts_loaded) {
+ purple_debug_error("account", "Attempted to save accounts before "
+ "they were read!\n");
+ return;
+ }
+
+ node = accounts_to_xmlnode(manager);
+ data = xmlnode_to_formatted_str(node, NULL);
+ purple_util_write_data_to_file("accounts.xml", data, -1);
+ g_free(data);
+ xmlnode_free(node);
+
+ g_source_remove(priv->save_timer);
+ priv->save_timer = 0;
+}
+
+static gboolean
+save_cb(gpointer data)
+{
+ sync_accounts(PURPLE_ACCOUNT_MANAGER(data));
+ return FALSE;
+}
+
+static void
+schedule_accounts_save(PurpleAccountManager *manager)
+{
+ PurpleAccountManagerPrivate *priv = PURPLE_ACCOUNT_MANAGER_GET_PRIVATE(manager);
+ if (priv->save_timer == 0)
+ priv->save_timer = purple_timeout_add_seconds(5, save_cb, manager);
+}
+
============================================================
--- libpurple/accountmanager.h 8b6b2c2be2d057d196431dfceca52d1b658d6e1a
+++ libpurple/accountmanager.h 1a182fae0515e7350897843d9ebaf20f7795e080
@@ -67,7 +67,7 @@ G_BEGIN_DECLS
/**************************************************************************/
/*@{*/
-GType purple_account_manager_get_gtype(void);
+GType purple_account_manager_get_type(void);
PurpleAccountManager *purple_account_manager_get(void);
void purple_account_manager_add_account(PurpleAccountManager *manager, PurpleAccount *account);
More information about the Commits
mailing list