2 * @file gtkpounce.c GTK+ Buddy Pounce API
8 * Pidgin is the legal property of its developers, whose names are too numerous
9 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * source distribution.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
31 #include "conversation.h"
40 #include "gtkdialogs.h"
41 #include "gtkimhtml.h"
42 #include "gtkpounce.h"
43 #include "gtknotify.h"
44 #include "pidginstock.h"
48 * These are used for the GtkTreeView when you're scrolling through
49 * all your saved pounces.
53 /* Hidden column containing the PurplePounce */
54 POUNCES_MANAGER_COLUMN_POUNCE
,
55 POUNCES_MANAGER_COLUMN_ICON
,
56 POUNCES_MANAGER_COLUMN_TARGET
,
57 POUNCES_MANAGER_COLUMN_ACCOUNT
,
58 POUNCES_MANAGER_COLUMN_RECURRING
,
59 POUNCES_MANAGER_NUM_COLUMNS
66 PurpleAccount
*account
;
72 GtkWidget
*account_menu
;
73 GtkWidget
*buddy_entry
;
78 /* Pounce When Buddy... */
82 GtkWidget
*away_return
;
84 GtkWidget
*idle_return
;
87 GtkWidget
*stop_typing
;
88 GtkWidget
*message_recv
;
93 GtkWidget
*popup_entry
;
95 GtkWidget
*send_msg_entry
;
97 GtkWidget
*exec_cmd_entry
;
98 GtkWidget
*exec_cmd_browse
;
99 GtkWidget
*play_sound
;
100 GtkWidget
*play_sound_entry
;
101 GtkWidget
*play_sound_browse
;
102 GtkWidget
*play_sound_test
;
103 GtkWidget
*play_sound_reset
;
105 GtkWidget
*save_pounce
;
108 GtkWidget
*save_button
;
110 } PidginPounceDialog
;
117 GtkWidget
*modify_button
;
118 GtkWidget
*delete_button
;
121 static PouncesManager
*pounces_manager
= NULL
;
123 /**************************************************************************
125 **************************************************************************/
127 delete_win_cb(GtkWidget
*w
, GdkEventAny
*e
, PidginPounceDialog
*dialog
)
129 gtk_widget_destroy(dialog
->window
);
136 cancel_cb(GtkWidget
*w
, PidginPounceDialog
*dialog
)
138 delete_win_cb(NULL
, NULL
, dialog
);
142 pounce_update_entry_fields(void *user_data
, const char *filename
)
144 GtkWidget
*entry
= (GtkWidget
*)user_data
;
146 gtk_entry_set_text(GTK_ENTRY(entry
), filename
);
150 filesel(GtkWidget
*widget
, gpointer data
)
155 entry
= (GtkWidget
*)data
;
156 name
= gtk_entry_get_text(GTK_ENTRY(entry
));
158 purple_request_file(entry
, _("Select a file"), name
, FALSE
,
159 G_CALLBACK(pounce_update_entry_fields
), NULL
,
162 g_signal_connect_swapped(G_OBJECT(entry
), "destroy",
163 G_CALLBACK(purple_request_close_with_handle
), entry
);
167 pounce_test_sound(GtkWidget
*w
, GtkWidget
*entry
)
169 const char *filename
;
172 temp_mute
= purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/sound/mute");
174 if (temp_mute
) purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/sound/mute", FALSE
);
176 filename
= gtk_entry_get_text(GTK_ENTRY(entry
));
178 if (filename
!= NULL
&& *filename
!= '\0' && !purple_strequal(filename
, _("(default)")))
179 purple_sound_play_file(filename
, NULL
);
181 purple_sound_play_event(PURPLE_SOUND_POUNCE_DEFAULT
, NULL
);
183 if (temp_mute
) purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/sound/mute", TRUE
);
187 pounce_reset_sound(GtkWidget
*w
, GtkWidget
*entry
)
189 gtk_entry_set_text(GTK_ENTRY(entry
), _("(default)"));
193 add_pounce_to_treeview(GtkListStore
*model
, PurplePounce
*pounce
)
196 PurpleAccount
*account
;
202 account
= purple_pounce_get_pouncer(pounce
);
204 pixbuf
= pidgin_create_prpl_icon(account
, PIDGIN_PRPL_ICON_MEDIUM
);
206 pouncer
= purple_account_get_username(account
);
207 pouncee
= purple_pounce_get_pouncee(pounce
);
208 recurring
= purple_pounce_get_save(pounce
);
210 gtk_list_store_append(model
, &iter
);
211 gtk_list_store_set(model
, &iter
,
212 POUNCES_MANAGER_COLUMN_POUNCE
, pounce
,
213 POUNCES_MANAGER_COLUMN_ICON
, pixbuf
,
214 POUNCES_MANAGER_COLUMN_TARGET
, pouncee
,
215 POUNCES_MANAGER_COLUMN_ACCOUNT
, pouncer
,
216 POUNCES_MANAGER_COLUMN_RECURRING
, recurring
,
220 g_object_unref(pixbuf
);
224 populate_pounces_list(PouncesManager
*dialog
)
228 gtk_list_store_clear(dialog
->model
);
230 for (pounces
= purple_pounces_get_all_for_ui(PIDGIN_UI
); pounces
!= NULL
;
231 pounces
= g_list_delete_link(pounces
, pounces
))
233 add_pounce_to_treeview(dialog
->model
, pounces
->data
);
240 /* Rebuild the pounces list if the pounces manager is open */
241 if (pounces_manager
!= NULL
)
243 populate_pounces_list(pounces_manager
);
248 signed_on_off_cb(PurpleConnection
*gc
, gpointer user_data
)
254 save_pounce_cb(GtkWidget
*w
, PidginPounceDialog
*dialog
)
257 const char *command
, *sound
, *reason
;
259 PurplePounceEvent events
= PURPLE_POUNCE_NONE
;
260 PurplePounceOption options
= PURPLE_POUNCE_OPTION_NONE
;
262 name
= gtk_entry_get_text(GTK_ENTRY(dialog
->buddy_entry
));
266 purple_notify_error(NULL
, NULL
,
267 _("Please enter a buddy to pounce."), NULL
);
272 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->on_away
)))
273 options
|= PURPLE_POUNCE_OPTION_AWAY
;
276 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->signon
)))
277 events
|= PURPLE_POUNCE_SIGNON
;
279 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->signoff
)))
280 events
|= PURPLE_POUNCE_SIGNOFF
;
282 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->away
)))
283 events
|= PURPLE_POUNCE_AWAY
;
285 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->away_return
)))
286 events
|= PURPLE_POUNCE_AWAY_RETURN
;
288 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->idle
)))
289 events
|= PURPLE_POUNCE_IDLE
;
291 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->idle_return
)))
292 events
|= PURPLE_POUNCE_IDLE_RETURN
;
294 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->typing
)))
295 events
|= PURPLE_POUNCE_TYPING
;
297 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->typed
)))
298 events
|= PURPLE_POUNCE_TYPED
;
300 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->stop_typing
)))
301 events
|= PURPLE_POUNCE_TYPING_STOPPED
;
303 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->message_recv
)))
304 events
|= PURPLE_POUNCE_MESSAGE_RECEIVED
;
307 message
= gtk_imhtml_get_markup(GTK_IMHTML(dialog
->send_msg_entry
));
308 command
= gtk_entry_get_text(GTK_ENTRY(dialog
->exec_cmd_entry
));
309 sound
= gtk_entry_get_text(GTK_ENTRY(dialog
->play_sound_entry
));
310 reason
= gtk_entry_get_text(GTK_ENTRY(dialog
->popup_entry
));
312 if (*reason
== '\0') reason
= NULL
;
313 if (*message
== '\0') {
317 if (*command
== '\0') command
= NULL
;
318 if (*sound
== '\0' || purple_strequal(sound
, _("(default)"))) sound
= NULL
;
320 /* If the pounce has already been triggered, let's pretend it is a new one */
321 if (dialog
->pounce
!= NULL
322 && g_list_find(purple_pounces_get_all(), dialog
->pounce
) == NULL
) {
323 purple_debug_info("gtkpounce", "Saving pounce that no longer exists; creating new pounce.\n");
324 dialog
->pounce
= NULL
;
327 if (dialog
->pounce
== NULL
)
329 dialog
->pounce
= purple_pounce_new(PIDGIN_UI
, dialog
->account
,
330 name
, events
, options
);
333 purple_pounce_set_events(dialog
->pounce
, events
);
334 purple_pounce_set_options(dialog
->pounce
, options
);
335 purple_pounce_set_pouncer(dialog
->pounce
, dialog
->account
);
336 purple_pounce_set_pouncee(dialog
->pounce
, name
);
340 purple_pounce_action_set_enabled(dialog
->pounce
, "open-window",
341 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->open_win
)));
342 purple_pounce_action_set_enabled(dialog
->pounce
, "popup-notify",
343 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->popup
)));
344 purple_pounce_action_set_enabled(dialog
->pounce
, "send-message",
345 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
)));
346 purple_pounce_action_set_enabled(dialog
->pounce
, "execute-command",
347 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
)));
348 purple_pounce_action_set_enabled(dialog
->pounce
, "play-sound",
349 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
)));
351 purple_pounce_action_set_attribute(dialog
->pounce
, "send-message",
353 purple_pounce_action_set_attribute(dialog
->pounce
, "execute-command",
355 purple_pounce_action_set_attribute(dialog
->pounce
, "play-sound",
357 purple_pounce_action_set_attribute(dialog
->pounce
, "popup-notify",
360 /* Set the defaults for next time. */
361 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/open-window",
362 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->open_win
)));
363 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/popup-notify",
364 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->popup
)));
365 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/send-message",
366 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
)));
367 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/execute-command",
368 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
)));
369 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/play-sound",
370 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
)));
372 purple_pounce_set_save(dialog
->pounce
,
373 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->save_pounce
)));
378 delete_win_cb(NULL
, NULL
, dialog
);
382 pounce_choose_cb(GtkWidget
*item
, PurpleAccount
*account
,
383 PidginPounceDialog
*dialog
)
385 dialog
->account
= account
;
389 buddy_changed_cb(GtkEntry
*entry
, PidginPounceDialog
*dialog
)
391 if (dialog
->save_button
== NULL
)
394 gtk_widget_set_sensitive(dialog
->save_button
,
395 *gtk_entry_get_text(entry
) != '\0');
399 message_recv_toggle(GtkButton
*message_recv
, GtkWidget
*send_msg
)
401 gboolean active
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(message_recv
));
403 gtk_widget_set_sensitive(send_msg
, !active
);
405 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(send_msg
), FALSE
);
409 pounce_dnd_recv(GtkWidget
*widget
, GdkDragContext
*dc
, gint x
, gint y
,
410 GtkSelectionData
*sd
, guint info
, guint t
, gpointer data
)
412 PidginPounceDialog
*dialog
;
414 if (sd
->target
== gdk_atom_intern("PURPLE_BLIST_NODE", FALSE
))
416 PurpleBlistNode
*node
= NULL
;
419 memcpy(&node
, sd
->data
, sizeof(node
));
421 if (PURPLE_BLIST_NODE_IS_CONTACT(node
))
422 buddy
= purple_contact_get_priority_buddy((PurpleContact
*)node
);
423 else if (PURPLE_BLIST_NODE_IS_BUDDY(node
))
424 buddy
= (PurpleBuddy
*)node
;
428 dialog
= (PidginPounceDialog
*)data
;
430 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
), buddy
->name
);
431 dialog
->account
= buddy
->account
;
432 pidgin_account_option_menu_set_selected(dialog
->account_menu
, buddy
->account
);
434 gtk_drag_finish(dc
, TRUE
, (dc
->action
== GDK_ACTION_MOVE
), t
);
436 else if (sd
->target
== gdk_atom_intern("application/x-im-contact", FALSE
))
438 char *protocol
= NULL
;
439 char *username
= NULL
;
440 PurpleAccount
*account
;
442 if (pidgin_parse_x_im_contact((const char *)sd
->data
, FALSE
, &account
,
443 &protocol
, &username
, NULL
))
447 purple_notify_error(NULL
, NULL
,
448 _("You are not currently signed on with an account that "
449 "can add that buddy."), NULL
);
453 dialog
= (PidginPounceDialog
*)data
;
455 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
), username
);
456 dialog
->account
= account
;
457 pidgin_account_option_menu_set_selected(dialog
->account_menu
, account
);
464 gtk_drag_finish(dc
, TRUE
, (dc
->action
== GDK_ACTION_MOVE
), t
);
468 static const GtkTargetEntry dnd_targets
[] =
470 {"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP
, 0},
471 {"application/x-im-contact", 0, 1}
475 reset_send_msg_entry(PidginPounceDialog
*dialog
, GtkWidget
*dontcare
)
477 PurpleAccount
*account
= pidgin_account_option_menu_get_selected(dialog
->account_menu
);
478 gtk_imhtml_setup_entry(GTK_IMHTML(dialog
->send_msg_entry
),
479 (account
&& account
->gc
) ? account
->gc
->flags
: PURPLE_CONNECTION_HTML
);
483 pidgin_pounce_editor_show(PurpleAccount
*account
, const char *name
,
484 PurplePounce
*cur_pounce
)
486 PidginPounceDialog
*dialog
;
489 GtkWidget
*vbox1
, *vbox2
;
495 GPtrArray
*sound_widgets
;
496 GPtrArray
*exec_widgets
;
497 GtkWidget
*send_msg_imhtml
;
499 g_return_if_fail((cur_pounce
!= NULL
) ||
501 (purple_accounts_get_all() != NULL
));
503 dialog
= g_new0(PidginPounceDialog
, 1);
505 if (cur_pounce
!= NULL
)
507 dialog
->pounce
= cur_pounce
;
508 dialog
->account
= purple_pounce_get_pouncer(cur_pounce
);
510 else if (account
!= NULL
)
512 dialog
->pounce
= NULL
;
513 dialog
->account
= account
;
517 GList
*connections
= purple_connections_get_all();
518 PurpleConnection
*gc
;
520 if (connections
!= NULL
)
522 gc
= (PurpleConnection
*)connections
->data
;
523 dialog
->account
= purple_connection_get_account(gc
);
526 dialog
->account
= purple_accounts_get_all()->data
;
528 dialog
->pounce
= NULL
;
531 sg
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
533 /* Create the window. */
534 dialog
->window
= window
= gtk_dialog_new();
535 gtk_window_set_title(GTK_WINDOW(window
), (cur_pounce
== NULL
? _("Add Buddy Pounce") : _("Modify Buddy Pounce")));
536 gtk_window_set_role(GTK_WINDOW(window
), "buddy_pounce");
537 gtk_container_set_border_width(GTK_CONTAINER(dialog
->window
), PIDGIN_HIG_BORDER
);
539 g_signal_connect(G_OBJECT(window
), "delete_event",
540 G_CALLBACK(delete_win_cb
), dialog
);
542 /* Create the parent vbox for everything. */
543 vbox1
= GTK_DIALOG(window
)->vbox
;
545 /* Create the vbox that will contain all the prefs stuff. */
546 vbox2
= gtk_vbox_new(FALSE
, PIDGIN_HIG_BOX_SPACE
);
547 gtk_box_pack_start(GTK_BOX(vbox1
), vbox2
, TRUE
, TRUE
, 0);
549 /* Create the "Pounce on Whom" frame. */
550 frame
= pidgin_make_frame(vbox2
, _("Pounce on Whom"));
553 hbox
= gtk_hbox_new(FALSE
, PIDGIN_HIG_BOX_SPACE
);
554 gtk_box_pack_start(GTK_BOX(frame
), hbox
, FALSE
, FALSE
, 0);
555 gtk_widget_show(hbox
);
557 label
= gtk_label_new_with_mnemonic(_("_Account:"));
558 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
559 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
560 gtk_widget_show(label
);
561 gtk_size_group_add_widget(sg
, label
);
563 dialog
->account_menu
=
564 pidgin_account_option_menu_new(dialog
->account
, TRUE
,
565 G_CALLBACK(pounce_choose_cb
),
568 gtk_box_pack_start(GTK_BOX(hbox
), dialog
->account_menu
, FALSE
, FALSE
, 0);
569 gtk_widget_show(dialog
->account_menu
);
570 pidgin_set_accessible_label (dialog
->account_menu
, label
);
573 hbox
= gtk_hbox_new(FALSE
, PIDGIN_HIG_BOX_SPACE
);
574 gtk_box_pack_start(GTK_BOX(frame
), hbox
, FALSE
, FALSE
, 0);
575 gtk_widget_show(hbox
);
577 label
= gtk_label_new_with_mnemonic(_("_Buddy name:"));
578 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
579 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
580 gtk_widget_show(label
);
581 gtk_size_group_add_widget(sg
, label
);
583 dialog
->buddy_entry
= gtk_entry_new();
585 pidgin_setup_screenname_autocomplete_with_filter(dialog
->buddy_entry
, dialog
->account_menu
, pidgin_screenname_autocomplete_default_filter
, GINT_TO_POINTER(FALSE
));
587 gtk_box_pack_start(GTK_BOX(hbox
), dialog
->buddy_entry
, TRUE
, TRUE
, 0);
588 gtk_widget_show(dialog
->buddy_entry
);
590 g_signal_connect(G_OBJECT(dialog
->buddy_entry
), "changed",
591 G_CALLBACK(buddy_changed_cb
), dialog
);
592 pidgin_set_accessible_label (dialog
->buddy_entry
, label
);
594 if (cur_pounce
!= NULL
) {
595 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
),
596 purple_pounce_get_pouncee(cur_pounce
));
598 else if (name
!= NULL
) {
599 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
), name
);
602 /* Create the "Pounce When Buddy..." frame. */
603 frame
= pidgin_make_frame(vbox2
, _("Pounce When Buddy..."));
605 table
= gtk_table_new(5, 2, FALSE
);
606 gtk_container_add(GTK_CONTAINER(frame
), table
);
607 gtk_table_set_col_spacings(GTK_TABLE(table
), PIDGIN_HIG_BORDER
);
608 gtk_widget_show(table
);
611 gtk_check_button_new_with_mnemonic(_("Si_gns on"));
613 gtk_check_button_new_with_mnemonic(_("Signs o_ff"));
615 gtk_check_button_new_with_mnemonic(_("Goes a_way"));
616 dialog
->away_return
=
617 gtk_check_button_new_with_mnemonic(_("Ret_urns from away"));
619 gtk_check_button_new_with_mnemonic(_("Becomes _idle"));
620 dialog
->idle_return
=
621 gtk_check_button_new_with_mnemonic(_("Is no longer i_dle"));
623 gtk_check_button_new_with_mnemonic(_("Starts _typing"));
625 gtk_check_button_new_with_mnemonic(_("P_auses while typing"));
626 dialog
->stop_typing
=
627 gtk_check_button_new_with_mnemonic(_("Stops t_yping"));
628 dialog
->message_recv
=
629 gtk_check_button_new_with_mnemonic(_("Sends a _message"));
631 gtk_table_attach(GTK_TABLE(table
), dialog
->message_recv
, 0, 1, 0, 1,
633 gtk_table_attach(GTK_TABLE(table
), dialog
->signon
, 0, 1, 1, 2,
635 gtk_table_attach(GTK_TABLE(table
), dialog
->signoff
, 0, 1, 2, 3,
637 gtk_table_attach(GTK_TABLE(table
), dialog
->away
, 1, 2, 0, 1,
639 gtk_table_attach(GTK_TABLE(table
), dialog
->away_return
, 1, 2, 1, 2,
641 gtk_table_attach(GTK_TABLE(table
), dialog
->idle
, 1, 2, 2, 3,
643 gtk_table_attach(GTK_TABLE(table
), dialog
->idle_return
, 2, 3, 0, 1,
645 gtk_table_attach(GTK_TABLE(table
), dialog
->typing
, 2, 3, 1, 2,
647 gtk_table_attach(GTK_TABLE(table
), dialog
->typed
, 2, 3, 2, 3,
649 gtk_table_attach(GTK_TABLE(table
), dialog
->stop_typing
, 3, 4, 0, 1,
652 gtk_widget_show(dialog
->signon
);
653 gtk_widget_show(dialog
->signoff
);
654 gtk_widget_show(dialog
->away
);
655 gtk_widget_show(dialog
->away_return
);
656 gtk_widget_show(dialog
->idle
);
657 gtk_widget_show(dialog
->idle_return
);
658 gtk_widget_show(dialog
->typing
);
659 gtk_widget_show(dialog
->typed
);
660 gtk_widget_show(dialog
->stop_typing
);
661 gtk_widget_show(dialog
->message_recv
);
663 /* Create the "Action" frame. */
664 frame
= pidgin_make_frame(vbox2
, _("Action"));
666 table
= gtk_table_new(3, 6, FALSE
);
667 gtk_container_add(GTK_CONTAINER(frame
), table
);
668 gtk_table_set_col_spacings(GTK_TABLE(table
), PIDGIN_HIG_BORDER
);
669 gtk_widget_show(table
);
672 = gtk_check_button_new_with_mnemonic(_("Ope_n an IM window"));
674 = gtk_check_button_new_with_mnemonic(_("_Pop up a notification"));
676 = gtk_check_button_new_with_mnemonic(_("Send a _message"));
678 = gtk_check_button_new_with_mnemonic(_("E_xecute a command"));
680 = gtk_check_button_new_with_mnemonic(_("P_lay a sound"));
682 send_msg_imhtml
= pidgin_create_imhtml(TRUE
, &dialog
->send_msg_entry
, NULL
, NULL
);
683 reset_send_msg_entry(dialog
, NULL
);
684 dialog
->exec_cmd_entry
= gtk_entry_new();
685 dialog
->popup_entry
= gtk_entry_new();
686 dialog
->exec_cmd_browse
= gtk_button_new_with_mnemonic(_("Brows_e..."));
687 dialog
->play_sound_entry
= gtk_entry_new();
688 gtk_entry_set_text(GTK_ENTRY(dialog
->play_sound_entry
), _("(default)"));
689 gtk_editable_set_editable(GTK_EDITABLE(dialog
->play_sound_entry
), FALSE
);
690 dialog
->play_sound_browse
= gtk_button_new_with_mnemonic(_("Br_owse..."));
691 dialog
->play_sound_test
= gtk_button_new_with_mnemonic(_("Pre_view"));
692 dialog
->play_sound_reset
= gtk_button_new_with_mnemonic(_("Reset"));
694 gtk_widget_set_sensitive(send_msg_imhtml
, FALSE
);
695 gtk_widget_set_sensitive(dialog
->exec_cmd_entry
, FALSE
);
696 gtk_widget_set_sensitive(dialog
->popup_entry
, FALSE
);
697 gtk_widget_set_sensitive(dialog
->exec_cmd_browse
, FALSE
);
698 gtk_widget_set_sensitive(dialog
->play_sound_entry
, FALSE
);
699 gtk_widget_set_sensitive(dialog
->play_sound_browse
, FALSE
);
700 gtk_widget_set_sensitive(dialog
->play_sound_test
, FALSE
);
701 gtk_widget_set_sensitive(dialog
->play_sound_reset
, FALSE
);
705 sg
= gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL
);
706 gtk_size_group_add_widget(sg
, dialog
->open_win
);
707 gtk_size_group_add_widget(sg
, dialog
->popup
);
708 gtk_size_group_add_widget(sg
, dialog
->popup_entry
);
709 gtk_size_group_add_widget(sg
, dialog
->exec_cmd
);
710 gtk_size_group_add_widget(sg
, dialog
->exec_cmd_entry
);
711 gtk_size_group_add_widget(sg
, dialog
->exec_cmd_browse
);
712 gtk_size_group_add_widget(sg
, dialog
->play_sound
);
713 gtk_size_group_add_widget(sg
, dialog
->play_sound_entry
);
714 gtk_size_group_add_widget(sg
, dialog
->play_sound_browse
);
715 gtk_size_group_add_widget(sg
, dialog
->play_sound_test
);
716 gtk_size_group_add_widget(sg
, dialog
->play_sound_reset
);
721 gtk_table_attach(GTK_TABLE(table
), dialog
->open_win
, 0, 1, 0, 1,
723 gtk_table_attach(GTK_TABLE(table
), dialog
->popup
, 0, 1, 1, 2,
725 gtk_table_attach(GTK_TABLE(table
), dialog
->popup_entry
, 1, 5, 1, 2,
727 gtk_table_attach(GTK_TABLE(table
), dialog
->send_msg
, 0, 5, 2, 3,
729 gtk_table_attach(GTK_TABLE(table
), send_msg_imhtml
, 0, 5, 3, 4,
731 gtk_table_attach(GTK_TABLE(table
), dialog
->exec_cmd
, 0, 1, 4, 5,
733 gtk_table_attach(GTK_TABLE(table
), dialog
->exec_cmd_entry
, 1, 2, 4, 5,
735 gtk_table_attach(GTK_TABLE(table
), dialog
->exec_cmd_browse
, 2, 3, 4, 5,
736 GTK_FILL
| GTK_EXPAND
, 0, 0, 0);
737 gtk_table_attach(GTK_TABLE(table
), dialog
->play_sound
, 0, 1, 5, 6,
739 gtk_table_attach(GTK_TABLE(table
), dialog
->play_sound_entry
, 1, 2, 5, 6,
741 gtk_table_attach(GTK_TABLE(table
), dialog
->play_sound_browse
,2, 3, 5, 6,
742 GTK_FILL
| GTK_EXPAND
, 0, 0, 0);
743 gtk_table_attach(GTK_TABLE(table
), dialog
->play_sound_test
, 3, 4, 5, 6,
744 GTK_FILL
| GTK_EXPAND
, 0, 0, 0);
745 gtk_table_attach(GTK_TABLE(table
), dialog
->play_sound_reset
, 4, 5, 5, 6,
746 GTK_FILL
| GTK_EXPAND
, 0, 0, 0);
748 gtk_table_set_row_spacings(GTK_TABLE(table
), PIDGIN_HIG_BOX_SPACE
/ 2);
750 gtk_widget_show(dialog
->open_win
);
751 gtk_widget_show(dialog
->popup
);
752 gtk_widget_show(dialog
->popup_entry
);
753 gtk_widget_show(dialog
->send_msg
);
754 gtk_widget_show(send_msg_imhtml
);
755 gtk_widget_show(dialog
->exec_cmd
);
756 gtk_widget_show(dialog
->exec_cmd_entry
);
757 gtk_widget_show(dialog
->exec_cmd_browse
);
758 gtk_widget_show(dialog
->play_sound
);
759 gtk_widget_show(dialog
->play_sound_entry
);
760 gtk_widget_show(dialog
->play_sound_browse
);
761 gtk_widget_show(dialog
->play_sound_test
);
762 gtk_widget_show(dialog
->play_sound_reset
);
764 g_signal_connect(G_OBJECT(dialog
->message_recv
), "clicked",
765 G_CALLBACK(message_recv_toggle
),
768 g_signal_connect(G_OBJECT(dialog
->send_msg
), "clicked",
769 G_CALLBACK(pidgin_toggle_sensitive
),
772 g_signal_connect(G_OBJECT(dialog
->popup
), "clicked",
773 G_CALLBACK(pidgin_toggle_sensitive
),
774 dialog
->popup_entry
);
776 exec_widgets
= g_ptr_array_new();
777 g_ptr_array_add(exec_widgets
,dialog
->exec_cmd_entry
);
778 g_ptr_array_add(exec_widgets
,dialog
->exec_cmd_browse
);
780 g_signal_connect(G_OBJECT(dialog
->exec_cmd
), "clicked",
781 G_CALLBACK(pidgin_toggle_sensitive_array
),
783 g_signal_connect(G_OBJECT(dialog
->exec_cmd_browse
), "clicked",
785 dialog
->exec_cmd_entry
);
786 g_object_set_data_full(G_OBJECT(dialog
->window
), "exec-widgets",
787 exec_widgets
, (GDestroyNotify
)g_ptr_array_free
);
789 sound_widgets
= g_ptr_array_new();
790 g_ptr_array_add(sound_widgets
,dialog
->play_sound_entry
);
791 g_ptr_array_add(sound_widgets
,dialog
->play_sound_browse
);
792 g_ptr_array_add(sound_widgets
,dialog
->play_sound_test
);
793 g_ptr_array_add(sound_widgets
,dialog
->play_sound_reset
);
795 g_signal_connect(G_OBJECT(dialog
->play_sound
), "clicked",
796 G_CALLBACK(pidgin_toggle_sensitive_array
),
798 g_signal_connect(G_OBJECT(dialog
->play_sound_browse
), "clicked",
800 dialog
->play_sound_entry
);
801 g_signal_connect(G_OBJECT(dialog
->play_sound_test
), "clicked",
802 G_CALLBACK(pounce_test_sound
),
803 dialog
->play_sound_entry
);
804 g_signal_connect(G_OBJECT(dialog
->play_sound_reset
), "clicked",
805 G_CALLBACK(pounce_reset_sound
),
806 dialog
->play_sound_entry
);
807 g_object_set_data_full(G_OBJECT(dialog
->window
), "sound-widgets",
808 sound_widgets
, (GDestroyNotify
)g_ptr_array_free
);
810 g_signal_connect_swapped(G_OBJECT(dialog
->send_msg_entry
), "format_function_clear",
811 G_CALLBACK(reset_send_msg_entry
), dialog
);
812 g_signal_connect_swapped(G_OBJECT(dialog
->account_menu
), "changed",
813 G_CALLBACK(reset_send_msg_entry
), dialog
);
815 g_signal_connect(G_OBJECT(dialog
->send_msg_entry
), "message_send",
816 G_CALLBACK(save_pounce_cb
), dialog
);
817 g_signal_connect(G_OBJECT(dialog
->popup_entry
), "activate",
818 G_CALLBACK(save_pounce_cb
), dialog
);
819 g_signal_connect(G_OBJECT(dialog
->exec_cmd_entry
), "activate",
820 G_CALLBACK(save_pounce_cb
), dialog
);
822 /* Create the "Options" frame. */
823 frame
= pidgin_make_frame(vbox2
, _("Options"));
825 table
= gtk_table_new(2, 1, FALSE
);
826 gtk_container_add(GTK_CONTAINER(frame
), table
);
827 gtk_table_set_col_spacings(GTK_TABLE(table
), PIDGIN_HIG_BORDER
);
828 gtk_widget_show(table
);
831 gtk_check_button_new_with_mnemonic(_("P_ounce only when my status is not Available"));
832 gtk_table_attach(GTK_TABLE(table
), dialog
->on_away
, 0, 1, 0, 1,
835 dialog
->save_pounce
= gtk_check_button_new_with_mnemonic(
837 gtk_table_attach(GTK_TABLE(table
), dialog
->save_pounce
, 0, 1, 1, 2,
840 gtk_widget_show(dialog
->on_away
);
841 gtk_widget_show(dialog
->save_pounce
);
844 button
= gtk_dialog_add_button(GTK_DIALOG(window
), GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
);
845 g_signal_connect(G_OBJECT(button
), "clicked",
846 G_CALLBACK(cancel_cb
), dialog
);
848 /* Save/Add button */
849 dialog
->save_button
= button
= gtk_dialog_add_button(GTK_DIALOG(window
),
850 (cur_pounce
== NULL
? GTK_STOCK_ADD
: GTK_STOCK_SAVE
),
852 g_signal_connect(G_OBJECT(button
), "clicked",
853 G_CALLBACK(save_pounce_cb
), dialog
);
855 if (*gtk_entry_get_text(GTK_ENTRY(dialog
->buddy_entry
)) == '\0')
856 gtk_widget_set_sensitive(button
, FALSE
);
858 /* Setup drag-and-drop */
859 gtk_drag_dest_set(window
,
860 GTK_DEST_DEFAULT_MOTION
|
861 GTK_DEST_DEFAULT_DROP
,
863 sizeof(dnd_targets
) / sizeof(GtkTargetEntry
),
865 gtk_drag_dest_set(dialog
->buddy_entry
,
866 GTK_DEST_DEFAULT_MOTION
|
867 GTK_DEST_DEFAULT_DROP
,
869 sizeof(dnd_targets
) / sizeof(GtkTargetEntry
),
872 g_signal_connect(G_OBJECT(window
), "drag_data_received",
873 G_CALLBACK(pounce_dnd_recv
), dialog
);
874 g_signal_connect(G_OBJECT(dialog
->buddy_entry
), "drag_data_received",
875 G_CALLBACK(pounce_dnd_recv
), dialog
);
877 /* Set the values of stuff. */
878 if (cur_pounce
!= NULL
)
880 PurplePounceEvent events
= purple_pounce_get_events(cur_pounce
);
881 PurplePounceOption options
= purple_pounce_get_options(cur_pounce
);
885 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->on_away
),
886 (options
& PURPLE_POUNCE_OPTION_AWAY
));
889 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->signon
),
890 (events
& PURPLE_POUNCE_SIGNON
));
891 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->signoff
),
892 (events
& PURPLE_POUNCE_SIGNOFF
));
893 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->away
),
894 (events
& PURPLE_POUNCE_AWAY
));
895 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->away_return
),
896 (events
& PURPLE_POUNCE_AWAY_RETURN
));
897 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->idle
),
898 (events
& PURPLE_POUNCE_IDLE
));
899 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->idle_return
),
900 (events
& PURPLE_POUNCE_IDLE_RETURN
));
901 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->typing
),
902 (events
& PURPLE_POUNCE_TYPING
));
903 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->typed
),
904 (events
& PURPLE_POUNCE_TYPED
));
905 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->stop_typing
),
906 (events
& PURPLE_POUNCE_TYPING_STOPPED
));
907 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->message_recv
),
908 (events
& PURPLE_POUNCE_MESSAGE_RECEIVED
));
911 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->open_win
),
912 purple_pounce_action_is_enabled(cur_pounce
, "open-window"));
913 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->popup
),
914 purple_pounce_action_is_enabled(cur_pounce
, "popup-notify"));
915 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
),
916 purple_pounce_action_is_enabled(cur_pounce
, "send-message"));
917 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
),
918 purple_pounce_action_is_enabled(cur_pounce
, "execute-command"));
919 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
),
920 purple_pounce_action_is_enabled(cur_pounce
, "play-sound"));
922 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->save_pounce
),
923 purple_pounce_get_save(cur_pounce
));
925 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
929 gtk_imhtml_append_text(GTK_IMHTML(dialog
->send_msg_entry
), value
, 0);
932 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
936 gtk_entry_set_text(GTK_ENTRY(dialog
->popup_entry
), value
);
939 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
943 gtk_entry_set_text(GTK_ENTRY(dialog
->exec_cmd_entry
), value
);
946 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
948 "filename")) != NULL
)
950 gtk_entry_set_text(GTK_ENTRY(dialog
->play_sound_entry
), (value
&& *value
!= '\0') ? value
: _("(default)"));
955 PurpleBuddy
*buddy
= NULL
;
958 buddy
= purple_find_buddy(account
, name
);
960 /* Set some defaults */
963 gtk_toggle_button_set_active(
964 GTK_TOGGLE_BUTTON(dialog
->signon
), TRUE
);
968 if (!PURPLE_BUDDY_IS_ONLINE(buddy
))
970 gtk_toggle_button_set_active(
971 GTK_TOGGLE_BUTTON(dialog
->signon
), TRUE
);
975 gboolean default_set
= FALSE
;
976 PurplePresence
*presence
= purple_buddy_get_presence(buddy
);
978 if (purple_presence_is_idle(presence
))
980 gtk_toggle_button_set_active(
981 GTK_TOGGLE_BUTTON(dialog
->idle_return
), TRUE
);
986 if (!purple_presence_is_available(presence
))
988 gtk_toggle_button_set_active(
989 GTK_TOGGLE_BUTTON(dialog
->away_return
), TRUE
);
996 gtk_toggle_button_set_active(
997 GTK_TOGGLE_BUTTON(dialog
->signon
), TRUE
);
1002 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->open_win
),
1003 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/open-window"));
1004 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->popup
),
1005 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/popup-notify"));
1006 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
),
1007 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/send-message"));
1008 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
),
1009 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/execute-command"));
1010 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
),
1011 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/play-sound"));
1014 gtk_widget_show(vbox2
);
1015 gtk_widget_show(window
);
1019 pounces_manager_configure_cb(GtkWidget
*widget
, GdkEventConfigure
*event
, PouncesManager
*dialog
)
1021 if (GTK_WIDGET_VISIBLE(widget
)) {
1022 purple_prefs_set_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/width", event
->width
);
1023 purple_prefs_set_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/height", event
->height
);
1030 pounces_manager_find_pounce(GtkTreeIter
*iter
, PurplePounce
*pounce
)
1032 GtkTreeModel
*model
= GTK_TREE_MODEL(pounces_manager
->model
);
1035 if (!gtk_tree_model_get_iter_first(model
, iter
))
1038 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &p
, -1);
1042 while (gtk_tree_model_iter_next(model
, iter
))
1044 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &p
, -1);
1053 pounces_manager_destroy_cb(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
)
1055 PouncesManager
*dialog
= user_data
;
1057 dialog
->window
= NULL
;
1058 pidgin_pounces_manager_hide();
1064 pounces_manager_connection_cb(PurpleConnection
*gc
, GtkWidget
*add_button
)
1066 gtk_widget_set_sensitive(add_button
, (purple_connections_get_all() != NULL
));
1070 pounces_manager_add_cb(GtkButton
*button
, gpointer user_data
)
1072 pidgin_pounce_editor_show(NULL
, NULL
, NULL
);
1076 pounces_manager_modify_foreach(GtkTreeModel
*model
, GtkTreePath
*path
,
1077 GtkTreeIter
*iter
, gpointer user_data
)
1079 PurplePounce
*pounce
;
1081 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
, -1);
1082 pidgin_pounce_editor_show(NULL
, NULL
, pounce
);
1086 pounces_manager_modify_cb(GtkButton
*button
, gpointer user_data
)
1088 PouncesManager
*dialog
= user_data
;
1089 GtkTreeSelection
*selection
;
1091 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->treeview
));
1093 gtk_tree_selection_selected_foreach(selection
, pounces_manager_modify_foreach
, user_data
);
1097 pounces_manager_delete_confirm_cb(PurplePounce
*pounce
)
1101 if (pounces_manager
&& pounces_manager_find_pounce(&iter
, pounce
))
1102 gtk_list_store_remove(pounces_manager
->model
, &iter
);
1104 purple_request_close_with_handle(pounce
);
1105 purple_pounce_destroy(pounce
);
1109 pounces_manager_delete_foreach(GtkTreeModel
*model
, GtkTreePath
*path
,
1110 GtkTreeIter
*iter
, gpointer user_data
)
1112 PurplePounce
*pounce
;
1113 PurpleAccount
*account
;
1114 const char *pouncer
, *pouncee
;
1117 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
, -1);
1118 account
= purple_pounce_get_pouncer(pounce
);
1119 pouncer
= purple_account_get_username(account
);
1120 pouncee
= purple_pounce_get_pouncee(pounce
);
1122 buf
= g_strdup_printf(_("Are you sure you want to delete the pounce on %s for %s?"), pouncee
, pouncer
);
1123 purple_request_action(pounce
, NULL
, buf
, NULL
, 0,
1124 account
, pouncee
, NULL
,
1126 _("Delete"), pounces_manager_delete_confirm_cb
,
1132 pounces_manager_delete_cb(GtkButton
*button
, gpointer user_data
)
1134 PouncesManager
*dialog
= user_data
;
1135 GtkTreeSelection
*selection
;
1137 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->treeview
));
1139 gtk_tree_selection_selected_foreach(selection
, pounces_manager_delete_foreach
, user_data
);
1143 pounces_manager_close_cb(GtkButton
*button
, gpointer user_data
)
1145 pidgin_pounces_manager_hide();
1149 pounce_selected_cb(GtkTreeSelection
*sel
, gpointer user_data
)
1151 PouncesManager
*dialog
= user_data
;
1152 int num_selected
= 0;
1154 num_selected
= gtk_tree_selection_count_selected_rows(sel
);
1156 gtk_widget_set_sensitive(dialog
->modify_button
, (num_selected
> 0));
1157 gtk_widget_set_sensitive(dialog
->delete_button
, (num_selected
> 0));
1161 pounce_double_click_cb(GtkTreeView
*treeview
, GdkEventButton
*event
, gpointer user_data
)
1163 PouncesManager
*dialog
= user_data
;
1166 PurplePounce
*pounce
;
1168 /* Figure out which node was clicked */
1169 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(dialog
->treeview
), event
->x
, event
->y
, &path
, NULL
, NULL
, NULL
))
1171 gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog
->model
), &iter
, path
);
1172 gtk_tree_path_free(path
);
1173 gtk_tree_model_get(GTK_TREE_MODEL(dialog
->model
), &iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
, -1);
1175 if ((pounce
!= NULL
) && (event
->button
== 1) &&
1176 (event
->type
== GDK_2BUTTON_PRESS
))
1178 pidgin_pounce_editor_show(NULL
, NULL
, pounce
);
1186 pounces_manager_recurring_cb(GtkCellRendererToggle
*renderer
, gchar
*path_str
,
1189 PouncesManager
*dialog
= user_data
;
1190 PurplePounce
*pounce
;
1192 GtkTreeModel
*model
= GTK_TREE_MODEL(dialog
->model
);
1195 gtk_tree_model_get_iter_from_string(model
, &iter
, path_str
);
1196 gtk_tree_model_get(model
, &iter
,
1197 POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
,
1198 POUNCES_MANAGER_COLUMN_RECURRING
, &recurring
,
1201 purple_pounce_set_save(pounce
, !recurring
);
1207 search_func(GtkTreeModel
*model
, gint column
, const gchar
*key
, GtkTreeIter
*iter
, gpointer search_data
)
1212 gtk_tree_model_get(model
, iter
, column
, &haystack
, -1);
1214 result
= (purple_strcasestr(haystack
, key
) == NULL
);
1222 create_pounces_list(PouncesManager
*dialog
)
1224 GtkWidget
*treeview
;
1225 GtkTreeSelection
*sel
;
1226 GtkTreeViewColumn
*column
;
1227 GtkCellRenderer
*renderer
;
1229 /* Create the list model */
1230 dialog
->model
= gtk_list_store_new(POUNCES_MANAGER_NUM_COLUMNS
,
1238 /* Create the treeview */
1239 treeview
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog
->model
));
1240 g_object_unref(G_OBJECT(dialog
->model
));
1241 dialog
->treeview
= treeview
;
1242 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview
), TRUE
);
1244 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
));
1245 gtk_tree_selection_set_mode(sel
, GTK_SELECTION_MULTIPLE
);
1246 g_signal_connect(G_OBJECT(sel
), "changed",
1247 G_CALLBACK(pounce_selected_cb
), dialog
);
1249 /* Handle double-clicking */
1250 g_signal_connect(G_OBJECT(treeview
), "button_press_event",
1251 G_CALLBACK(pounce_double_click_cb
), dialog
);
1252 gtk_widget_show(treeview
);
1254 /* Pouncee Column */
1255 column
= gtk_tree_view_column_new();
1256 gtk_tree_view_column_set_title(column
, _("Pounce Target"));
1257 gtk_tree_view_column_set_resizable(column
, TRUE
);
1258 gtk_tree_view_column_set_min_width(column
, 200);
1259 gtk_tree_view_column_set_sort_column_id(column
,
1260 POUNCES_MANAGER_COLUMN_TARGET
);
1261 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
1264 renderer
= gtk_cell_renderer_pixbuf_new();
1265 gtk_tree_view_column_pack_start(column
, renderer
, FALSE
);
1266 gtk_tree_view_column_add_attribute(column
, renderer
, "pixbuf",
1267 POUNCES_MANAGER_COLUMN_ICON
);
1270 renderer
= gtk_cell_renderer_text_new();
1271 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1272 gtk_tree_view_column_add_attribute(column
, renderer
, "text",
1273 POUNCES_MANAGER_COLUMN_TARGET
);
1276 /* Account Column */
1277 column
= gtk_tree_view_column_new();
1278 gtk_tree_view_column_set_title(column
, _("Account"));
1279 gtk_tree_view_column_set_resizable(column
, TRUE
);
1280 gtk_tree_view_column_set_min_width(column
, 200);
1281 gtk_tree_view_column_set_sort_column_id(column
,
1282 POUNCES_MANAGER_COLUMN_ACCOUNT
);
1283 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
1284 renderer
= gtk_cell_renderer_text_new();
1285 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1286 gtk_tree_view_column_add_attribute(column
, renderer
, "text",
1287 POUNCES_MANAGER_COLUMN_ACCOUNT
);
1289 /* Recurring Column */
1290 renderer
= gtk_cell_renderer_toggle_new();
1291 column
= gtk_tree_view_column_new_with_attributes(_("Recurring"), renderer
,
1292 "active", POUNCES_MANAGER_COLUMN_RECURRING
, NULL
);
1293 gtk_tree_view_column_set_sort_column_id(column
,
1294 POUNCES_MANAGER_COLUMN_RECURRING
);
1295 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
1296 g_signal_connect(G_OBJECT(renderer
), "toggled",
1297 G_CALLBACK(pounces_manager_recurring_cb
), dialog
);
1299 /* Enable CTRL+F searching */
1300 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview
), POUNCES_MANAGER_COLUMN_TARGET
);
1301 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(treeview
), search_func
, NULL
, NULL
);
1303 /* Sort the pouncee column by default */
1304 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog
->model
),
1305 POUNCES_MANAGER_COLUMN_TARGET
,
1306 GTK_SORT_ASCENDING
);
1309 populate_pounces_list(dialog
);
1311 return pidgin_make_scrollable(treeview
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
, GTK_SHADOW_IN
, -1, -1);
1315 pidgin_pounces_manager_show(void)
1317 PouncesManager
*dialog
;
1324 if (pounces_manager
!= NULL
) {
1325 gtk_window_present(GTK_WINDOW(pounces_manager
->window
));
1329 pounces_manager
= dialog
= g_new0(PouncesManager
, 1);
1331 width
= purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/width");
1332 height
= purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/height");
1334 dialog
->window
= win
= pidgin_create_dialog(_("Buddy Pounces"), PIDGIN_HIG_BORDER
, "pounces", TRUE
);
1335 gtk_window_set_default_size(GTK_WINDOW(win
), width
, height
);
1337 g_signal_connect(G_OBJECT(win
), "delete_event",
1338 G_CALLBACK(pounces_manager_destroy_cb
), dialog
);
1339 g_signal_connect(G_OBJECT(win
), "configure_event",
1340 G_CALLBACK(pounces_manager_configure_cb
), dialog
);
1342 /* Setup the vbox */
1343 vbox
= pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win
), FALSE
, PIDGIN_HIG_BORDER
);
1345 /* List of saved buddy pounces */
1346 list
= create_pounces_list(dialog
);
1347 gtk_box_pack_start(GTK_BOX(vbox
), list
, TRUE
, TRUE
, 0);
1350 button
= pidgin_dialog_add_button(GTK_DIALOG(win
), PIDGIN_STOCK_ADD
, G_CALLBACK(pounces_manager_add_cb
), dialog
);
1351 gtk_widget_set_sensitive(button
, (purple_accounts_get_all() != NULL
));
1353 purple_signal_connect(purple_connections_get_handle(), "signed-on",
1354 pounces_manager
, PURPLE_CALLBACK(pounces_manager_connection_cb
), button
);
1355 purple_signal_connect(purple_connections_get_handle(), "signed-off",
1356 pounces_manager
, PURPLE_CALLBACK(pounces_manager_connection_cb
), button
);
1359 button
= pidgin_dialog_add_button(GTK_DIALOG(win
), PIDGIN_STOCK_MODIFY
, G_CALLBACK(pounces_manager_modify_cb
), dialog
);
1360 gtk_widget_set_sensitive(button
, FALSE
);
1361 dialog
->modify_button
= button
;
1364 button
= pidgin_dialog_add_button(GTK_DIALOG(win
), GTK_STOCK_DELETE
, G_CALLBACK(pounces_manager_delete_cb
), dialog
);
1365 gtk_widget_set_sensitive(button
, FALSE
);
1366 dialog
->delete_button
= button
;
1369 pidgin_dialog_add_button(GTK_DIALOG(win
), GTK_STOCK_CLOSE
, G_CALLBACK(pounces_manager_close_cb
), dialog
);
1371 gtk_widget_show(win
);
1375 pidgin_pounces_manager_hide(void)
1377 if (pounces_manager
== NULL
)
1380 if (pounces_manager
->window
!= NULL
)
1381 gtk_widget_destroy(pounces_manager
->window
);
1383 purple_signals_disconnect_by_handle(pounces_manager
);
1385 g_free(pounces_manager
);
1386 pounces_manager
= NULL
;
1390 pounce_cb(PurplePounce
*pounce
, PurplePounceEvent events
, void *data
)
1392 PurpleConversation
*conv
;
1393 PurpleAccount
*account
;
1395 const char *pouncee
;
1398 pouncee
= purple_pounce_get_pouncee(pounce
);
1399 account
= purple_pounce_get_pouncer(pounce
);
1401 buddy
= purple_find_buddy(account
, pouncee
);
1404 alias
= purple_buddy_get_alias(buddy
);
1411 if (purple_pounce_action_is_enabled(pounce
, "open-window"))
1413 if (!purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM
, pouncee
, account
))
1414 purple_conversation_new(PURPLE_CONV_TYPE_IM
, account
, pouncee
);
1417 if (purple_pounce_action_is_enabled(pounce
, "popup-notify"))
1421 reason
= purple_pounce_action_get_attribute(pounce
, "popup-notify",
1425 * Here we place the protocol name in the pounce dialog to lessen
1426 * confusion about what protocol a pounce is for.
1429 (events
& PURPLE_POUNCE_TYPING
) ?
1430 _("Started typing") :
1431 (events
& PURPLE_POUNCE_TYPED
) ?
1432 _("Paused while typing") :
1433 (events
& PURPLE_POUNCE_SIGNON
) ?
1435 (events
& PURPLE_POUNCE_IDLE_RETURN
) ?
1436 _("Returned from being idle") :
1437 (events
& PURPLE_POUNCE_AWAY_RETURN
) ?
1438 _("Returned from being away") :
1439 (events
& PURPLE_POUNCE_TYPING_STOPPED
) ?
1440 _("Stopped typing") :
1441 (events
& PURPLE_POUNCE_SIGNOFF
) ?
1443 (events
& PURPLE_POUNCE_IDLE
) ?
1445 (events
& PURPLE_POUNCE_AWAY
) ?
1447 (events
& PURPLE_POUNCE_MESSAGE_RECEIVED
) ?
1448 _("Sent a message") :
1449 _("Unknown.... Please report this!")
1452 pidgin_notify_pounce_add(account
, pounce
, alias
, tmp
, reason
,
1453 purple_date_format_full(NULL
));
1458 if (purple_pounce_action_is_enabled(pounce
, "send-message"))
1460 const char *message
;
1462 message
= purple_pounce_action_get_attribute(pounce
, "send-message",
1465 if (message
!= NULL
)
1467 conv
= purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM
, pouncee
, account
);
1470 conv
= purple_conversation_new(PURPLE_CONV_TYPE_IM
, account
, pouncee
);
1472 purple_conversation_write(conv
, NULL
, message
,
1473 PURPLE_MESSAGE_SEND
, time(NULL
));
1475 serv_send_im(account
->gc
, (char *)pouncee
, (char *)message
, 0);
1479 if (purple_pounce_action_is_enabled(pounce
, "execute-command"))
1481 const char *command
;
1483 command
= purple_pounce_action_get_attribute(pounce
,
1484 "execute-command", "command");
1486 if (command
!= NULL
)
1489 char *localecmd
= g_locale_from_utf8(command
, -1, NULL
,
1492 if (localecmd
!= NULL
)
1501 args
[2] = (char *)localecmd
;
1504 execvp(args
[0], args
);
1511 winpidgin_shell_execute(command
, "open", NULL
);
1512 #endif /* !_WIN32 */
1516 if (purple_pounce_action_is_enabled(pounce
, "play-sound"))
1520 sound
= purple_pounce_action_get_attribute(pounce
,
1521 "play-sound", "filename");
1524 purple_sound_play_file(sound
, account
);
1526 purple_sound_play_event(PURPLE_SOUND_POUNCE_DEFAULT
, account
);
1531 free_pounce(PurplePounce
*pounce
)
1537 new_pounce(PurplePounce
*pounce
)
1539 purple_pounce_action_register(pounce
, "open-window");
1540 purple_pounce_action_register(pounce
, "popup-notify");
1541 purple_pounce_action_register(pounce
, "send-message");
1542 purple_pounce_action_register(pounce
, "execute-command");
1543 purple_pounce_action_register(pounce
, "play-sound");
1549 pidgin_pounces_get_handle() {
1556 pidgin_pounces_init(void)
1558 purple_pounces_register_handler(PIDGIN_UI
, pounce_cb
, new_pounce
,
1561 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/pounces");
1562 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/pounces/default_actions");
1563 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/open-window",
1565 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/popup-notify",
1567 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/send-message",
1569 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/execute-command",
1571 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/play-sound",
1573 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/pounces/dialog");
1574 purple_prefs_add_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/width", 520);
1575 purple_prefs_add_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/height", 321);
1577 purple_signal_connect(purple_connections_get_handle(), "signed-on",
1578 pidgin_pounces_get_handle(),
1579 PURPLE_CALLBACK(signed_on_off_cb
), NULL
);
1580 purple_signal_connect(purple_connections_get_handle(), "signed-off",
1581 pidgin_pounces_get_handle(),
1582 PURPLE_CALLBACK(signed_on_off_cb
), NULL
);