# HG changeset patch # User hanzz@soc.pidgin.im # Date 1248672052 0 # Node ID 14ce47859540f1451c296b1b8c23c03260abc041 # Parent 2cb2da84663d9893e0dde11b371f1d859e48976f Add blist ui-ops to overload the saving of data to blist.xml. Closes #9630. Patch from Jan "HanzZ" Kaluza with some changes by me so that it's easier to merge with Sulabh and Eric's SoC projects (mostly so grim wouldn't yell at me). Anyway, any bugs introduced by me (darkrain42). committer: Paul Aurich diff -r 2cb2da84663d -r 14ce47859540 ChangeLog.API --- a/ChangeLog.API Mon Jul 27 05:09:21 2009 +0000 +++ b/ChangeLog.API Mon Jul 27 05:20:52 2009 +0000 @@ -15,6 +15,9 @@ * account-destroying * blist-node-added and blist-node-removed signals (see blist-signals.dox) + * Three Blist UI ops used to overload libpurple's built-in saving + of the buddy list to blist.xml. If a UI implements these, it probably + wants to add the buddies itself and not call purple_blist_load. * Jabber plugin signals (see jabber-signals.dox) * purple_account_remove_setting * purple_buddy_destroy diff -r 2cb2da84663d -r 14ce47859540 libpurple/account.c --- a/libpurple/account.c Mon Jul 27 05:09:21 2009 +0000 +++ b/libpurple/account.c Mon Jul 27 05:20:52 2009 +0000 @@ -1534,6 +1534,8 @@ void purple_account_set_username(PurpleAccount *account, const char *username) { + PurpleBlistUiOps *blist_ops; + g_return_if_fail(account != NULL); g_free(account->username); @@ -1543,7 +1545,9 @@ /* if the name changes, we should re-write the buddy list * to disk with the new name */ - purple_blist_schedule_save(); + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); } void diff -r 2cb2da84663d -r 14ce47859540 libpurple/blist.c --- a/libpurple/blist.c Mon Jul 27 05:09:21 2009 +0000 +++ b/libpurple/blist.c Mon Jul 27 05:20:52 2009 +0000 @@ -393,13 +393,42 @@ return FALSE; } -void -purple_blist_schedule_save() +static void +_purple_blist_schedule_save() { if (save_timer == 0) save_timer = purple_timeout_add_seconds(5, save_cb, NULL); } +static void +purple_blist_save_account(PurpleAccount *account) +{ +#if 1 + _purple_blist_schedule_save(); +#else + if (account != NULL) { + /* Save the buddies and privacy data for this account */ + } else { + /* Save all buddies and privacy data */ + } +#endif +} + +static void +purple_blist_save_node(PurpleBlistNode *node) +{ + _purple_blist_schedule_save(); +} + +void purple_blist_schedule_save() +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + + /* Save everything */ + if (ops && ops->save_account) + ops->save_account(NULL); +} + /********************************************************************* * Reading from disk * @@ -971,7 +1000,8 @@ g_free(buddy->name); buddy->name = g_strdup(name); - purple_blist_schedule_save(); + if (ops && ops->save_node) + ops->save_node((PurpleBlistNode *) buddy); if (ops && ops->update) ops->update(purplebuddylist, (PurpleBlistNode *)buddy); @@ -1011,7 +1041,8 @@ g_free(new_alias); /* could be "\0" */ } - purple_blist_schedule_save(); + if (ops && ops->save_node) + ops->save_node((PurpleBlistNode*) contact); if (ops && ops->update) ops->update(purplebuddylist, (PurpleBlistNode *)contact); @@ -1056,7 +1087,8 @@ g_free(new_alias); /* could be "\0" */ } - purple_blist_schedule_save(); + if (ops && ops->save_node) + ops->save_node((PurpleBlistNode*) chat); if (ops && ops->update) ops->update(purplebuddylist, (PurpleBlistNode *)chat); @@ -1092,7 +1124,8 @@ g_free(new_alias); /* could be "\0" */ } - purple_blist_schedule_save(); + if (ops && ops->save_node) + ops->save_node((PurpleBlistNode*) buddy); if (ops && ops->update) ops->update(purplebuddylist, (PurpleBlistNode *)buddy); @@ -1133,7 +1166,8 @@ g_free(new_alias); /* could be "\0"; */ } - purple_blist_schedule_save(); + if (ops && ops->save_node) + ops->save_node((PurpleBlistNode*) buddy); if (ops && ops->update) ops->update(purplebuddylist, (PurpleBlistNode *)buddy); @@ -1235,7 +1269,8 @@ } /* Save our changes */ - purple_blist_schedule_save(); + if (ops && ops->save_node) + ops->save_node((PurpleBlistNode*) source); /* Update the UI */ if (ops && ops->update) @@ -1493,8 +1528,6 @@ * reinitialize it */ if (ops && ops->new_node) ops->new_node(cnode); - - purple_blist_schedule_save(); } if (node != NULL) { @@ -1523,7 +1556,8 @@ } } - purple_blist_schedule_save(); + if (ops && ops->save_node) + ops->save_node(cnode); if (ops && ops->update) ops->update(purplebuddylist, (PurpleBlistNode *)cnode); @@ -1601,8 +1635,6 @@ if (ops && ops->remove) ops->remove(purplebuddylist, bnode); - purple_blist_schedule_save(); - if (bnode->parent->parent != (PurpleBlistNode*)g) { struct _purple_hbuddy hb; hb.name = (gchar *)purple_normalize(buddy->account, buddy->name); @@ -1667,7 +1699,8 @@ purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy)); - purple_blist_schedule_save(); + if (ops && ops->save_node) + ops->save_node((PurpleBlistNode*) buddy); if (ops && ops->update) ops->update(purplebuddylist, (PurpleBlistNode*)buddy); @@ -1886,7 +1919,8 @@ if (ops && ops->remove) ops->remove(purplebuddylist, cnode); - purple_blist_schedule_save(); + if (ops && ops->remove_node) + ops->remove_node(cnode); } if (node && (PURPLE_BLIST_NODE_IS_CONTACT(node) || @@ -1912,7 +1946,13 @@ g->currentsize++; g->totalsize++; - purple_blist_schedule_save(); + if (ops && ops->save_node) + { + if (cnode->child) + ops->save_node(cnode); + for (bnode = cnode->child; bnode; bnode = bnode->next) + ops->save_node(bnode); + } if (ops && ops->update) { @@ -2012,7 +2052,11 @@ purplebuddylist->root = gnode; } - purple_blist_schedule_save(); + if (ops && ops->save_node) { + ops->save_node(gnode); + for (node = gnode->child; node; node = node->next) + ops->save_node(node); + } if (ops && ops->update) { ops->update(purplebuddylist, gnode); @@ -2058,12 +2102,13 @@ if (node->next) node->next->prev = node->prev; - purple_blist_schedule_save(); - /* Update the UI */ if (ops && ops->remove) ops->remove(purplebuddylist, node); + if (ops && ops->remove_node) + ops->remove_node(node); + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", PURPLE_BLIST_NODE(contact)); @@ -2119,8 +2164,6 @@ } } - purple_blist_schedule_save(); - /* Remove this buddy from the buddies hash table */ hb.name = (gchar *)purple_normalize(buddy->account, buddy->name); hb.account = buddy->account; @@ -2134,6 +2177,9 @@ if (ops && ops->remove) ops->remove(purplebuddylist, node); + if (ops && ops->remove_node) + ops->remove_node(node); + /* Signal that the buddy has been removed before freeing the memory for it */ purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy); @@ -2176,13 +2222,15 @@ } group->totalsize--; - purple_blist_schedule_save(); } /* Update the UI */ if (ops && ops->remove) ops->remove(purplebuddylist, node); + if (ops && ops->remove_node) + ops->remove_node(node); + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", PURPLE_BLIST_NODE(chat)); @@ -2217,12 +2265,13 @@ g_hash_table_remove(groups_cache, key); g_free(key); - purple_blist_schedule_save(); - /* Update the UI */ if (ops && ops->remove) ops->remove(purplebuddylist, node); + if (ops && ops->remove_node) + ops->remove_node(node); + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", PURPLE_BLIST_NODE(group)); @@ -2827,13 +2876,16 @@ void purple_blist_node_remove_setting(PurpleBlistNode *node, const char *key) { + PurpleBlistUiOps *ops; g_return_if_fail(node != NULL); g_return_if_fail(node->settings != NULL); g_return_if_fail(key != NULL); g_hash_table_remove(node->settings, key); - purple_blist_schedule_save(); + ops = purple_blist_get_ui_ops(); + if (ops && ops->save_node) + ops->save_node(node); } void @@ -2863,6 +2915,7 @@ purple_blist_node_set_bool(PurpleBlistNode* node, const char *key, gboolean data) { PurpleValue *value; + PurpleBlistUiOps *ops; g_return_if_fail(node != NULL); g_return_if_fail(node->settings != NULL); @@ -2873,7 +2926,9 @@ g_hash_table_replace(node->settings, g_strdup(key), value); - purple_blist_schedule_save(); + ops = purple_blist_get_ui_ops(); + if (ops && ops->save_node) + ops->save_node(node); } gboolean @@ -2899,6 +2954,7 @@ purple_blist_node_set_int(PurpleBlistNode* node, const char *key, int data) { PurpleValue *value; + PurpleBlistUiOps *ops; g_return_if_fail(node != NULL); g_return_if_fail(node->settings != NULL); @@ -2909,7 +2965,9 @@ g_hash_table_replace(node->settings, g_strdup(key), value); - purple_blist_schedule_save(); + ops = purple_blist_get_ui_ops(); + if (ops && ops->save_node) + ops->save_node(node); } int @@ -2935,6 +2993,7 @@ purple_blist_node_set_string(PurpleBlistNode* node, const char *key, const char *data) { PurpleValue *value; + PurpleBlistUiOps *ops; g_return_if_fail(node != NULL); g_return_if_fail(node->settings != NULL); @@ -2945,7 +3004,9 @@ g_hash_table_replace(node->settings, g_strdup(key), value); - purple_blist_schedule_save(); + ops = purple_blist_get_ui_ops(); + if (ops && ops->save_node) + ops->save_node(node); } const char * @@ -2999,7 +3060,31 @@ void purple_blist_set_ui_ops(PurpleBlistUiOps *ops) { + gboolean overrode = FALSE; blist_ui_ops = ops; + + if (!ops) + return; + + if (!ops->save_node) { + ops->save_node = purple_blist_save_node; + overrode = TRUE; + } + if (!ops->remove_node) { + ops->remove_node = purple_blist_save_node; + overrode = TRUE; + } + if (!ops->save_account) { + ops->save_account = purple_blist_save_account; + overrode = TRUE; + } + + if (overrode && (ops->save_node != purple_blist_save_node || + ops->remove_node != purple_blist_save_node || + ops->save_account != purple_blist_save_account)) { + purple_debug_warning("blist", "Only some of the blist saving UI ops " + "were overridden. This probably is not what you want!\n"); + } } PurpleBlistUiOps * diff -r 2cb2da84663d -r 14ce47859540 libpurple/blist.h --- a/libpurple/blist.h Mon Jul 27 05:09:21 2009 +0000 +++ b/libpurple/blist.h Mon Jul 27 05:20:52 2009 +0000 @@ -216,10 +216,49 @@ const char *alias, const char *name); void (*request_add_group)(void); + /** + * This is called when a node has been modified and should be saved. + * + * Implementation of this UI op is OPTIONAL. If not implemented, it will + * be set to a fallback function that saves data to blist.xml like in + * previous libpurple versions. + * + * @attrib node The node which has been modified. + * + * @since 2.6.0. + */ + void (*save_node)(PurpleBlistNode *node); + + /** + * Called when a node is about to be removed from the buddy list. + * The UI op should update the relevant data structures to remove this + * node (for example, removing a buddy from the group this node is in). + * + * Implementation of this UI op is OPTIONAL. If not implemented, it will + * be set to a fallback function that saves data to blist.xml like in + * previous libpurple versions. + * + * @attrib node The node which has been modified. + * @since 2.6.0. + */ + void (*remove_node)(PurpleBlistNode *node); + + /** + * Called to save all the data for an account. If the UI sets this, + * the callback must save the privacy and buddy list data for an account. + * If the account is NULL, save the data for all accounts. + * + * Implementation of this UI op is OPTIONAL. If not implemented, it will + * be set to a fallback function that saves data to blist.xml like in + * previous libpurple versions. + * + * @attrib account The account whose data to save. If NULL, save all data + * for all accounts. + * @since 2.6.0. + */ + void (*save_account)(PurpleAccount *account); + void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); }; #ifdef __cplusplus diff -r 2cb2da84663d -r 14ce47859540 libpurple/privacy.c --- a/libpurple/privacy.c Mon Jul 27 05:09:21 2009 +0000 +++ b/libpurple/privacy.c Mon Jul 27 05:20:52 2009 +0000 @@ -35,6 +35,7 @@ GSList *l; char *name; PurpleBuddy *buddy; + PurpleBlistUiOps *blist_ops; g_return_val_if_fail(account != NULL, FALSE); g_return_val_if_fail(who != NULL, FALSE); @@ -62,7 +63,9 @@ if (privacy_ops != NULL && privacy_ops->permit_added != NULL) privacy_ops->permit_added(account, who); - purple_blist_schedule_save(); + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); /* This lets the UI know a buddy has had its privacy setting changed */ buddy = purple_find_buddy(account, name); @@ -81,6 +84,7 @@ const char *name; PurpleBuddy *buddy; char *del; + PurpleBlistUiOps *blist_ops; g_return_val_if_fail(account != NULL, FALSE); g_return_val_if_fail(who != NULL, FALSE); @@ -109,7 +113,9 @@ if (privacy_ops != NULL && privacy_ops->permit_removed != NULL) privacy_ops->permit_removed(account, who); - purple_blist_schedule_save(); + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); buddy = purple_find_buddy(account, name); if (buddy != NULL) { @@ -127,6 +133,7 @@ GSList *l; char *name; PurpleBuddy *buddy; + PurpleBlistUiOps *blist_ops; g_return_val_if_fail(account != NULL, FALSE); g_return_val_if_fail(who != NULL, FALSE); @@ -154,7 +161,9 @@ if (privacy_ops != NULL && privacy_ops->deny_added != NULL) privacy_ops->deny_added(account, who); - purple_blist_schedule_save(); + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); buddy = purple_find_buddy(account, name); if (buddy != NULL) { @@ -172,6 +181,7 @@ const char *normalized; char *name; PurpleBuddy *buddy; + PurpleBlistUiOps *blist_ops; g_return_val_if_fail(account != NULL, FALSE); g_return_val_if_fail(who != NULL, FALSE); @@ -205,7 +215,10 @@ } g_free(name); - purple_blist_schedule_save(); + + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); return TRUE; }