comparison pidgin/gtkblist.c @ 32819:2c6510167895 default tip

propagate from branch 'im.pidgin.pidgin.2.x.y' (head 3315c5dfbd0ad16511bdcf865e5b07c02d07df24) to branch 'im.pidgin.pidgin' (head cbd1eda6bcbf0565ae7766396bb8f6f419cb6a9a)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sat, 02 Jun 2012 02:30:49 +0000
parents 1056a2803806
children
comparison
equal deleted inserted replaced
32818:01ff09d4a463 32819:2c6510167895
122 } PidginBuddyListPrivate; 122 } PidginBuddyListPrivate;
123 123
124 #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \ 124 #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \
125 ((PidginBuddyListPrivate *)((list)->priv)) 125 ((PidginBuddyListPrivate *)((list)->priv))
126 126
127 #if !GTK_CHECK_VERSION(2,18,0)
128 #define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x)
129 #define gtk_widget_has_focus(x) GTK_WIDGET_HAS_FOCUS(x)
130 #endif
131
127 static GtkWidget *accountmenu = NULL; 132 static GtkWidget *accountmenu = NULL;
128 133
129 static guint visibility_manager_count = 0; 134 static guint visibility_manager_count = 0;
130 static GdkVisibilityState gtk_blist_visibility = GDK_VISIBILITY_UNOBSCURED; 135 static GdkVisibilityState gtk_blist_visibility = GDK_VISIBILITY_UNOBSCURED;
131 static gboolean gtk_blist_focused = FALSE; 136 static gboolean gtk_blist_focused = FALSE;
136 static void sort_method_none(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); 141 static void sort_method_none(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
137 142
138 static void sort_method_alphabetical(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); 143 static void sort_method_alphabetical(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
139 static void sort_method_status(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); 144 static void sort_method_status(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
140 static void sort_method_log_activity(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); 145 static void sort_method_log_activity(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
146 static guint sort_merge_id;
147 static GtkActionGroup *sort_action_group = NULL;
148
141 static PidginBuddyList *gtkblist = NULL; 149 static PidginBuddyList *gtkblist = NULL;
142 150
143 static GList *groups_tree(void); 151 static GList *groups_tree(void);
144 static gboolean pidgin_blist_refresh_timer(PurpleBuddyList *list); 152 static gboolean pidgin_blist_refresh_timer(PurpleBuddyList *list);
145 static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *node, gboolean status_change); 153 static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *node, gboolean status_change);
146 static void pidgin_blist_selection_changed(GtkTreeSelection *selection, gpointer data); 154 static void pidgin_blist_selection_changed(GtkTreeSelection *selection, gpointer data);
147 static void pidgin_blist_update(PurpleBuddyList *list, PurpleBlistNode *node); 155 static void pidgin_blist_update(PurpleBuddyList *list, PurpleBlistNode *node);
148 static void pidgin_blist_update_group(PurpleBuddyList *list, PurpleBlistNode *node); 156 static void pidgin_blist_update_group(PurpleBuddyList *list, PurpleBlistNode *node);
149 static void pidgin_blist_update_contact(PurpleBuddyList *list, PurpleBlistNode *node); 157 static void pidgin_blist_update_contact(PurpleBuddyList *list, PurpleBlistNode *node);
150 static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full); 158 static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full);
151 static const char *item_factory_translate_func (const char *path, gpointer func_data);
152 static gboolean get_iter_from_node(PurpleBlistNode *node, GtkTreeIter *iter); 159 static gboolean get_iter_from_node(PurpleBlistNode *node, GtkTreeIter *iter);
153 static gboolean buddy_is_displayable(PurpleBuddy *buddy); 160 static gboolean buddy_is_displayable(PurpleBuddy *buddy);
154 static void redo_buddy_list(PurpleBuddyList *list, gboolean remove, gboolean rerender); 161 static void redo_buddy_list(PurpleBuddyList *list, gboolean remove, gboolean rerender);
155 static void pidgin_blist_collapse_contact_cb(GtkWidget *w, PurpleBlistNode *node); 162 static void pidgin_blist_collapse_contact_cb(GtkWidget *w, PurpleBlistNode *node);
156 static char *pidgin_get_group_title(PurpleBlistNode *gnode, gboolean expanded); 163 static char *pidgin_get_group_title(PurpleBlistNode *gnode, gboolean expanded);
240 * to work correctly. - Robot101 */ 247 * to work correctly. - Robot101 */
241 gint x, y; 248 gint x, y;
242 249
243 /* check for visibility because when we aren't visible, this will * 250 /* check for visibility because when we aren't visible, this will *
244 * give us bogus (0,0) coordinates. - xOr */ 251 * give us bogus (0,0) coordinates. - xOr */
245 if (GTK_WIDGET_VISIBLE(w)) 252 if (gtk_widget_get_visible(w))
246 gtk_window_get_position(GTK_WINDOW(w), &x, &y); 253 gtk_window_get_position(GTK_WINDOW(w), &x, &y);
247 else 254 else
248 return FALSE; /* carry on normally */ 255 return FALSE; /* carry on normally */
249 256
250 #ifdef _WIN32 257 #ifdef _WIN32
341 348
342 } 349 }
343 350
344 static void gtk_blist_menu_autojoin_cb(GtkWidget *w, PurpleChat *chat) 351 static void gtk_blist_menu_autojoin_cb(GtkWidget *w, PurpleChat *chat)
345 { 352 {
346 purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin", 353 purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin",
347 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); 354 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)));
348 } 355 }
349 356
350 static void gtk_blist_menu_persistent_cb(GtkWidget *w, PurpleChat *chat) 357 static void gtk_blist_menu_persistent_cb(GtkWidget *w, PurpleChat *chat)
351 { 358 {
352 purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent", 359 purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-persistent",
353 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); 360 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)));
354 } 361 }
355 362
356 static PurpleConversation * 363 static PurpleConversation *
357 find_conversation_with_buddy(PurpleBuddy *buddy) 364 find_conversation_with_buddy(PurpleBuddy *buddy)
914 } 921 }
915 922
916 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), GTK_RESPONSE_OK, sensitive); 923 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), GTK_RESPONSE_OK, sensitive);
917 924
918 gc = purple_account_get_connection(data->rq_data.account); 925 gc = purple_account_get_connection(data->rq_data.account);
919 prpl_info = (gc != NULL) ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL; 926 prpl_info = (gc != NULL) ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL;
920 sensitive = (prpl_info != NULL && prpl_info->roomlist_get_list != NULL); 927 sensitive = (prpl_info != NULL && prpl_info->roomlist_get_list != NULL);
921 928
922 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), 1, sensitive); 929 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), 1, sensitive);
923 } 930 }
924 931
938 PurplePluginProtocolInfo *prpl_info = NULL; 945 PurplePluginProtocolInfo *prpl_info = NULL;
939 946
940 if (gc == NULL) 947 if (gc == NULL)
941 return FALSE; 948 return FALSE;
942 949
943 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 950 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
944 951
945 return (prpl_info->chat_info != NULL); 952 return (prpl_info->chat_info != NULL);
946 } 953 }
947 954
948 gboolean 955 gboolean
1028 1035
1029 static void 1036 static void
1030 rebuild_chat_entries(PidginChatData *data, const char *default_chat_name) 1037 rebuild_chat_entries(PidginChatData *data, const char *default_chat_name)
1031 { 1038 {
1032 PurpleConnection *gc; 1039 PurpleConnection *gc;
1040 PurplePluginProtocolInfo *prpl_info;
1033 GList *list = NULL, *tmp; 1041 GList *list = NULL, *tmp;
1034 GHashTable *defaults = NULL; 1042 GHashTable *defaults = NULL;
1035 struct proto_chat_entry *pce; 1043 struct proto_chat_entry *pce;
1036 gboolean focus = TRUE; 1044 gboolean focus = TRUE;
1037 1045
1038 g_return_if_fail(data->rq_data.account != NULL); 1046 g_return_if_fail(data->rq_data.account != NULL);
1039 1047
1040 gc = purple_account_get_connection(data->rq_data.account); 1048 gc = purple_account_get_connection(data->rq_data.account);
1049 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1041 1050
1042 gtk_container_foreach(GTK_CONTAINER(data->rq_data.vbox), (GtkCallback)gtk_widget_destroy, NULL); 1051 gtk_container_foreach(GTK_CONTAINER(data->rq_data.vbox), (GtkCallback)gtk_widget_destroy, NULL);
1043 1052
1044 g_list_free(data->entries); 1053 g_list_free(data->entries);
1045 data->entries = NULL; 1054 data->entries = NULL;
1046 1055
1047 if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) 1056 if (prpl_info->chat_info != NULL)
1048 list = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc); 1057 list = prpl_info->chat_info(gc);
1049 1058
1050 if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) 1059 if (prpl_info->chat_info_defaults != NULL)
1051 defaults = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, default_chat_name); 1060 defaults = prpl_info->chat_info_defaults(gc, default_chat_name);
1052 1061
1053 for (tmp = list; tmp; tmp = tmp->next) 1062 for (tmp = list; tmp; tmp = tmp->next)
1054 { 1063 {
1055 GtkWidget *input; 1064 GtkWidget *input;
1056 1065
1409 void 1418 void
1410 pidgin_append_blist_node_proto_menu(GtkWidget *menu, PurpleConnection *gc, 1419 pidgin_append_blist_node_proto_menu(GtkWidget *menu, PurpleConnection *gc,
1411 PurpleBlistNode *node) 1420 PurpleBlistNode *node)
1412 { 1421 {
1413 GList *l, *ll; 1422 GList *l, *ll;
1414 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 1423 PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
1415 1424
1416 if(!prpl_info || !prpl_info->blist_node_menu) 1425 if(!prpl_info || !prpl_info->blist_node_menu)
1417 return; 1426 return;
1418 1427
1419 for(l = ll = prpl_info->blist_node_menu(node); l; l = l->next) { 1428 for(l = ll = prpl_info->blist_node_menu(node); l; l = l->next) {
1517 1526
1518 #endif 1527 #endif
1519 1528
1520 if (prpl_info && prpl_info->send_file) { 1529 if (prpl_info && prpl_info->send_file) {
1521 if (!prpl_info->can_receive_file || 1530 if (!prpl_info->can_receive_file ||
1522 prpl_info->can_receive_file(buddy->account->gc, buddy->name)) 1531 prpl_info->can_receive_file(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy)))
1523 { 1532 {
1524 pidgin_new_item_from_stock(menu, _("_Send File..."), 1533 pidgin_new_item_from_stock(menu, _("_Send File..."),
1525 PIDGIN_STOCK_TOOLBAR_SEND_FILE, 1534 PIDGIN_STOCK_TOOLBAR_SEND_FILE,
1526 G_CALLBACK(gtk_blist_menu_send_file_cb), 1535 G_CALLBACK(gtk_blist_menu_send_file_cb),
1527 buddy, 0, 0, NULL); 1536 buddy, 0, 0, NULL);
1545 gboolean show_offline = purple_blist_node_get_bool(node, "show_offline"); 1554 gboolean show_offline = purple_blist_node_get_bool(node, "show_offline");
1546 pidgin_new_item_from_stock(menu, show_offline ? _("Hide When Offline") : _("Show When Offline"), 1555 pidgin_new_item_from_stock(menu, show_offline ? _("Hide When Offline") : _("Show When Offline"),
1547 NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL); 1556 NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL);
1548 } 1557 }
1549 1558
1550 pidgin_append_blist_node_proto_menu(menu, buddy->account->gc, node); 1559 pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(purple_buddy_get_account(buddy)), node);
1551 pidgin_append_blist_node_extended_menu(menu, node); 1560 pidgin_append_blist_node_extended_menu(menu, node);
1552 1561
1553 if (!contact_expanded && contact != NULL) 1562 if (!contact_expanded && contact != NULL)
1554 pidgin_append_blist_node_move_to_menu(menu, (PurpleBlistNode *)contact); 1563 pidgin_append_blist_node_move_to_menu(menu, PURPLE_BLIST_NODE(contact));
1555 1564
1556 if (node->parent && node->parent->child->next && 1565 if (node->parent && node->parent->child->next &&
1557 !sub && !contact_expanded) { 1566 !sub && !contact_expanded) {
1558 pidgin_separator(menu); 1567 pidgin_separator(menu);
1559 pidgin_append_blist_node_privacy_menu(menu, node); 1568 pidgin_append_blist_node_privacy_menu(menu, node);
1598 buddy = (PurpleBuddy*)node; 1607 buddy = (PurpleBuddy*)node;
1599 } else { 1608 } else {
1600 return FALSE; 1609 return FALSE;
1601 } 1610 }
1602 if(buddy) 1611 if(buddy)
1603 pidgin_retrieve_user_info(buddy->account->gc, buddy->name); 1612 pidgin_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy));
1604 } else { 1613 } else {
1605 switch (event->keyval) { 1614 switch (event->keyval) {
1606 case GDK_F2: 1615 case GDK_F2:
1607 gtk_blist_menu_alias_cb(tv, node); 1616 gtk_blist_menu_alias_cb(tv, node);
1608 break; 1617 break;
1751 pidgin_new_check_item(menu, _("Persistent"), 1760 pidgin_new_check_item(menu, _("Persistent"),
1752 G_CALLBACK(gtk_blist_menu_persistent_cb), node, persistent); 1761 G_CALLBACK(gtk_blist_menu_persistent_cb), node, persistent);
1753 pidgin_new_item_from_stock(menu, _("View _Log"), NULL, 1762 pidgin_new_item_from_stock(menu, _("View _Log"), NULL,
1754 G_CALLBACK(gtk_blist_menu_showlog_cb), node, 0, 0, NULL); 1763 G_CALLBACK(gtk_blist_menu_showlog_cb), node, 0, 0, NULL);
1755 1764
1756 pidgin_append_blist_node_proto_menu(menu, c->account->gc, node); 1765 pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(purple_chat_get_account(c)), node);
1757 pidgin_append_blist_node_extended_menu(menu, node); 1766 pidgin_append_blist_node_extended_menu(menu, node);
1758 1767
1759 pidgin_separator(menu); 1768 pidgin_separator(menu);
1760 1769
1761 pidgin_new_item_from_stock(menu, _("_Edit Settings..."), NULL, 1770 pidgin_new_item_from_stock(menu, _("_Edit Settings..."), NULL,
1801 } 1810 }
1802 1811
1803 static GtkWidget * 1812 static GtkWidget *
1804 create_buddy_menu(PurpleBlistNode *node, PurpleBuddy *b) 1813 create_buddy_menu(PurpleBlistNode *node, PurpleBuddy *b)
1805 { 1814 {
1806 struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data; 1815 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
1807 GtkWidget *menu; 1816 GtkWidget *menu;
1808 GtkWidget *menuitem; 1817 GtkWidget *menuitem;
1809 gboolean show_offline = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies"); 1818 gboolean show_offline = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies");
1810 1819
1811 menu = gtk_menu_new(); 1820 menu = gtk_menu_new();
1836 GtkWidget *submenu; 1845 GtkWidget *submenu;
1837 GtkWidget *image; 1846 GtkWidget *image;
1838 1847
1839 if(buddy == b) 1848 if(buddy == b)
1840 continue; 1849 continue;
1841 if(!buddy->account->gc) 1850 if(!purple_account_get_connection(purple_buddy_get_account(buddy)))
1842 continue; 1851 continue;
1843 if(!show_offline && !PURPLE_BUDDY_IS_ONLINE(buddy)) 1852 if(!show_offline && !PURPLE_BUDDY_IS_ONLINE(buddy))
1844 continue; 1853 continue;
1845 1854
1846 menuitem = gtk_image_menu_item_new_with_label(buddy->name); 1855 menuitem = gtk_image_menu_item_new_with_label(purple_buddy_get_name(buddy));
1847 buf = pidgin_create_prpl_icon(buddy->account,PIDGIN_PRPL_ICON_SMALL); 1856 buf = pidgin_create_prpl_icon(purple_buddy_get_account(buddy), PIDGIN_PRPL_ICON_SMALL);
1848 image = gtk_image_new_from_pixbuf(buf); 1857 image = gtk_image_new_from_pixbuf(buf);
1849 g_object_unref(G_OBJECT(buf)); 1858 g_object_unref(G_OBJECT(buf));
1850 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), 1859 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),
1851 image); 1860 image);
1852 gtk_widget_show(image); 1861 gtk_widget_show(image);
1869 GtkMenuPositionFunc func, 1878 GtkMenuPositionFunc func,
1870 GtkWidget *tv, 1879 GtkWidget *tv,
1871 guint button, 1880 guint button,
1872 guint32 time) 1881 guint32 time)
1873 { 1882 {
1874 struct _pidgin_blist_node *gtknode; 1883 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
1875 GtkWidget *menu = NULL; 1884 GtkWidget *menu = NULL;
1876 gboolean handled = FALSE; 1885 gboolean handled = FALSE;
1877
1878 gtknode = (struct _pidgin_blist_node *)node->ui_data;
1879 1886
1880 /* Create a menu based on the thing we right-clicked on */ 1887 /* Create a menu based on the thing we right-clicked on */
1881 if (PURPLE_BLIST_NODE_IS_GROUP(node)) { 1888 if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
1882 PurpleGroup *g = (PurpleGroup *)node; 1889 PurpleGroup *g = (PurpleGroup *)node;
1883 1890
1936 /* Here we figure out which node was clicked */ 1943 /* Here we figure out which node was clicked */
1937 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL)) 1944 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL))
1938 return FALSE; 1945 return FALSE;
1939 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); 1946 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path);
1940 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); 1947 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1);
1941 gtknode = (struct _pidgin_blist_node *)node->ui_data; 1948 gtknode = purple_blist_node_get_ui_data(node);
1942 1949
1943 /* Right click draws a context menu */ 1950 /* Right click draws a context menu */
1944 if ((event->button == 3) && (event->type == GDK_BUTTON_PRESS)) { 1951 if ((event->button == 3) && (event->type == GDK_BUTTON_PRESS)) {
1945 handled = pidgin_blist_show_context_menu(node, NULL, tv, 3, event->time); 1952 handled = pidgin_blist_show_context_menu(node, NULL, tv, 3, event->time);
1946 1953
1960 if(PURPLE_BLIST_NODE_IS_CONTACT(node)) 1967 if(PURPLE_BLIST_NODE_IS_CONTACT(node))
1961 b = purple_contact_get_priority_buddy((PurpleContact*)node); 1968 b = purple_contact_get_priority_buddy((PurpleContact*)node);
1962 else 1969 else
1963 b = (PurpleBuddy *)node; 1970 b = (PurpleBuddy *)node;
1964 1971
1965 prpl = purple_find_prpl(purple_account_get_protocol_id(b->account)); 1972 prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b)));
1966 if (prpl != NULL) 1973 if (prpl != NULL)
1967 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 1974 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
1968 1975
1969 if (prpl && prpl_info->get_info) 1976 if (prpl && prpl_info->get_info)
1970 pidgin_retrieve_user_info(b->account->gc, b->name); 1977 pidgin_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(b)), purple_buddy_get_name(b));
1971 handled = TRUE; 1978 handled = TRUE;
1972 } 1979 }
1973 else if ((event->button == 1) && (event->type == GDK_2BUTTON_PRESS) && 1980 else if ((event->button == 1) && (event->type == GDK_2BUTTON_PRESS) &&
1974 ((PURPLE_BLIST_NODE_IS_CONTACT(node)) || (PURPLE_BLIST_NODE_IS_BUDDY(node)))) { 1981 ((PURPLE_BLIST_NODE_IS_CONTACT(node)) || (PURPLE_BLIST_NODE_IS_BUDDY(node)))) {
1975 handled = TRUE; 1982 handled = TRUE;
2014 handled = pidgin_blist_show_context_menu(node, pidgin_treeview_popup_menu_position_func, tv, 0, GDK_CURRENT_TIME); 2021 handled = pidgin_blist_show_context_menu(node, pidgin_treeview_popup_menu_position_func, tv, 0, GDK_CURRENT_TIME);
2015 2022
2016 return handled; 2023 return handled;
2017 } 2024 }
2018 2025
2019 static void pidgin_blist_buddy_details_cb(gpointer data, guint action, GtkWidget *item) 2026 static void gtk_blist_show_xfer_dialog_cb(GtkAction *item, gpointer data)
2027 {
2028 pidgin_xfer_dialog_show(NULL);
2029 }
2030
2031 static void pidgin_blist_buddy_details_cb(GtkToggleAction *item, gpointer data)
2020 { 2032 {
2021 pidgin_set_cursor(gtkblist->window, GDK_WATCH); 2033 pidgin_set_cursor(gtkblist->window, GDK_WATCH);
2022 2034
2023 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons", 2035 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons",
2024 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); 2036 gtk_toggle_action_get_active(item));
2025 2037
2026 pidgin_clear_cursor(gtkblist->window); 2038 pidgin_clear_cursor(gtkblist->window);
2027 } 2039 }
2028 2040
2029 static void pidgin_blist_show_idle_time_cb(gpointer data, guint action, GtkWidget *item) 2041 static void pidgin_blist_show_idle_time_cb(GtkToggleAction *item, gpointer data)
2030 { 2042 {
2031 pidgin_set_cursor(gtkblist->window, GDK_WATCH); 2043 pidgin_set_cursor(gtkblist->window, GDK_WATCH);
2032 2044
2033 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time", 2045 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time",
2034 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); 2046 gtk_toggle_action_get_active(item));
2035 2047
2036 pidgin_clear_cursor(gtkblist->window); 2048 pidgin_clear_cursor(gtkblist->window);
2037 } 2049 }
2038 2050
2039 static void pidgin_blist_show_protocol_icons_cb(gpointer data, guint action, GtkWidget *item) 2051 static void pidgin_blist_show_protocol_icons_cb(GtkToggleAction *item, gpointer data)
2040 { 2052 {
2041 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons", 2053 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons",
2042 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); 2054 gtk_toggle_action_get_active(item));
2043 } 2055 }
2044 2056
2045 static void pidgin_blist_show_empty_groups_cb(gpointer data, guint action, GtkWidget *item) 2057 static void pidgin_blist_show_empty_groups_cb(GtkToggleAction *item, gpointer data)
2046 { 2058 {
2047 pidgin_set_cursor(gtkblist->window, GDK_WATCH); 2059 pidgin_set_cursor(gtkblist->window, GDK_WATCH);
2048 2060
2049 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_empty_groups", 2061 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_empty_groups",
2050 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); 2062 gtk_toggle_action_get_active(item));
2051 2063
2052 pidgin_clear_cursor(gtkblist->window); 2064 pidgin_clear_cursor(gtkblist->window);
2053 } 2065 }
2054 2066
2055 static void pidgin_blist_edit_mode_cb(gpointer callback_data, guint callback_action, 2067 static void pidgin_blist_edit_mode_cb(GtkToggleAction *checkitem, gpointer data)
2056 GtkWidget *checkitem)
2057 { 2068 {
2058 pidgin_set_cursor(gtkblist->window, GDK_WATCH); 2069 pidgin_set_cursor(gtkblist->window, GDK_WATCH);
2059 2070
2060 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies", 2071 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies",
2061 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(checkitem))); 2072 gtk_toggle_action_get_active(checkitem));
2062 2073
2063 pidgin_clear_cursor(gtkblist->window); 2074 pidgin_clear_cursor(gtkblist->window);
2064 } 2075 }
2065 2076
2066 static void pidgin_blist_mute_sounds_cb(gpointer data, guint action, GtkWidget *item) 2077 static void pidgin_blist_mute_sounds_cb(GtkToggleAction *item, gpointer data)
2067 { 2078 {
2068 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute", GTK_CHECK_MENU_ITEM(item)->active); 2079 purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute",
2069 } 2080 gtk_toggle_action_get_active(item));
2081 }
2082
2070 2083
2071 static void 2084 static void
2072 pidgin_blist_mute_pref_cb(const char *name, PurplePrefType type, 2085 pidgin_blist_mute_pref_cb(const char *name, PurplePrefType type,
2073 gconstpointer value, gpointer data) 2086 gconstpointer value, gpointer data)
2074 { 2087 {
2075 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(gtkblist->ift, 2088 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui,
2076 N_("/Tools/Mute Sounds"))), (gboolean)GPOINTER_TO_INT(value)); 2089 "/BList/ToolsMenu/MuteSounds")), (gboolean)GPOINTER_TO_INT(value));
2077 } 2090 }
2078 2091
2079 static void 2092 static void
2080 pidgin_blist_sound_method_pref_cb(const char *name, PurplePrefType type, 2093 pidgin_blist_sound_method_pref_cb(const char *name, PurplePrefType type,
2081 gconstpointer value, gpointer data) 2094 gconstpointer value, gpointer data)
2083 gboolean sensitive = TRUE; 2096 gboolean sensitive = TRUE;
2084 2097
2085 if(!strcmp(value, "none")) 2098 if(!strcmp(value, "none"))
2086 sensitive = FALSE; 2099 sensitive = FALSE;
2087 2100
2088 gtk_widget_set_sensitive(gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Mute Sounds")), sensitive); 2101 gtk_action_set_sensitive(gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/MuteSounds"), sensitive);
2089 } 2102 }
2090 2103
2091 static void 2104 static void
2092 add_buddies_from_vcard(const char *prpl_id, PurpleGroup *group, GList *list, 2105 add_buddies_from_vcard(const char *prpl_id, PurpleGroup *group, GList *list,
2093 const char *alias) 2106 const char *alias)
2113 if (account != NULL) 2126 if (account != NULL)
2114 { 2127 {
2115 for (l = list; l != NULL; l = l->next) 2128 for (l = list; l != NULL; l = l->next)
2116 { 2129 {
2117 purple_blist_request_add_buddy(account, l->data, 2130 purple_blist_request_add_buddy(account, l->data,
2118 (group ? group->name : NULL), 2131 (group ? purple_group_get_name(group) : NULL),
2119 alias); 2132 alias);
2120 } 2133 }
2121 } 2134 }
2122 2135
2123 g_list_foreach(list, (GFunc)g_free, NULL); 2136 g_list_foreach(list, (GFunc)g_free, NULL);
2294 else 2307 else
2295 { 2308 {
2296 buddy = (PurpleBuddy *)node; 2309 buddy = (PurpleBuddy *)node;
2297 } 2310 }
2298 2311
2299 gc = purple_account_get_connection(buddy->account); 2312 gc = purple_account_get_connection(purple_buddy_get_account(buddy));
2300 2313
2301 if (gc == NULL) 2314 if (gc == NULL)
2302 { 2315 {
2303 gtk_tree_path_free(sourcerow); 2316 gtk_tree_path_free(sourcerow);
2304 return; 2317 return;
2305 } 2318 }
2306 2319
2307 protocol = 2320 protocol =
2308 PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->list_icon(buddy->account, 2321 PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->list_icon(purple_buddy_get_account(buddy),
2309 buddy); 2322 buddy);
2310 2323
2311 str = g_string_new(NULL); 2324 str = g_string_new(NULL);
2312 g_string_printf(str, 2325 g_string_printf(str,
2313 "MIME-Version: 1.0\r\n" 2326 "MIME-Version: 1.0\r\n"
2314 "Content-Type: application/x-im-contact\r\n" 2327 "Content-Type: application/x-im-contact\r\n"
2315 "X-IM-Protocol: %s\r\n" 2328 "X-IM-Protocol: %s\r\n"
2316 "X-IM-Username: %s\r\n", 2329 "X-IM-Username: %s\r\n",
2317 protocol, 2330 protocol,
2318 buddy->name); 2331 purple_buddy_get_name(buddy));
2319 2332
2320 if (buddy->alias != NULL) 2333 if (purple_buddy_get_local_buddy_alias(buddy) != NULL)
2321 { 2334 {
2322 g_string_append_printf(str, 2335 g_string_append_printf(str,
2323 "X-IM-Alias: %s\r\n", 2336 "X-IM-Alias: %s\r\n",
2324 buddy->alias); 2337 purple_buddy_get_local_buddy_alias(buddy));
2325 } 2338 }
2326 2339
2327 g_string_append(str, "\r\n"); 2340 g_string_append(str, "\r\n");
2328 2341
2329 gtk_selection_data_set(data, 2342 gtk_selection_data_set(data,
2358 2371
2359 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), 2372 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel),
2360 &iter, path); 2373 &iter, path);
2361 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), 2374 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel),
2362 &iter, NODE_COLUMN, &node, -1); 2375 &iter, NODE_COLUMN, &node, -1);
2363 gtknode = node->ui_data; 2376 gtknode = purple_blist_node_get_ui_data(node);
2364 2377
2365 if (PURPLE_BLIST_NODE_IS_CONTACT(n)) { 2378 if (PURPLE_BLIST_NODE_IS_CONTACT(n)) {
2366 PurpleContact *c = (PurpleContact*)n; 2379 PurpleContact *c = (PurpleContact*)n;
2367 if (PURPLE_BLIST_NODE_IS_CONTACT(node) && gtknode->contact_expanded) { 2380 if (PURPLE_BLIST_NODE_IS_CONTACT(node) && gtknode->contact_expanded) {
2368 purple_blist_merge_contact(c, node); 2381 purple_blist_merge_contact(c, node);
2535 "can add that buddy."), NULL); 2548 "can add that buddy."), NULL);
2536 } 2549 }
2537 else 2550 else
2538 { 2551 {
2539 purple_blist_request_add_buddy(account, username, 2552 purple_blist_request_add_buddy(account, username,
2540 (group ? group->name : NULL), 2553 (group ? purple_group_get_name(group) : NULL),
2541 alias); 2554 alias);
2542 } 2555 }
2543 } 2556 }
2544 2557
2545 g_free(username); 2558 g_free(username);
2602 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), 2615 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel),
2603 &iter, NODE_COLUMN, &node, -1); 2616 &iter, NODE_COLUMN, &node, -1);
2604 2617
2605 if (PURPLE_BLIST_NODE_IS_BUDDY(node) || PURPLE_BLIST_NODE_IS_CONTACT(node)) { 2618 if (PURPLE_BLIST_NODE_IS_BUDDY(node) || PURPLE_BLIST_NODE_IS_CONTACT(node)) {
2606 PurpleBuddy *b = PURPLE_BLIST_NODE_IS_BUDDY(node) ? PURPLE_BUDDY(node) : purple_contact_get_priority_buddy(PURPLE_CONTACT(node)); 2619 PurpleBuddy *b = PURPLE_BLIST_NODE_IS_BUDDY(node) ? PURPLE_BUDDY(node) : purple_contact_get_priority_buddy(PURPLE_CONTACT(node));
2607 pidgin_dnd_file_manage(sd, b->account, b->name); 2620 pidgin_dnd_file_manage(sd, purple_buddy_get_account(b), purple_buddy_get_name(b));
2608 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); 2621 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
2609 } else { 2622 } else {
2610 gtk_drag_finish(dc, FALSE, FALSE, t); 2623 gtk_drag_finish(dc, FALSE, FALSE, t);
2611 } 2624 }
2612 } 2625 }
2675 2688
2676 if (buddy) { 2689 if (buddy) {
2677 account = purple_buddy_get_account(buddy); 2690 account = purple_buddy_get_account(buddy);
2678 } 2691 }
2679 2692
2680 if(account && account->gc) { 2693 if(account && purple_account_get_connection(account)) {
2681 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl); 2694 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account)));
2682 } 2695 }
2683 2696
2684 #if 0 2697 #if 0
2685 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons")) 2698 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"))
2686 return NULL; 2699 return NULL;
2689 /* If we have a contact then this is either a contact or a buddy and 2702 /* If we have a contact then this is either a contact or a buddy and
2690 * we want to fetch the custom icon for the contact. If we don't have 2703 * we want to fetch the custom icon for the contact. If we don't have
2691 * a contact then this is a group or some other type of node and we 2704 * a contact then this is a group or some other type of node and we
2692 * want to use that directly. */ 2705 * want to use that directly. */
2693 if (contact) { 2706 if (contact) {
2694 custom_img = purple_buddy_icons_node_find_custom_icon((PurpleBlistNode*)contact); 2707 custom_img = purple_buddy_icons_node_find_custom_icon(PURPLE_BLIST_NODE(contact));
2695 } else { 2708 } else {
2696 custom_img = purple_buddy_icons_node_find_custom_icon(node); 2709 custom_img = purple_buddy_icons_node_find_custom_icon(node);
2697 } 2710 }
2698 2711
2699 if (custom_img) { 2712 if (custom_img) {
2702 } 2715 }
2703 2716
2704 if (data == NULL) { 2717 if (data == NULL) {
2705 if (buddy) { 2718 if (buddy) {
2706 /* Not sure I like this...*/ 2719 /* Not sure I like this...*/
2707 if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name))) 2720 if (!(icon = purple_buddy_icons_find(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))))
2708 return NULL; 2721 return NULL;
2709 data = purple_buddy_icon_get_data(icon, &len); 2722 data = purple_buddy_icon_get_data(icon, &len);
2710 } 2723 }
2711 2724
2712 if(data == NULL) 2725 if(data == NULL)
2872 struct tooltip_data *td = g_new0(struct tooltip_data, 1); 2885 struct tooltip_data *td = g_new0(struct tooltip_data, 1);
2873 PurpleAccount *account = NULL; 2886 PurpleAccount *account = NULL;
2874 char *tmp = NULL, *node_name = NULL, *tooltip_text = NULL; 2887 char *tmp = NULL, *node_name = NULL, *tooltip_text = NULL;
2875 2888
2876 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { 2889 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
2877 account = ((PurpleBuddy*)(node))->account; 2890 account = purple_buddy_get_account((PurpleBuddy*)(node));
2878 } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { 2891 } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
2879 account = ((PurpleChat*)(node))->account; 2892 account = purple_chat_get_account((PurpleChat*)(node));
2880 } 2893 }
2881 2894
2882 td->padding = TOOLTIP_BORDER; 2895 td->padding = TOOLTIP_BORDER;
2883 td->status_icon = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_LARGE); 2896 td->status_icon = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_LARGE);
2884 td->avatar = pidgin_blist_get_buddy_icon(node, !full, FALSE); 2897 td->avatar = pidgin_blist_get_buddy_icon(node, !full, FALSE);
2928 2941
2929 static gboolean 2942 static gboolean
2930 pidgin_blist_paint_tip(GtkWidget *widget, gpointer null) 2943 pidgin_blist_paint_tip(GtkWidget *widget, gpointer null)
2931 { 2944 {
2932 GtkStyle *style; 2945 GtkStyle *style;
2946 cairo_t *cr;
2933 int current_height, max_width; 2947 int current_height, max_width;
2934 int max_text_width; 2948 int max_text_width;
2935 int max_avatar_width; 2949 int max_avatar_width;
2936 GList *l; 2950 GList *l;
2937 int prpl_col = 0; 2951 int prpl_col = 0;
2961 if (dir == GTK_TEXT_DIR_RTL) 2975 if (dir == GTK_TEXT_DIR_RTL)
2962 prpl_col = TOOLTIP_BORDER + max_avatar_width + SMALL_SPACE; 2976 prpl_col = TOOLTIP_BORDER + max_avatar_width + SMALL_SPACE;
2963 else 2977 else
2964 prpl_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PRPL_SIZE; 2978 prpl_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PRPL_SIZE;
2965 2979
2980 cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(gtkblist->tipwindow)));
2966 current_height = 12; 2981 current_height = 12;
2967 for(l = gtkblist->tooltipdata; l; l = l->next) 2982 for(l = gtkblist->tooltipdata; l; l = l->next)
2968 { 2983 {
2969 struct tooltip_data *td = l->data; 2984 struct tooltip_data *td = l->data;
2970 2985
2980 max_width - (td->avatar_width+ TOOLTIP_BORDER)-1, 2995 max_width - (td->avatar_width+ TOOLTIP_BORDER)-1,
2981 current_height-1,td->avatar_width+2, td->avatar_height+2); 2996 current_height-1,td->avatar_width+2, td->avatar_height+2);
2982 } 2997 }
2983 2998
2984 if (td->status_icon) { 2999 if (td->status_icon) {
2985 if (dir == GTK_TEXT_DIR_RTL) 3000 if (dir == GTK_TEXT_DIR_RTL) {
2986 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, td->status_icon, 3001 gdk_cairo_set_source_pixbuf(cr, td->status_icon,
2987 0, 0, max_width - TOOLTIP_BORDER - status_size, current_height, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); 3002 max_width - TOOLTIP_BORDER - status_size,
2988 else 3003 current_height);
2989 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, td->status_icon, 3004 cairo_paint(cr);
2990 0, 0, TOOLTIP_BORDER, current_height, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); 3005 } else {
3006 gdk_cairo_set_source_pixbuf(cr, td->status_icon,
3007 TOOLTIP_BORDER, current_height);
3008 cairo_paint(cr);
3009 }
2991 } 3010 }
2992 3011
2993 if(td->avatar) { 3012 if(td->avatar) {
2994 if (dir == GTK_TEXT_DIR_RTL) 3013 if (dir == GTK_TEXT_DIR_RTL) {
2995 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, 3014 gdk_cairo_set_source_pixbuf(cr, td->avatar,
2996 td->avatar, 0, 0, TOOLTIP_BORDER, current_height, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); 3015 TOOLTIP_BORDER, current_height);
2997 else 3016 cairo_paint(cr);
2998 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, 3017 } else {
2999 td->avatar, 0, 0, max_width - (td->avatar_width + TOOLTIP_BORDER), 3018 gdk_cairo_set_source_pixbuf(cr, td->avatar,
3000 current_height, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); 3019 max_width - (td->avatar_width + TOOLTIP_BORDER),
3001 } 3020 current_height);
3002 3021 cairo_paint(cr);
3003 if (!td->avatar_is_prpl_icon && td->prpl_icon) 3022 }
3004 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, td->prpl_icon, 3023 }
3005 0, 0, 3024
3006 prpl_col, 3025 if (!td->avatar_is_prpl_icon && td->prpl_icon) {
3007 current_height + ((td->name_height / 2) - (PRPL_SIZE / 2)), 3026 gdk_cairo_set_source_pixbuf(cr, td->prpl_icon, prpl_col,
3008 -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); 3027 current_height +
3028 (td->name_height - PRPL_SIZE) / 2);
3029 cairo_paint(cr);
3030 }
3009 3031
3010 if (td->name_layout) { 3032 if (td->name_layout) {
3011 if (dir == GTK_TEXT_DIR_RTL) { 3033 if (dir == GTK_TEXT_DIR_RTL) {
3012 gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE, 3034 gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
3013 NULL, gtkblist->tipwindow, "tooltip", 3035 NULL, gtkblist->tipwindow, "tooltip",
3034 } 3056 }
3035 } 3057 }
3036 3058
3037 current_height += MAX(td->name_height + td->height, td->avatar_height) + td->padding; 3059 current_height += MAX(td->name_height + td->height, td->avatar_height) + td->padding;
3038 } 3060 }
3061
3062 cairo_destroy(cr);
3039 return FALSE; 3063 return FALSE;
3040 } 3064 }
3041 3065
3042 static void 3066 static void
3043 pidgin_blist_destroy_tooltip_data(void) 3067 pidgin_blist_destroy_tooltip_data(void)
3174 if(!PURPLE_BLIST_NODE_IS_CONTACT(node)) { 3198 if(!PURPLE_BLIST_NODE_IS_CONTACT(node)) {
3175 gtk_tree_path_free(path); 3199 gtk_tree_path_free(path);
3176 return FALSE; 3200 return FALSE;
3177 } 3201 }
3178 3202
3179 gtknode = node->ui_data; 3203 gtknode = purple_blist_node_get_ui_data(node);
3180 3204
3181 if (!gtknode->contact_expanded) { 3205 if (!gtknode->contact_expanded) {
3182 GtkTreeIter i; 3206 GtkTreeIter i;
3183 3207
3184 pidgin_blist_expand_contact_cb(NULL, node); 3208 pidgin_blist_expand_contact_cb(NULL, node);
3203 struct _pidgin_blist_node *gtknode; 3227 struct _pidgin_blist_node *gtknode;
3204 3228
3205 if(!buddy) 3229 if(!buddy)
3206 return FALSE; 3230 return FALSE;
3207 3231
3208 gtknode = ((PurpleBlistNode*)buddy)->ui_data; 3232 gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
3209 3233
3210 return (purple_account_is_connected(buddy->account) && 3234 return (purple_account_is_connected(purple_buddy_get_account(buddy)) &&
3211 (purple_presence_is_online(buddy->presence) || 3235 (purple_presence_is_online(purple_buddy_get_presence(buddy)) ||
3212 (gtknode && gtknode->recent_signonoff) || 3236 (gtknode && gtknode->recent_signonoff) ||
3213 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies") || 3237 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies") ||
3214 purple_blist_node_get_bool((PurpleBlistNode*)buddy, "show_offline"))); 3238 purple_blist_node_get_bool(PURPLE_BLIST_NODE(buddy), "show_offline")));
3215 } 3239 }
3216 3240
3217 void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget) 3241 void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget)
3218 { 3242 {
3219 pidgin_tooltip_show(widget, node, pidgin_blist_create_tooltip_for_node, pidgin_blist_paint_tip); 3243 pidgin_tooltip_show(widget, node, pidgin_blist_create_tooltip_for_node, pidgin_blist_paint_tip);
3384 3408
3385 if (gc) { 3409 if (gc) {
3386 const char *text; 3410 const char *text;
3387 PurpleAccount *account = purple_connection_get_account(gc); 3411 PurpleAccount *account = purple_connection_get_account(gc);
3388 3412
3389 if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES) { 3413 if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES) {
3390 PurpleRequestField *text_field; 3414 PurpleRequestField *text_field;
3391 text_field = purple_request_fields_get_field(fields, "text"); 3415 text_field = purple_request_fields_get_field(fields, "text");
3392 text = purple_request_field_string_get_value(text_field); 3416 text = purple_request_field_string_get_value(text_field);
3393 } else { 3417 } else {
3394 text = NULL; 3418 text = NULL;
3400 3424
3401 for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) { 3425 for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
3402 PurpleAccount *account = (PurpleAccount *) accounts->data; 3426 PurpleAccount *account = (PurpleAccount *) accounts->data;
3403 PurpleConnection *gc = purple_account_get_connection(account); 3427 PurpleConnection *gc = purple_account_get_connection(account);
3404 3428
3405 if (gc && gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) { 3429 if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS)) {
3406 update_status_with_mood(account, mood, NULL); 3430 update_status_with_mood(account, mood, NULL);
3407 } 3431 }
3408 } 3432 }
3409 } 3433 }
3410 } 3434 }
3435 for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) { 3459 for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
3436 PurpleAccount *account = (PurpleAccount *) accounts->data; 3460 PurpleAccount *account = (PurpleAccount *) accounts->data;
3437 if (purple_account_is_connected(account)) { 3461 if (purple_account_is_connected(account)) {
3438 PurpleConnection *gc = purple_account_get_connection(account); 3462 PurpleConnection *gc = purple_account_get_connection(account);
3439 3463
3440 if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) { 3464 if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS) {
3441 PurplePluginProtocolInfo *prpl_info = 3465 PurplePluginProtocolInfo *prpl_info =
3442 PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 3466 PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
3443 PurpleMood *mood = NULL; 3467 PurpleMood *mood = NULL;
3444 3468
3445 /* PURPLE_CONNECTION_SUPPORT_MOODS would not be set if the prpl doesn't 3469 /* PURPLE_CONNECTION_SUPPORT_MOODS would not be set if the prpl doesn't
3446 * have get_moods, so using PURPLE_PROTOCOL_PLUGIN_HAS_FUNC isn't necessary 3470 * have get_moods, so using PURPLE_PROTOCOL_PLUGIN_HAS_FUNC isn't necessary
3447 * here */ 3471 * here */
3495 3519
3496 for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) { 3520 for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
3497 PurpleAccount *account = (PurpleAccount *) accounts->data; 3521 PurpleAccount *account = (PurpleAccount *) accounts->data;
3498 3522
3499 if (purple_account_is_connected(account) && 3523 if (purple_account_is_connected(account) &&
3500 (purple_account_get_connection(account)->flags & 3524 (purple_connection_get_flags(purple_account_get_connection(account)) &
3501 PURPLE_CONNECTION_SUPPORT_MOODS)) { 3525 PURPLE_CONNECTION_SUPPORT_MOODS)) {
3502 PurplePresence *presence = purple_account_get_presence(account); 3526 PurplePresence *presence = purple_account_get_presence(account);
3503 PurpleStatus *status = purple_presence_get_status(presence, "mood"); 3527 PurpleStatus *status = purple_presence_get_status(presence, "mood");
3504 const gchar *curr_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME); 3528 const gchar *curr_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
3505 3529
3530 3554
3531 if (account) { 3555 if (account) {
3532 PurplePresence *presence = purple_account_get_presence(account); 3556 PurplePresence *presence = purple_account_get_presence(account);
3533 PurpleStatus *status = purple_presence_get_status(presence, "mood"); 3557 PurpleStatus *status = purple_presence_get_status(presence, "mood");
3534 gc = purple_account_get_connection(account); 3558 gc = purple_account_get_connection(account);
3535 g_return_if_fail(gc->prpl != NULL); 3559 g_return_if_fail(purple_connection_get_prpl(gc) != NULL);
3536 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); 3560 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
3537 current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME); 3561 current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
3538 } else { 3562 } else {
3539 current_mood = get_global_mood_status(); 3563 current_mood = get_global_mood_status();
3540 } 3564 }
3541 3565
3542 fields = purple_request_fields_new(); 3566 fields = purple_request_fields_new();
3543 g = purple_request_field_group_new(NULL); 3567 g = purple_request_field_group_new(NULL);
3544 f = purple_request_field_list_new("mood", _("Please select your mood from the list")); 3568 f = purple_request_field_list_new("mood", _("Please select your mood from the list"));
3545 3569
3546 purple_request_field_list_add(f, _("None"), ""); 3570 purple_request_field_list_add_icon(f, _("None"), NULL, "");
3547 if (current_mood == NULL) 3571 if (current_mood == NULL)
3548 purple_request_field_list_add_selected(f, _("None")); 3572 purple_request_field_list_add_selected(f, _("None"));
3549 3573
3550 /* TODO: rlaager wants this sorted. */ 3574 /* TODO: rlaager wants this sorted. */
3551 /* TODO: darkrain wants it sorted post-translation */ 3575 /* TODO: darkrain wants it sorted post-translation */
3570 purple_request_field_group_add_field(g, f); 3594 purple_request_field_group_add_field(g, f);
3571 3595
3572 purple_request_fields_add_group(fields, g); 3596 purple_request_fields_add_group(fields, g);
3573 3597
3574 /* if the connection allows setting a mood message */ 3598 /* if the connection allows setting a mood message */
3575 if (gc && (gc->flags & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES)) { 3599 if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES)) {
3576 g = purple_request_field_group_new(NULL); 3600 g = purple_request_field_group_new(NULL);
3577 f = purple_request_field_string_new("text", 3601 f = purple_request_field_string_new("text",
3578 _("Message (optional)"), NULL, FALSE); 3602 _("Message (optional)"), NULL, FALSE);
3579 purple_request_field_group_add_field(g, f); 3603 purple_request_field_group_add_field(g, f);
3580 purple_request_fields_add_group(fields, g); 3604 purple_request_fields_add_group(fields, g);
3597 } 3621 }
3598 3622
3599 /*************************************************** 3623 /***************************************************
3600 * Crap * 3624 * Crap *
3601 ***************************************************/ 3625 ***************************************************/
3602 static GtkItemFactoryEntry blist_menu[] = 3626 /* TODO: fill out tooltips... */
3603 { 3627 static const GtkActionEntry blist_menu_entries[] = {
3604 /* NOTE: Do not set any accelerator to Control+O. It is mapped by 3628 /* NOTE: Do not set any accelerator to Control+O. It is mapped by
3605 gtk_blist_key_press_cb to "Get User Info" on the selected buddy. */ 3629 gtk_blist_key_press_cb to "Get User Info" on the selected buddy. */
3606
3607 /* Buddies menu */ 3630 /* Buddies menu */
3608 { N_("/_Buddies"), NULL, NULL, 0, "<Branch>", NULL }, 3631 { "BuddiesMenu", NULL, N_("_Buddies"), NULL, NULL, NULL },
3609 { N_("/Buddies/New Instant _Message..."), "<CTL>M", pidgin_dialogs_im, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW }, 3632 { "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "<control>M", NULL, pidgin_dialogs_im },
3610 { N_("/Buddies/Join a _Chat..."), "<CTL>C", pidgin_blist_joinchat_show, 0, "<StockItem>", PIDGIN_STOCK_CHAT }, 3633 { "JoinAChat", PIDGIN_STOCK_CHAT, N_("Join a _Chat..."), "<control>C", NULL, pidgin_blist_joinchat_show },
3611 { N_("/Buddies/Get User _Info..."), "<CTL>I", pidgin_dialogs_info, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_USER_INFO }, 3634 { "GetUserInfo", PIDGIN_STOCK_TOOLBAR_USER_INFO, N_("Get User _Info..."), "<control>I", NULL, pidgin_dialogs_info },
3612 { N_("/Buddies/View User _Log..."), "<CTL>L", pidgin_dialogs_log, 0, "<Item>", NULL }, 3635 { "ViewUserLog", NULL, N_("View User _Log..."), "<control>L", NULL, pidgin_dialogs_log },
3613 { "/Buddies/sep1", NULL, NULL, 0, "<Separator>", NULL }, 3636 { "ShowMenu", NULL, N_("Sh_ow"), NULL, NULL, NULL },
3614 { N_("/Buddies/Sh_ow"), NULL, NULL, 0, "<Branch>", NULL}, 3637 { "SortMenu", NULL, N_("_Sort Buddies"), NULL, NULL, NULL },
3615 { N_("/Buddies/Show/_Offline Buddies"), NULL, pidgin_blist_edit_mode_cb, 1, "<CheckItem>", NULL }, 3638 { "AddBuddy", GTK_STOCK_ADD, N_("_Add Buddy..."), "<control>B", NULL, pidgin_blist_add_buddy_cb },
3616 { N_("/Buddies/Show/_Empty Groups"), NULL, pidgin_blist_show_empty_groups_cb, 1, "<CheckItem>", NULL }, 3639 { "AddChat", GTK_STOCK_ADD, N_("Add C_hat..."), NULL, NULL, pidgin_blist_add_chat_cb },
3617 { N_("/Buddies/Show/Buddy _Details"), NULL, pidgin_blist_buddy_details_cb, 1, "<CheckItem>", NULL }, 3640 { "AddGroup", GTK_STOCK_ADD, N_("Add _Group..."), NULL, NULL, purple_blist_request_add_group },
3618 { N_("/Buddies/Show/Idle _Times"), NULL, pidgin_blist_show_idle_time_cb, 1, "<CheckItem>", NULL }, 3641 { "Quit", GTK_STOCK_QUIT, N_("_Quit"), "<control>Q", NULL, purple_core_quit },
3619 { N_("/Buddies/Show/_Protocol Icons"), NULL, pidgin_blist_show_protocol_icons_cb, 1, "<CheckItem>", NULL },
3620 { N_("/Buddies/_Sort Buddies"), NULL, NULL, 0, "<Branch>", NULL },
3621 { "/Buddies/sep2", NULL, NULL, 0, "<Separator>", NULL },
3622 { N_("/Buddies/_Add Buddy..."), "<CTL>B", pidgin_blist_add_buddy_cb, 0, "<StockItem>", GTK_STOCK_ADD },
3623 { N_("/Buddies/Add C_hat..."), NULL, pidgin_blist_add_chat_cb, 0, "<StockItem>", GTK_STOCK_ADD },
3624 { N_("/Buddies/Add _Group..."), NULL, purple_blist_request_add_group, 0, "<StockItem>", GTK_STOCK_ADD },
3625 { "/Buddies/sep3", NULL, NULL, 0, "<Separator>", NULL },
3626 { N_("/Buddies/_Quit"), "<CTL>Q", purple_core_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
3627 3642
3628 /* Accounts menu */ 3643 /* Accounts menu */
3629 { N_("/_Accounts"), NULL, NULL, 0, "<Branch>", NULL }, 3644 { "AccountsMenu", NULL, N_("_Accounts"), NULL, NULL, NULL },
3630 { N_("/Accounts/Manage Accounts"), "<CTL>A", pidgin_accounts_window_show, 0, "<Item>", NULL }, 3645 { "ManageAccounts", NULL, N_("Manage Accounts"), "<control>A", NULL, pidgin_accounts_window_show },
3631 3646
3632 /* Tools */ 3647 /* Tools */
3633 { N_("/_Tools"), NULL, NULL, 0, "<Branch>", NULL }, 3648 { "ToolsMenu", NULL, N_("_Tools"), NULL, NULL, NULL },
3634 { N_("/Tools/Buddy _Pounces"), NULL, pidgin_pounces_manager_show, 1, "<Item>", NULL }, 3649 { "BuddyPounces", NULL, N_("Buddy _Pounces"), NULL, NULL, pidgin_pounces_manager_show },
3635 { N_("/Tools/_Certificates"), NULL, pidgin_certmgr_show, 0, "<Item>", NULL }, 3650 { "Certificates", NULL, N_("_Certificates"), NULL, NULL, pidgin_certmgr_show },
3636 { N_("/Tools/Custom Smile_ys"), "<CTL>Y", pidgin_smiley_manager_show, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SMILEY }, 3651 { "CustomSmileys", PIDGIN_STOCK_TOOLBAR_SMILEY, N_("Custom Smile_ys"), "<control>Y", NULL, pidgin_smiley_manager_show },
3637 { N_("/Tools/Plu_gins"), "<CTL>U", pidgin_plugin_dialog_show, 2, "<StockItem>", PIDGIN_STOCK_TOOLBAR_PLUGINS }, 3652 { "Plugins", PIDGIN_STOCK_TOOLBAR_PLUGINS, N_("Plu_gins"), "<control>U", NULL, pidgin_plugin_dialog_show },
3638 { N_("/Tools/Pr_eferences"), "<CTL>P", pidgin_prefs_show, 0, "<StockItem>", GTK_STOCK_PREFERENCES }, 3653 { "Preferences", GTK_STOCK_PREFERENCES, N_("Pr_eferences"), "<control>P", NULL, pidgin_prefs_show },
3639 { N_("/Tools/Pr_ivacy"), NULL, pidgin_privacy_dialog_show, 0, "<Item>", NULL }, 3654 { "Privacy", NULL, N_("Pr_ivacy"), NULL, NULL, pidgin_privacy_dialog_show },
3640 { N_("/Tools/Set _Mood"), "<CTL>D", set_mood_show, 0, "<Item>", NULL }, 3655 { "SetMood", NULL, N_("Set _Mood"), "<control>D", NULL, set_mood_show },
3641 { "/Tools/sep2", NULL, NULL, 0, "<Separator>", NULL }, 3656 { "FileTransfers", PIDGIN_STOCK_TOOLBAR_TRANSFER, N_("_File Transfers"), "<control>T", NULL, G_CALLBACK(gtk_blist_show_xfer_dialog_cb) },
3642 { N_("/Tools/_File Transfers"), "<CTL>T", pidgin_xfer_dialog_show, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_TRANSFER }, 3657 { "RoomList", NULL, N_("R_oom List"), NULL, NULL, pidgin_roomlist_dialog_show },
3643 { N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL }, 3658 { "SystemLog", NULL, N_("System _Log"), NULL, NULL, gtk_blist_show_systemlog_cb },
3644 { N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 3, "<Item>", NULL }, 3659
3645 { "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL },
3646 { N_("/Tools/Mute _Sounds"), NULL, pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL },
3647 /* Help */ 3660 /* Help */
3648 { N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL }, 3661 { "HelpMenu", NULL, N_("_Help"), NULL, NULL, NULL },
3649 { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP }, 3662 { "OnlineHelp", GTK_STOCK_HELP, N_("Online _Help"), "F1", NULL, gtk_blist_show_onlinehelp_cb },
3650 { "/Help/sep1", NULL, NULL, 0, "<Separator>", NULL }, 3663 { "BuildInformation", NULL, N_("_Build Information"), NULL, NULL, pidgin_dialogs_buildinfo },
3651 { N_("/Help/_Build Information"), NULL, pidgin_dialogs_buildinfo, 0, "<Item>", NULL }, 3664 { "DebugWindow", NULL, N_("_Debug Window"), NULL, NULL, toggle_debug },
3652 { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL }, 3665 { "DeveloperInformation", NULL, N_("De_veloper Information"), NULL, NULL, pidgin_dialogs_developers },
3653 { N_("/Help/De_veloper Information"), NULL, pidgin_dialogs_developers, 0, "<Item>", NULL }, 3666 { "PluginInformation", NULL, N_("_Plugin Information"), NULL, NULL, pidgin_dialogs_plugins_info },
3654 { N_("/Help/_Plugin Information"), NULL, pidgin_dialogs_plugins_info, 0, "<Item>", NULL }, 3667 { "TranslatorInformation", NULL, N_("_Translator Information"), NULL, NULL, pidgin_dialogs_translators },
3655 { N_("/Help/_Translator Information"), NULL, pidgin_dialogs_translators, 0, "<Item>", NULL }, 3668 { "About", GTK_STOCK_ABOUT, N_("_About"), NULL, NULL, pidgin_dialogs_about },
3656 { "/Help/sep2", NULL, NULL, 0, "<Separator>", NULL },
3657 { N_("/Help/_About"), NULL, pidgin_dialogs_about, 4, "<StockItem>", GTK_STOCK_ABOUT },
3658 }; 3669 };
3670
3671 /* Toggle items */
3672 static const GtkToggleActionEntry blist_menu_toggle_entries[] = {
3673 /* Buddies->Show menu */
3674 { "ShowOffline", NULL, N_("_Offline Buddies"), NULL, NULL, G_CALLBACK(pidgin_blist_edit_mode_cb), FALSE },
3675 { "ShowEmptyGroups", NULL, N_("_Empty Groups"), NULL, NULL, G_CALLBACK(pidgin_blist_show_empty_groups_cb), FALSE },
3676 { "ShowBuddyDetails", NULL, N_("Buddy _Details"), NULL, NULL, G_CALLBACK(pidgin_blist_buddy_details_cb), FALSE },
3677 { "ShowIdleTimes", NULL, N_("Idle _Times"), NULL, NULL, G_CALLBACK(pidgin_blist_show_idle_time_cb), FALSE },
3678 { "ShowProtocolIcons", NULL, N_("_Protocol Icons"), NULL, NULL, G_CALLBACK(pidgin_blist_show_protocol_icons_cb), FALSE },
3679
3680 /* Tools menu */
3681 { "MuteSounds", NULL, N_("Mute _Sounds"), NULL, NULL, G_CALLBACK(pidgin_blist_mute_sounds_cb), FALSE },
3682 };
3683
3684 static const char *blist_menu =
3685 "<ui>"
3686 "<menubar name='BList'>"
3687 "<menu action='BuddiesMenu'>"
3688 "<menuitem action='NewInstantMessage'/>"
3689 "<menuitem action='JoinAChat'/>"
3690 "<menuitem action='GetUserInfo'/>"
3691 "<menuitem action='ViewUserLog'/>"
3692 "<separator/>"
3693 "<menu action='ShowMenu'>"
3694 "<menuitem action='ShowOffline'/>"
3695 "<menuitem action='ShowEmptyGroups'/>"
3696 "<menuitem action='ShowBuddyDetails'/>"
3697 "<menuitem action='ShowIdleTimes'/>"
3698 "<menuitem action='ShowProtocolIcons'/>"
3699 "</menu>"
3700 "<menu action='SortMenu'/>"
3701 "<separator/>"
3702 "<menuitem action='AddBuddy'/>"
3703 "<menuitem action='AddChat'/>"
3704 "<menuitem action='AddGroup'/>"
3705 "<separator/>"
3706 "<menuitem action='Quit'/>"
3707 "</menu>"
3708 "<menu action='AccountsMenu'>"
3709 "<menuitem action='ManageAccounts'/>"
3710 "</menu>"
3711 "<menu action='ToolsMenu'>"
3712 "<menuitem action='BuddyPounces'/>"
3713 "<menuitem action='Certificates'/>"
3714 "<menuitem action='CustomSmileys'/>"
3715 "<menuitem action='Plugins'/>"
3716 "<menuitem action='Preferences'/>"
3717 "<menuitem action='Privacy'/>"
3718 "<menuitem action='SetMood'/>"
3719 "<separator/>"
3720 "<menuitem action='FileTransfers'/>"
3721 "<menuitem action='RoomList'/>"
3722 "<menuitem action='SystemLog'/>"
3723 "<separator/>"
3724 "<menuitem action='MuteSounds'/>"
3725 "<placeholder name='PluginActions'/>"
3726 "</menu>"
3727 "<menu action='HelpMenu'>"
3728 "<menuitem action='OnlineHelp'/>"
3729 "<separator/>"
3730 "<menuitem action='BuildInformation'/>"
3731 "<menuitem action='DebugWindow'/>"
3732 "<menuitem action='DeveloperInformation'/>"
3733 "<menuitem action='PluginInformation'/>"
3734 "<menuitem action='TranslatorInformation'/>"
3735 "<separator/>"
3736 "<menuitem action='About'/>"
3737 "</menu>"
3738 "</menubar>"
3739 "</ui>";
3659 3740
3660 /********************************************************* 3741 /*********************************************************
3661 * Private Utility functions * 3742 * Private Utility functions *
3662 *********************************************************/ 3743 *********************************************************/
3663 3744
3674 GList *connections; 3755 GList *connections;
3675 GList *cur; 3756 GList *cur;
3676 struct proto_chat_entry *pce; 3757 struct proto_chat_entry *pce;
3677 char *name, *value; 3758 char *name, *value;
3678 PurpleConversation *conv; 3759 PurpleConversation *conv;
3679 PidginBlistNode *bnode = node->ui_data; 3760 PidginBlistNode *bnode = purple_blist_node_get_ui_data(node);
3680 3761
3681 chat = (PurpleChat *)node; 3762 chat = (PurpleChat *)node;
3682 prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account)); 3763 prpl = purple_find_prpl(purple_account_get_protocol_id(purple_chat_get_account(chat)));
3683 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 3764 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
3684 3765
3685 connections = purple_connections_get_all(); 3766 connections = purple_connections_get_all();
3686 if (connections && connections->next) 3767 if (connections && connections->next)
3687 { 3768 {
3688 tmp = g_markup_escape_text(chat->account->username, -1); 3769 tmp = g_markup_escape_text(purple_account_get_username(purple_chat_get_account(chat)), -1);
3689 g_string_append_printf(str, _("<b>Account:</b> %s"), tmp); 3770 g_string_append_printf(str, _("<b>Account:</b> %s"), tmp);
3690 g_free(tmp); 3771 g_free(tmp);
3691 } 3772 }
3692 3773
3693 if (bnode && bnode->conv.conv) { 3774 if (bnode && bnode->conv.conv) {
3694 conv = bnode->conv.conv; 3775 conv = bnode->conv.conv;
3695 } else { 3776 } else {
3696 char *chat_name; 3777 char *chat_name;
3697 if (prpl_info && prpl_info->get_chat_name) 3778 if (prpl_info && prpl_info->get_chat_name)
3698 chat_name = prpl_info->get_chat_name(chat->components); 3779 chat_name = prpl_info->get_chat_name(purple_chat_get_components(chat));
3699 else 3780 else
3700 chat_name = g_strdup(purple_chat_get_name(chat)); 3781 chat_name = g_strdup(purple_chat_get_name(chat));
3701 3782
3702 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, chat_name, 3783 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, chat_name,
3703 chat->account); 3784 purple_chat_get_account(chat));
3704 g_free(chat_name); 3785 g_free(chat_name);
3705 } 3786 }
3706 3787
3707 if (conv && !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) { 3788 if (conv && !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) {
3708 g_string_append_printf(str, _("\n<b>Occupants:</b> %d"), 3789 g_string_append_printf(str, _("\n<b>Occupants:</b> %d"),
3715 g_free(topic); 3796 g_free(topic);
3716 } 3797 }
3717 } 3798 }
3718 3799
3719 if (prpl_info && prpl_info->chat_info != NULL) 3800 if (prpl_info && prpl_info->chat_info != NULL)
3720 cur = prpl_info->chat_info(chat->account->gc); 3801 cur = prpl_info->chat_info(purple_account_get_connection(purple_chat_get_account(chat)));
3721 else 3802 else
3722 cur = NULL; 3803 cur = NULL;
3723 3804
3724 while (cur != NULL) 3805 while (cur != NULL)
3725 { 3806 {
3726 pce = cur->data; 3807 pce = cur->data;
3727 3808
3728 if (!pce->secret && (!pce->required && 3809 if (!pce->secret && (!pce->required &&
3729 g_hash_table_lookup(chat->components, pce->identifier) == NULL)) 3810 g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier) == NULL))
3730 { 3811 {
3731 tmp = purple_text_strip_mnemonic(pce->label); 3812 tmp = purple_text_strip_mnemonic(pce->label);
3732 name = g_markup_escape_text(tmp, -1); 3813 name = g_markup_escape_text(tmp, -1);
3733 g_free(tmp); 3814 g_free(tmp);
3734 value = g_markup_escape_text(g_hash_table_lookup( 3815 value = g_markup_escape_text(g_hash_table_lookup(
3735 chat->components, pce->identifier), -1); 3816 purple_chat_get_components(chat), pce->identifier), -1);
3736 g_string_append_printf(str, "\n<b>%s</b> %s", 3817 g_string_append_printf(str, "\n<b>%s</b> %s",
3737 name ? name : "", 3818 name ? name : "",
3738 value ? value : ""); 3819 value ? value : "");
3739 g_free(name); 3820 g_free(name);
3740 g_free(value); 3821 g_free(value);
3766 { 3847 {
3767 b = (PurpleBuddy *)node; 3848 b = (PurpleBuddy *)node;
3768 c = purple_buddy_get_contact(b); 3849 c = purple_buddy_get_contact(b);
3769 } 3850 }
3770 3851
3771 prpl = purple_find_prpl(purple_account_get_protocol_id(b->account)); 3852 prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b)));
3772 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 3853 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
3773 3854
3774 presence = purple_buddy_get_presence(b); 3855 presence = purple_buddy_get_presence(b);
3775 user_info = purple_notify_user_info_new(); 3856 user_info = purple_notify_user_info_new();
3776 3857
3777 /* Account */ 3858 /* Account */
3778 connections = purple_connections_get_all(); 3859 connections = purple_connections_get_all();
3779 if (full && connections && connections->next) 3860 if (full && connections && connections->next)
3780 { 3861 {
3781 tmp = g_markup_escape_text(purple_account_get_username( 3862 purple_notify_user_info_add_pair_plaintext(user_info, _("Account"),
3782 purple_buddy_get_account(b)), -1); 3863 purple_account_get_username(purple_buddy_get_account(b)));
3783 purple_notify_user_info_add_pair(user_info, _("Account"), tmp);
3784 g_free(tmp);
3785 } 3864 }
3786 3865
3787 /* Alias */ 3866 /* Alias */
3788 /* If there's not a contact alias, the node is being displayed with 3867 /* If there's not a contact alias, the node is being displayed with
3789 * this alias, so there's no point in showing it in the tooltip. */ 3868 * this alias, so there's no point in showing it in the tooltip. */
3790 if (full && c && b->alias != NULL && b->alias[0] != '\0' && 3869 if (full && c && purple_buddy_get_local_buddy_alias(b) != NULL && purple_buddy_get_local_buddy_alias(b)[0] != '\0' &&
3791 (c->alias != NULL && c->alias[0] != '\0') && 3870 (c->alias != NULL && c->alias[0] != '\0') &&
3792 strcmp(c->alias, b->alias) != 0) 3871 strcmp(c->alias, purple_buddy_get_local_buddy_alias(b)) != 0)
3793 { 3872 {
3794 tmp = g_markup_escape_text(b->alias, -1); 3873 purple_notify_user_info_add_pair_plaintext(user_info,
3795 purple_notify_user_info_add_pair(user_info, _("Buddy Alias"), tmp); 3874 _("Buddy Alias"), purple_buddy_get_local_buddy_alias(b));
3796 g_free(tmp);
3797 } 3875 }
3798 3876
3799 /* Nickname/Server Alias */ 3877 /* Nickname/Server Alias */
3800 /* I'd like to only show this if there's a contact or buddy 3878 /* I'd like to only show this if there's a contact or buddy
3801 * alias, but many people on MSN set long nicknames, which 3879 * alias, but many people on MSN set long nicknames, which
3802 * get ellipsized, so the only way to see the whole thing is 3880 * get ellipsized, so the only way to see the whole thing is
3803 * to look at the tooltip. */ 3881 * to look at the tooltip. */
3804 if (full && b->server_alias != NULL && b->server_alias[0] != '\0') 3882 if (full && purple_buddy_get_server_alias(b))
3805 { 3883 {
3806 tmp = g_markup_escape_text(b->server_alias, -1); 3884 purple_notify_user_info_add_pair_plaintext(user_info,
3807 purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); 3885 _("Nickname"), purple_buddy_get_server_alias(b));
3808 g_free(tmp);
3809 } 3886 }
3810 3887
3811 /* Logged In */ 3888 /* Logged In */
3812 signon = purple_presence_get_login_time(presence); 3889 signon = purple_presence_get_login_time(presence);
3813 if (full && PURPLE_BUDDY_IS_ONLINE(b) && signon > 0) 3890 if (full && PURPLE_BUDDY_IS_ONLINE(b) && signon > 0)
3819 * "4 days", etc. 3896 * "4 days", etc.
3820 */ 3897 */
3821 tmp = g_strdup(purple_date_format_long(localtime(&signon))); 3898 tmp = g_strdup(purple_date_format_long(localtime(&signon)));
3822 } else 3899 } else
3823 tmp = purple_str_seconds_to_string(time(NULL) - signon); 3900 tmp = purple_str_seconds_to_string(time(NULL) - signon);
3824 purple_notify_user_info_add_pair(user_info, _("Logged In"), tmp); 3901 purple_notify_user_info_add_pair_plaintext(user_info, _("Logged In"), tmp);
3825 g_free(tmp); 3902 g_free(tmp);
3826 } 3903 }
3827 3904
3828 /* Idle */ 3905 /* Idle */
3829 if (purple_presence_is_idle(presence)) 3906 if (purple_presence_is_idle(presence))
3830 { 3907 {
3831 idle_secs = purple_presence_get_idle_time(presence); 3908 idle_secs = purple_presence_get_idle_time(presence);
3832 if (idle_secs > 0) 3909 if (idle_secs > 0)
3833 { 3910 {
3834 tmp = purple_str_seconds_to_string(time(NULL) - idle_secs); 3911 tmp = purple_str_seconds_to_string(time(NULL) - idle_secs);
3835 purple_notify_user_info_add_pair(user_info, _("Idle"), tmp); 3912 purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), tmp);
3836 g_free(tmp); 3913 g_free(tmp);
3837 } 3914 }
3838 } 3915 }
3839 3916
3840 /* Last Seen */ 3917 /* Last Seen */
3841 if (full && c && !PURPLE_BUDDY_IS_ONLINE(b)) 3918 if (full && c && !PURPLE_BUDDY_IS_ONLINE(b))
3842 { 3919 {
3843 struct _pidgin_blist_node *gtknode = ((PurpleBlistNode *)c)->ui_data; 3920 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(c));
3844 PurpleBlistNode *bnode; 3921 PurpleBlistNode *bnode;
3845 int lastseen = 0; 3922 int lastseen = 0;
3846 3923
3847 if (gtknode && (!gtknode->contact_expanded || PURPLE_BLIST_NODE_IS_CONTACT(node))) 3924 if (gtknode && (!gtknode->contact_expanded || PURPLE_BLIST_NODE_IS_CONTACT(node)))
3848 { 3925 {
3865 } 3942 }
3866 3943
3867 if (lastseen > 0) 3944 if (lastseen > 0)
3868 { 3945 {
3869 tmp = purple_str_seconds_to_string(time(NULL) - lastseen); 3946 tmp = purple_str_seconds_to_string(time(NULL) - lastseen);
3870 purple_notify_user_info_add_pair(user_info, _("Last Seen"), tmp); 3947 purple_notify_user_info_add_pair_plaintext(user_info, _("Last Seen"), tmp);
3871 g_free(tmp); 3948 g_free(tmp);
3872 } 3949 }
3873 } 3950 }
3874 3951
3875 3952
3876 /* Offline? */ 3953 /* Offline? */
3877 /* FIXME: Why is this status special-cased by the core? --rlaager 3954 /* FIXME: Why is this status special-cased by the core? --rlaager
3878 * FIXME: Alternatively, why not have the core do all of them? --rlaager */ 3955 * FIXME: Alternatively, why not have the core do all of them? --rlaager */
3879 if (!PURPLE_BUDDY_IS_ONLINE(b)) { 3956 if (!PURPLE_BUDDY_IS_ONLINE(b)) {
3880 purple_notify_user_info_add_pair(user_info, _("Status"), _("Offline")); 3957 purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Offline"));
3881 } 3958 }
3882 3959
3883 if (purple_account_is_connected(b->account) && 3960 if (purple_account_is_connected(purple_buddy_get_account(b)) &&
3884 prpl_info && prpl_info->tooltip_text) 3961 prpl_info && prpl_info->tooltip_text)
3885 { 3962 {
3886 /* Additional text from the PRPL */ 3963 /* Additional text from the PRPL */
3887 prpl_info->tooltip_text(b, user_info, full); 3964 prpl_info->tooltip_text(b, user_info, full);
3888 } 3965 }
3889 3966
3890 /* These are Easter Eggs. Patches to remove them will be rejected. */ 3967 /* These are Easter Eggs. Patches to remove them will be rejected. */
3891 if (!g_ascii_strcasecmp(b->name, "robflynn")) 3968 if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "robflynn"))
3892 purple_notify_user_info_add_pair(user_info, _("Description"), _("Spooky")); 3969 purple_notify_user_info_add_pair_plaintext(user_info, _("Description"), _("Spooky"));
3893 if (!g_ascii_strcasecmp(b->name, "seanegn")) 3970 if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "seanegn"))
3894 purple_notify_user_info_add_pair(user_info, _("Status"), _("Awesome")); 3971 purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Awesome"));
3895 if (!g_ascii_strcasecmp(b->name, "chipx86")) 3972 if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "chipx86"))
3896 purple_notify_user_info_add_pair(user_info, _("Status"), _("Rockin'")); 3973 purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Rockin'"));
3897 3974
3898 tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n"); 3975 tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n");
3899 g_string_append(str, tmp); 3976 g_string_append(str, tmp);
3900 g_free(tmp); 3977 g_free(tmp);
3901 3978
3906 PurpleNotifyUserInfo *user_info; 3983 PurpleNotifyUserInfo *user_info;
3907 3984
3908 user_info = purple_notify_user_info_new(); 3985 user_info = purple_notify_user_info_new();
3909 3986
3910 count = purple_blist_get_group_online_count(group); 3987 count = purple_blist_get_group_online_count(group);
3911
3912 if (count != 0) { 3988 if (count != 0) {
3913 /* Online buddies in group */ 3989 /* Online buddies in group */
3914 tmp = g_strdup_printf("%d", count); 3990 char tmp2[12];
3915 purple_notify_user_info_add_pair(user_info, 3991 sprintf(tmp2, "%d", count);
3916 _("Online Buddies"), 3992 purple_notify_user_info_add_pair_plaintext(user_info,
3917 tmp); 3993 _("Online Buddies"), tmp2);
3918 g_free(tmp);
3919 } 3994 }
3920 3995
3921 count = purple_blist_get_group_size(group, FALSE); 3996 count = purple_blist_get_group_size(group, FALSE);
3922 if (count != 0) { 3997 if (count != 0) {
3923 /* Total buddies (from online accounts) in group */ 3998 /* Total buddies (from online accounts) in group */
3924 tmp = g_strdup_printf("%d", count); 3999 char tmp2[12];
3925 purple_notify_user_info_add_pair(user_info, 4000 sprintf(tmp2, "%d", count);
3926 _("Total Buddies"), 4001 purple_notify_user_info_add_pair_html(user_info,
3927 tmp); 4002 _("Total Buddies"), tmp2);
3928 g_free(tmp);
3929 } 4003 }
3930 4004
3931 tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n"); 4005 tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n");
3932 g_string_append(str, tmp); 4006 g_string_append(str, tmp);
3933 g_free(tmp); 4007 g_free(tmp);
3970 4044
3971 GdkPixbuf * 4045 GdkPixbuf *
3972 pidgin_blist_get_emblem(PurpleBlistNode *node) 4046 pidgin_blist_get_emblem(PurpleBlistNode *node)
3973 { 4047 {
3974 PurpleBuddy *buddy = NULL; 4048 PurpleBuddy *buddy = NULL;
3975 struct _pidgin_blist_node *gtknode = node->ui_data; 4049 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
3976 PurplePlugin *prpl; 4050 PurplePlugin *prpl;
3977 PurplePluginProtocolInfo *prpl_info; 4051 PurplePluginProtocolInfo *prpl_info;
3978 const char *name = NULL; 4052 const char *name = NULL;
3979 char *filename, *path; 4053 char *filename, *path;
3980 PurplePresence *p = NULL; 4054 PurplePresence *p = NULL;
3993 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emotes", 4067 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emotes",
3994 "small", "mobile.png", NULL); 4068 "small", "mobile.png", NULL);
3995 return _pidgin_blist_get_cached_emblem(path); 4069 return _pidgin_blist_get_cached_emblem(path);
3996 } 4070 }
3997 4071
3998 if (((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded) { 4072 if (((struct _pidgin_blist_node*)purple_blist_node_get_ui_data(node->parent))->contact_expanded) {
3999 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) 4073 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"))
4000 return NULL; 4074 return NULL;
4001 return pidgin_create_prpl_icon(((PurpleBuddy*)node)->account, PIDGIN_PRPL_ICON_SMALL); 4075 return pidgin_create_prpl_icon(purple_buddy_get_account((PurpleBuddy*)node), PIDGIN_PRPL_ICON_SMALL);
4002 } 4076 }
4003 } else { 4077 } else {
4004 return NULL; 4078 return NULL;
4005 } 4079 }
4006 4080
4007 g_return_val_if_fail(buddy != NULL, NULL); 4081 g_return_val_if_fail(buddy != NULL, NULL);
4008 4082
4009 if (!purple_privacy_check(buddy->account, purple_buddy_get_name(buddy))) { 4083 if (!purple_privacy_check(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))) {
4010 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "blocked.png", NULL); 4084 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "blocked.png", NULL);
4011 return _pidgin_blist_get_cached_emblem(path); 4085 return _pidgin_blist_get_cached_emblem(path);
4012 } 4086 }
4013 4087
4014 /* If we came through the contact code flow above, we didn't need 4088 /* If we came through the contact code flow above, we didn't need
4040 /* This emblem comes from the small emoticon set now, to reduce duplication. */ 4114 /* This emblem comes from the small emoticon set now, to reduce duplication. */
4041 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emotes", "small", "music.png", NULL); 4115 path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emotes", "small", "music.png", NULL);
4042 return _pidgin_blist_get_cached_emblem(path); 4116 return _pidgin_blist_get_cached_emblem(path);
4043 } 4117 }
4044 4118
4045 prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); 4119 prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(buddy)));
4046 if (!prpl) 4120 if (!prpl)
4047 return NULL; 4121 return NULL;
4048 4122
4049 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 4123 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
4050 if (prpl_info && prpl_info->list_emblem) 4124 if (prpl_info && prpl_info->list_emblem)
4077 GdkPixbuf * 4151 GdkPixbuf *
4078 pidgin_blist_get_status_icon(PurpleBlistNode *node, PidginStatusIconSize size) 4152 pidgin_blist_get_status_icon(PurpleBlistNode *node, PidginStatusIconSize size)
4079 { 4153 {
4080 GdkPixbuf *ret; 4154 GdkPixbuf *ret;
4081 const char *icon = NULL; 4155 const char *icon = NULL;
4082 struct _pidgin_blist_node *gtknode = node->ui_data; 4156 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
4083 struct _pidgin_blist_node *gtkbuddynode = NULL; 4157 struct _pidgin_blist_node *gtkbuddynode = NULL;
4084 PurpleBuddy *buddy = NULL; 4158 PurpleBuddy *buddy = NULL;
4085 PurpleChat *chat = NULL; 4159 PurpleChat *chat = NULL;
4086 GtkIconSize icon_size = gtk_icon_size_from_name((size == PIDGIN_STATUS_ICON_LARGE) ? PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL : 4160 GtkIconSize icon_size = gtk_icon_size_from_name((size == PIDGIN_STATUS_ICON_LARGE) ? PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL :
4087 PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC); 4161 PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC);
4088 4162
4089 if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { 4163 if(PURPLE_BLIST_NODE_IS_CONTACT(node)) {
4090 if(!gtknode->contact_expanded) { 4164 if(!gtknode->contact_expanded) {
4091 buddy = purple_contact_get_priority_buddy((PurpleContact*)node); 4165 buddy = purple_contact_get_priority_buddy((PurpleContact*)node);
4092 if (buddy != NULL) 4166 if (buddy != NULL)
4093 gtkbuddynode = ((PurpleBlistNode*)buddy)->ui_data; 4167 gtkbuddynode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
4094 } 4168 }
4095 } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { 4169 } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
4096 buddy = (PurpleBuddy*)node; 4170 buddy = (PurpleBuddy*)node;
4097 gtkbuddynode = node->ui_data; 4171 gtkbuddynode = purple_blist_node_get_ui_data(node);
4098 } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { 4172 } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) {
4099 chat = (PurpleChat*)node; 4173 chat = (PurpleChat*)node;
4100 } else { 4174 } else {
4101 return NULL; 4175 return NULL;
4102 } 4176 }
4104 if(buddy || chat) { 4178 if(buddy || chat) {
4105 PurpleAccount *account; 4179 PurpleAccount *account;
4106 PurplePlugin *prpl; 4180 PurplePlugin *prpl;
4107 4181
4108 if(buddy) 4182 if(buddy)
4109 account = buddy->account; 4183 account = purple_buddy_get_account(buddy);
4110 else 4184 else
4111 account = chat->account; 4185 account = purple_chat_get_account(chat);
4112 4186
4113 prpl = purple_find_prpl(purple_account_get_protocol_id(account)); 4187 prpl = purple_find_prpl(purple_account_get_protocol_id(account));
4114 if(!prpl) 4188 if(!prpl)
4115 return NULL; 4189 return NULL;
4116 } 4190 }
4121 gboolean trans; 4195 gboolean trans;
4122 4196
4123 if(conv != NULL) { 4197 if(conv != NULL) {
4124 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); 4198 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
4125 if (gtkconv == NULL && size == PIDGIN_STATUS_ICON_SMALL) { 4199 if (gtkconv == NULL && size == PIDGIN_STATUS_ICON_SMALL) {
4126 PidginBlistNode *ui = buddy->node.ui_data; 4200 PidginBlistNode *ui = purple_blist_node_get_ui_data(&(buddy->node));
4127 if (ui == NULL || (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE)) 4201 if (ui == NULL || (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE))
4128 return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), 4202 return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview),
4129 PIDGIN_STOCK_STATUS_MESSAGE, icon_size, "GtkTreeView"); 4203 PIDGIN_STOCK_STATUS_MESSAGE, icon_size, "GtkTreeView");
4130 } 4204 }
4131 } 4205 }
4205 gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); 4279 gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
4206 PidginThemeFont *statusfont = NULL, *namefont = NULL; 4280 PidginThemeFont *statusfont = NULL, *namefont = NULL;
4207 PidginBlistTheme *theme; 4281 PidginBlistTheme *theme;
4208 4282
4209 if (conv != NULL) { 4283 if (conv != NULL) {
4210 PidginBlistNode *ui = b->node.ui_data; 4284 PidginBlistNode *ui = purple_blist_node_get_ui_data(&(b->node));
4211 if (ui) { 4285 if (ui) {
4212 if (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE) 4286 if (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE)
4213 hidden_conv = TRUE; 4287 hidden_conv = TRUE;
4214 } else { 4288 } else {
4215 if (PIDGIN_CONVERSATION(conv) == NULL) 4289 if (PIDGIN_CONVERSATION(conv) == NULL)
4239 4313
4240 /* Name is all that is needed */ 4314 /* Name is all that is needed */
4241 if (!aliased || biglist) { 4315 if (!aliased || biglist) {
4242 4316
4243 /* Status Info */ 4317 /* Status Info */
4244 prpl = purple_find_prpl(purple_account_get_protocol_id(b->account)); 4318 prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b)));
4245 4319
4246 if (prpl != NULL) 4320 if (prpl != NULL)
4247 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); 4321 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
4248 4322
4249 if (prpl_info && prpl_info->status_text && b->account->gc) { 4323 if (prpl_info && prpl_info->status_text && purple_account_get_connection(purple_buddy_get_account(b))) {
4250 char *tmp = prpl_info->status_text(b); 4324 char *tmp = prpl_info->status_text(b);
4251 const char *end; 4325 const char *end;
4252 4326
4253 if(tmp && !g_utf8_validate(tmp, -1, &end)) { 4327 if(tmp && !g_utf8_validate(tmp, -1, &end)) {
4254 char *new = g_strndup(tmp, 4328 char *new = g_strndup(tmp,
4395 blist_width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width"); 4469 blist_width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width");
4396 4470
4397 /* if the window exists, is hidden, we're saving positions, and the 4471 /* if the window exists, is hidden, we're saving positions, and the
4398 * position is sane... */ 4472 * position is sane... */
4399 if (gtkblist && gtkblist->window && 4473 if (gtkblist && gtkblist->window &&
4400 !GTK_WIDGET_VISIBLE(gtkblist->window) && blist_width != 0) { 4474 !gtk_widget_get_visible(gtkblist->window) && blist_width != 0) {
4401 4475
4402 blist_x = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/x"); 4476 blist_x = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/x");
4403 blist_y = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/y"); 4477 blist_y = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/y");
4404 blist_height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/height"); 4478 blist_height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/height");
4405 4479
4425 static gboolean pidgin_blist_refresh_timer(PurpleBuddyList *list) 4499 static gboolean pidgin_blist_refresh_timer(PurpleBuddyList *list)
4426 { 4500 {
4427 PurpleBlistNode *gnode, *cnode; 4501 PurpleBlistNode *gnode, *cnode;
4428 4502
4429 if (gtk_blist_visibility == GDK_VISIBILITY_FULLY_OBSCURED 4503 if (gtk_blist_visibility == GDK_VISIBILITY_FULLY_OBSCURED
4430 || !GTK_WIDGET_VISIBLE(gtkblist->window)) 4504 || !gtk_widget_get_visible(gtkblist->window))
4431 return TRUE; 4505 return TRUE;
4432 4506
4433 for(gnode = list->root; gnode; gnode = gnode->next) { 4507 for(gnode = list->root; gnode; gnode = gnode->next) {
4434 if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) 4508 if(!PURPLE_BLIST_NODE_IS_GROUP(gnode))
4435 continue; 4509 continue;
4439 4513
4440 buddy = purple_contact_get_priority_buddy((PurpleContact*)cnode); 4514 buddy = purple_contact_get_priority_buddy((PurpleContact*)cnode);
4441 4515
4442 if (buddy && 4516 if (buddy &&
4443 purple_presence_is_idle(purple_buddy_get_presence(buddy))) 4517 purple_presence_is_idle(purple_buddy_get_presence(buddy)))
4444 pidgin_blist_update_contact(list, (PurpleBlistNode*)buddy); 4518 pidgin_blist_update_contact(list, PURPLE_BLIST_NODE(buddy));
4445 } 4519 }
4446 } 4520 }
4447 } 4521 }
4448 4522
4449 /* keep on going */ 4523 /* keep on going */
4450 return TRUE; 4524 return TRUE;
4451 } 4525 }
4452 4526
4453 static void pidgin_blist_hide_node(PurpleBuddyList *list, PurpleBlistNode *node, gboolean update) 4527 static void pidgin_blist_hide_node(PurpleBuddyList *list, PurpleBlistNode *node, gboolean update)
4454 { 4528 {
4455 struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data; 4529 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
4456 GtkTreeIter iter; 4530 GtkTreeIter iter;
4457 4531
4458 if (!gtknode || !gtknode->row || !gtkblist) 4532 if (!gtknode || !gtknode->row || !gtkblist)
4459 return; 4533 return;
4460 4534
4471 gtknode->row = NULL; 4545 gtknode->row = NULL;
4472 } 4546 }
4473 4547
4474 static const char *require_connection[] = 4548 static const char *require_connection[] =
4475 { 4549 {
4476 N_("/Buddies/New Instant Message..."), 4550 "/BList/BuddiesMenu/NewInstantMessage",
4477 N_("/Buddies/Join a Chat..."), 4551 "/BList/BuddiesMenu/JoinAChat",
4478 N_("/Buddies/Get User Info..."), 4552 "/BList/BuddiesMenu/GetUserInfo",
4479 N_("/Buddies/Add Buddy..."), 4553 "/BList/BuddiesMenu/AddBuddy",
4480 N_("/Buddies/Add Chat..."), 4554 "/BList/BuddiesMenu/AddChat",
4481 N_("/Buddies/Add Group..."), 4555 "/BList/BuddiesMenu/AddGroup",
4556 "/BList/ToolsMenu/Privacy",
4482 }; 4557 };
4483 4558
4484 static const int require_connection_size = sizeof(require_connection) 4559 static const int require_connection_size = sizeof(require_connection)
4485 / sizeof(*require_connection); 4560 / sizeof(*require_connection);
4486 4561
4489 * where appropriate. 4564 * where appropriate.
4490 */ 4565 */
4491 static void 4566 static void
4492 update_menu_bar(PidginBuddyList *gtkblist) 4567 update_menu_bar(PidginBuddyList *gtkblist)
4493 { 4568 {
4494 GtkWidget *widget; 4569 GtkAction *action;
4495 gboolean sensitive; 4570 gboolean sensitive;
4496 int i; 4571 int i;
4497 4572
4498 g_return_if_fail(gtkblist != NULL); 4573 g_return_if_fail(gtkblist != NULL);
4499 4574
4501 4576
4502 sensitive = (purple_connections_get_all() != NULL); 4577 sensitive = (purple_connections_get_all() != NULL);
4503 4578
4504 for (i = 0; i < require_connection_size; i++) 4579 for (i = 0; i < require_connection_size; i++)
4505 { 4580 {
4506 widget = gtk_item_factory_get_widget(gtkblist->ift, require_connection[i]); 4581 action = gtk_ui_manager_get_action(gtkblist->ui, require_connection[i]);
4507 gtk_widget_set_sensitive(widget, sensitive); 4582 gtk_action_set_sensitive(action, sensitive);
4508 } 4583 }
4509 4584
4510 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Buddies/Join a Chat...")); 4585 action = gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/JoinAChat");
4511 gtk_widget_set_sensitive(widget, pidgin_blist_joinchat_is_showable()); 4586 gtk_action_set_sensitive(action, pidgin_blist_joinchat_is_showable());
4512 4587
4513 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Buddies/Add Chat...")); 4588 action = gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/AddChat");
4514 gtk_widget_set_sensitive(widget, pidgin_blist_joinchat_is_showable()); 4589 gtk_action_set_sensitive(action, pidgin_blist_joinchat_is_showable());
4515 4590
4516 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Privacy")); 4591 action = gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/RoomList");
4517 gtk_widget_set_sensitive(widget, sensitive); 4592 gtk_action_set_sensitive(action, pidgin_roomlist_is_showable());
4518
4519 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Room List"));
4520 gtk_widget_set_sensitive(widget, pidgin_roomlist_is_showable());
4521 } 4593 }
4522 4594
4523 static void 4595 static void
4524 sign_on_off_cb(PurpleConnection *gc, PurpleBuddyList *blist) 4596 sign_on_off_cb(PurpleConnection *gc, PurpleBuddyList *blist)
4525 { 4597 {
4599 4671
4600 static void 4672 static void
4601 conversation_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type, 4673 conversation_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type,
4602 PidginBuddyList *gtkblist) 4674 PidginBuddyList *gtkblist)
4603 { 4675 {
4676 PurpleAccount *account = purple_conversation_get_account(conv);
4604 GList *convs = NULL; 4677 GList *convs = NULL;
4605 GList *ims, *chats; 4678 GList *ims, *chats;
4606 GList *l = NULL; 4679 GList *l = NULL;
4607 4680
4608 if (type != PURPLE_CONV_UPDATE_UNSEEN) 4681 if (type != PURPLE_CONV_UPDATE_UNSEEN)
4609 return; 4682 return;
4610 4683
4611 if(conv->account != NULL && conv->name != NULL) { 4684 if(account != NULL && purple_conversation_get_name(conv) != NULL) {
4612 PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); 4685 PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
4613 if(buddy != NULL) 4686 if(buddy != NULL)
4614 pidgin_blist_update_buddy(NULL, (PurpleBlistNode *)buddy, TRUE); 4687 pidgin_blist_update_buddy(NULL, PURPLE_BLIST_NODE(buddy), TRUE);
4615 } 4688 }
4616 4689
4617 if (gtkblist->menutrayicon) { 4690 if (gtkblist->menutrayicon) {
4618 gtk_widget_destroy(gtkblist->menutrayicon); 4691 gtk_widget_destroy(gtkblist->menutrayicon);
4619 gtkblist->menutrayicon = NULL; 4692 gtkblist->menutrayicon = NULL;
4689 4762
4690 static void 4763 static void
4691 written_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message, 4764 written_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message,
4692 PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node) 4765 PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node)
4693 { 4766 {
4694 PidginBlistNode *ui = node->ui_data; 4767 PidginBlistNode *ui = purple_blist_node_get_ui_data(node);
4695 if (ui->conv.conv != conv || !pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv)) || 4768 if (ui->conv.conv != conv || !pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv)) ||
4696 !(flag & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV))) 4769 !(flag & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV)))
4697 return; 4770 return;
4698 ui->conv.flags |= PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE; 4771 ui->conv.flags |= PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE;
4699 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT 4772 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT
4705 } 4778 }
4706 4779
4707 static void 4780 static void
4708 displayed_msg_update_ui_cb(PidginConversation *gtkconv, PurpleBlistNode *node) 4781 displayed_msg_update_ui_cb(PidginConversation *gtkconv, PurpleBlistNode *node)
4709 { 4782 {
4710 PidginBlistNode *ui = node->ui_data; 4783 PidginBlistNode *ui = purple_blist_node_get_ui_data(node);
4711 if (ui->conv.conv != gtkconv->active_conv) 4784 if (ui->conv.conv != gtkconv->active_conv)
4712 return; 4785 return;
4713 ui->conv.flags &= ~(PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE | 4786 ui->conv.flags &= ~(PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE |
4714 PIDGIN_BLIST_CHAT_HAS_PENDING_MESSAGE_WITH_NICK); 4787 PIDGIN_BLIST_CHAT_HAS_PENDING_MESSAGE_WITH_NICK);
4715 pidgin_blist_update(purple_get_blist(), node); 4788 pidgin_blist_update(purple_get_blist(), node);
4716 } 4789 }
4717 4790
4718 static void 4791 static void
4719 conversation_created_cb(PurpleConversation *conv, PidginBuddyList *gtkblist) 4792 conversation_created_cb(PurpleConversation *conv, PidginBuddyList *gtkblist)
4720 { 4793 {
4721 switch (conv->type) { 4794 PurpleAccount *account = purple_conversation_get_account(conv);
4795
4796 switch (purple_conversation_get_type(conv)) {
4722 case PURPLE_CONV_TYPE_IM: 4797 case PURPLE_CONV_TYPE_IM:
4723 { 4798 {
4724 GSList *buddies = purple_find_buddies(conv->account, conv->name); 4799 GSList *buddies = purple_find_buddies(account, purple_conversation_get_name(conv));
4725 while (buddies) { 4800 while (buddies) {
4726 PurpleBlistNode *buddy = buddies->data; 4801 PurpleBlistNode *buddy = buddies->data;
4727 struct _pidgin_blist_node *ui = buddy->ui_data; 4802 struct _pidgin_blist_node *ui = purple_blist_node_get_ui_data(buddy);
4728 buddies = g_slist_delete_link(buddies, buddies); 4803 buddies = g_slist_delete_link(buddies, buddies);
4729 if (!ui) 4804 if (!ui)
4730 continue; 4805 continue;
4731 ui->conv.conv = conv; 4806 ui->conv.conv = conv;
4732 ui->conv.flags = 0; 4807 ui->conv.flags = 0;
4740 } 4815 }
4741 } 4816 }
4742 break; 4817 break;
4743 case PURPLE_CONV_TYPE_CHAT: 4818 case PURPLE_CONV_TYPE_CHAT:
4744 { 4819 {
4745 PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); 4820 PurpleChat *chat = purple_blist_find_chat(account, purple_conversation_get_name(conv));
4746 struct _pidgin_blist_node *ui; 4821 struct _pidgin_blist_node *ui;
4747 if (!chat) 4822 if (!chat)
4748 break; 4823 break;
4749 ui = chat->node.ui_data; 4824 ui = purple_blist_node_get_ui_data(&(chat->node));
4750 if (!ui) 4825 if (!ui)
4751 break; 4826 break;
4752 ui->conv.conv = conv; 4827 ui->conv.conv = conv;
4753 ui->conv.flags = 0; 4828 ui->conv.flags = 0;
4754 ui->conv.last_message = 0; 4829 ui->conv.last_message = 0;
4772 static void pidgin_blist_new_list(PurpleBuddyList *blist) 4847 static void pidgin_blist_new_list(PurpleBuddyList *blist)
4773 { 4848 {
4774 PidginBuddyList *gtkblist; 4849 PidginBuddyList *gtkblist;
4775 4850
4776 gtkblist = g_new0(PidginBuddyList, 1); 4851 gtkblist = g_new0(PidginBuddyList, 1);
4777 gtkblist->connection_errors = g_hash_table_new_full(g_direct_hash,
4778 g_direct_equal, NULL, g_free);
4779 gtkblist->priv = g_new0(PidginBuddyListPrivate, 1); 4852 gtkblist->priv = g_new0(PidginBuddyListPrivate, 1);
4780 4853
4781 blist->ui_data = gtkblist; 4854 blist->ui_data = gtkblist;
4782 } 4855 }
4783 4856
4784 static void pidgin_blist_new_node(PurpleBlistNode *node) 4857 static void pidgin_blist_new_node(PurpleBlistNode *node)
4785 { 4858 {
4786 node->ui_data = g_new0(struct _pidgin_blist_node, 1); 4859 purple_blist_node_set_ui_data(node, g_new0(struct _pidgin_blist_node, 1));
4787 } 4860 }
4788 4861
4789 gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node) 4862 gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node)
4790 { 4863 {
4791 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { 4864 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
4794 return FALSE; 4867 return FALSE;
4795 } 4868 }
4796 4869
4797 g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE); 4870 g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE);
4798 4871
4799 return ((struct _pidgin_blist_node *)node->ui_data)->contact_expanded; 4872 return ((struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node))->contact_expanded;
4800 } 4873 }
4801 4874
4802 enum { 4875 enum {
4803 DRAG_BUDDY, 4876 DRAG_BUDDY,
4804 DRAG_ROW, 4877 DRAG_ROW,
4806 DRAG_TEXT, 4879 DRAG_TEXT,
4807 DRAG_URI, 4880 DRAG_URI,
4808 NUM_TARGETS 4881 NUM_TARGETS
4809 }; 4882 };
4810 4883
4811 static const char *
4812 item_factory_translate_func (const char *path, gpointer func_data)
4813 {
4814 return _((char *)path);
4815 }
4816
4817 void pidgin_blist_setup_sort_methods() 4884 void pidgin_blist_setup_sort_methods()
4818 { 4885 {
4819 const char *id; 4886 const char *id;
4820 4887
4821 pidgin_blist_sort_method_reg("none", _("Manually"), sort_method_none); 4888 pidgin_blist_sort_method_reg("none", _("Manually"), sort_method_none);
4850 if (node) 4917 if (node)
4851 { 4918 {
4852 struct _pidgin_blist_node *gtknode; 4919 struct _pidgin_blist_node *gtknode;
4853 GtkTreePath *path; 4920 GtkTreePath *path;
4854 4921
4855 gtknode = node->ui_data; 4922 gtknode = purple_blist_node_get_ui_data(node);
4856 if (gtknode && gtknode->row) 4923 if (gtknode && gtknode->row)
4857 { 4924 {
4858 path = gtk_tree_row_reference_get_path(gtknode->row); 4925 path = gtk_tree_row_reference_get_path(gtknode->row);
4859 gtk_tree_selection_select_path(sel, path); 4926 gtk_tree_selection_select_path(sel, path);
4860 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(gtkblist->treeview), path, NULL, FALSE, 0, 0); 4927 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(gtkblist->treeview), path, NULL, FALSE, 0, 0);
5087 5154
5088 static void 5155 static void
5089 generic_error_destroy_cb(GtkObject *dialog, 5156 generic_error_destroy_cb(GtkObject *dialog,
5090 PurpleAccount *account) 5157 PurpleAccount *account)
5091 { 5158 {
5092 g_hash_table_remove(gtkblist->connection_errors, account);
5093 /* If the error dialog is being destroyed in response to the 5159 /* If the error dialog is being destroyed in response to the
5094 * account-error-changed signal, we don't want to clear the current 5160 * account-error-changed signal, we don't want to clear the current
5095 * error. 5161 * error.
5096 */ 5162 */
5097 if (g_object_get_data(G_OBJECT(dialog), DO_NOT_CLEAR_ERROR) == NULL) 5163 if (g_object_get_data(G_OBJECT(dialog), DO_NOT_CLEAR_ERROR) == NULL)
5358 const char *desc; 5424 const char *desc;
5359 5425
5360 if (old == NULL && new == NULL) 5426 if (old == NULL && new == NULL)
5361 return; 5427 return;
5362 5428
5363 /* For backwards compatibility: */
5364 if (new)
5365 pidgin_blist_update_account_error_state(account, new->description);
5366 else
5367 pidgin_blist_update_account_error_state(account, NULL);
5368
5369 if (new != NULL) 5429 if (new != NULL)
5370 pidgin_blist_select_notebook_page(gtkblist); 5430 pidgin_blist_select_notebook_page(gtkblist);
5371 5431
5372 if (old != NULL && new == NULL) { 5432 if (old != NULL && new == NULL) {
5373 if(old->type == PURPLE_CONNECTION_ERROR_NAME_IN_USE) 5433 if(old->type == PURPLE_CONNECTION_ERROR_NAME_IN_USE)
5427 account = l->data; 5487 account = l->data;
5428 err = purple_account_get_current_error(account); 5488 err = purple_account_get_current_error(account);
5429 5489
5430 update_account_error_state(account, NULL, err, gtkblist); 5490 update_account_error_state(account, NULL, err, gtkblist);
5431 } 5491 }
5432 }
5433
5434 void
5435 pidgin_blist_update_account_error_state(PurpleAccount *account, const char *text)
5436 {
5437 /* connection_errors isn't actually used anywhere; it's just kept in
5438 * sync with reality in case a plugin uses it.
5439 */
5440 if (text == NULL)
5441 g_hash_table_remove(gtkblist->connection_errors, account);
5442 else
5443 g_hash_table_insert(gtkblist->connection_errors, account, g_strdup(text));
5444 } 5492 }
5445 5493
5446 static gboolean 5494 static gboolean
5447 paint_headline_hbox (GtkWidget *widget, 5495 paint_headline_hbox (GtkWidget *widget,
5448 GdkEventExpose *event, 5496 GdkEventExpose *event,
5480 5528
5481 static void 5529 static void
5482 headline_style_set (GtkWidget *widget, 5530 headline_style_set (GtkWidget *widget,
5483 GtkStyle *prev_style) 5531 GtkStyle *prev_style)
5484 { 5532 {
5485 GtkTooltips *tooltips;
5486 GtkStyle *style; 5533 GtkStyle *style;
5534 #if GTK_CHECK_VERSION(2,12,0)
5535 GtkWidget *window;
5487 5536
5488 if (gtkblist->changing_style) 5537 if (gtkblist->changing_style)
5489 return; 5538 return;
5490 5539
5540 /* This is a hack needed to use the tooltip background colour */
5541 window = gtk_window_new(GTK_WINDOW_POPUP);
5542 gtk_widget_set_name(window, "gtk-tooltip");
5543 gtk_widget_ensure_style(window);
5544 style = gtk_widget_get_style(window);
5545
5546 gtkblist->changing_style = TRUE;
5547 gtk_widget_set_style(gtkblist->headline_hbox, style);
5548 gtkblist->changing_style = FALSE;
5549
5550 gtk_widget_destroy(window);
5551
5552 gtk_widget_queue_draw(gtkblist->headline_hbox);
5553 #else
5554 GtkTooltips *tooltips;
5555
5556 if (gtkblist->changing_style)
5557 return;
5558
5491 tooltips = gtk_tooltips_new (); 5559 tooltips = gtk_tooltips_new ();
5492 g_object_ref_sink (tooltips); 5560 g_object_ref_sink (tooltips);
5493 5561
5494 gtk_tooltips_force_window (tooltips); 5562 gtk_tooltips_force_window (tooltips);
5495 #if GTK_CHECK_VERSION(2, 12, 0)
5496 gtk_widget_set_name (tooltips->tip_window, "gtk-tooltips");
5497 #endif
5498 gtk_widget_ensure_style (tooltips->tip_window); 5563 gtk_widget_ensure_style (tooltips->tip_window);
5499 style = gtk_widget_get_style (tooltips->tip_window); 5564 style = gtk_widget_get_style (tooltips->tip_window);
5500 5565
5501 gtkblist->changing_style = TRUE; 5566 gtkblist->changing_style = TRUE;
5502 gtk_widget_set_style (gtkblist->headline_hbox, style); 5567 gtk_widget_set_style (gtkblist->headline_hbox, style);
5503 gtkblist->changing_style = FALSE; 5568 gtkblist->changing_style = FALSE;
5504 5569
5505 g_object_unref (tooltips); 5570 g_object_unref (tooltips);
5571 #endif
5506 } 5572 }
5507 5573
5508 /******************************************/ 5574 /******************************************/
5509 /* End of connection error handling stuff */ 5575 /* End of connection error handling stuff */
5510 /******************************************/ 5576 /******************************************/
5737 GtkWidget *sep; 5803 GtkWidget *sep;
5738 GtkWidget *label; 5804 GtkWidget *label;
5739 GtkWidget *close; 5805 GtkWidget *close;
5740 char *pretty, *tmp; 5806 char *pretty, *tmp;
5741 const char *theme_name; 5807 const char *theme_name;
5808 GtkActionGroup *action_group;
5809 GError *error;
5742 GtkAccelGroup *accel_group; 5810 GtkAccelGroup *accel_group;
5743 GtkTreeSelection *selection; 5811 GtkTreeSelection *selection;
5744 GtkTargetEntry dte[] = {{"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW}, 5812 GtkTargetEntry dte[] = {{"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW},
5745 {"application/x-im-contact", 0, DRAG_BUDDY}, 5813 {"application/x-im-contact", 0, DRAG_BUDDY},
5746 {"text/x-vcard", 0, DRAG_VCARD }, 5814 {"text/x-vcard", 0, DRAG_VCARD },
5786 g_signal_connect(G_OBJECT(gtkblist->window), "window_state_event", G_CALLBACK(gtk_blist_window_state_cb), NULL); 5854 g_signal_connect(G_OBJECT(gtkblist->window), "window_state_event", G_CALLBACK(gtk_blist_window_state_cb), NULL);
5787 g_signal_connect(G_OBJECT(gtkblist->window), "key_press_event", G_CALLBACK(gtk_blist_window_key_press_cb), gtkblist); 5855 g_signal_connect(G_OBJECT(gtkblist->window), "key_press_event", G_CALLBACK(gtk_blist_window_key_press_cb), gtkblist);
5788 gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK); 5856 gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK);
5789 5857
5790 /******************************* Menu bar *************************************/ 5858 /******************************* Menu bar *************************************/
5791 accel_group = gtk_accel_group_new(); 5859 action_group = gtk_action_group_new("BListActions");
5792 gtk_window_add_accel_group(GTK_WINDOW (gtkblist->window), accel_group); 5860 gtk_action_group_add_actions(action_group,
5793 g_object_unref(accel_group); 5861 blist_menu_entries,
5794 gtkblist->ift = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<PurpleMain>", accel_group); 5862 G_N_ELEMENTS(blist_menu_entries),
5795 gtk_item_factory_set_translate_func(gtkblist->ift, 5863 GTK_WINDOW(gtkblist->window));
5796 (GtkTranslateFunc)item_factory_translate_func, 5864 gtk_action_group_add_toggle_actions(action_group,
5797 NULL, NULL); 5865 blist_menu_toggle_entries,
5798 gtk_item_factory_create_items(gtkblist->ift, sizeof(blist_menu) / sizeof(*blist_menu), 5866 G_N_ELEMENTS(blist_menu_toggle_entries),
5799 blist_menu, NULL); 5867 GTK_WINDOW(gtkblist->window));
5868 #ifdef ENABLE_NLS
5869 gtk_action_group_set_translation_domain(action_group,
5870 PACKAGE);
5871 #endif
5872
5873 gtkblist->ui = gtk_ui_manager_new();
5874 gtk_ui_manager_insert_action_group(gtkblist->ui, action_group, 0);
5875
5876 accel_group = gtk_ui_manager_get_accel_group(gtkblist->ui);
5877 gtk_window_add_accel_group(GTK_WINDOW(gtkblist->window), accel_group);
5800 pidgin_load_accels(); 5878 pidgin_load_accels();
5801 g_signal_connect(G_OBJECT(accel_group), "accel-changed", G_CALLBACK(pidgin_save_accels_cb), NULL); 5879 g_signal_connect(G_OBJECT(accel_group), "accel-changed", G_CALLBACK(pidgin_save_accels_cb), NULL);
5802 5880
5803 menu = gtk_item_factory_get_widget(gtkblist->ift, "<PurpleMain>"); 5881 error = NULL;
5882 if (!gtk_ui_manager_add_ui_from_string(gtkblist->ui, blist_menu, -1, &error))
5883 {
5884 g_message("building menus failed: %s", error->message);
5885 g_error_free(error);
5886 exit(EXIT_FAILURE);
5887 }
5888
5889 menu = gtk_ui_manager_get_widget(gtkblist->ui, "/BList");
5804 gtkblist->menutray = pidgin_menu_tray_new(); 5890 gtkblist->menutray = pidgin_menu_tray_new();
5805 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtkblist->menutray); 5891 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtkblist->menutray);
5806 gtk_widget_show(gtkblist->menutray); 5892 gtk_widget_show(gtkblist->menutray);
5807 gtk_widget_show(menu); 5893 gtk_widget_show(menu);
5808 gtk_box_pack_start(GTK_BOX(gtkblist->main_vbox), menu, FALSE, FALSE, 0); 5894 gtk_box_pack_start(GTK_BOX(gtkblist->main_vbox), menu, FALSE, FALSE, 0);
5809 5895
5810 accountmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Accounts")); 5896 menu = gtk_ui_manager_get_widget(gtkblist->ui, "/BList/AccountsMenu");
5811 5897 accountmenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
5812 5898
5813 /****************************** Notebook *************************************/ 5899 /****************************** Notebook *************************************/
5814 gtkblist->notebook = gtk_notebook_new(); 5900 gtkblist->notebook = gtk_notebook_new();
5815 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gtkblist->notebook), FALSE); 5901 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gtkblist->notebook), FALSE);
5816 gtk_notebook_set_show_border(GTK_NOTEBOOK(gtkblist->notebook), FALSE); 5902 gtk_notebook_set_show_border(GTK_NOTEBOOK(gtkblist->notebook), FALSE);
5863 "expose_event", 5949 "expose_event",
5864 G_CALLBACK (paint_headline_hbox), 5950 G_CALLBACK (paint_headline_hbox),
5865 NULL); 5951 NULL);
5866 gtk_widget_set_name(gtkblist->headline_hbox, "gtk-tooltips"); 5952 gtk_widget_set_name(gtkblist->headline_hbox, "gtk-tooltips");
5867 5953
5868 gtkblist->headline_close = gtk_widget_render_icon(ebox, GTK_STOCK_CLOSE,
5869 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC), NULL);
5870 gtkblist->hand_cursor = gdk_cursor_new (GDK_HAND2); 5954 gtkblist->hand_cursor = gdk_cursor_new (GDK_HAND2);
5871 gtkblist->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); 5955 gtkblist->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR);
5872 5956
5873 /* Close button. */ 5957 /* Close button. */
5874 close = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); 5958 close = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
5971 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), sep, FALSE, FALSE, 0); 6055 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), sep, FALSE, FALSE, 0);
5972 6056
5973 gtkblist->scrollbook = pidgin_scroll_book_new(); 6057 gtkblist->scrollbook = pidgin_scroll_book_new();
5974 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->scrollbook, FALSE, FALSE, 0); 6058 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->scrollbook, FALSE, FALSE, 0);
5975 6059
5976 /* Create an vbox which holds the scrollbook which is actually used to
5977 * display connection errors. The vbox needs to still exist for
5978 * backwards compatibility.
5979 */
5980 gtkblist->error_buttons = gtk_vbox_new(FALSE, 0);
5981 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->error_buttons, FALSE, FALSE, 0);
5982 gtk_container_set_border_width(GTK_CONTAINER(gtkblist->error_buttons), 0);
5983
5984 priv->error_scrollbook = PIDGIN_SCROLL_BOOK(pidgin_scroll_book_new()); 6060 priv->error_scrollbook = PIDGIN_SCROLL_BOOK(pidgin_scroll_book_new());
5985 gtk_box_pack_start(GTK_BOX(gtkblist->error_buttons), 6061 gtk_box_pack_start(GTK_BOX(gtkblist->vbox),
5986 GTK_WIDGET(priv->error_scrollbook), FALSE, FALSE, 0); 6062 GTK_WIDGET(priv->error_scrollbook), FALSE, FALSE, 0);
5987
5988 6063
5989 /* Add the statusbox */ 6064 /* Add the statusbox */
5990 gtkblist->statusbox = pidgin_status_box_new(); 6065 gtkblist->statusbox = pidgin_status_box_new();
5991 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->statusbox, FALSE, TRUE, 0); 6066 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->statusbox, FALSE, TRUE, 0);
5992 gtk_widget_set_name(gtkblist->statusbox, "pidgin_blist_statusbox"); 6067 gtk_widget_set_name(gtkblist->statusbox, "pidgin_blist_statusbox");
5994 gtk_widget_show(gtkblist->statusbox); 6069 gtk_widget_show(gtkblist->statusbox);
5995 6070
5996 /* set the Show Offline Buddies option. must be done 6071 /* set the Show Offline Buddies option. must be done
5997 * after the treeview or faceprint gets mad. -Robot101 6072 * after the treeview or faceprint gets mad. -Robot101
5998 */ 6073 */
5999 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Offline Buddies"))), 6074 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowOffline")),
6000 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies")); 6075 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies"));
6001 6076
6002 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Empty Groups"))), 6077 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowEmptyGroups")),
6003 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_empty_groups")); 6078 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_empty_groups"));
6004 6079
6005 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Tools/Mute Sounds"))), 6080 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/MuteSounds")),
6006 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/sound/mute")); 6081 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/sound/mute"));
6007 6082
6008 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Buddy Details"))), 6083 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowBuddyDetails")),
6009 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons")); 6084 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"));
6010 6085
6011 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Idle Times"))), 6086 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowIdleTimes")),
6012 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time")); 6087 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time"));
6013 6088
6014 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Protocol Icons"))), 6089 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowProtocolIcons")),
6015 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")); 6090 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"));
6016 6091
6017 if(!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"), "none")) 6092 if(!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"), "none"))
6018 gtk_widget_set_sensitive(gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Mute Sounds")), FALSE); 6093 gtk_action_set_sensitive(gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/MuteSounds"), FALSE);
6019 6094
6020 /* Update some dynamic things */ 6095 /* Update some dynamic things */
6021 update_menu_bar(gtkblist); 6096 update_menu_bar(gtkblist);
6022 pidgin_blist_update_plugin_actions(); 6097 pidgin_blist_update_plugin_actions();
6023 pidgin_blist_update_sort_methods(); 6098 pidgin_blist_update_sort_methods();
6155 6230
6156 gtkblist->refresh_timer = purple_timeout_add_seconds(30,(GSourceFunc)pidgin_blist_refresh_timer, blist); 6231 gtkblist->refresh_timer = purple_timeout_add_seconds(30,(GSourceFunc)pidgin_blist_refresh_timer, blist);
6157 } 6232 }
6158 6233
6159 static gboolean get_iter_from_node(PurpleBlistNode *node, GtkTreeIter *iter) { 6234 static gboolean get_iter_from_node(PurpleBlistNode *node, GtkTreeIter *iter) {
6160 struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data; 6235 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
6161 GtkTreePath *path; 6236 GtkTreePath *path;
6162 6237
6163 if (!gtknode) { 6238 if (!gtknode) {
6164 return FALSE; 6239 return FALSE;
6165 } 6240 }
6184 return TRUE; 6259 return TRUE;
6185 } 6260 }
6186 6261
6187 static void pidgin_blist_remove(PurpleBuddyList *list, PurpleBlistNode *node) 6262 static void pidgin_blist_remove(PurpleBuddyList *list, PurpleBlistNode *node)
6188 { 6263 {
6189 struct _pidgin_blist_node *gtknode = node->ui_data; 6264 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
6190 6265
6191 purple_request_close_with_handle(node); 6266 purple_request_close_with_handle(node);
6192 6267
6193 pidgin_blist_hide_node(list, node, TRUE); 6268 pidgin_blist_hide_node(list, node, TRUE);
6194 6269
6206 6281
6207 if(gtknode) { 6282 if(gtknode) {
6208 if(gtknode->recent_signonoff_timer > 0) 6283 if(gtknode->recent_signonoff_timer > 0)
6209 purple_timeout_remove(gtknode->recent_signonoff_timer); 6284 purple_timeout_remove(gtknode->recent_signonoff_timer);
6210 6285
6211 purple_signals_disconnect_by_handle(node->ui_data); 6286 purple_signals_disconnect_by_handle(gtknode);
6212 g_free(node->ui_data); 6287 g_free(gtknode);
6213 node->ui_data = NULL; 6288 purple_blist_node_set_ui_data(node, NULL);
6214 } 6289 }
6215 } 6290 }
6216 6291
6217 static gboolean do_selection_changed(PurpleBlistNode *new_selection) 6292 static gboolean do_selection_changed(PurpleBlistNode *new_selection)
6218 { 6293 {
6252 } 6327 }
6253 } 6328 }
6254 6329
6255 static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter) 6330 static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter)
6256 { 6331 {
6257 GtkTreeIter parent_iter, cur, *curptr = NULL; 6332 GtkTreeIter parent_iter = {0, NULL, NULL, NULL}, cur, *curptr = NULL;
6258 struct _pidgin_blist_node *gtknode = node->ui_data; 6333 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
6259 GtkTreePath *newpath; 6334 GtkTreePath *newpath;
6260 6335
6261 if(!iter) 6336 if(!iter)
6262 return FALSE; 6337 return FALSE;
6263 6338
6275 6350
6276 if(gtknode != NULL) { 6351 if(gtknode != NULL) {
6277 gtk_tree_row_reference_free(gtknode->row); 6352 gtk_tree_row_reference_free(gtknode->row);
6278 } else { 6353 } else {
6279 pidgin_blist_new_node(node); 6354 pidgin_blist_new_node(node);
6280 gtknode = (struct _pidgin_blist_node *)node->ui_data; 6355 gtknode = purple_blist_node_get_ui_data(node);
6281 } 6356 }
6282 6357
6283 newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), 6358 newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel),
6284 iter); 6359 iter);
6285 gtknode->row = 6360 gtknode->row =
6293 NODE_COLUMN, node, 6368 NODE_COLUMN, node,
6294 -1); 6369 -1);
6295 6370
6296 if(node->parent) { 6371 if(node->parent) {
6297 GtkTreePath *expand = NULL; 6372 GtkTreePath *expand = NULL;
6298 struct _pidgin_blist_node *gtkparentnode = node->parent->ui_data; 6373 struct _pidgin_blist_node *gtkparentnode = purple_blist_node_get_ui_data(node->parent);
6299 6374
6300 if(PURPLE_BLIST_NODE_IS_GROUP(node->parent)) { 6375 if(PURPLE_BLIST_NODE_IS_GROUP(node->parent)) {
6301 if(!purple_blist_node_get_bool(node->parent, "collapsed")) 6376 if(!purple_blist_node_get_bool(node->parent, "collapsed"))
6302 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &parent_iter); 6377 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &parent_iter);
6303 } else if(PURPLE_BLIST_NODE_IS_CONTACT(node->parent) && 6378 } else if(PURPLE_BLIST_NODE_IS_CONTACT(node->parent) &&
6315 6390
6316 static gboolean pidgin_blist_group_has_show_offline_buddy(PurpleGroup *group) 6391 static gboolean pidgin_blist_group_has_show_offline_buddy(PurpleGroup *group)
6317 { 6392 {
6318 PurpleBlistNode *gnode, *cnode, *bnode; 6393 PurpleBlistNode *gnode, *cnode, *bnode;
6319 6394
6320 gnode = (PurpleBlistNode *)group; 6395 gnode = PURPLE_BLIST_NODE(group);
6321 for(cnode = gnode->child; cnode; cnode = cnode->next) { 6396 for(cnode = gnode->child; cnode; cnode = cnode->next) {
6322 if(PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { 6397 if(PURPLE_BLIST_NODE_IS_CONTACT(cnode)) {
6323 for(bnode = cnode->child; bnode; bnode = bnode->next) { 6398 for(bnode = cnode->child; bnode; bnode = bnode->next) {
6324 PurpleBuddy *buddy = (PurpleBuddy *)bnode; 6399 PurpleBuddy *buddy = (PurpleBuddy *)bnode;
6325 if (purple_account_is_connected(buddy->account) && 6400 if (purple_account_is_connected(purple_buddy_get_account(buddy)) &&
6326 purple_blist_node_get_bool(bnode, "show_offline")) 6401 purple_blist_node_get_bool(bnode, "show_offline"))
6327 return TRUE; 6402 return TRUE;
6328 } 6403 }
6329 } 6404 }
6330 } 6405 }
6460 6535
6461 6536
6462 text_color = selected ? NULL : theme_font_get_color_default(pair, NULL); 6537 text_color = selected ? NULL : theme_font_get_color_default(pair, NULL);
6463 text_font = theme_font_get_face_default(pair, ""); 6538 text_font = theme_font_get_face_default(pair, "");
6464 6539
6465 esc = g_markup_escape_text(group->name, -1); 6540 esc = g_markup_escape_text(purple_group_get_name(group), -1);
6466 if (text_color) { 6541 if (text_color) {
6467 mark = g_strdup_printf("<span foreground='%s' font_desc='%s'><b>%s</b>%s%s%s</span>", 6542 mark = g_strdup_printf("<span foreground='%s' font_desc='%s'><b>%s</b>%s%s%s</span>",
6468 text_color, text_font, 6543 text_color, text_font,
6469 esc ? esc : "", 6544 esc ? esc : "",
6470 !expanded ? " <span weight='light'>(</span>" : "", 6545 !expanded ? " <span weight='light'>(</span>" : "",
6487 PurplePresence *presence = purple_buddy_get_presence(buddy); 6562 PurplePresence *presence = purple_buddy_get_presence(buddy);
6488 GdkPixbuf *status, *avatar, *emblem, *prpl_icon; 6563 GdkPixbuf *status, *avatar, *emblem, *prpl_icon;
6489 GdkColor *color = NULL; 6564 GdkColor *color = NULL;
6490 char *mark; 6565 char *mark;
6491 char *idle = NULL; 6566 char *idle = NULL;
6492 gboolean expanded = ((struct _pidgin_blist_node *)(node->parent->ui_data))->contact_expanded; 6567 gboolean expanded = ((struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node->parent))->contact_expanded;
6493 gboolean selected = (gtkblist->selected_node == node); 6568 gboolean selected = (gtkblist->selected_node == node);
6494 gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); 6569 gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
6495 PidginBlistTheme *theme; 6570 PidginBlistTheme *theme;
6496 6571
6497 if (editing_blist) 6572 if (editing_blist)
6498 return; 6573 return;
6499 6574
6500 status = pidgin_blist_get_status_icon((PurpleBlistNode*)buddy, 6575 status = pidgin_blist_get_status_icon(PURPLE_BLIST_NODE(buddy),
6501 biglist ? PIDGIN_STATUS_ICON_LARGE : PIDGIN_STATUS_ICON_SMALL); 6576 biglist ? PIDGIN_STATUS_ICON_LARGE : PIDGIN_STATUS_ICON_SMALL);
6502 6577
6503 /* Speed it up if we don't want buddy icons. */ 6578 /* Speed it up if we don't want buddy icons. */
6504 if(biglist) 6579 if(biglist)
6505 avatar = pidgin_blist_get_buddy_icon((PurpleBlistNode *)buddy, TRUE, TRUE); 6580 avatar = pidgin_blist_get_buddy_icon(PURPLE_BLIST_NODE(buddy), TRUE, TRUE);
6506 else 6581 else
6507 avatar = NULL; 6582 avatar = NULL;
6508 6583
6509 if (!avatar) { 6584 if (!avatar) {
6510 g_object_ref(G_OBJECT(gtkblist->empty_avatar)); 6585 g_object_ref(G_OBJECT(gtkblist->empty_avatar));
6511 avatar = gtkblist->empty_avatar; 6586 avatar = gtkblist->empty_avatar;
6512 } else if ((!PURPLE_BUDDY_IS_ONLINE(buddy) || purple_presence_is_idle(presence))) { 6587 } else if ((!PURPLE_BUDDY_IS_ONLINE(buddy) || purple_presence_is_idle(presence))) {
6513 do_alphashift(avatar, 77); 6588 do_alphashift(avatar, 77);
6514 } 6589 }
6515 6590
6516 emblem = pidgin_blist_get_emblem((PurpleBlistNode*) buddy); 6591 emblem = pidgin_blist_get_emblem(PURPLE_BLIST_NODE(buddy));
6517 mark = pidgin_blist_get_name_markup(buddy, selected, TRUE); 6592 mark = pidgin_blist_get_name_markup(buddy, selected, TRUE);
6518 6593
6519 theme = pidgin_blist_get_theme(); 6594 theme = pidgin_blist_get_theme();
6520 6595
6521 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time") && 6596 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time") &&
6552 ihrs, imin); 6627 ihrs, imin);
6553 } 6628 }
6554 } 6629 }
6555 } 6630 }
6556 6631
6557 prpl_icon = pidgin_create_prpl_icon(buddy->account, PIDGIN_PRPL_ICON_SMALL); 6632 prpl_icon = pidgin_create_prpl_icon(purple_buddy_get_account(buddy), PIDGIN_PRPL_ICON_SMALL);
6558 6633
6559 if (theme != NULL) 6634 if (theme != NULL)
6560 color = pidgin_blist_theme_get_contact_color(theme); 6635 color = pidgin_blist_theme_get_contact_color(theme);
6561 6636
6562 gtk_tree_store_set(gtkblist->treemodel, iter, 6637 gtk_tree_store_set(gtkblist->treemodel, iter,
6623 GtkTreeIter iter; 6698 GtkTreeIter iter;
6624 6699
6625 if(!insert_node(list, cnode, &iter)) 6700 if(!insert_node(list, cnode, &iter))
6626 return; 6701 return;
6627 6702
6628 gtknode = (struct _pidgin_blist_node *)cnode->ui_data; 6703 gtknode = purple_blist_node_get_ui_data(cnode);
6629 6704
6630 if(gtknode->contact_expanded) { 6705 if(gtknode->contact_expanded) {
6631 GdkPixbuf *status; 6706 GdkPixbuf *status;
6632 gchar *mark, *tmp; 6707 gchar *mark, *tmp;
6633 const gchar *fg_color, *font; 6708 const gchar *fg_color, *font;
6700 buddy = (PurpleBuddy*)node; 6775 buddy = (PurpleBuddy*)node;
6701 6776
6702 /* First things first, update the contact */ 6777 /* First things first, update the contact */
6703 pidgin_blist_update_contact(list, node); 6778 pidgin_blist_update_contact(list, node);
6704 6779
6705 gtkparentnode = (struct _pidgin_blist_node *)node->parent->ui_data; 6780 gtkparentnode = purple_blist_node_get_ui_data(node->parent);
6706 6781
6707 if (gtkparentnode->contact_expanded && buddy_is_displayable(buddy)) 6782 if (gtkparentnode->contact_expanded && buddy_is_displayable(buddy))
6708 { 6783 {
6709 GtkTreeIter iter; 6784 GtkTreeIter iter;
6710 6785
6731 /* First things first, update the group */ 6806 /* First things first, update the group */
6732 pidgin_blist_update_group(list, node->parent); 6807 pidgin_blist_update_group(list, node->parent);
6733 6808
6734 chat = (PurpleChat*)node; 6809 chat = (PurpleChat*)node;
6735 6810
6736 if(purple_account_is_connected(chat->account)) { 6811 if(purple_account_is_connected(purple_chat_get_account(chat))) {
6737 GtkTreeIter iter; 6812 GtkTreeIter iter;
6738 GdkPixbuf *status, *avatar, *emblem, *prpl_icon; 6813 GdkPixbuf *status, *avatar, *emblem, *prpl_icon;
6739 const gchar *color, *font; 6814 const gchar *color, *font;
6740 gchar *mark, *tmp; 6815 gchar *mark, *tmp;
6741 gboolean showicons = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); 6816 gboolean showicons = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
6750 gboolean nick_said = FALSE; 6825 gboolean nick_said = FALSE;
6751 6826
6752 if (!insert_node(list, node, &iter)) 6827 if (!insert_node(list, node, &iter))
6753 return; 6828 return;
6754 6829
6755 ui = node->ui_data; 6830 ui = purple_blist_node_get_ui_data(node);
6756 conv = ui->conv.conv; 6831 conv = ui->conv.conv;
6757 if (conv && pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv))) { 6832 if (conv && pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv))) {
6758 hidden = (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE); 6833 hidden = (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE);
6759 nick_said = (ui->conv.flags & PIDGIN_BLIST_CHAT_HAS_PENDING_MESSAGE_WITH_NICK); 6834 nick_said = (ui->conv.flags & PIDGIN_BLIST_CHAT_HAS_PENDING_MESSAGE_WITH_NICK);
6760 } 6835 }
6795 font, hidden ? "bold" : "normal", mark); 6870 font, hidden ? "bold" : "normal", mark);
6796 } 6871 }
6797 g_free(mark); 6872 g_free(mark);
6798 mark = tmp; 6873 mark = tmp;
6799 6874
6800 prpl_icon = pidgin_create_prpl_icon(chat->account, PIDGIN_PRPL_ICON_SMALL); 6875 prpl_icon = pidgin_create_prpl_icon(purple_chat_get_account(chat), PIDGIN_PRPL_ICON_SMALL);
6801 6876
6802 if (theme != NULL) 6877 if (theme != NULL)
6803 bgcolor = pidgin_blist_theme_get_contact_color(theme); 6878 bgcolor = pidgin_blist_theme_get_contact_color(theme);
6804 6879
6805 gtk_tree_store_set(gtkblist->treemodel, &iter, 6880 gtk_tree_store_set(gtkblist->treemodel, &iter,
6836 if (list) 6911 if (list)
6837 gtkblist = PIDGIN_BLIST(list); 6912 gtkblist = PIDGIN_BLIST(list);
6838 if(!gtkblist || !gtkblist->treeview || !node) 6913 if(!gtkblist || !gtkblist->treeview || !node)
6839 return; 6914 return;
6840 6915
6841 if (node->ui_data == NULL) 6916 if (purple_blist_node_get_ui_data(node) == NULL)
6842 pidgin_blist_new_node(node); 6917 pidgin_blist_new_node(node);
6843 6918
6844 switch(node->type) { 6919 switch (purple_blist_node_get_type(node)) {
6845 case PURPLE_BLIST_GROUP_NODE: 6920 case PURPLE_BLIST_GROUP_NODE:
6846 pidgin_blist_update_group(list, node); 6921 pidgin_blist_update_group(list, node);
6847 break; 6922 break;
6848 case PURPLE_BLIST_CONTACT_NODE: 6923 case PURPLE_BLIST_CONTACT_NODE:
6849 pidgin_blist_update_contact(list, node); 6924 pidgin_blist_update_contact(list, node);
6869 6944
6870 g_return_if_fail(list->ui_data == gtkblist); 6945 g_return_if_fail(list->ui_data == gtkblist);
6871 6946
6872 purple_signals_disconnect_by_handle(gtkblist); 6947 purple_signals_disconnect_by_handle(gtkblist);
6873 6948
6874 if (gtkblist->headline_close)
6875 gdk_pixbuf_unref(gtkblist->headline_close);
6876
6877 gtk_widget_destroy(gtkblist->window); 6949 gtk_widget_destroy(gtkblist->window);
6878 6950
6879 pidgin_blist_tooltip_destroy(); 6951 pidgin_blist_tooltip_destroy();
6880 6952
6881 if (gtkblist->refresh_timer) 6953 if (gtkblist->refresh_timer)
6883 if (gtkblist->timeout) 6955 if (gtkblist->timeout)
6884 g_source_remove(gtkblist->timeout); 6956 g_source_remove(gtkblist->timeout);
6885 if (gtkblist->drag_timeout) 6957 if (gtkblist->drag_timeout)
6886 g_source_remove(gtkblist->drag_timeout); 6958 g_source_remove(gtkblist->drag_timeout);
6887 6959
6888 g_hash_table_destroy(gtkblist->connection_errors);
6889 gtkblist->refresh_timer = 0; 6960 gtkblist->refresh_timer = 0;
6890 gtkblist->timeout = 0; 6961 gtkblist->timeout = 0;
6891 gtkblist->drag_timeout = 0; 6962 gtkblist->drag_timeout = 0;
6892 gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL; 6963 gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL;
6893 g_object_unref(G_OBJECT(gtkblist->treemodel)); 6964 g_object_unref(G_OBJECT(gtkblist->treemodel));
6894 gtkblist->treemodel = NULL; 6965 gtkblist->treemodel = NULL;
6895 g_object_unref(G_OBJECT(gtkblist->ift)); 6966 g_object_unref(G_OBJECT(gtkblist->ui));
6896 g_object_unref(G_OBJECT(gtkblist->empty_avatar)); 6967 g_object_unref(G_OBJECT(gtkblist->empty_avatar));
6897 6968
6898 gdk_cursor_unref(gtkblist->hand_cursor); 6969 gdk_cursor_unref(gtkblist->hand_cursor);
6899 gdk_cursor_unref(gtkblist->arrow_cursor); 6970 gdk_cursor_unref(gtkblist->arrow_cursor);
6900 gtkblist->hand_cursor = NULL; 6971 gtkblist->hand_cursor = NULL;
6915 { 6986 {
6916 if (!(gtkblist && gtkblist->window)) 6987 if (!(gtkblist && gtkblist->window))
6917 return; 6988 return;
6918 6989
6919 if (show) { 6990 if (show) {
6920 if(!PIDGIN_WINDOW_ICONIFIED(gtkblist->window) && !GTK_WIDGET_VISIBLE(gtkblist->window)) 6991 if(!PIDGIN_WINDOW_ICONIFIED(gtkblist->window) && !gtk_widget_get_visible(gtkblist->window))
6921 purple_signal_emit(pidgin_blist_get_handle(), "gtkblist-unhiding", gtkblist); 6992 purple_signal_emit(pidgin_blist_get_handle(), "gtkblist-unhiding", gtkblist);
6922 pidgin_blist_restore_position(); 6993 pidgin_blist_restore_position();
6923 gtk_window_present(GTK_WINDOW(gtkblist->window)); 6994 gtk_window_present(GTK_WINDOW(gtkblist->window));
6924 } else { 6995 } else {
6925 if(visibility_manager_count) { 6996 if(visibility_manager_count) {
6926 purple_signal_emit(pidgin_blist_get_handle(), "gtkblist-hiding", gtkblist); 6997 purple_signal_emit(pidgin_blist_get_handle(), "gtkblist-hiding", gtkblist);
6927 gtk_widget_hide(gtkblist->window); 6998 gtk_widget_hide(gtkblist->window);
6928 } else { 6999 } else {
6929 if (!GTK_WIDGET_VISIBLE(gtkblist->window)) 7000 if (!gtk_widget_get_visible(gtkblist->window))
6930 gtk_widget_show(gtkblist->window); 7001 gtk_widget_show(gtkblist->window);
6931 gtk_window_iconify(GTK_WINDOW(gtkblist->window)); 7002 gtk_window_iconify(GTK_WINDOW(gtkblist->window));
6932 } 7003 }
6933 } 7004 }
6934 } 7005 }
6935 7006
6936 static GList * 7007 static GList *
6937 groups_tree(void) 7008 groups_tree(void)
6938 { 7009 {
6939 static GList *list = NULL; 7010 static GList *list = NULL;
6940 char *tmp2;
6941 PurpleGroup *g; 7011 PurpleGroup *g;
6942 PurpleBlistNode *gnode; 7012 PurpleBlistNode *gnode;
6943 7013
6944 g_list_free(list); 7014 g_list_free(list);
6945 list = NULL; 7015 list = NULL;
6955 gnode = gnode->next) 7025 gnode = gnode->next)
6956 { 7026 {
6957 if (PURPLE_BLIST_NODE_IS_GROUP(gnode)) 7027 if (PURPLE_BLIST_NODE_IS_GROUP(gnode))
6958 { 7028 {
6959 g = (PurpleGroup *)gnode; 7029 g = (PurpleGroup *)gnode;
6960 tmp2 = g->name; 7030 list = g_list_append(list, (char *) purple_group_get_name(g));
6961 list = g_list_append(list, tmp2);
6962 } 7031 }
6963 } 7032 }
6964 } 7033 }
6965 7034
6966 return list; 7035 return list;
7039 { 7108 {
7040 b = purple_buddy_new(account, who, whoalias); 7109 b = purple_buddy_new(account, who, whoalias);
7041 purple_blist_add_buddy(b, NULL, g, NULL); 7110 purple_blist_add_buddy(b, NULL, g, NULL);
7042 } 7111 }
7043 7112
7044 purple_account_add_buddy_with_invite(account, b, invite); 7113 purple_account_add_buddy(account, b, invite);
7045 7114
7046 /* Offer to merge people with the same alias. */ 7115 /* Offer to merge people with the same alias. */
7047 if (whoalias != NULL && g != NULL) 7116 if (whoalias != NULL && g != NULL)
7048 gtk_blist_auto_personize((PurpleBlistNode *)g, whoalias); 7117 gtk_blist_auto_personize(PURPLE_BLIST_NODE(g), whoalias);
7049 7118
7050 /* 7119 /*
7051 * XXX 7120 * XXX
7052 * It really seems like it would be better if the call to 7121 * It really seems like it would be better if the call to
7053 * purple_account_add_buddy() and purple_conversation_update() were done in 7122 * purple_account_add_buddy() and purple_conversation_update() were done in
7191 } 7260 }
7192 7261
7193 purple_blist_add_chat(chat, group, NULL); 7262 purple_blist_add_chat(chat, group, NULL);
7194 7263
7195 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->autojoin))) 7264 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->autojoin)))
7196 purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin", TRUE); 7265 purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin", TRUE);
7197 7266
7198 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->persistent))) 7267 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->persistent)))
7199 purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent", TRUE); 7268 purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-persistent", TRUE);
7200 } 7269 }
7201 7270
7202 gtk_widget_destroy(data->chat_data.rq_data.window); 7271 gtk_widget_destroy(data->chat_data.rq_data.window);
7203 g_free(data->chat_data.default_chat_name); 7272 g_free(data->chat_data.default_chat_name);
7204 g_list_free(data->chat_data.entries); 7273 g_list_free(data->chat_data.entries);
7231 { 7300 {
7232 PidginAddChatData *data; 7301 PidginAddChatData *data;
7233 GList *l; 7302 GList *l;
7234 PurpleConnection *gc; 7303 PurpleConnection *gc;
7235 GtkBox *vbox; 7304 GtkBox *vbox;
7305 PurplePluginProtocolInfo *prpl_info = NULL;
7236 7306
7237 if (account != NULL) { 7307 if (account != NULL) {
7238 gc = purple_account_get_connection(account); 7308 gc = purple_account_get_connection(account);
7239 7309 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
7240 if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat == NULL) { 7310
7311 if (prpl_info->join_chat == NULL) {
7241 purple_notify_error(gc, NULL, _("This protocol does not support chat rooms."), NULL); 7312 purple_notify_error(gc, NULL, _("This protocol does not support chat rooms."), NULL);
7242 return; 7313 return;
7243 } 7314 }
7244 } else { 7315 } else {
7245 /* Find an account with chat capabilities */ 7316 /* Find an account with chat capabilities */
7246 for (l = purple_connections_get_all(); l != NULL; l = l->next) { 7317 for (l = purple_connections_get_all(); l != NULL; l = l->next) {
7247 gc = (PurpleConnection *)l->data; 7318 gc = (PurpleConnection *)l->data;
7248 7319 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
7249 if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat != NULL) { 7320
7321 if (prpl_info->join_chat != NULL) {
7250 account = purple_connection_get_account(gc); 7322 account = purple_connection_get_account(gc);
7251 break; 7323 break;
7252 } 7324 }
7253 } 7325 }
7254 7326
7288 data->chat_data.rq_data.sg, data->alias_entry, 7360 data->chat_data.rq_data.sg, data->alias_entry,
7289 TRUE, NULL); 7361 TRUE, NULL);
7290 if (name != NULL) 7362 if (name != NULL)
7291 gtk_widget_grab_focus(data->alias_entry); 7363 gtk_widget_grab_focus(data->alias_entry);
7292 7364
7293 data->group_combo = pidgin_text_combo_box_entry_new(group ? group->name : NULL, groups_tree()); 7365 data->group_combo = pidgin_text_combo_box_entry_new(group ? purple_group_get_name(group) : NULL, groups_tree());
7294 pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Group:"), 7366 pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Group:"),
7295 data->chat_data.rq_data.sg, data->group_combo, 7367 data->chat_data.rq_data.sg, data->group_combo,
7296 TRUE, NULL); 7368 TRUE, NULL);
7297 7369
7298 data->autojoin = gtk_check_button_new_with_mnemonic(_("Auto_join when account connects.")); 7370 data->autojoin = gtk_check_button_new_with_mnemonic(_("Auto_join when account connects."));
7329 7401
7330 void 7402 void
7331 pidgin_blist_toggle_visibility() 7403 pidgin_blist_toggle_visibility()
7332 { 7404 {
7333 if (gtkblist && gtkblist->window) { 7405 if (gtkblist && gtkblist->window) {
7334 if (GTK_WIDGET_VISIBLE(gtkblist->window)) { 7406 if (gtk_widget_get_visible(gtkblist->window)) {
7335 /* make the buddy list visible if it is iconified or if it is 7407 /* make the buddy list visible if it is iconified or if it is
7336 * obscured and not currently focused (the focus part ensures 7408 * obscured and not currently focused (the focus part ensures
7337 * that we do something reasonable if the buddy list is obscured 7409 * that we do something reasonable if the buddy list is obscured
7338 * by a window set to always be on top), otherwise hide the 7410 * by a window set to always be on top), otherwise hide the
7339 * buddy list 7411 * buddy list
7394 7466
7395 7467
7396 static void 7468 static void
7397 set_urgent(void) 7469 set_urgent(void)
7398 { 7470 {
7399 if (gtkblist->window && !GTK_WIDGET_HAS_FOCUS(gtkblist->window)) 7471 if (gtkblist->window && !gtk_widget_has_focus(gtkblist->window))
7400 pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE); 7472 pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE);
7401 } 7473 }
7402 7474
7403 static PurpleBlistUiOps blist_ui_ops = 7475 static PurpleBlistUiOps blist_ui_ops =
7404 { 7476 {
7445 if(!PURPLE_BLIST_NODE_IS_CHAT(cnode)) 7517 if(!PURPLE_BLIST_NODE_IS_CHAT(cnode))
7446 continue; 7518 continue;
7447 7519
7448 chat = (PurpleChat *)cnode; 7520 chat = (PurpleChat *)cnode;
7449 7521
7450 if(chat->account != account) 7522 if(purple_chat_get_account(chat) != account)
7451 continue; 7523 continue;
7452 7524
7453 if (purple_blist_node_get_bool((PurpleBlistNode*)chat, "gtk-autojoin")) 7525 if (purple_blist_node_get_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin"))
7454 serv_join_chat(gc, chat->components); 7526 serv_join_chat(gc, purple_chat_get_components(chat));
7455 } 7527 }
7456 } 7528 }
7457 7529
7458 /* Stop processing; we handled the autojoins. */ 7530 /* Stop processing; we handled the autojoins. */
7459 return TRUE; 7531 return TRUE;
7466 return &handle; 7538 return &handle;
7467 } 7539 }
7468 7540
7469 static gboolean buddy_signonoff_timeout_cb(PurpleBuddy *buddy) 7541 static gboolean buddy_signonoff_timeout_cb(PurpleBuddy *buddy)
7470 { 7542 {
7471 struct _pidgin_blist_node *gtknode = ((PurpleBlistNode*)buddy)->ui_data; 7543 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
7472 7544
7473 gtknode->recent_signonoff = FALSE; 7545 gtknode->recent_signonoff = FALSE;
7474 gtknode->recent_signonoff_timer = 0; 7546 gtknode->recent_signonoff_timer = 0;
7475 7547
7476 pidgin_blist_update(NULL, (PurpleBlistNode*)buddy); 7548 pidgin_blist_update(NULL, PURPLE_BLIST_NODE(buddy));
7477 7549
7478 return FALSE; 7550 return FALSE;
7479 } 7551 }
7480 7552
7481 static void buddy_signonoff_cb(PurpleBuddy *buddy) 7553 static void buddy_signonoff_cb(PurpleBuddy *buddy)
7482 { 7554 {
7483 struct _pidgin_blist_node *gtknode; 7555 struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
7484 7556
7485 if(!((PurpleBlistNode*)buddy)->ui_data) { 7557 if(!gtknode) {
7486 pidgin_blist_new_node((PurpleBlistNode*)buddy); 7558 pidgin_blist_new_node(PURPLE_BLIST_NODE(buddy));
7487 } 7559 }
7488 7560
7489 gtknode = ((PurpleBlistNode*)buddy)->ui_data; 7561 gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
7490 7562
7491 gtknode->recent_signonoff = TRUE; 7563 gtknode->recent_signonoff = TRUE;
7492 7564
7493 if(gtknode->recent_signonoff_timer > 0) 7565 if(gtknode->recent_signonoff_timer > 0)
7494 purple_timeout_remove(gtknode->recent_signonoff_timer); 7566 purple_timeout_remove(gtknode->recent_signonoff_timer);
7851 if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { 7923 if(PURPLE_BLIST_NODE_IS_CONTACT(node)) {
7852 PurpleBlistNode *n; 7924 PurpleBlistNode *n;
7853 PurpleBuddy *buddy; 7925 PurpleBuddy *buddy;
7854 for (n = node->child; n; n = n->next) { 7926 for (n = node->child; n; n = n->next) {
7855 buddy = (PurpleBuddy*)n; 7927 buddy = (PurpleBuddy*)n;
7856 activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, buddy->name, buddy->account); 7928 activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
7857 } 7929 }
7858 buddy_name = purple_contact_get_alias((PurpleContact*)node); 7930 buddy_name = purple_contact_get_alias((PurpleContact*)node);
7859 } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { 7931 } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) {
7860 /* we don't have a reliable way of getting the log filename 7932 /* we don't have a reliable way of getting the log filename
7861 * from the chat info in the blist, yet */ 7933 * from the chat info in the blist, yet */
7887 this_log_activity_score = 0; 7959 this_log_activity_score = 0;
7888 7960
7889 if(PURPLE_BLIST_NODE_IS_CONTACT(n)) { 7961 if(PURPLE_BLIST_NODE_IS_CONTACT(n)) {
7890 for (n2 = n->child; n2; n2 = n2->next) { 7962 for (n2 = n->child; n2; n2 = n2->next) {
7891 buddy = (PurpleBuddy*)n2; 7963 buddy = (PurpleBuddy*)n2;
7892 this_log_activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, buddy->name, buddy->account); 7964 this_log_activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
7893 } 7965 }
7894 this_buddy_name = purple_contact_get_alias((PurpleContact*)n); 7966 this_buddy_name = purple_contact_get_alias((PurpleContact*)n);
7895 } else { 7967 } else {
7896 this_buddy_name = NULL; 7968 this_buddy_name = NULL;
7897 } 7969 }
7929 if (pam && pam->callback) 8001 if (pam && pam->callback)
7930 pam->callback(pam); 8002 pam->callback(pam);
7931 } 8003 }
7932 8004
7933 static void 8005 static void
7934 build_plugin_actions(GtkWidget *menu, PurplePlugin *plugin, 8006 build_plugin_actions(GtkActionGroup *action_group, GString *ui, char *parent,
7935 gpointer context) 8007 PurplePlugin *plugin, gpointer context)
7936 { 8008 {
7937 GtkWidget *menuitem; 8009 GtkAction *menuaction;
7938 PurplePluginAction *action = NULL; 8010 PurplePluginAction *action = NULL;
7939 GList *actions, *l; 8011 GList *actions, *l;
8012 char *name;
8013 int count = 0;
7940 8014
7941 actions = PURPLE_PLUGIN_ACTIONS(plugin, context); 8015 actions = PURPLE_PLUGIN_ACTIONS(plugin, context);
7942 8016
7943 for (l = actions; l != NULL; l = l->next) 8017 for (l = actions; l != NULL; l = l->next) {
7944 { 8018 if (l->data) {
7945 if (l->data) 8019 action = (PurplePluginAction *)l->data;
7946 {
7947 action = (PurplePluginAction *) l->data;
7948 action->plugin = plugin; 8020 action->plugin = plugin;
7949 action->context = context; 8021 action->context = context;
7950 8022
7951 menuitem = gtk_menu_item_new_with_label(action->label); 8023 name = g_strdup_printf("%s-action-%d", parent, count++);
7952 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); 8024 menuaction = gtk_action_new(name, action->label, NULL, NULL);
7953 8025 gtk_action_group_add_action(action_group, menuaction);
7954 g_signal_connect(G_OBJECT(menuitem), "activate", 8026 g_string_append_printf(ui, "<menuitem action='%s'/>", name);
8027
8028 g_signal_connect(G_OBJECT(menuaction), "activate",
7955 G_CALLBACK(plugin_act), action); 8029 G_CALLBACK(plugin_act), action);
7956 g_object_set_data_full(G_OBJECT(menuitem), "plugin_action", 8030 g_object_set_data_full(G_OBJECT(menuaction), "plugin_action",
7957 action, 8031 action,
7958 (GDestroyNotify)purple_plugin_action_free); 8032 (GDestroyNotify)purple_plugin_action_free);
7959 gtk_widget_show(menuitem); 8033 g_free(name);
7960 } 8034 }
7961 else 8035 else
7962 pidgin_separator(menu); 8036 g_string_append(ui, "<separator/>");
7963 } 8037 }
7964 8038
7965 g_list_free(actions); 8039 g_list_free(actions);
7966 } 8040 }
8041
7967 8042
7968 static void 8043 static void
7969 modify_account_cb(GtkWidget *widget, gpointer data) 8044 modify_account_cb(GtkWidget *widget, gpointer data)
7970 { 8045 {
7971 pidgin_account_dialog_show(PIDGIN_MODIFY_ACCOUNT_DIALOG, data); 8046 pidgin_account_dialog_show(PIDGIN_MODIFY_ACCOUNT_DIALOG, data);
7989 PurpleAccount *account = data; 8064 PurpleAccount *account = data;
7990 8065
7991 purple_account_set_enabled(account, PIDGIN_UI, FALSE); 8066 purple_account_set_enabled(account, PIDGIN_UI, FALSE);
7992 } 8067 }
7993 8068
7994
7995
7996 void 8069 void
7997 pidgin_blist_update_accounts_menu(void) 8070 pidgin_blist_update_accounts_menu(void)
7998 { 8071 {
7999 GtkWidget *menuitem = NULL, *submenu = NULL; 8072 GtkWidget *menuitem, *submenu;
8000 GtkAccelGroup *accel_group = NULL; 8073 GtkAccelGroup *accel_group;
8001 GList *l = NULL, *accounts = NULL; 8074 GList *l, *accounts;
8002 gboolean disabled_accounts = FALSE; 8075 gboolean disabled_accounts = FALSE;
8003 gboolean enabled_accounts = FALSE; 8076 gboolean enabled_accounts = FALSE;
8004 8077
8005 if (accountmenu == NULL) 8078 if (accountmenu == NULL)
8006 return; 8079 return;
8007 8080
8008 /* Clear the old Accounts menu */ 8081 /* Clear the old Accounts menu */
8009 for (l = gtk_container_get_children(GTK_CONTAINER(accountmenu)); l; l = g_list_delete_link(l, l)) { 8082 for (l = gtk_container_get_children(GTK_CONTAINER(accountmenu)); l; l = g_list_delete_link(l, l)) {
8010 menuitem = l->data; 8083 menuitem = l->data;
8011 8084
8012 if (menuitem != gtk_item_factory_get_widget(gtkblist->ift, N_("/Accounts/Manage Accounts"))) 8085 if (menuitem != gtk_ui_manager_get_widget(gtkblist->ui, "/BList/AccountsMenu/ManageAccounts"))
8013 gtk_widget_destroy(menuitem); 8086 gtk_widget_destroy(menuitem);
8014 } 8087 }
8088
8089 accel_group = gtk_menu_get_accel_group(GTK_MENU(accountmenu));
8015 8090
8016 for (accounts = purple_accounts_get_all(); accounts; accounts = accounts->next) { 8091 for (accounts = purple_accounts_get_all(); accounts; accounts = accounts->next) {
8017 char *buf = NULL; 8092 char *buf = NULL;
8018 GtkWidget *image = NULL; 8093 GtkWidget *image = NULL;
8019 PurpleAccount *account = NULL; 8094 PurpleAccount *account = NULL;
8020 GdkPixbuf *pixbuf = NULL; 8095 GdkPixbuf *pixbuf = NULL;
8021 8096
8022 account = accounts->data; 8097 account = accounts->data;
8023 8098
8024 if(!purple_account_get_enabled(account, PIDGIN_UI)) { 8099 if (!purple_account_get_enabled(account, PIDGIN_UI)) {
8025 if (!disabled_accounts) { 8100 if (!disabled_accounts) {
8026 menuitem = gtk_menu_item_new_with_label(_("Enable Account")); 8101 menuitem = gtk_menu_item_new_with_label(_("Enable Account"));
8027 gtk_menu_shell_append(GTK_MENU_SHELL(accountmenu), menuitem); 8102 gtk_menu_shell_append(GTK_MENU_SHELL(accountmenu), menuitem);
8028 8103
8029 submenu = gtk_menu_new(); 8104 submenu = gtk_menu_new();
8030 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); 8105 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group);
8031 gtk_menu_set_accel_path(GTK_MENU(submenu), N_("<PurpleMain>/Accounts/Enable Account")); 8106 gtk_menu_set_accel_path(GTK_MENU(submenu), "<Actions>/BListActions/EnableAccount");
8032 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); 8107 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
8033 8108
8034 disabled_accounts = TRUE; 8109 disabled_accounts = TRUE;
8035 } 8110 }
8036 8111
8037 buf = g_strconcat(purple_account_get_username(account), " (", 8112 buf = g_strconcat(purple_account_get_username(account), " (",
8038 purple_account_get_protocol_name(account), ")", NULL); 8113 purple_account_get_protocol_name(account), ")", NULL);
8039 menuitem = gtk_image_menu_item_new_with_label(buf); 8114 menuitem = gtk_image_menu_item_new_with_label(buf);
8040 g_free(buf); 8115 g_free(buf);
8116
8041 pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); 8117 pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
8042 if (pixbuf != NULL) 8118 if (pixbuf != NULL) {
8043 {
8044 if (!purple_account_is_connected(account)) 8119 if (!purple_account_is_connected(account))
8045 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); 8120 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
8046 image = gtk_image_new_from_pixbuf(pixbuf); 8121 image = gtk_image_new_from_pixbuf(pixbuf);
8047 g_object_unref(G_OBJECT(pixbuf)); 8122 g_object_unref(G_OBJECT(pixbuf));
8048 gtk_widget_show(image); 8123 gtk_widget_show(image);
8049 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); 8124 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
8050 } 8125 }
8126
8051 g_signal_connect(G_OBJECT(menuitem), "activate", 8127 g_signal_connect(G_OBJECT(menuitem), "activate",
8052 G_CALLBACK(enable_account_cb), account); 8128 G_CALLBACK(enable_account_cb), account);
8053 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); 8129 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
8130
8054 } else { 8131 } else {
8055 enabled_accounts = TRUE; 8132 enabled_accounts = TRUE;
8056 } 8133 }
8057 } 8134 }
8058 8135
8060 gtk_widget_show_all(accountmenu); 8137 gtk_widget_show_all(accountmenu);
8061 return; 8138 return;
8062 } 8139 }
8063 8140
8064 pidgin_separator(accountmenu); 8141 pidgin_separator(accountmenu);
8065 accel_group = gtk_menu_get_accel_group(GTK_MENU(accountmenu));
8066 8142
8067 for (accounts = purple_accounts_get_all(); accounts; accounts = accounts->next) { 8143 for (accounts = purple_accounts_get_all(); accounts; accounts = accounts->next) {
8068 char *buf = NULL; 8144 char *buf = NULL;
8069 char *accel_path_buf = NULL; 8145 char *accel_path_buf = NULL;
8070 GtkWidget *image = NULL; 8146 GtkWidget *image = NULL;
8080 continue; 8156 continue;
8081 8157
8082 buf = g_strconcat(purple_account_get_username(account), " (", 8158 buf = g_strconcat(purple_account_get_username(account), " (",
8083 purple_account_get_protocol_name(account), ")", NULL); 8159 purple_account_get_protocol_name(account), ")", NULL);
8084 menuitem = gtk_image_menu_item_new_with_label(buf); 8160 menuitem = gtk_image_menu_item_new_with_label(buf);
8085 accel_path_buf = g_strconcat(N_("<PurpleMain>/Accounts/"), buf, NULL); 8161 accel_path_buf = g_strconcat("<Actions>/AccountActions/", buf, NULL);
8086 g_free(buf); 8162 g_free(buf);
8163
8087 pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); 8164 pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
8088 if (pixbuf != NULL) { 8165 if (pixbuf != NULL) {
8089 if (!purple_account_is_connected(account)) 8166 if (!purple_account_is_connected(account))
8090 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 8167 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf,
8091 0.0, FALSE); 8168 0.0, FALSE);
8092 image = gtk_image_new_from_pixbuf(pixbuf); 8169 image = gtk_image_new_from_pixbuf(pixbuf);
8093 g_object_unref(G_OBJECT(pixbuf)); 8170 g_object_unref(G_OBJECT(pixbuf));
8094 gtk_widget_show(image); 8171 gtk_widget_show(image);
8095 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); 8172 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
8096 } 8173 }
8174
8097 gtk_menu_shell_append(GTK_MENU_SHELL(accountmenu), menuitem); 8175 gtk_menu_shell_append(GTK_MENU_SHELL(accountmenu), menuitem);
8098 8176
8099 submenu = gtk_menu_new(); 8177 submenu = gtk_menu_new();
8100 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); 8178 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group);
8101 gtk_menu_set_accel_path(GTK_MENU(submenu), accel_path_buf); 8179 gtk_menu_set_accel_path(GTK_MENU(submenu), accel_path_buf);
8102 g_free(accel_path_buf); 8180 g_free(accel_path_buf);
8103 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); 8181 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
8104 8182
8105
8106 menuitem = gtk_menu_item_new_with_mnemonic(_("_Edit Account")); 8183 menuitem = gtk_menu_item_new_with_mnemonic(_("_Edit Account"));
8107 g_signal_connect(G_OBJECT(menuitem), "activate", 8184 g_signal_connect(G_OBJECT(menuitem), "activate",
8108 G_CALLBACK(modify_account_cb), account); 8185 G_CALLBACK(modify_account_cb), account);
8109 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); 8186 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
8110 8187
8111 pidgin_separator(submenu); 8188 pidgin_separator(submenu);
8112 8189
8113 gc = purple_account_get_connection(account); 8190 gc = purple_account_get_connection(account);
8114 plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? gc->prpl : NULL; 8191 plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? purple_connection_get_prpl(gc) : NULL;
8115 prpl_info = plugin ? PURPLE_PLUGIN_PROTOCOL_INFO(plugin) : NULL; 8192 prpl_info = plugin ? PURPLE_PLUGIN_PROTOCOL_INFO(plugin) : NULL;
8116 8193
8117 if (prpl_info && 8194 if (prpl_info &&
8118 (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) || 8195 (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) ||
8119 PURPLE_PLUGIN_HAS_ACTIONS(plugin))) { 8196 PURPLE_PLUGIN_HAS_ACTIONS(plugin))) {
8120 if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) && 8197 if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) &&
8121 gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) { 8198 (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS)) {
8122 8199
8123 if (purple_account_get_status(account, "mood")) { 8200 if (purple_account_get_status(account, "mood")) {
8124 menuitem = gtk_menu_item_new_with_mnemonic(_("Set _Mood...")); 8201 menuitem = gtk_menu_item_new_with_mnemonic(_("Set _Mood..."));
8125 g_signal_connect(G_OBJECT(menuitem), "activate", 8202 g_signal_connect(G_OBJECT(menuitem), "activate",
8126 G_CALLBACK(set_mood_cb), account); 8203 G_CALLBACK(set_mood_cb), account);
8127 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); 8204 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
8128 } 8205 }
8129 } 8206 }
8207
8130 if (PURPLE_PLUGIN_HAS_ACTIONS(plugin)) { 8208 if (PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
8131 build_plugin_actions(submenu, plugin, gc); 8209 GtkWidget *menuitem;
8210 PurplePluginAction *action = NULL;
8211 GList *actions, *l;
8212
8213 actions = PURPLE_PLUGIN_ACTIONS(plugin, gc);
8214
8215 for (l = actions; l != NULL; l = l->next)
8216 {
8217 if (l->data)
8218 {
8219 action = (PurplePluginAction *) l->data;
8220 action->plugin = plugin;
8221 action->context = gc;
8222
8223 menuitem = gtk_menu_item_new_with_label(action->label);
8224 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
8225
8226 g_signal_connect(G_OBJECT(menuitem), "activate",
8227 G_CALLBACK(plugin_act), action);
8228 g_object_set_data_full(G_OBJECT(menuitem), "plugin_action",
8229 action,
8230 (GDestroyNotify)purple_plugin_action_free);
8231 gtk_widget_show(menuitem);
8232 }
8233 else
8234 pidgin_separator(submenu);
8235 }
8236
8237 g_list_free(actions);
8132 } 8238 }
8133 } else { 8239 } else {
8134 menuitem = gtk_menu_item_new_with_label(_("No actions available")); 8240 menuitem = gtk_menu_item_new_with_label(_("No actions available"));
8135 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); 8241 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
8136 gtk_widget_set_sensitive(menuitem, FALSE); 8242 gtk_widget_set_sensitive(menuitem, FALSE);
8141 menuitem = gtk_menu_item_new_with_mnemonic(_("_Disable")); 8247 menuitem = gtk_menu_item_new_with_mnemonic(_("_Disable"));
8142 g_signal_connect(G_OBJECT(menuitem), "activate", 8248 g_signal_connect(G_OBJECT(menuitem), "activate",
8143 G_CALLBACK(disable_account_cb), account); 8249 G_CALLBACK(disable_account_cb), account);
8144 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); 8250 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
8145 } 8251 }
8252
8146 gtk_widget_show_all(accountmenu); 8253 gtk_widget_show_all(accountmenu);
8147 } 8254 }
8148 8255
8149 static GList *plugin_submenus = NULL; 8256 static guint plugins_merge_id;
8257 static GtkActionGroup *plugins_action_group = NULL;
8150 8258
8151 void 8259 void
8152 pidgin_blist_update_plugin_actions(void) 8260 pidgin_blist_update_plugin_actions(void)
8153 { 8261 {
8154 GtkWidget *menuitem, *submenu;
8155 PurplePlugin *plugin = NULL; 8262 PurplePlugin *plugin = NULL;
8156 GList *l; 8263 GList *l;
8157 GtkAccelGroup *accel_group; 8264
8158 8265 GtkAction *action;
8159 GtkWidget *pluginmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools")); 8266 GString *plugins_ui;
8160 8267 gchar *ui_string;
8161 g_return_if_fail(pluginmenu != NULL); 8268 int count = 0;
8162 8269
8163 /* Remove old plugin action submenus from the Tools menu */ 8270 if ((gtkblist == NULL) || (gtkblist->ui == NULL))
8164 for (l = plugin_submenus; l; l = l->next) 8271 return;
8165 gtk_widget_destroy(GTK_WIDGET(l->data)); 8272
8166 g_list_free(plugin_submenus); 8273 /* Clear the old menu */
8167 plugin_submenus = NULL; 8274 if (plugins_action_group) {
8168 8275 gtk_ui_manager_remove_ui(gtkblist->ui, plugins_merge_id);
8169 accel_group = gtk_menu_get_accel_group(GTK_MENU(pluginmenu)); 8276 gtk_ui_manager_remove_action_group(gtkblist->ui, plugins_action_group);
8277 g_object_unref(G_OBJECT(plugins_action_group));
8278 }
8279
8280 plugins_action_group = gtk_action_group_new("PluginActions");
8281 #ifdef ENABLE_NLS
8282 gtk_action_group_set_translation_domain(plugins_action_group, PACKAGE);
8283 #endif
8284 plugins_ui = g_string_new(NULL);
8170 8285
8171 /* Add a submenu for each plugin with custom actions */ 8286 /* Add a submenu for each plugin with custom actions */
8172 for (l = purple_plugins_get_loaded(); l; l = l->next) { 8287 for (l = purple_plugins_get_loaded(); l; l = l->next) {
8173 char *path; 8288 char *name;
8174 8289
8175 plugin = (PurplePlugin *) l->data; 8290 plugin = (PurplePlugin *)l->data;
8176 8291
8177 if (PURPLE_IS_PROTOCOL_PLUGIN(plugin)) 8292 if (PURPLE_IS_PROTOCOL_PLUGIN(plugin))
8178 continue; 8293 continue;
8179 8294
8180 if (!PURPLE_PLUGIN_HAS_ACTIONS(plugin)) 8295 if (!PURPLE_PLUGIN_HAS_ACTIONS(plugin))
8181 continue; 8296 continue;
8182 8297
8183 menuitem = gtk_image_menu_item_new_with_label(_(plugin->info->name)); 8298 name = g_strdup_printf("plugin%d", count);
8184 gtk_menu_shell_append(GTK_MENU_SHELL(pluginmenu), menuitem); 8299 action = gtk_action_new(name, plugin->info->name, NULL, NULL);
8185 8300 gtk_action_group_add_action(plugins_action_group, action);
8186 plugin_submenus = g_list_append(plugin_submenus, menuitem); 8301 g_string_append_printf(plugins_ui, "<menu action='%s'>", name);
8187 8302
8188 submenu = gtk_menu_new(); 8303 build_plugin_actions(plugins_action_group, plugins_ui, name, plugin, NULL);
8189 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); 8304
8190 8305 g_string_append(plugins_ui, "</menu>");
8191 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); 8306 count++;
8192 path = g_strdup_printf("%s/Tools/%s", gtkblist->ift->path, plugin->info->name); 8307
8193 gtk_menu_set_accel_path(GTK_MENU(submenu), path); 8308 g_free(name);
8194 g_free(path); 8309 }
8195 8310
8196 build_plugin_actions(submenu, plugin, NULL); 8311 ui_string = g_strconcat("<ui><menubar action='BList'><menu action='ToolsMenu'><placeholder name='PluginActions'>",
8197 } 8312 plugins_ui->str,
8198 gtk_widget_show_all(pluginmenu); 8313 "</placeholder></menu></menubar></ui>",
8314 NULL);
8315 gtk_ui_manager_insert_action_group(gtkblist->ui, plugins_action_group, 1);
8316 plugins_merge_id = gtk_ui_manager_add_ui_from_string(gtkblist->ui, ui_string, -1, NULL);
8317
8318 g_string_free(plugins_ui, TRUE);
8319 g_free(ui_string);
8199 } 8320 }
8200 8321
8201 static void 8322 static void
8202 sortmethod_act(GtkCheckMenuItem *checkmenuitem, char *id) 8323 sortmethod_act(GtkRadioAction *action, GtkRadioAction *current, char *id)
8203 { 8324 {
8204 if (gtk_check_menu_item_get_active(checkmenuitem)) 8325 if (action == current)
8205 { 8326 {
8206 pidgin_set_cursor(gtkblist->window, GDK_WATCH); 8327 pidgin_set_cursor(gtkblist->window, GDK_WATCH);
8207 /* This is redundant. I think. */ 8328 /* This is redundant. I think. */
8208 /* pidgin_blist_sort_method_set(id); */ 8329 /* pidgin_blist_sort_method_set(id); */
8209 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/blist/sort_type", id); 8330 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/blist/sort_type", id);
8213 } 8334 }
8214 8335
8215 void 8336 void
8216 pidgin_blist_update_sort_methods(void) 8337 pidgin_blist_update_sort_methods(void)
8217 { 8338 {
8218 GtkWidget *menuitem = NULL, *activeitem = NULL;
8219 PidginBlistSortMethod *method = NULL; 8339 PidginBlistSortMethod *method = NULL;
8220 GList *l; 8340 GList *l;
8221 GSList *sl = NULL; 8341 GSList *sl = NULL;
8222 GtkWidget *sortmenu;
8223 const char *m = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/sort_type"); 8342 const char *m = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/sort_type");
8224 8343
8225 if ((gtkblist == NULL) || (gtkblist->ift == NULL)) 8344 GtkRadioAction *action;
8345 GString *ui_string;
8346
8347 if ((gtkblist == NULL) || (gtkblist->ui == NULL))
8226 return; 8348 return;
8227 8349
8228 g_return_if_fail(m != NULL);
8229
8230 sortmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Buddies/Sort Buddies"));
8231
8232 if (sortmenu == NULL)
8233 return;
8234
8235 /* Clear the old menu */ 8350 /* Clear the old menu */
8236 for (l = gtk_container_get_children(GTK_CONTAINER(sortmenu)); l; l = g_list_delete_link(l, l)) { 8351 if (sort_action_group) {
8237 menuitem = l->data; 8352 gtk_ui_manager_remove_ui(gtkblist->ui, sort_merge_id);
8238 gtk_widget_destroy(GTK_WIDGET(menuitem)); 8353 gtk_ui_manager_remove_action_group(gtkblist->ui, sort_action_group);
8239 } 8354 g_object_unref(G_OBJECT(sort_action_group));
8355 }
8356
8357 sort_action_group = gtk_action_group_new("SortMethods");
8358 #ifdef ENABLE_NLS
8359 gtk_action_group_set_translation_domain(sort_action_group, PACKAGE);
8360 #endif
8361 ui_string = g_string_new("<ui><menubar name='BList'>"
8362 "<menu action='BuddiesMenu'><menu action='SortMenu'>");
8240 8363
8241 for (l = pidgin_blist_sort_methods; l; l = l->next) { 8364 for (l = pidgin_blist_sort_methods; l; l = l->next) {
8242 method = (PidginBlistSortMethod *) l->data; 8365 method = (PidginBlistSortMethod *)l->data;
8243 menuitem = gtk_radio_menu_item_new_with_label(sl, _(method->name)); 8366
8244 if (g_str_equal(m, method->id)) 8367 g_string_append_printf(ui_string, "<menuitem action='%s'/>", method->id);
8245 activeitem = menuitem; 8368 action = gtk_radio_action_new(method->id,
8246 sl = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem)); 8369 method->name,
8247 gtk_menu_shell_append(GTK_MENU_SHELL(sortmenu), menuitem); 8370 NULL,
8248 g_signal_connect(G_OBJECT(menuitem), "toggled", 8371 NULL,
8249 G_CALLBACK(sortmethod_act), method->id); 8372 0);
8250 gtk_widget_show(menuitem); 8373 gtk_action_group_add_action_with_accel(sort_action_group, GTK_ACTION(action), NULL);
8251 } 8374
8252 if (activeitem) 8375 gtk_radio_action_set_group(action, sl);
8253 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(activeitem), TRUE); 8376 sl = gtk_radio_action_get_group(action);
8254 } 8377
8378 if (!strcmp(m, method->id))
8379 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
8380 else
8381 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), FALSE);
8382
8383 g_signal_connect(G_OBJECT(action), "changed",
8384 G_CALLBACK(sortmethod_act), method->id);
8385 }
8386
8387 g_string_append(ui_string, "</menu></menu></menubar></ui>");
8388 gtk_ui_manager_insert_action_group(gtkblist->ui, sort_action_group, 1);
8389 sort_merge_id = gtk_ui_manager_add_ui_from_string(gtkblist->ui, ui_string->str, -1, NULL);
8390
8391 g_string_free(ui_string, TRUE);
8392 }
8393