comparison libpurple/blist.c @ 28035:14ce47859540

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 <paul@darkrain42.org>
author hanzz@soc.pidgin.im
date Mon, 27 Jul 2009 05:20:52 +0000
parents 429fce11f244
children 12ab4c1112e5
comparison
equal deleted inserted replaced
28034:2cb2da84663d 28035:14ce47859540
391 purple_blist_sync(); 391 purple_blist_sync();
392 save_timer = 0; 392 save_timer = 0;
393 return FALSE; 393 return FALSE;
394 } 394 }
395 395
396 void 396 static void
397 purple_blist_schedule_save() 397 _purple_blist_schedule_save()
398 { 398 {
399 if (save_timer == 0) 399 if (save_timer == 0)
400 save_timer = purple_timeout_add_seconds(5, save_cb, NULL); 400 save_timer = purple_timeout_add_seconds(5, save_cb, NULL);
401 }
402
403 static void
404 purple_blist_save_account(PurpleAccount *account)
405 {
406 #if 1
407 _purple_blist_schedule_save();
408 #else
409 if (account != NULL) {
410 /* Save the buddies and privacy data for this account */
411 } else {
412 /* Save all buddies and privacy data */
413 }
414 #endif
415 }
416
417 static void
418 purple_blist_save_node(PurpleBlistNode *node)
419 {
420 _purple_blist_schedule_save();
421 }
422
423 void purple_blist_schedule_save()
424 {
425 PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
426
427 /* Save everything */
428 if (ops && ops->save_account)
429 ops->save_account(NULL);
401 } 430 }
402 431
403 432
404 /********************************************************************* 433 /*********************************************************************
405 * Reading from disk * 434 * Reading from disk *
969 g_hash_table_replace(account_buddies, hb2, buddy); 998 g_hash_table_replace(account_buddies, hb2, buddy);
970 999
971 g_free(buddy->name); 1000 g_free(buddy->name);
972 buddy->name = g_strdup(name); 1001 buddy->name = g_strdup(name);
973 1002
974 purple_blist_schedule_save(); 1003 if (ops && ops->save_node)
1004 ops->save_node((PurpleBlistNode *) buddy);
975 1005
976 if (ops && ops->update) 1006 if (ops && ops->update)
977 ops->update(purplebuddylist, (PurpleBlistNode *)buddy); 1007 ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
978 } 1008 }
979 1009
1009 else { 1039 else {
1010 contact->alias = NULL; 1040 contact->alias = NULL;
1011 g_free(new_alias); /* could be "\0" */ 1041 g_free(new_alias); /* could be "\0" */
1012 } 1042 }
1013 1043
1014 purple_blist_schedule_save(); 1044 if (ops && ops->save_node)
1045 ops->save_node((PurpleBlistNode*) contact);
1015 1046
1016 if (ops && ops->update) 1047 if (ops && ops->update)
1017 ops->update(purplebuddylist, (PurpleBlistNode *)contact); 1048 ops->update(purplebuddylist, (PurpleBlistNode *)contact);
1018 1049
1019 for(bnode = ((PurpleBlistNode *)contact)->child; bnode != NULL; bnode = bnode->next) 1050 for(bnode = ((PurpleBlistNode *)contact)->child; bnode != NULL; bnode = bnode->next)
1054 else { 1085 else {
1055 chat->alias = NULL; 1086 chat->alias = NULL;
1056 g_free(new_alias); /* could be "\0" */ 1087 g_free(new_alias); /* could be "\0" */
1057 } 1088 }
1058 1089
1059 purple_blist_schedule_save(); 1090 if (ops && ops->save_node)
1091 ops->save_node((PurpleBlistNode*) chat);
1060 1092
1061 if (ops && ops->update) 1093 if (ops && ops->update)
1062 ops->update(purplebuddylist, (PurpleBlistNode *)chat); 1094 ops->update(purplebuddylist, (PurpleBlistNode *)chat);
1063 1095
1064 purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", 1096 purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased",
1090 else { 1122 else {
1091 buddy->alias = NULL; 1123 buddy->alias = NULL;
1092 g_free(new_alias); /* could be "\0" */ 1124 g_free(new_alias); /* could be "\0" */
1093 } 1125 }
1094 1126
1095 purple_blist_schedule_save(); 1127 if (ops && ops->save_node)
1128 ops->save_node((PurpleBlistNode*) buddy);
1096 1129
1097 if (ops && ops->update) 1130 if (ops && ops->update)
1098 ops->update(purplebuddylist, (PurpleBlistNode *)buddy); 1131 ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
1099 1132
1100 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, 1133 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name,
1131 else { 1164 else {
1132 buddy->server_alias = NULL; 1165 buddy->server_alias = NULL;
1133 g_free(new_alias); /* could be "\0"; */ 1166 g_free(new_alias); /* could be "\0"; */
1134 } 1167 }
1135 1168
1136 purple_blist_schedule_save(); 1169 if (ops && ops->save_node)
1170 ops->save_node((PurpleBlistNode*) buddy);
1137 1171
1138 if (ops && ops->update) 1172 if (ops && ops->update)
1139 ops->update(purplebuddylist, (PurpleBlistNode *)buddy); 1173 ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
1140 1174
1141 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, 1175 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name,
1233 key = g_utf8_collate_key(new_name, -1); 1267 key = g_utf8_collate_key(new_name, -1);
1234 g_hash_table_insert(groups_cache, key, source); 1268 g_hash_table_insert(groups_cache, key, source);
1235 } 1269 }
1236 1270
1237 /* Save our changes */ 1271 /* Save our changes */
1238 purple_blist_schedule_save(); 1272 if (ops && ops->save_node)
1273 ops->save_node((PurpleBlistNode*) source);
1239 1274
1240 /* Update the UI */ 1275 /* Update the UI */
1241 if (ops && ops->update) 1276 if (ops && ops->update)
1242 ops->update(purplebuddylist, (PurpleBlistNode*)source); 1277 ops->update(purplebuddylist, (PurpleBlistNode*)source);
1243 1278
1491 ops->remove(purplebuddylist, cnode); 1526 ops->remove(purplebuddylist, cnode);
1492 /* ops->remove() cleaned up the cnode's ui_data, so we need to 1527 /* ops->remove() cleaned up the cnode's ui_data, so we need to
1493 * reinitialize it */ 1528 * reinitialize it */
1494 if (ops && ops->new_node) 1529 if (ops && ops->new_node)
1495 ops->new_node(cnode); 1530 ops->new_node(cnode);
1496
1497 purple_blist_schedule_save();
1498 } 1531 }
1499 1532
1500 if (node != NULL) { 1533 if (node != NULL) {
1501 if (node->next) 1534 if (node->next)
1502 node->next->prev = cnode; 1535 node->next->prev = cnode;
1521 group->online++; 1554 group->online++;
1522 group->currentsize++; 1555 group->currentsize++;
1523 } 1556 }
1524 } 1557 }
1525 1558
1526 purple_blist_schedule_save(); 1559 if (ops && ops->save_node)
1560 ops->save_node(cnode);
1527 1561
1528 if (ops && ops->update) 1562 if (ops && ops->update)
1529 ops->update(purplebuddylist, (PurpleBlistNode *)cnode); 1563 ops->update(purplebuddylist, (PurpleBlistNode *)cnode);
1530 1564
1531 purple_signal_emit(purple_blist_get_handle(), "blist-node-added", 1565 purple_signal_emit(purple_blist_get_handle(), "blist-node-added",
1599 bnode->parent->child = bnode->next; 1633 bnode->parent->child = bnode->next;
1600 1634
1601 if (ops && ops->remove) 1635 if (ops && ops->remove)
1602 ops->remove(purplebuddylist, bnode); 1636 ops->remove(purplebuddylist, bnode);
1603 1637
1604 purple_blist_schedule_save();
1605
1606 if (bnode->parent->parent != (PurpleBlistNode*)g) { 1638 if (bnode->parent->parent != (PurpleBlistNode*)g) {
1607 struct _purple_hbuddy hb; 1639 struct _purple_hbuddy hb;
1608 hb.name = (gchar *)purple_normalize(buddy->account, buddy->name); 1640 hb.name = (gchar *)purple_normalize(buddy->account, buddy->name);
1609 hb.account = buddy->account; 1641 hb.account = buddy->account;
1610 hb.group = bnode->parent->parent; 1642 hb.group = bnode->parent->parent;
1665 1697
1666 g_hash_table_replace(account_buddies, hb2, buddy); 1698 g_hash_table_replace(account_buddies, hb2, buddy);
1667 1699
1668 purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy)); 1700 purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy));
1669 1701
1670 purple_blist_schedule_save(); 1702 if (ops && ops->save_node)
1703 ops->save_node((PurpleBlistNode*) buddy);
1671 1704
1672 if (ops && ops->update) 1705 if (ops && ops->update)
1673 ops->update(purplebuddylist, (PurpleBlistNode*)buddy); 1706 ops->update(purplebuddylist, (PurpleBlistNode*)buddy);
1674 1707
1675 /* Signal that the buddy has been added */ 1708 /* Signal that the buddy has been added */
1884 ((PurpleGroup*)cnode->parent)->totalsize--; 1917 ((PurpleGroup*)cnode->parent)->totalsize--;
1885 1918
1886 if (ops && ops->remove) 1919 if (ops && ops->remove)
1887 ops->remove(purplebuddylist, cnode); 1920 ops->remove(purplebuddylist, cnode);
1888 1921
1889 purple_blist_schedule_save(); 1922 if (ops && ops->remove_node)
1923 ops->remove_node(cnode);
1890 } 1924 }
1891 1925
1892 if (node && (PURPLE_BLIST_NODE_IS_CONTACT(node) || 1926 if (node && (PURPLE_BLIST_NODE_IS_CONTACT(node) ||
1893 PURPLE_BLIST_NODE_IS_CHAT(node))) { 1927 PURPLE_BLIST_NODE_IS_CHAT(node))) {
1894 if (node->next) 1928 if (node->next)
1910 g->online++; 1944 g->online++;
1911 if (contact->currentsize > 0) 1945 if (contact->currentsize > 0)
1912 g->currentsize++; 1946 g->currentsize++;
1913 g->totalsize++; 1947 g->totalsize++;
1914 1948
1915 purple_blist_schedule_save(); 1949 if (ops && ops->save_node)
1950 {
1951 if (cnode->child)
1952 ops->save_node(cnode);
1953 for (bnode = cnode->child; bnode; bnode = bnode->next)
1954 ops->save_node(bnode);
1955 }
1916 1956
1917 if (ops && ops->update) 1957 if (ops && ops->update)
1918 { 1958 {
1919 if (cnode->child) 1959 if (cnode->child)
1920 ops->update(purplebuddylist, cnode); 1960 ops->update(purplebuddylist, cnode);
2010 gnode->next = purplebuddylist->root; 2050 gnode->next = purplebuddylist->root;
2011 gnode->prev = NULL; 2051 gnode->prev = NULL;
2012 purplebuddylist->root = gnode; 2052 purplebuddylist->root = gnode;
2013 } 2053 }
2014 2054
2015 purple_blist_schedule_save(); 2055 if (ops && ops->save_node) {
2056 ops->save_node(gnode);
2057 for (node = gnode->child; node; node = node->next)
2058 ops->save_node(node);
2059 }
2016 2060
2017 if (ops && ops->update) { 2061 if (ops && ops->update) {
2018 ops->update(purplebuddylist, gnode); 2062 ops->update(purplebuddylist, gnode);
2019 for (node = gnode->child; node; node = node->next) 2063 for (node = gnode->child; node; node = node->next)
2020 ops->update(purplebuddylist, node); 2064 ops->update(purplebuddylist, node);
2056 if (node->prev) 2100 if (node->prev)
2057 node->prev->next = node->next; 2101 node->prev->next = node->next;
2058 if (node->next) 2102 if (node->next)
2059 node->next->prev = node->prev; 2103 node->next->prev = node->prev;
2060 2104
2061 purple_blist_schedule_save();
2062
2063 /* Update the UI */ 2105 /* Update the UI */
2064 if (ops && ops->remove) 2106 if (ops && ops->remove)
2065 ops->remove(purplebuddylist, node); 2107 ops->remove(purplebuddylist, node);
2108
2109 if (ops && ops->remove_node)
2110 ops->remove_node(node);
2066 2111
2067 purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", 2112 purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
2068 PURPLE_BLIST_NODE(contact)); 2113 PURPLE_BLIST_NODE(contact));
2069 2114
2070 /* Delete the node */ 2115 /* Delete the node */
2117 if (ops && ops->update) 2162 if (ops && ops->update)
2118 ops->update(purplebuddylist, cnode); 2163 ops->update(purplebuddylist, cnode);
2119 } 2164 }
2120 } 2165 }
2121 2166
2122 purple_blist_schedule_save();
2123
2124 /* Remove this buddy from the buddies hash table */ 2167 /* Remove this buddy from the buddies hash table */
2125 hb.name = (gchar *)purple_normalize(buddy->account, buddy->name); 2168 hb.name = (gchar *)purple_normalize(buddy->account, buddy->name);
2126 hb.account = buddy->account; 2169 hb.account = buddy->account;
2127 hb.group = gnode; 2170 hb.group = gnode;
2128 g_hash_table_remove(purplebuddylist->buddies, &hb); 2171 g_hash_table_remove(purplebuddylist->buddies, &hb);
2131 g_hash_table_remove(account_buddies, &hb); 2174 g_hash_table_remove(account_buddies, &hb);
2132 2175
2133 /* Update the UI */ 2176 /* Update the UI */
2134 if (ops && ops->remove) 2177 if (ops && ops->remove)
2135 ops->remove(purplebuddylist, node); 2178 ops->remove(purplebuddylist, node);
2179
2180 if (ops && ops->remove_node)
2181 ops->remove_node(node);
2136 2182
2137 /* Signal that the buddy has been removed before freeing the memory for it */ 2183 /* Signal that the buddy has been removed before freeing the memory for it */
2138 purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy); 2184 purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy);
2139 2185
2140 purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", 2186 purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
2174 group->online--; 2220 group->online--;
2175 group->currentsize--; 2221 group->currentsize--;
2176 } 2222 }
2177 group->totalsize--; 2223 group->totalsize--;
2178 2224
2179 purple_blist_schedule_save();
2180 } 2225 }
2181 2226
2182 /* Update the UI */ 2227 /* Update the UI */
2183 if (ops && ops->remove) 2228 if (ops && ops->remove)
2184 ops->remove(purplebuddylist, node); 2229 ops->remove(purplebuddylist, node);
2230
2231 if (ops && ops->remove_node)
2232 ops->remove_node(node);
2185 2233
2186 purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", 2234 purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
2187 PURPLE_BLIST_NODE(chat)); 2235 PURPLE_BLIST_NODE(chat));
2188 2236
2189 /* Delete the node */ 2237 /* Delete the node */
2215 2263
2216 key = g_utf8_collate_key(group->name, -1); 2264 key = g_utf8_collate_key(group->name, -1);
2217 g_hash_table_remove(groups_cache, key); 2265 g_hash_table_remove(groups_cache, key);
2218 g_free(key); 2266 g_free(key);
2219 2267
2220 purple_blist_schedule_save();
2221
2222 /* Update the UI */ 2268 /* Update the UI */
2223 if (ops && ops->remove) 2269 if (ops && ops->remove)
2224 ops->remove(purplebuddylist, node); 2270 ops->remove(purplebuddylist, node);
2271
2272 if (ops && ops->remove_node)
2273 ops->remove_node(node);
2225 2274
2226 purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", 2275 purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
2227 PURPLE_BLIST_NODE(group)); 2276 PURPLE_BLIST_NODE(group));
2228 2277
2229 /* Remove the group from all accounts that are online */ 2278 /* Remove the group from all accounts that are online */
2825 (GDestroyNotify)purple_blist_node_setting_free); 2874 (GDestroyNotify)purple_blist_node_setting_free);
2826 } 2875 }
2827 2876
2828 void purple_blist_node_remove_setting(PurpleBlistNode *node, const char *key) 2877 void purple_blist_node_remove_setting(PurpleBlistNode *node, const char *key)
2829 { 2878 {
2879 PurpleBlistUiOps *ops;
2830 g_return_if_fail(node != NULL); 2880 g_return_if_fail(node != NULL);
2831 g_return_if_fail(node->settings != NULL); 2881 g_return_if_fail(node->settings != NULL);
2832 g_return_if_fail(key != NULL); 2882 g_return_if_fail(key != NULL);
2833 2883
2834 g_hash_table_remove(node->settings, key); 2884 g_hash_table_remove(node->settings, key);
2835 2885
2836 purple_blist_schedule_save(); 2886 ops = purple_blist_get_ui_ops();
2887 if (ops && ops->save_node)
2888 ops->save_node(node);
2837 } 2889 }
2838 2890
2839 void 2891 void
2840 purple_blist_node_set_flags(PurpleBlistNode *node, PurpleBlistNodeFlags flags) 2892 purple_blist_node_set_flags(PurpleBlistNode *node, PurpleBlistNodeFlags flags)
2841 { 2893 {
2861 2913
2862 void 2914 void
2863 purple_blist_node_set_bool(PurpleBlistNode* node, const char *key, gboolean data) 2915 purple_blist_node_set_bool(PurpleBlistNode* node, const char *key, gboolean data)
2864 { 2916 {
2865 PurpleValue *value; 2917 PurpleValue *value;
2918 PurpleBlistUiOps *ops;
2866 2919
2867 g_return_if_fail(node != NULL); 2920 g_return_if_fail(node != NULL);
2868 g_return_if_fail(node->settings != NULL); 2921 g_return_if_fail(node->settings != NULL);
2869 g_return_if_fail(key != NULL); 2922 g_return_if_fail(key != NULL);
2870 2923
2871 value = purple_value_new(PURPLE_TYPE_BOOLEAN); 2924 value = purple_value_new(PURPLE_TYPE_BOOLEAN);
2872 purple_value_set_boolean(value, data); 2925 purple_value_set_boolean(value, data);
2873 2926
2874 g_hash_table_replace(node->settings, g_strdup(key), value); 2927 g_hash_table_replace(node->settings, g_strdup(key), value);
2875 2928
2876 purple_blist_schedule_save(); 2929 ops = purple_blist_get_ui_ops();
2930 if (ops && ops->save_node)
2931 ops->save_node(node);
2877 } 2932 }
2878 2933
2879 gboolean 2934 gboolean
2880 purple_blist_node_get_bool(PurpleBlistNode* node, const char *key) 2935 purple_blist_node_get_bool(PurpleBlistNode* node, const char *key)
2881 { 2936 {
2897 2952
2898 void 2953 void
2899 purple_blist_node_set_int(PurpleBlistNode* node, const char *key, int data) 2954 purple_blist_node_set_int(PurpleBlistNode* node, const char *key, int data)
2900 { 2955 {
2901 PurpleValue *value; 2956 PurpleValue *value;
2957 PurpleBlistUiOps *ops;
2902 2958
2903 g_return_if_fail(node != NULL); 2959 g_return_if_fail(node != NULL);
2904 g_return_if_fail(node->settings != NULL); 2960 g_return_if_fail(node->settings != NULL);
2905 g_return_if_fail(key != NULL); 2961 g_return_if_fail(key != NULL);
2906 2962
2907 value = purple_value_new(PURPLE_TYPE_INT); 2963 value = purple_value_new(PURPLE_TYPE_INT);
2908 purple_value_set_int(value, data); 2964 purple_value_set_int(value, data);
2909 2965
2910 g_hash_table_replace(node->settings, g_strdup(key), value); 2966 g_hash_table_replace(node->settings, g_strdup(key), value);
2911 2967
2912 purple_blist_schedule_save(); 2968 ops = purple_blist_get_ui_ops();
2969 if (ops && ops->save_node)
2970 ops->save_node(node);
2913 } 2971 }
2914 2972
2915 int 2973 int
2916 purple_blist_node_get_int(PurpleBlistNode* node, const char *key) 2974 purple_blist_node_get_int(PurpleBlistNode* node, const char *key)
2917 { 2975 {
2933 2991
2934 void 2992 void
2935 purple_blist_node_set_string(PurpleBlistNode* node, const char *key, const char *data) 2993 purple_blist_node_set_string(PurpleBlistNode* node, const char *key, const char *data)
2936 { 2994 {
2937 PurpleValue *value; 2995 PurpleValue *value;
2996 PurpleBlistUiOps *ops;
2938 2997
2939 g_return_if_fail(node != NULL); 2998 g_return_if_fail(node != NULL);
2940 g_return_if_fail(node->settings != NULL); 2999 g_return_if_fail(node->settings != NULL);
2941 g_return_if_fail(key != NULL); 3000 g_return_if_fail(key != NULL);
2942 3001
2943 value = purple_value_new(PURPLE_TYPE_STRING); 3002 value = purple_value_new(PURPLE_TYPE_STRING);
2944 purple_value_set_string(value, data); 3003 purple_value_set_string(value, data);
2945 3004
2946 g_hash_table_replace(node->settings, g_strdup(key), value); 3005 g_hash_table_replace(node->settings, g_strdup(key), value);
2947 3006
2948 purple_blist_schedule_save(); 3007 ops = purple_blist_get_ui_ops();
3008 if (ops && ops->save_node)
3009 ops->save_node(node);
2949 } 3010 }
2950 3011
2951 const char * 3012 const char *
2952 purple_blist_node_get_string(PurpleBlistNode* node, const char *key) 3013 purple_blist_node_get_string(PurpleBlistNode* node, const char *key)
2953 { 3014 {
2997 } 3058 }
2998 3059
2999 void 3060 void
3000 purple_blist_set_ui_ops(PurpleBlistUiOps *ops) 3061 purple_blist_set_ui_ops(PurpleBlistUiOps *ops)
3001 { 3062 {
3063 gboolean overrode = FALSE;
3002 blist_ui_ops = ops; 3064 blist_ui_ops = ops;
3065
3066 if (!ops)
3067 return;
3068
3069 if (!ops->save_node) {
3070 ops->save_node = purple_blist_save_node;
3071 overrode = TRUE;
3072 }
3073 if (!ops->remove_node) {
3074 ops->remove_node = purple_blist_save_node;
3075 overrode = TRUE;
3076 }
3077 if (!ops->save_account) {
3078 ops->save_account = purple_blist_save_account;
3079 overrode = TRUE;
3080 }
3081
3082 if (overrode && (ops->save_node != purple_blist_save_node ||
3083 ops->remove_node != purple_blist_save_node ||
3084 ops->save_account != purple_blist_save_account)) {
3085 purple_debug_warning("blist", "Only some of the blist saving UI ops "
3086 "were overridden. This probably is not what you want!\n");
3087 }
3003 } 3088 }
3004 3089
3005 PurpleBlistUiOps * 3090 PurpleBlistUiOps *
3006 purple_blist_get_ui_ops(void) 3091 purple_blist_get_ui_ops(void)
3007 { 3092 {