Mercurial > pidgin
comparison libpurple/blist.c @ 26520:0cbdc2639ce2
Add purple_{buddy,chat,group,contact}_destroy to the blist API, free
blist data on libpurple unload. Thanks to Nick Hebner for this.
References #8683
committer: Ethan Blanton <elb@pidgin.im>
author | Nick Hebner <hebnern@gmail.com> |
---|---|
date | Thu, 09 Apr 2009 17:33:20 +0000 |
parents | 6e1967b0f90b |
children | 9a2e4aebfa91 |
comparison
equal
deleted
inserted
replaced
26519:00f13da82914 | 26520:0cbdc2639ce2 |
---|---|
1200 | 1200 |
1201 PURPLE_DBUS_REGISTER_POINTER(chat, PurpleChat); | 1201 PURPLE_DBUS_REGISTER_POINTER(chat, PurpleChat); |
1202 return chat; | 1202 return chat; |
1203 } | 1203 } |
1204 | 1204 |
1205 void | |
1206 purple_chat_destroy(PurpleChat *chat) | |
1207 { | |
1208 g_hash_table_destroy(chat->components); | |
1209 g_hash_table_destroy(chat->node.settings); | |
1210 g_free(chat->alias); | |
1211 PURPLE_DBUS_UNREGISTER_POINTER(chat); | |
1212 g_free(chat); | |
1213 } | |
1214 | |
1205 PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const char *alias) | 1215 PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const char *alias) |
1206 { | 1216 { |
1207 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); | 1217 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); |
1208 PurpleBuddy *buddy; | 1218 PurpleBuddy *buddy; |
1209 | 1219 |
1224 if (ops && ops->new_node) | 1234 if (ops && ops->new_node) |
1225 ops->new_node((PurpleBlistNode *)buddy); | 1235 ops->new_node((PurpleBlistNode *)buddy); |
1226 | 1236 |
1227 PURPLE_DBUS_REGISTER_POINTER(buddy, PurpleBuddy); | 1237 PURPLE_DBUS_REGISTER_POINTER(buddy, PurpleBuddy); |
1228 return buddy; | 1238 return buddy; |
1239 } | |
1240 | |
1241 void | |
1242 purple_buddy_destroy(PurpleBuddy *buddy) | |
1243 { | |
1244 PurplePlugin *prpl; | |
1245 PurplePluginProtocolInfo *prpl_info; | |
1246 | |
1247 /* | |
1248 * Tell the owner PRPL that we're about to free the buddy so it | |
1249 * can free proto_data | |
1250 */ | |
1251 prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); | |
1252 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); | |
1253 if (prpl_info && prpl_info->buddy_free) | |
1254 prpl_info->buddy_free(buddy); | |
1255 | |
1256 /* Delete the node */ | |
1257 purple_buddy_icon_unref(buddy->icon); | |
1258 g_hash_table_destroy(buddy->node.settings); | |
1259 purple_presence_destroy(buddy->presence); | |
1260 g_free(buddy->name); | |
1261 g_free(buddy->alias); | |
1262 g_free(buddy->server_alias); | |
1263 | |
1264 PURPLE_DBUS_UNREGISTER_POINTER(buddy); | |
1265 g_free(buddy); | |
1266 | |
1267 /* FIXME: Once PurpleBuddy is a GObject, timeout callbacks can | |
1268 * g_object_ref() it when connecting the callback and | |
1269 * g_object_unref() it in the handler. That way, it won't | |
1270 * get freed while the timeout is pending and this line can | |
1271 * be removed. */ | |
1272 while (g_source_remove_by_user_data((gpointer *)buddy)); | |
1229 } | 1273 } |
1230 | 1274 |
1231 void | 1275 void |
1232 purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon) | 1276 purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon) |
1233 { | 1277 { |
1517 | 1561 |
1518 PURPLE_DBUS_REGISTER_POINTER(contact, PurpleContact); | 1562 PURPLE_DBUS_REGISTER_POINTER(contact, PurpleContact); |
1519 return contact; | 1563 return contact; |
1520 } | 1564 } |
1521 | 1565 |
1566 void | |
1567 purple_contact_destroy(PurpleContact *contact) | |
1568 { | |
1569 g_hash_table_destroy(contact->node.settings); | |
1570 PURPLE_DBUS_UNREGISTER_POINTER(contact); | |
1571 g_free(contact); | |
1572 } | |
1573 | |
1522 void purple_contact_set_alias(PurpleContact *contact, const char *alias) | 1574 void purple_contact_set_alias(PurpleContact *contact, const char *alias) |
1523 { | 1575 { |
1524 purple_blist_alias_contact(contact,alias); | 1576 purple_blist_alias_contact(contact,alias); |
1525 } | 1577 } |
1526 | 1578 |
1584 if (ops && ops->new_node) | 1636 if (ops && ops->new_node) |
1585 ops->new_node((PurpleBlistNode *)group); | 1637 ops->new_node((PurpleBlistNode *)group); |
1586 | 1638 |
1587 PURPLE_DBUS_REGISTER_POINTER(group, PurpleGroup); | 1639 PURPLE_DBUS_REGISTER_POINTER(group, PurpleGroup); |
1588 return group; | 1640 return group; |
1641 } | |
1642 | |
1643 void | |
1644 purple_group_destroy(PurpleGroup *group) | |
1645 { | |
1646 g_hash_table_destroy(group->node.settings); | |
1647 g_free(group->name); | |
1648 PURPLE_DBUS_UNREGISTER_POINTER(group); | |
1649 g_free(group); | |
1589 } | 1650 } |
1590 | 1651 |
1591 void purple_blist_add_contact(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node) | 1652 void purple_blist_add_contact(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node) |
1592 { | 1653 { |
1593 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); | 1654 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); |
1846 /* Update the UI */ | 1907 /* Update the UI */ |
1847 if (ops && ops->remove) | 1908 if (ops && ops->remove) |
1848 ops->remove(purplebuddylist, node); | 1909 ops->remove(purplebuddylist, node); |
1849 | 1910 |
1850 /* Delete the node */ | 1911 /* Delete the node */ |
1851 g_hash_table_destroy(contact->node.settings); | 1912 purple_contact_destroy(contact); |
1852 PURPLE_DBUS_UNREGISTER_POINTER(contact); | |
1853 g_free(contact); | |
1854 } | 1913 } |
1855 } | 1914 } |
1856 | 1915 |
1857 void purple_blist_remove_buddy(PurpleBuddy *buddy) | 1916 void purple_blist_remove_buddy(PurpleBuddy *buddy) |
1858 { | 1917 { |
1859 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); | 1918 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); |
1860 PurpleBlistNode *node, *cnode, *gnode; | 1919 PurpleBlistNode *node, *cnode, *gnode; |
1861 PurpleContact *contact; | 1920 PurpleContact *contact; |
1862 PurpleGroup *group; | 1921 PurpleGroup *group; |
1863 struct _purple_hbuddy hb; | 1922 struct _purple_hbuddy hb; |
1864 PurplePlugin *prpl; | |
1865 PurplePluginProtocolInfo *prpl_info = NULL; | |
1866 | 1923 |
1867 g_return_if_fail(buddy != NULL); | 1924 g_return_if_fail(buddy != NULL); |
1868 | 1925 |
1869 node = (PurpleBlistNode *)buddy; | 1926 node = (PurpleBlistNode *)buddy; |
1870 cnode = node->parent; | 1927 cnode = node->parent; |
1916 ops->remove(purplebuddylist, node); | 1973 ops->remove(purplebuddylist, node); |
1917 | 1974 |
1918 /* Signal that the buddy has been removed before freeing the memory for it */ | 1975 /* Signal that the buddy has been removed before freeing the memory for it */ |
1919 purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy); | 1976 purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy); |
1920 | 1977 |
1921 /* | 1978 purple_buddy_destroy(buddy); |
1922 * Tell the owner PRPL that we're about to free the buddy so it | |
1923 * can free proto_data | |
1924 */ | |
1925 prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); | |
1926 if (prpl) | |
1927 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); | |
1928 if (prpl_info && prpl_info->buddy_free) | |
1929 prpl_info->buddy_free(buddy); | |
1930 | |
1931 /* Delete the node */ | |
1932 purple_buddy_icon_unref(buddy->icon); | |
1933 g_hash_table_destroy(buddy->node.settings); | |
1934 purple_presence_destroy(buddy->presence); | |
1935 g_free(buddy->name); | |
1936 g_free(buddy->alias); | |
1937 g_free(buddy->server_alias); | |
1938 | |
1939 PURPLE_DBUS_UNREGISTER_POINTER(buddy); | |
1940 g_free(buddy); | |
1941 | |
1942 /* FIXME: Once PurpleBuddy is a GObject, timeout callbacks can | |
1943 * g_object_ref() it when connecting the callback and | |
1944 * g_object_unref() it in the handler. That way, it won't | |
1945 * get freed while the timeout is pending and this line can | |
1946 * be removed. */ | |
1947 while (g_source_remove_by_user_data((gpointer *)buddy)); | |
1948 | 1979 |
1949 /* If the contact is empty then remove it */ | 1980 /* If the contact is empty then remove it */ |
1950 if ((contact != NULL) && !cnode->child) | 1981 if ((contact != NULL) && !cnode->child) |
1951 purple_blist_remove_contact(contact); | 1982 purple_blist_remove_contact(contact); |
1952 } | 1983 } |
1986 /* Update the UI */ | 2017 /* Update the UI */ |
1987 if (ops && ops->remove) | 2018 if (ops && ops->remove) |
1988 ops->remove(purplebuddylist, node); | 2019 ops->remove(purplebuddylist, node); |
1989 | 2020 |
1990 /* Delete the node */ | 2021 /* Delete the node */ |
1991 g_hash_table_destroy(chat->components); | 2022 purple_chat_destroy(chat); |
1992 g_hash_table_destroy(chat->node.settings); | |
1993 g_free(chat->alias); | |
1994 PURPLE_DBUS_UNREGISTER_POINTER(chat); | |
1995 g_free(chat); | |
1996 } | 2023 } |
1997 | 2024 |
1998 void purple_blist_remove_group(PurpleGroup *group) | 2025 void purple_blist_remove_group(PurpleGroup *group) |
1999 { | 2026 { |
2000 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); | 2027 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); |
2031 if (purple_connection_get_state(gc) == PURPLE_CONNECTED) | 2058 if (purple_connection_get_state(gc) == PURPLE_CONNECTED) |
2032 purple_account_remove_group(purple_connection_get_account(gc), group); | 2059 purple_account_remove_group(purple_connection_get_account(gc), group); |
2033 } | 2060 } |
2034 | 2061 |
2035 /* Delete the node */ | 2062 /* Delete the node */ |
2036 g_hash_table_destroy(group->node.settings); | 2063 purple_group_destroy(group); |
2037 g_free(group->name); | |
2038 PURPLE_DBUS_UNREGISTER_POINTER(group); | |
2039 g_free(group); | |
2040 } | 2064 } |
2041 | 2065 |
2042 PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact) | 2066 PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact) |
2043 { | 2067 { |
2044 g_return_val_if_fail(contact != NULL, NULL); | 2068 g_return_val_if_fail(contact != NULL, NULL); |
2585 if (ui_ops != NULL && ui_ops->request_add_group != NULL) | 2609 if (ui_ops != NULL && ui_ops->request_add_group != NULL) |
2586 ui_ops->request_add_group(); | 2610 ui_ops->request_add_group(); |
2587 } | 2611 } |
2588 | 2612 |
2589 static void | 2613 static void |
2614 purple_blist_node_destroy(PurpleBlistNode *node) | |
2615 { | |
2616 PurpleBlistNode *child, *next_child; | |
2617 | |
2618 child = node->child; | |
2619 while (child) { | |
2620 next_child = child->next; | |
2621 purple_blist_node_destroy(child); | |
2622 child = next_child; | |
2623 } | |
2624 | |
2625 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) | |
2626 purple_buddy_destroy((PurpleBuddy*)node); | |
2627 else if (PURPLE_BLIST_NODE_IS_CHAT(node)) | |
2628 purple_chat_destroy((PurpleChat*)node); | |
2629 else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) | |
2630 purple_contact_destroy((PurpleContact*)node); | |
2631 else if (PURPLE_BLIST_NODE_IS_GROUP(node)) | |
2632 purple_group_destroy((PurpleGroup*)node); | |
2633 } | |
2634 | |
2635 static void | |
2590 purple_blist_node_setting_free(gpointer data) | 2636 purple_blist_node_setting_free(gpointer data) |
2591 { | 2637 { |
2592 PurpleValue *value; | 2638 PurpleValue *value; |
2593 | 2639 |
2594 value = (PurpleValue *)data; | 2640 value = (PurpleValue *)data; |
2872 } | 2918 } |
2873 | 2919 |
2874 void | 2920 void |
2875 purple_blist_uninit(void) | 2921 purple_blist_uninit(void) |
2876 { | 2922 { |
2877 if (save_timer != 0) | 2923 PurpleBlistNode *node, *next_node; |
2878 { | 2924 |
2925 if (save_timer != 0) { | |
2879 purple_timeout_remove(save_timer); | 2926 purple_timeout_remove(save_timer); |
2880 save_timer = 0; | 2927 save_timer = 0; |
2881 purple_blist_sync(); | 2928 purple_blist_sync(); |
2882 } | 2929 } |
2883 | 2930 |
2931 node = purple_blist_get_root(); | |
2932 while (node) { | |
2933 next_node = node->next; | |
2934 purple_blist_node_destroy(node); | |
2935 node = next_node; | |
2936 } | |
2937 | |
2884 purple_signals_unregister_by_instance(purple_blist_get_handle()); | 2938 purple_signals_unregister_by_instance(purple_blist_get_handle()); |
2885 } | 2939 } |