comparison libpurple/blist.c @ 26602: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
26601:00f13da82914 26602: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 }