Mercurial > pidgin
comparison src/gtkblist.c @ 8986:8cf32769ba1b
[gaim-migrate @ 9761]
" This patch adds a Plugin Actions menu item after the
Account Actions menu. The Plugin Actions menu is
populated from the added 'actions' slot in
GaimPluginInfo. As a demonstration, the Idle Maker
plugin has been converted to no longer require GTK code
and the Preferences interface just to perform its
actions. Instead, it uses a Plugin Action to spawn a
Fields Request.
There's also a minor fix for consistency in the menu
building for buddy actions. The pre-existing method for
instructing a menu list to display a separator was to
insert a NULL rather than a proto_buddy_menu into the
GList of actions. The code for the buddy menus was
instead checking for a proto_buddy_menu with a '-'
label. This has been fixed, and it now correctly uses
NULL to indicate a separator."
"Date: 2004-05-16 02:25
Sender: taliesein
Logged In: YES
user_id=77326
I need to add a callback to this patch to watch for
loading/unloading of plugins (to determine when to rebuild
the menu). Since the appropriate way to handle Plugin
Actions is still mildly up for debate, I'm holding of on
correcting the patch until I know for sure whether I should
fix this patch, or scrap it and write a new one using a
different method."
"Date: 2004-05-18 12:26
Sender: taliesein
Logged In: YES
user_id=77326
I've completed changes to this patch to also add plugin load
and unload signals (it looks like plugin.c actually had
pre-signal callbacks in place, but they were never used or
converted to signals)
This patch now will correctly update the Plugin Action menu
as plugins load and unload."
I'm not entirely sure i like the ui of a plugins actions menu, but i think
that having some way for plugins to add actions on an account is a good
thing, and i'm not sure that every viable action fits under the accounts
actions menu. we may want to merge the two (the existing accounts actions
and this plugins actions), but both times it came up in #gaim no one seemed
to want to comment, and on one commented to the gaim-devel post either.
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Thu, 20 May 2004 05:11:44 +0000 |
parents | 574393ccd705 |
children | d494fd1bd90b |
comparison
equal
deleted
inserted
replaced
8985:8abc99ed5d93 | 8986:8cf32769ba1b |
---|---|
27 #include "debug.h" | 27 #include "debug.h" |
28 #include "multi.h" | 28 #include "multi.h" |
29 #include "notify.h" | 29 #include "notify.h" |
30 #include "prpl.h" | 30 #include "prpl.h" |
31 #include "prefs.h" | 31 #include "prefs.h" |
32 #include "plugin.h" | |
32 #include "request.h" | 33 #include "request.h" |
33 #include "signals.h" | 34 #include "signals.h" |
34 #include "sound.h" | 35 #include "sound.h" |
35 #include "stock.h" | 36 #include "stock.h" |
36 #include "util.h" | 37 #include "util.h" |
97 | 98 |
98 GList *entries; | 99 GList *entries; |
99 } GaimGtkJoinChatData; | 100 } GaimGtkJoinChatData; |
100 | 101 |
101 | 102 |
102 static GtkWidget *protomenu = NULL; | 103 static GtkWidget *protomenu = NULL, *pluginmenu = NULL; |
103 | 104 |
104 GSList *gaim_gtk_blist_sort_methods = NULL; | 105 GSList *gaim_gtk_blist_sort_methods = NULL; |
105 static struct gaim_gtk_blist_sort_method *current_sort_method = NULL; | 106 static struct gaim_gtk_blist_sort_method *current_sort_method = NULL; |
106 static GtkTreeIter sort_method_none(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); | 107 static GtkTreeIter sort_method_none(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); |
107 | 108 |
1092 list = prpl_info->buddy_menu(b->account->gc, b->name); | 1093 list = prpl_info->buddy_menu(b->account->gc, b->name); |
1093 | 1094 |
1094 for(l = list; l; l = l->next) { | 1095 for(l = list; l; l = l->next) { |
1095 struct proto_buddy_menu *pbm = l->data; | 1096 struct proto_buddy_menu *pbm = l->data; |
1096 | 1097 |
1097 /* draw "-" titled menu items as a separator. Since the | 1098 /* draw NULL menu items as a separator. Since the |
1098 pbm is not being used in a callback, it needs to be | 1099 pbm is not being used in a callback, it needs to be |
1099 freed. Also, do some simple checking to prevent | 1100 freed. Also, do some simple checking to prevent |
1100 doubled-up separators */ | 1101 doubled-up separators */ |
1101 if('-' == *pbm->label) { | 1102 if(pbm == NULL) { |
1102 if(! dup_separator) { | 1103 if(! dup_separator) { |
1103 gaim_separator(menu); | 1104 gaim_separator(menu); |
1104 dup_separator = TRUE; | 1105 dup_separator = TRUE; |
1105 } | 1106 } |
1106 g_free(pbm); | |
1107 continue; | 1107 continue; |
1108 } else { | 1108 } else { |
1109 dup_separator = FALSE; | 1109 dup_separator = FALSE; |
1110 } | 1110 } |
1111 | 1111 |
1122 plugins. */ | 1122 plugins. */ |
1123 list = gaim_buddy_get_extended_menu(b); | 1123 list = gaim_buddy_get_extended_menu(b); |
1124 for(l = list; l; l = l->next) { | 1124 for(l = list; l; l = l->next) { |
1125 struct proto_buddy_menu *pbm = l->data; | 1125 struct proto_buddy_menu *pbm = l->data; |
1126 | 1126 |
1127 /* draw "-" titled menu items as a separator. see previous, | 1127 /* draw NULL menu items as a separator. see previous, |
1128 identical-looking code. */ | 1128 identical-looking code. */ |
1129 if('-' == *pbm->label) { | 1129 if(pbm == NULL) { |
1130 if(! dup_separator) { | 1130 if(! dup_separator) { |
1131 gaim_separator(menu); | 1131 gaim_separator(menu); |
1132 dup_separator = TRUE; | 1132 dup_separator = TRUE; |
1133 } | 1133 } |
1134 g_free(pbm); | 1134 g_free(pbm); |
1211 | 1211 |
1212 list = gaim_group_get_extended_menu(g); | 1212 list = gaim_group_get_extended_menu(g); |
1213 for(l = list; l; l = l->next) { | 1213 for(l = list; l; l = l->next) { |
1214 struct proto_group_menu *pgm = l->data; | 1214 struct proto_group_menu *pgm = l->data; |
1215 | 1215 |
1216 /* draw "-" titled menu items as a separator. see previous, | 1216 /* draw NULL menu items as a separator. see previous, |
1217 identical-looking code. (in make_buddy_menu)*/ | 1217 identical-looking code. (in make_buddy_menu)*/ |
1218 if(pgm == NULL) { | 1218 if(pgm == NULL) { |
1219 if(! dup_separator) { | 1219 if(! dup_separator) { |
1220 gaim_separator(menu); | 1220 gaim_separator(menu); |
1221 dup_separator = TRUE; | 1221 dup_separator = TRUE; |
2353 /* Tools */ | 2353 /* Tools */ |
2354 { N_("/_Tools"), NULL, NULL, 0, "<Branch>" }, | 2354 { N_("/_Tools"), NULL, NULL, 0, "<Branch>" }, |
2355 { N_("/Tools/_Away"), NULL, NULL, 0, "<Branch>" }, | 2355 { N_("/Tools/_Away"), NULL, NULL, 0, "<Branch>" }, |
2356 { N_("/Tools/Buddy _Pounce"), NULL, NULL, 0, "<Branch>" }, | 2356 { N_("/Tools/Buddy _Pounce"), NULL, NULL, 0, "<Branch>" }, |
2357 { N_("/Tools/Account Ac_tions"), NULL, NULL, 0, "<Branch>" }, | 2357 { N_("/Tools/Account Ac_tions"), NULL, NULL, 0, "<Branch>" }, |
2358 { N_("/Tools/Pl_ugin Actions"), NULL, NULL, 0, "<Branch>" }, | |
2358 { "/Tools/sep1", NULL, NULL, 0, "<Separator>" }, | 2359 { "/Tools/sep1", NULL, NULL, 0, "<Separator>" }, |
2359 { N_("/Tools/A_ccounts"), "<CTL>A", gaim_gtk_accounts_window_show, 0, "<StockItem>", GAIM_STOCK_ACCOUNTS }, | 2360 { N_("/Tools/A_ccounts"), "<CTL>A", gaim_gtk_accounts_window_show, 0, "<StockItem>", GAIM_STOCK_ACCOUNTS }, |
2360 { N_("/Tools/_File Transfers"), NULL, gaim_show_xfer_dialog, 0, "<StockItem>", GAIM_STOCK_FILE_TRANSFER }, | 2361 { N_("/Tools/_File Transfers"), NULL, gaim_show_xfer_dialog, 0, "<StockItem>", GAIM_STOCK_FILE_TRANSFER }, |
2361 { N_("/Tools/R_oom List"), NULL, gaim_gtk_roomlist_dialog_show, 0, NULL }, | 2362 { N_("/Tools/R_oom List"), NULL, gaim_gtk_roomlist_dialog_show, 0, NULL }, |
2362 { N_("/Tools/Pr_eferences"), "<CTL>P", gaim_gtk_prefs_show, 0, "<StockItem>", GTK_STOCK_PREFERENCES }, | 2363 { N_("/Tools/Pr_eferences"), "<CTL>P", gaim_gtk_prefs_show, 0, "<StockItem>", GTK_STOCK_PREFERENCES }, |
2925 | 2926 |
2926 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Privacy")); | 2927 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Privacy")); |
2927 gtk_widget_set_sensitive(widget, gaim_gtk_privacy_is_showable()); | 2928 gtk_widget_set_sensitive(widget, gaim_gtk_privacy_is_showable()); |
2928 } | 2929 } |
2929 | 2930 |
2931 | |
2932 static void | |
2933 plugin_changed_cb(GaimPlugin *p, gpointer *data) | |
2934 { | |
2935 gaim_gtk_blist_update_plugin_actions(); | |
2936 } | |
2937 | |
2938 | |
2930 /* this is called on all sorts of signals, and we have no reason to pass | 2939 /* this is called on all sorts of signals, and we have no reason to pass |
2931 * it anything, so it remains without arguments. If you need anything | 2940 * it anything, so it remains without arguments. If you need anything |
2932 * more specific, do as below, and create another callback that calls | 2941 * more specific, do as below, and create another callback that calls |
2933 * this */ | 2942 * this */ |
2934 static void | 2943 static void |
3066 gtkblist->bpmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Buddy Pounce")); | 3075 gtkblist->bpmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Buddy Pounce")); |
3067 gaim_gtkpounce_menu_build(gtkblist->bpmenu); | 3076 gaim_gtkpounce_menu_build(gtkblist->bpmenu); |
3068 | 3077 |
3069 protomenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Account Actions")); | 3078 protomenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Account Actions")); |
3070 gaim_gtk_blist_update_protocol_actions(); | 3079 gaim_gtk_blist_update_protocol_actions(); |
3080 | |
3081 pluginmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Plugin Actions")); | |
3082 gaim_gtk_blist_update_plugin_actions(); | |
3071 /****************************** GtkTreeView **********************************/ | 3083 /****************************** GtkTreeView **********************************/ |
3072 sw = gtk_scrolled_window_new(NULL,NULL); | 3084 sw = gtk_scrolled_window_new(NULL,NULL); |
3073 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); | 3085 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); |
3074 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | 3086 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
3075 | 3087 |
3280 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", | 3292 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", |
3281 gtkblist, GAIM_CALLBACK(sign_on_off_cb), list); | 3293 gtkblist, GAIM_CALLBACK(sign_on_off_cb), list); |
3282 gaim_signal_connect(gaim_connections_get_handle(), "signed-off", | 3294 gaim_signal_connect(gaim_connections_get_handle(), "signed-off", |
3283 gtkblist, GAIM_CALLBACK(sign_on_off_cb), list); | 3295 gtkblist, GAIM_CALLBACK(sign_on_off_cb), list); |
3284 | 3296 |
3297 gaim_signal_connect(gaim_plugins_get_handle(), "plugin-load", | |
3298 gtkblist, GAIM_CALLBACK(plugin_changed_cb), NULL); | |
3299 gaim_signal_connect(gaim_plugins_get_handle(), "plugin-unload", | |
3300 gtkblist, GAIM_CALLBACK(plugin_changed_cb), NULL); | |
3301 | |
3285 /* emit our created signal */ | 3302 /* emit our created signal */ |
3286 gaim_signal_emit(gaim_gtk_blist_get_handle(), "gtkblist-created", list); | 3303 gaim_signal_emit(gaim_gtk_blist_get_handle(), "gtkblist-created", list); |
3287 } | 3304 } |
3288 | 3305 |
3289 /* XXX: does this need fixing? */ | 3306 /* XXX: does this need fixing? */ |
3791 gtkblist->idle_column = NULL; | 3808 gtkblist->idle_column = NULL; |
3792 gtkblist->warning_column = gtkblist->buddy_icon_column = NULL; | 3809 gtkblist->warning_column = gtkblist->buddy_icon_column = NULL; |
3793 gtkblist->bbox = NULL; | 3810 gtkblist->bbox = NULL; |
3794 g_object_unref(G_OBJECT(gtkblist->ift)); | 3811 g_object_unref(G_OBJECT(gtkblist->ift)); |
3795 protomenu = NULL; | 3812 protomenu = NULL; |
3813 pluginmenu = NULL; | |
3796 awaymenu = NULL; | 3814 awaymenu = NULL; |
3797 gtkblist = NULL; | 3815 gtkblist = NULL; |
3798 | 3816 |
3799 while(blist_prefs_callbacks) { | 3817 while(blist_prefs_callbacks) { |
3800 gaim_prefs_disconnect_callback(GPOINTER_TO_INT(blist_prefs_callbacks->data)); | 3818 gaim_prefs_disconnect_callback(GPOINTER_TO_INT(blist_prefs_callbacks->data)); |
4876 { | 4894 { |
4877 if (pam->callback && pam->gc) | 4895 if (pam->callback && pam->gc) |
4878 pam->callback(pam->gc); | 4896 pam->callback(pam->gc); |
4879 } | 4897 } |
4880 | 4898 |
4899 | |
4900 static void | |
4901 plugin_act(GtkObject *obk, struct plugin_actions_menu *pam) | |
4902 { | |
4903 if (pam->callback && pam->plugin) | |
4904 pam->callback(pam->plugin); | |
4905 } | |
4906 | |
4907 | |
4881 void | 4908 void |
4882 gaim_gtk_blist_update_protocol_actions(void) | 4909 gaim_gtk_blist_update_protocol_actions(void) |
4883 { | 4910 { |
4884 GtkWidget *menuitem; | 4911 GtkWidget *menuitem; |
4885 GtkWidget *submenu; | 4912 GtkWidget *submenu; |
5006 gaim_separator(submenu); | 5033 gaim_separator(submenu); |
5007 } | 5034 } |
5008 } | 5035 } |
5009 } | 5036 } |
5010 } | 5037 } |
5038 | |
5039 | |
5040 | |
5041 void | |
5042 gaim_gtk_blist_update_plugin_actions(void) | |
5043 { | |
5044 GtkWidget *menuitem; | |
5045 GtkWidget *submenu; | |
5046 GaimPluginInfo *plugin_info = NULL; | |
5047 GList *l; | |
5048 GList *c; | |
5049 struct plugin_actions_menu *pam; | |
5050 int count = 0; | |
5051 | |
5052 if (pluginmenu == NULL) | |
5053 return; | |
5054 | |
5055 for (l = gtk_container_get_children(GTK_CONTAINER(pluginmenu)); | |
5056 l != NULL; | |
5057 l = l->next) { | |
5058 | |
5059 menuitem = l->data; | |
5060 pam = g_object_get_data(G_OBJECT(menuitem), "plugin_actions_menu"); | |
5061 g_free(pam); | |
5062 | |
5063 gtk_container_remove(GTK_CONTAINER(pluginmenu), GTK_WIDGET(menuitem)); | |
5064 } | |
5065 | |
5066 for (c = gaim_plugins_get_loaded(); c != NULL; c = c->next) { | |
5067 plugin_info = ((GaimPlugin *)c->data)->info; | |
5068 if (plugin_info->actions) | |
5069 count++; | |
5070 } | |
5071 | |
5072 if (count == 0) { | |
5073 menuitem = gtk_menu_item_new_with_label(_("No actions available")); | |
5074 gtk_menu_shell_append(GTK_MENU_SHELL(pluginmenu), menuitem); | |
5075 gtk_widget_show(menuitem); | |
5076 | |
5077 } | |
5078 else if (count == 1) { | |
5079 GList *act; | |
5080 GaimPlugin *plugin = NULL; | |
5081 | |
5082 for (c = gaim_plugins_get_loaded(); c != NULL; c = c->next) { | |
5083 plugin = (GaimPlugin *) c->data; | |
5084 plugin_info = plugin->info; | |
5085 if (plugin_info->actions != NULL) | |
5086 break; | |
5087 } | |
5088 | |
5089 for (act = plugin_info->actions(plugin); act != NULL; act = act->next) { | |
5090 if (act->data) { | |
5091 struct plugin_actions_menu *pam = act->data; | |
5092 menuitem = gtk_menu_item_new_with_label(pam->label); | |
5093 gtk_menu_shell_append(GTK_MENU_SHELL(pluginmenu), menuitem); | |
5094 g_signal_connect(G_OBJECT(menuitem), "activate", | |
5095 G_CALLBACK(plugin_act), pam); | |
5096 g_object_set_data(G_OBJECT(menuitem), "plugin_actions_menu", pam); | |
5097 gtk_widget_show(menuitem); | |
5098 } | |
5099 else | |
5100 gaim_separator(pluginmenu); | |
5101 } | |
5102 } | |
5103 else { | |
5104 for (c = gaim_plugins_get_loaded(); c != NULL; c = c->next) { | |
5105 GList *act; | |
5106 GaimPlugin *plugin; | |
5107 | |
5108 plugin = (GaimPlugin *) c->data; | |
5109 plugin_info = plugin->info; | |
5110 if (plugin_info->actions == NULL) | |
5111 continue; | |
5112 | |
5113 menuitem = gtk_image_menu_item_new_with_label(plugin_info->name); | |
5114 gtk_menu_shell_append(GTK_MENU_SHELL(pluginmenu), menuitem); | |
5115 gtk_widget_show(menuitem); | |
5116 | |
5117 submenu = gtk_menu_new(); | |
5118 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); | |
5119 gtk_widget_show(submenu); | |
5120 | |
5121 for (act = plugin_info->actions(plugin); act != NULL; act = act->next) { | |
5122 if (act->data) { | |
5123 struct plugin_actions_menu *pam = act->data; | |
5124 menuitem = gtk_menu_item_new_with_label(pam->label); | |
5125 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); | |
5126 g_signal_connect(G_OBJECT(menuitem), "activate", | |
5127 G_CALLBACK(plugin_act), pam); | |
5128 g_object_set_data(G_OBJECT(menuitem), "plugin_actions_menu", pam); | |
5129 gtk_widget_show(menuitem); | |
5130 } | |
5131 else { | |
5132 gaim_separator(submenu); | |
5133 } | |
5134 } | |
5135 } | |
5136 } | |
5137 } | |
5138 |