comparison src/gtkpounce.c @ 12136:370f9d7868f9

[gaim-migrate @ 14436] SF Patch #1356575 from Kevin Stange (SimGuy) "This patch moves buddy pounces out of the menu and into a new dialog, as suggested by Sean. I'm not ready to say this is finished, but it's a solid starting point and it does work. I changed the namespacing a little from gaim_gtkpounce to gaim_gtk_pounce to be consistent with the rest of Gaim. I wanted to try to get more information into the pounce manager, but I wasn't sure how to display it. I thought perhaps a column containing a row of icons representing which events are being watched (so the user can see which of several pounces for the same buddy are which), however, while I know how to do this, there aren't icons in Gaim suitable for representing all the events. Like "returned from away" and "idle/unidle", as far as I can see. I'm not sure what else could be shown to make the manager dialog more "informative." The dialog updates automatically to show pounces only for connected accounts and updates when a pounce is added, changed, or removed in some other way than the dialog. I'd like to get feedback on it if anyone has anything they think I should change or fix, I'll do that and update this patch. Otherwise, feel free to commit. :)" As ridingpigs commented in the tracker, this is "far better than the current menu thing." I made a few small changes to this. I believe most of them were related to adding hooks to disable things if there were no accounts connected. I also sorte d the Tools menu a bit and updated the docklet to match. I wish the plugin action code could sort the items it added. committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Fri, 18 Nov 2005 16:37:51 +0000
parents 969fd533bd5d
children 44104dfce57b
comparison
equal deleted inserted replaced
12135:e09bf5bc81d8 12136:370f9d7868f9
37 #include "util.h" 37 #include "util.h"
38 38
39 #include "gtkblist.h" 39 #include "gtkblist.h"
40 #include "gtkdialogs.h" 40 #include "gtkdialogs.h"
41 #include "gtkpounce.h" 41 #include "gtkpounce.h"
42 #include "gtkstock.h"
42 #include "gtkutils.h" 43 #include "gtkutils.h"
44
45 /**
46 * These are used for the GtkTreeView when you're scrolling through
47 * all your saved pounces.
48 */
49 enum
50 {
51 /* Hidden column containing the GaimPounce */
52 POUNCES_MANAGER_COLUMN_POUNCE,
53 POUNCES_MANAGER_COLUMN_ICON,
54 POUNCES_MANAGER_COLUMN_TARGET,
55 POUNCES_MANAGER_COLUMN_ACCOUNT,
56 POUNCES_MANAGER_COLUMN_PERSISTENCE,
57 POUNCES_MANAGER_NUM_COLUMNS
58 };
43 59
44 typedef struct 60 typedef struct
45 { 61 {
46 /* Pounce data */ 62 /* Pounce data */
47 GaimPounce *pounce; 63 GaimPounce *pounce;
82 /* Buttons */ 98 /* Buttons */
83 GtkWidget *save_button; 99 GtkWidget *save_button;
84 100
85 } GaimGtkPounceDialog; 101 } GaimGtkPounceDialog;
86 102
103 typedef struct
104 {
105 GtkWidget *window;
106 GtkListStore *model;
107 GtkWidget *treeview;
108 GtkWidget *modify_button;
109 GtkWidget *delete_button;
110 } PouncesManager;
111
112 static PouncesManager *pounces_manager = NULL;
113
87 /************************************************************************** 114 /**************************************************************************
88 * Callbacks 115 * Callbacks
89 **************************************************************************/ 116 **************************************************************************/
90 static gint 117 static gint
91 delete_win_cb(GtkWidget *w, GdkEventAny *e, GaimGtkPounceDialog *dialog) 118 delete_win_cb(GtkWidget *w, GdkEventAny *e, GaimGtkPounceDialog *dialog)
143 else 170 else
144 gaim_sound_play_event(GAIM_SOUND_POUNCE_DEFAULT, NULL); 171 gaim_sound_play_event(GAIM_SOUND_POUNCE_DEFAULT, NULL);
145 } 172 }
146 173
147 static void 174 static void
175 add_pounce_to_treeview(GtkListStore *model, GaimPounce *pounce)
176 {
177 GtkTreeIter iter;
178 GaimAccount *account;
179 GaimPounceEvent events;
180 gboolean persists;
181 const char *pouncer;
182 const char *pouncee;
183 GdkPixbuf *pixbuf, *scale = NULL;
184
185 account = gaim_pounce_get_pouncer(pounce);
186
187 if (gaim_account_is_disconnected(account))
188 return;
189
190 events = gaim_pounce_get_events(pounce);
191
192 pixbuf = gaim_gtk_create_prpl_icon(account);
193
194 if (pixbuf != NULL)
195 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16,
196 GDK_INTERP_BILINEAR);
197
198 pouncer = gaim_account_get_username(account);
199 pouncee = gaim_pounce_get_pouncee(pounce);
200 persists = gaim_pounce_get_save(pounce);
201
202 gtk_list_store_append(model, &iter);
203 gtk_list_store_set(model, &iter,
204 POUNCES_MANAGER_COLUMN_POUNCE, pounce,
205 POUNCES_MANAGER_COLUMN_ICON, scale,
206 POUNCES_MANAGER_COLUMN_TARGET, pouncee,
207 POUNCES_MANAGER_COLUMN_ACCOUNT, pouncer,
208 POUNCES_MANAGER_COLUMN_PERSISTENCE, persists,
209 -1);
210 }
211
212 static void
213 populate_pounces_list(PouncesManager *dialog)
214 {
215 const GList *pounces;
216
217 gtk_list_store_clear(dialog->model);
218
219 for (pounces = gaim_pounces_get_all(); pounces != NULL;
220 pounces = g_list_next(pounces))
221 {
222 add_pounce_to_treeview(dialog->model, pounces->data);
223 }
224 }
225
226 static void
227 update_pounces(void)
228 {
229 /* Rebuild the pounces list if the pounces manager is open */
230 if (pounces_manager != NULL)
231 {
232 populate_pounces_list(pounces_manager);
233 }
234 }
235
236 static void
237 signed_on_off_cb(GaimConnection *gc, gpointer user_data)
238 {
239 update_pounces();
240 }
241
242 static void
148 save_pounce_cb(GtkWidget *w, GaimGtkPounceDialog *dialog) 243 save_pounce_cb(GtkWidget *w, GaimGtkPounceDialog *dialog)
149 { 244 {
150 const char *name; 245 const char *name;
151 const char *message, *command, *sound; 246 const char *message, *command, *sound;
152 GaimBuddyList *blist;
153 GaimGtkBuddyList *gtkblist;
154 GaimPounceEvent events = GAIM_POUNCE_NONE; 247 GaimPounceEvent events = GAIM_POUNCE_NONE;
155 248
156 name = gtk_entry_get_text(GTK_ENTRY(dialog->buddy_entry)); 249 name = gtk_entry_get_text(GTK_ENTRY(dialog->buddy_entry));
157 250
158 if (*name == '\0') 251 if (*name == '\0')
239 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->play_sound))); 332 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->play_sound)));
240 333
241 gaim_pounce_set_save(dialog->pounce, 334 gaim_pounce_set_save(dialog->pounce,
242 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->save_pounce))); 335 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->save_pounce)));
243 336
337 update_pounces();
338
244 delete_win_cb(NULL, NULL, dialog); 339 delete_win_cb(NULL, NULL, dialog);
245
246 /* Rebuild the pounce menu */
247 blist = gaim_get_blist();
248
249 if (GAIM_IS_GTK_BLIST(blist))
250 {
251 gtkblist = GAIM_GTK_BLIST(blist);
252
253 gaim_gtkpounce_menu_build(gtkblist->bpmenu);
254 }
255 } 340 }
256 341
257 static void 342 static void
258 pounce_choose_cb(GtkWidget *item, GaimAccount *account, 343 pounce_choose_cb(GtkWidget *item, GaimAccount *account,
259 GaimGtkPounceDialog *dialog) 344 GaimGtkPounceDialog *dialog)
336 {"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, 0}, 421 {"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, 0},
337 {"application/x-im-contact", 0, 1} 422 {"application/x-im-contact", 0, 1}
338 }; 423 };
339 424
340 void 425 void
341 gaim_gtkpounce_dialog_show(GaimAccount *account, const char *name, 426 gaim_gtk_pounce_editor_show(GaimAccount *account, const char *name,
342 GaimPounce *cur_pounce) 427 GaimPounce *cur_pounce)
343 { 428 {
344 GaimGtkPounceDialog *dialog; 429 GaimGtkPounceDialog *dialog;
345 GtkWidget *window; 430 GtkWidget *window;
346 GtkWidget *label; 431 GtkWidget *label;
347 GtkWidget *bbox; 432 GtkWidget *bbox;
795 880
796 gtk_widget_show_all(vbox2); 881 gtk_widget_show_all(vbox2);
797 gtk_widget_show(window); 882 gtk_widget_show(window);
798 } 883 }
799 884
800 static void 885 static gboolean
801 new_pounce_cb(GtkWidget *w, GaimBuddy *b) 886 pounces_manager_configure_cb(GtkWidget *widget, GdkEventConfigure *event, PouncesManager *dialog)
802 { 887 {
803 if (b == NULL) 888 if (GTK_WIDGET_VISIBLE(widget)) {
804 gaim_gtkpounce_dialog_show(NULL, NULL, NULL); 889 gaim_prefs_set_int("/gaim/gtk/pounces/dialog/width", event->width);
805 else 890 gaim_prefs_set_int("/gaim/gtk/pounces/dialog/height", event->height);
806 gaim_gtkpounce_dialog_show(b->account, b->name, NULL); 891 }
807 } 892
808 893 return FALSE;
809 static void 894 }
810 delete_pounce_cb(GtkWidget *w, GaimPounce *pounce) 895
811 { 896 static gboolean
897 pounces_manager_find_pounce(GtkTreeIter *iter, GaimPounce *pounce)
898 {
899 GtkTreeModel *model = GTK_TREE_MODEL(pounces_manager->model);
900 GaimPounce *p;
901
902 if (!gtk_tree_model_get_iter_first(model, iter))
903 return FALSE;
904
905 gtk_tree_model_get(model, iter, POUNCES_MANAGER_COLUMN_POUNCE, &p, -1);
906 if (pounce == p)
907 return TRUE;
908
909 while (gtk_tree_model_iter_next(model, iter))
910 {
911 gtk_tree_model_get(model, iter, POUNCES_MANAGER_COLUMN_POUNCE, &p, -1);
912 if (pounce == p)
913 return TRUE;
914 }
915
916 return FALSE;
917 }
918
919 static gboolean
920 pounces_manager_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data)
921 {
922 PouncesManager *dialog = user_data;
923
924 dialog->window = NULL;
925 gaim_gtk_pounces_manager_hide();
926
927 return FALSE;
928 }
929
930 #if !GTK_CHECK_VERSION(2,2,0)
931 static void
932 count_selected_helper(GtkTreeModel *model, GtkTreePath *path,
933 GtkTreeIter *iter, gpointer user_data)
934 {
935 (*(gint *)user_data)++;
936 }
937 #endif
938
939 static void
940 pounces_manager_connection_cb(GaimConnection *gc, GtkWidget *add_button)
941 {
942 gtk_widget_set_sensitive(add_button, (gaim_connections_get_all() != NULL));
943 }
944
945 static void
946 pounces_manager_add_cb(GtkButton *button, gpointer user_data)
947 {
948 gaim_gtk_pounce_editor_show(NULL, NULL, NULL);
949 }
950
951 static void
952 pounces_manager_modify_foreach(GtkTreeModel *model, GtkTreePath *path,
953 GtkTreeIter *iter, gpointer user_data)
954 {
955 GaimPounce *pounce;
956
957 gtk_tree_model_get(model, iter, POUNCES_MANAGER_COLUMN_POUNCE, &pounce, -1);
958 gaim_gtk_pounce_editor_show(NULL, NULL, pounce);
959 }
960
961 static void
962 pounces_manager_modify_cb(GtkButton *button, gpointer user_data)
963 {
964 PouncesManager *dialog = user_data;
965 GtkTreeSelection *selection;
966
967 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
968
969 gtk_tree_selection_selected_foreach(selection, pounces_manager_modify_foreach, user_data);
970 }
971
972 static void
973 pounces_manager_delete_confirm_cb(GaimPounce *pounce)
974 {
975 GtkTreeIter iter;
976
977 if (pounces_manager_find_pounce(&iter, pounce))
978 gtk_list_store_remove(pounces_manager->model, &iter);
979
812 gaim_pounce_destroy(pounce); 980 gaim_pounce_destroy(pounce);
813 } 981 }
814 982
815 static void 983 static void
816 edit_pounce_cb(GtkWidget *w, GaimPounce *pounce) 984 pounces_manager_delete_foreach(GtkTreeModel *model, GtkTreePath *path,
817 { 985 GtkTreeIter *iter, gpointer user_data)
818 gaim_gtkpounce_dialog_show(NULL, NULL, pounce); 986 {
987 GaimPounce *pounce;
988 GaimAccount *account;
989 const char *pouncer, *pouncee;
990 char *buf;
991
992 gtk_tree_model_get(model, iter, POUNCES_MANAGER_COLUMN_POUNCE, &pounce, -1);
993 account = gaim_pounce_get_pouncer(pounce);
994 pouncer = gaim_account_get_username(account);
995 pouncee = gaim_pounce_get_pouncee(pounce);
996
997 buf = g_strdup_printf(_("Are you sure you want to delete the pounce on %s for %s?"), pouncee, pouncer);
998 gaim_request_action(NULL, NULL, buf, NULL, 0, pounce, 2,
999 _("Delete"), pounces_manager_delete_confirm_cb,
1000 _("Cancel"), g_free);
1001 g_free(buf);
1002 }
1003
1004 static void
1005 pounces_manager_delete_cb(GtkButton *button, gpointer user_data)
1006 {
1007 PouncesManager *dialog = user_data;
1008 GtkTreeSelection *selection;
1009
1010 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
1011
1012 gtk_tree_selection_selected_foreach(selection, pounces_manager_delete_foreach, user_data);
1013 }
1014
1015 static void
1016 pounces_manager_close_cb(GtkButton *button, gpointer user_data)
1017 {
1018 gaim_gtk_pounces_manager_hide();
1019 }
1020
1021 static void
1022 pounce_selected_cb(GtkTreeSelection *sel, gpointer user_data)
1023 {
1024 PouncesManager *dialog = user_data;
1025 int num_selected = 0;
1026
1027 #if GTK_CHECK_VERSION(2,2,0)
1028 num_selected = gtk_tree_selection_count_selected_rows(sel);
1029 #else
1030 gtk_tree_selection_selected_foreach(sel, count_selected_helper, &num_selected);
1031 #endif
1032
1033 gtk_widget_set_sensitive(dialog->modify_button, (num_selected > 0));
1034 gtk_widget_set_sensitive(dialog->delete_button, (num_selected > 0));
1035 }
1036
1037 static void
1038 pounces_manager_persists_cb(GtkCellRendererToggle *renderer, gchar *path_str,
1039 gpointer user_data)
1040 {
1041 PouncesManager *dialog = user_data;
1042 GaimPounce *pounce;
1043 gboolean persists;
1044 GtkTreeModel *model = GTK_TREE_MODEL(dialog->model);
1045 GtkTreeIter iter;
1046
1047 gtk_tree_model_get_iter_from_string(model, &iter, path_str);
1048 gtk_tree_model_get(model, &iter,
1049 POUNCES_MANAGER_COLUMN_POUNCE, &pounce,
1050 POUNCES_MANAGER_COLUMN_PERSISTENCE, &persists,
1051 -1);
1052
1053 gaim_pounce_set_save(pounce, !persists);
1054
1055 update_pounces();
819 } 1056 }
820 1057
821 static gboolean 1058 static gboolean
822 fill_menu(GtkWidget *menu, GCallback cb) 1059 search_func(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data)
823 { 1060 {
824 GtkWidget *image; 1061 gboolean result;
825 GtkWidget *item; 1062 char *haystack;
826 GdkPixbuf *pixbuf, *scale; 1063
827 GaimPounce *pounce; 1064 gtk_tree_model_get(model, iter, column, &haystack, -1);
828 GaimBuddy *buddy; 1065
829 const char *buddyname; 1066 result = (gaim_strcasestr(haystack, key) == NULL);
830 gboolean has_items = FALSE; 1067
831 GList *bp; 1068 g_free(haystack);
832 1069
833 for (bp = gaim_pounces_get_all(); bp != NULL; bp = bp->next) 1070 return result;
834 { 1071 }
835 pounce = (GaimPounce *)bp->data; 1072
836 1073 static GtkWidget *
837 /* Check if account is online, if not skip it */ 1074 create_pounces_list(PouncesManager *dialog)
838 if (!gaim_account_is_connected(gaim_pounce_get_pouncer(pounce))) 1075 {
839 continue; 1076 GtkWidget *sw;
840 1077 GtkWidget *treeview;
841 buddy = gaim_find_buddy(gaim_pounce_get_pouncer(pounce), gaim_pounce_get_pouncee(pounce)); 1078 GtkTreeSelection *sel;
842 1079 GtkTreeViewColumn *column;
843 if (buddy != NULL) 1080 GtkCellRenderer *renderer;
844 buddyname = gaim_buddy_get_contact_alias(buddy); 1081
845 else 1082 /* Create the scrolled window */
846 buddyname = gaim_pounce_get_pouncee(pounce); 1083 sw = gtk_scrolled_window_new(0, 0);
847 1084 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
848 has_items = TRUE; 1085 GTK_POLICY_AUTOMATIC,
849 1086 GTK_POLICY_ALWAYS);
850 /* Build the menu item */ 1087 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
851 item = gtk_image_menu_item_new_with_label(buddyname); 1088 GTK_SHADOW_IN);
852 1089 gtk_widget_show(sw);
853 /* Create a pixmap for the protocol icon. */ 1090
854 pixbuf = gaim_gtk_create_prpl_icon(gaim_pounce_get_pouncer(pounce)); 1091 /* Create the list model */
855 if (pixbuf != NULL) 1092 dialog->model = gtk_list_store_new(POUNCES_MANAGER_NUM_COLUMNS,
856 { 1093 G_TYPE_POINTER,
857 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, 1094 GDK_TYPE_PIXBUF,
858 GDK_INTERP_BILINEAR); 1095 G_TYPE_STRING,
859 1096 G_TYPE_STRING,
860 /* Now convert it to GtkImage */ 1097 G_TYPE_BOOLEAN
861 image = gtk_image_new_from_pixbuf(scale); 1098 );
862 g_object_unref(G_OBJECT(scale)); 1099
863 g_object_unref(G_OBJECT(pixbuf)); 1100 /* Create the treeview */
864 gtk_widget_show(image); 1101 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
865 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image); 1102 dialog->treeview = treeview;
866 } 1103 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
867 1104
868 /* Put the item in the menu */ 1105 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
869 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 1106 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
870 gtk_widget_show(item); 1107 g_signal_connect(G_OBJECT(sel), "changed",
871 1108 G_CALLBACK(pounce_selected_cb), dialog);
872 /* Set our callbacks. */ 1109
873 g_signal_connect(G_OBJECT(item), "activate", cb, pounce); 1110 gtk_container_add(GTK_CONTAINER(sw), treeview);
874 } 1111 gtk_widget_show(treeview);
875 1112
876 return has_items; 1113 /* Pouncee Column */
1114 column = gtk_tree_view_column_new();
1115 gtk_tree_view_column_set_title(column, _("Pounce Target"));
1116 gtk_tree_view_column_set_resizable(column, TRUE);
1117 gtk_tree_view_column_set_min_width(column, 200);
1118 gtk_tree_view_column_set_sort_column_id(column,
1119 POUNCES_MANAGER_COLUMN_TARGET);
1120 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
1121
1122 /* Icon */
1123 renderer = gtk_cell_renderer_pixbuf_new();
1124 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1125 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf",
1126 POUNCES_MANAGER_COLUMN_ICON);
1127
1128 /* Pouncee */
1129 renderer = gtk_cell_renderer_text_new();
1130 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1131 gtk_tree_view_column_add_attribute(column, renderer, "text",
1132 POUNCES_MANAGER_COLUMN_TARGET);
1133
1134
1135 /* Account Column */
1136 column = gtk_tree_view_column_new();
1137 gtk_tree_view_column_set_title(column, _("Account"));
1138 gtk_tree_view_column_set_resizable(column, TRUE);
1139 gtk_tree_view_column_set_min_width(column, 200);
1140 gtk_tree_view_column_set_sort_column_id(column,
1141 POUNCES_MANAGER_COLUMN_ACCOUNT);
1142 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
1143 renderer = gtk_cell_renderer_text_new();
1144 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1145 gtk_tree_view_column_add_attribute(column, renderer, "text",
1146 POUNCES_MANAGER_COLUMN_ACCOUNT);
1147
1148 /* Persistence Column */
1149 renderer = gtk_cell_renderer_toggle_new();
1150 column = gtk_tree_view_column_new_with_attributes(_("Persists"), renderer,
1151 "active", POUNCES_MANAGER_COLUMN_PERSISTENCE, NULL);
1152 gtk_tree_view_column_set_sort_column_id(column,
1153 POUNCES_MANAGER_COLUMN_PERSISTENCE);
1154 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
1155 g_signal_connect(G_OBJECT(renderer), "toggled",
1156 G_CALLBACK(pounces_manager_persists_cb), dialog);
1157
1158 /* Enable CTRL+F searching */
1159 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), POUNCES_MANAGER_COLUMN_TARGET);
1160 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(treeview), search_func, NULL, NULL);
1161
1162 /* Sort the pouncee column by default */
1163 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog->model),
1164 POUNCES_MANAGER_COLUMN_TARGET,
1165 GTK_SORT_ASCENDING);
1166
1167 /* Populate list */
1168 populate_pounces_list(dialog);
1169
1170 return sw;
877 } 1171 }
878 1172
879 void 1173 void
880 gaim_gtkpounce_menu_build(GtkWidget *menu) 1174 gaim_gtk_pounces_manager_show(void)
881 { 1175 {
882 GtkWidget *remmenu; 1176 PouncesManager *dialog;
883 GtkWidget *item; 1177 GtkWidget *bbox;
884 GList *children, *l; 1178 GtkWidget *button;
885 gboolean has_items; 1179 GtkWidget *list;
886 1180 GtkWidget *vbox;
887 g_return_if_fail(menu != NULL); 1181 GtkWidget *win;
888 1182 int width, height;
889 if ((children = gtk_container_get_children(GTK_CONTAINER(menu))) != NULL) 1183
890 { 1184 if (pounces_manager != NULL) {
891 for (l = children; l != NULL; l = l->next) 1185 gtk_window_present(GTK_WINDOW(pounces_manager->window));
892 gtk_widget_destroy(GTK_WIDGET(l->data)); 1186 return;
893 1187 }
894 g_list_free(children); 1188
895 } 1189 pounces_manager = dialog = g_new0(PouncesManager, 1);
896 1190
897 /* "New Buddy Pounce" */ 1191 width = gaim_prefs_get_int("/gaim/gtk/pounces/dialog/width");
898 item = gtk_menu_item_new_with_label(_("New Buddy Pounce")); 1192 height = gaim_prefs_get_int("/gaim/gtk/pounces/dialog/height");
899 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 1193
900 gtk_widget_set_sensitive(item, (gaim_connections_get_all() != NULL)); 1194 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
901 gtk_widget_show(item); 1195 gtk_window_set_default_size(GTK_WINDOW(win), width, height);
902 g_signal_connect(G_OBJECT(item), "activate", 1196 gtk_window_set_role(GTK_WINDOW(win), "pounces");
903 G_CALLBACK(new_pounce_cb), NULL); 1197 gtk_window_set_title(GTK_WINDOW(win), _("Buddy Pounces"));
904 1198 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER);
905 /* "Remove Buddy Pounce" */ 1199
906 item = gtk_menu_item_new_with_label(_("Remove Buddy Pounce")); 1200 g_signal_connect(G_OBJECT(win), "delete_event",
907 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 1201 G_CALLBACK(pounces_manager_destroy_cb), dialog);
908 1202 g_signal_connect(G_OBJECT(win), "configure_event",
909 /* "Remove Buddy Pounce" menu */ 1203 G_CALLBACK(pounces_manager_configure_cb), dialog);
910 remmenu = gtk_menu_new(); 1204
911 1205 /* Setup the vbox */
912 has_items = fill_menu(remmenu, G_CALLBACK(delete_pounce_cb)); 1206 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER);
913 1207 gtk_container_add(GTK_CONTAINER(win), vbox);
914 if (!has_items) 1208 gtk_widget_show(vbox);
915 gtk_widget_set_sensitive(item, FALSE); 1209
916 1210 /* List of saved buddy pounces */
917 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), remmenu); 1211 list = create_pounces_list(dialog);
918 gtk_widget_show(remmenu); 1212 gtk_box_pack_start(GTK_BOX(vbox), list, TRUE, TRUE, 0);
919 gtk_widget_show(item); 1213
920 1214 /* Button box. */
921 /* Separator */ 1215 bbox = gtk_hbutton_box_new();
922 if (has_items) 1216 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE);
923 { 1217 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
924 item = gtk_separator_menu_item_new(); 1218 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
925 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 1219 gtk_widget_show(bbox);
926 gtk_widget_show(item); 1220
927 } 1221 /* Add button */
928 fill_menu(menu, G_CALLBACK(edit_pounce_cb)); 1222 button = gtk_button_new_from_stock(GTK_STOCK_ADD);
1223 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1224 gtk_widget_set_sensitive(button, (gaim_connections_get_all() != NULL));
1225 gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
1226 pounces_manager, GAIM_CALLBACK(pounces_manager_connection_cb), button);
1227 gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
1228 pounces_manager, GAIM_CALLBACK(pounces_manager_connection_cb), button);
1229 gtk_widget_show(button);
1230
1231 g_signal_connect(G_OBJECT(button), "clicked",
1232 G_CALLBACK(pounces_manager_add_cb), dialog);
1233
1234 /* Modify button */
1235 button = gtk_button_new_from_stock(GAIM_STOCK_MODIFY);
1236 dialog->modify_button = button;
1237 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1238 gtk_widget_set_sensitive(button, FALSE);
1239 gtk_widget_show(button);
1240
1241 g_signal_connect(G_OBJECT(button), "clicked",
1242 G_CALLBACK(pounces_manager_modify_cb), dialog);
1243
1244 /* Delete button */
1245 button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1246 dialog->delete_button = button;
1247 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1248 gtk_widget_set_sensitive(button, FALSE);
1249 gtk_widget_show(button);
1250
1251 g_signal_connect(G_OBJECT(button), "clicked",
1252 G_CALLBACK(pounces_manager_delete_cb), dialog);
1253
1254 /* Close button */
1255 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
1256 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1257 gtk_widget_show(button);
1258
1259 g_signal_connect(G_OBJECT(button), "clicked",
1260 G_CALLBACK(pounces_manager_close_cb), dialog);
1261
1262 gtk_widget_show(win);
1263 }
1264
1265 void
1266 gaim_gtk_pounces_manager_hide(void)
1267 {
1268 if (pounces_manager == NULL)
1269 return;
1270
1271 if (pounces_manager->window != NULL)
1272 gtk_widget_destroy(pounces_manager->window);
1273
1274 gaim_signals_disconnect_by_handle(pounces_manager);
1275
1276 g_free(pounces_manager);
1277 pounces_manager = NULL;
929 } 1278 }
930 1279
931 static void 1280 static void
932 pounce_cb(GaimPounce *pounce, GaimPounceEvent events, void *data) 1281 pounce_cb(GaimPounce *pounce, GaimPounceEvent events, void *data)
933 { 1282 {
1111 } 1460 }
1112 1461
1113 static void 1462 static void
1114 free_pounce(GaimPounce *pounce) 1463 free_pounce(GaimPounce *pounce)
1115 { 1464 {
1116 GaimBuddyList *blist; 1465 update_pounces();
1117 GaimGtkBuddyList *gtkblist;
1118
1119 /* Rebuild the pounce menu */
1120 blist = gaim_get_blist();
1121
1122 if (GAIM_IS_GTK_BLIST(blist))
1123 {
1124 gtkblist = GAIM_GTK_BLIST(blist);
1125
1126 gaim_gtkpounce_menu_build(gtkblist->bpmenu);
1127 }
1128 } 1466 }
1129 1467
1130 static void 1468 static void
1131 new_pounce(GaimPounce *pounce) 1469 new_pounce(GaimPounce *pounce)
1132 { 1470 {
1133 gaim_pounce_action_register(pounce, "open-window"); 1471 gaim_pounce_action_register(pounce, "open-window");
1134 gaim_pounce_action_register(pounce, "popup-notify"); 1472 gaim_pounce_action_register(pounce, "popup-notify");
1135 gaim_pounce_action_register(pounce, "send-message"); 1473 gaim_pounce_action_register(pounce, "send-message");
1136 gaim_pounce_action_register(pounce, "execute-command"); 1474 gaim_pounce_action_register(pounce, "execute-command");
1137 gaim_pounce_action_register(pounce, "play-sound"); 1475 gaim_pounce_action_register(pounce, "play-sound");
1476
1477 update_pounces();
1478 }
1479
1480 void *
1481 gaim_gtk_pounces_get_handle() {
1482 static int handle;
1483
1484 return &handle;
1138 } 1485 }
1139 1486
1140 void 1487 void
1141 gaim_gtk_pounces_init(void) 1488 gaim_gtk_pounces_init(void)
1142 { 1489 {
1153 TRUE); 1500 TRUE);
1154 gaim_prefs_add_bool("/gaim/gtk/pounces/default_actions/execute-command", 1501 gaim_prefs_add_bool("/gaim/gtk/pounces/default_actions/execute-command",
1155 FALSE); 1502 FALSE);
1156 gaim_prefs_add_bool("/gaim/gtk/pounces/default_actions/play-sound", 1503 gaim_prefs_add_bool("/gaim/gtk/pounces/default_actions/play-sound",
1157 FALSE); 1504 FALSE);
1158 } 1505 gaim_prefs_add_none("/gaim/gtk/pounces/dialog");
1506 gaim_prefs_add_int("/gaim/gtk/pounces/dialog/width", 550);
1507 gaim_prefs_add_int("/gaim/gtk/pounces/dialog/height", 250);
1508
1509 gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
1510 gaim_gtk_pounces_get_handle(),
1511 GAIM_CALLBACK(signed_on_off_cb), NULL);
1512 gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
1513 gaim_gtk_pounces_get_handle(),
1514 GAIM_CALLBACK(signed_on_off_cb), NULL);
1515 }