# HG changeset patch # User Mark Doliner # Date 1085333265 0 # Node ID 7b574a641391478c3a7b0f5caced362a628986f5 # Parent 4670ebf1c180240900c01c7f1fa611d1e18d9ba1 [gaim-migrate @ 9806] Siege updated the code for creating right-click menu's for buddies, chats, groups, etc. It uses more stuff from the blist API and less stuff from multi.h. It also combines the code for right-click menus for chats, buddies, etc. (all types of blist nodes). So PRPLs and plugins can easily add right-click menu options to anything in the buddy list in a clean way. diff -r 4670ebf1c180 -r 7b574a641391 src/blist.c --- a/src/blist.c Sun May 23 08:06:38 2004 +0000 +++ b/src/blist.c Sun May 23 17:27:45 2004 +0000 @@ -2720,25 +2720,28 @@ /* XXX: end compat crap */ -GList *gaim_buddy_get_extended_menu(GaimBuddy *b) { +GList *gaim_blist_node_get_extended_menu(GaimBlistNode *n) { GList *menu = NULL; - gaim_signal_emit(gaim_blist_get_handle(), "buddy-extended-menu", - b, &menu); + + g_return_val_if_fail(n, NULL); + + gaim_signal_emit(gaim_blist_get_handle(), + "blist-node-extended-menu", + n, &menu); return menu; } -GList *gaim_chat_get_extended_menu(GaimChat *c) { - GList *menu = NULL; - gaim_signal_emit(gaim_blist_get_handle(), "chat-extended-menu", - c, &menu); - return menu; -} - -GList *gaim_group_get_extended_menu(GaimGroup *g) { - GList *menu = NULL; - gaim_signal_emit(gaim_blist_get_handle(), "group-extended-menu", - g, &menu); - return menu; + +GaimBlistNodeAction * +gaim_blist_node_action_new(char *label, + void (*callback)(GaimBlistNode *, gpointer), + gpointer data) +{ + GaimBlistNodeAction *act = g_new0(GaimBlistNodeAction, 1); + act->label = label; + act->callback = callback; + act->data = data; + return act; } @@ -2812,20 +2815,11 @@ GAIM_SUBTYPE_BLIST_BUDDY)); gaim_signal_register(handle, "update-idle", gaim_marshal_VOID, NULL, 0); - gaim_signal_register(handle, "buddy-extended-menu", + + gaim_signal_register(handle, "blist-node-extended-menu", gaim_marshal_VOID__POINTER_POINTER, NULL, 2, gaim_value_new(GAIM_TYPE_SUBTYPE, - GAIM_SUBTYPE_BLIST_BUDDY), - gaim_value_new(GAIM_TYPE_BOXED, "GList **")); - gaim_signal_register(handle, "chat-extended-menu", - gaim_marshal_VOID__POINTER_POINTER, NULL, 2, - gaim_value_new(GAIM_TYPE_SUBTYPE, - GAIM_SUBTYPE_BLIST_CHAT), - gaim_value_new(GAIM_TYPE_BOXED, "GList **")); - gaim_signal_register(handle, "group-extended-menu", - gaim_marshal_VOID__POINTER_POINTER, NULL, 2, - gaim_value_new(GAIM_TYPE_SUBTYPE, - GAIM_SUBTYPE_BLIST_GROUP), + GAIM_SUBTYPE_BLIST_NODE), gaim_value_new(GAIM_TYPE_BOXED, "GList **")); } @@ -2834,3 +2828,4 @@ { gaim_signals_unregister_by_instance(gaim_blist_get_handle()); } + diff -r 4670ebf1c180 -r 7b574a641391 src/blist.h --- a/src/blist.h Sun May 23 08:06:38 2004 +0000 +++ b/src/blist.h Sun May 23 17:27:45 2004 +0000 @@ -34,6 +34,8 @@ typedef struct _GaimBlistUiOps GaimBlistUiOps; typedef struct _GaimBlistNode GaimBlistNode; +typedef struct _GaimBlistNodeAction GaimBlistNodeAction; + typedef struct _GaimChat GaimChat; typedef struct _GaimGroup GaimGroup; typedef struct _GaimContact GaimContact; @@ -183,6 +185,14 @@ void (*request_add_group)(void); }; + +struct _GaimBlistNodeAction { + char *label; + void (*callback)(GaimBlistNode *, gpointer); + gpointer data; +}; + + #ifdef __cplusplus extern "C" { #endif @@ -857,22 +867,23 @@ /** - * Retrieves the extended menu items for a buddy. - * @param b The buddy to obtain the extended menu items for -*/ -GList *gaim_buddy_get_extended_menu(GaimBuddy *b); + * Retrieves the extended menu items for a buddy list node. + * @param n The blist node for which to obtain the extended menu items. + * @return list of GaimBlistNodeAction items, as harvested by the + * blist-node-extended-menu signal. + */ +GList *gaim_blist_node_get_extended_menu(GaimBlistNode *n); + /** - * Retrieves the extended menu items for a chat. - * @param c The chat to obtain the extended menu items for -*/ -GList *gaim_chat_get_extended_menu(GaimChat *c); - -/** - * Retrieves the extended menu items for a group. - * @param g The group to obtain the extended menu items for -*/ -GList *gaim_group_get_extended_menu(GaimGroup *g); + * Creates a new GaimBlistNodeAction. + * @param label The text label to display for this action. + * @param callback The function to be called when the action is used on + * a selected GaimBlistNode. + * @param data Additional data, to be passed to the callback + */ +GaimBlistNodeAction *gaim_blist_node_action_new(char *label, + void (*callback)(GaimBlistNode *, gpointer), gpointer data); /**************************************************************************/ diff -r 4670ebf1c180 -r 7b574a641391 src/gtkblist.c --- a/src/gtkblist.c Sun May 23 08:06:38 2004 +0000 +++ b/src/gtkblist.c Sun May 23 17:27:45 2004 +0000 @@ -1059,19 +1059,75 @@ } } -static void gaim_proto_menu_cb(GtkMenuItem *item, GaimBuddy *b) + +static void +blist_node_menu_cb(GtkMenuItem *item, GaimBlistNode *node) +{ + GaimBlistNodeAction *act; + act = (GaimBlistNodeAction *) g_object_get_data(G_OBJECT(item), + "gaimcallback"); + if(act->callback) + act->callback(node, act->data); +} + + +static void +append_blist_node_action (GtkWidget *menu, GaimBlistNodeAction *act, + GaimBlistNode *node, gboolean *dup_separator) { - struct proto_buddy_menu *pbm = g_object_get_data(G_OBJECT(item), "gaimcallback"); - if (pbm->callback) - pbm->callback(pbm->gc, b->name); + if(act == NULL) { + if(! *dup_separator) { + gaim_separator(menu); + *dup_separator = TRUE; + } + } else { + GtkWidget *menuitem; + + *dup_separator = FALSE; + + menuitem = gtk_menu_item_new_with_mnemonic(act->label); + g_object_set_data(G_OBJECT(menuitem), "gaimcallback", act); + g_signal_connect(G_OBJECT(menuitem), "activate", + G_CALLBACK(blist_node_menu_cb), node); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } } + +static void +append_blist_node_proto_menu (GtkWidget *menu, GaimConnection *gc, GaimBlistNode *node) +{ + GList *l, *ll; + gboolean dup_separator = FALSE; + GaimPluginProtocolInfo *prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); + + if(!prpl_info || !prpl_info->blist_node_menu) + return; + + for(l = ll = prpl_info->blist_node_menu(node); l; l = l->next) { + GaimBlistNodeAction *act = (GaimBlistNodeAction *) l->data; + append_blist_node_action(menu, act, node, &dup_separator); + } + g_list_free(ll); +} + + +static void +append_blist_node_extended_menu (GtkWidget *menu, GaimBlistNode *node) +{ + GList *l, *ll; + gboolean dup_separator = FALSE; + + for(l = ll = gaim_blist_node_get_extended_menu(node); l; l = l->next) { + GaimBlistNodeAction *act = (GaimBlistNodeAction *) l->data; + append_blist_node_action(menu, act, node, &dup_separator); + } + g_list_free(ll); +} + + static void make_buddy_menu(GtkWidget *menu, GaimPluginProtocolInfo *prpl_info, GaimBuddy *b) { - GList *list = NULL, *l = NULL; - gboolean dup_separator = FALSE; - GtkWidget *menuitem; - if (prpl_info && prpl_info->get_info) {