3 * Pidgin is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 #include "conversation.h"
34 #include "gtk3compat.h"
36 #include "gtkdialogs.h"
37 #include "gtkpounce.h"
38 #include "gtknotify.h"
39 #include "pidginstock.h"
41 #include "gtkwebview.h"
43 #include <gdk/gdkkeysyms.h>
46 * These are used for the GtkTreeView when you're scrolling through
47 * all your saved pounces.
51 /* Hidden column containing the PurplePounce */
52 POUNCES_MANAGER_COLUMN_POUNCE
,
53 POUNCES_MANAGER_COLUMN_ICON
,
54 POUNCES_MANAGER_COLUMN_TARGET
,
55 POUNCES_MANAGER_COLUMN_ACCOUNT
,
56 POUNCES_MANAGER_COLUMN_RECURRING
,
57 POUNCES_MANAGER_NUM_COLUMNS
64 PurpleAccount
*account
;
70 GtkWidget
*account_menu
;
71 GtkWidget
*buddy_entry
;
76 /* Pounce When Buddy... */
80 GtkWidget
*away_return
;
82 GtkWidget
*idle_return
;
85 GtkWidget
*stop_typing
;
86 GtkWidget
*message_recv
;
91 GtkWidget
*popup_entry
;
93 GtkWidget
*send_msg_entry
;
95 GtkWidget
*exec_cmd_entry
;
96 GtkWidget
*exec_cmd_browse
;
97 GtkWidget
*play_sound
;
98 GtkWidget
*play_sound_entry
;
99 GtkWidget
*play_sound_browse
;
100 GtkWidget
*play_sound_test
;
101 GtkWidget
*play_sound_reset
;
103 GtkWidget
*save_pounce
;
106 GtkWidget
*save_button
;
108 } PidginPounceDialog
;
115 GtkWidget
*modify_button
;
116 GtkWidget
*delete_button
;
119 static PouncesManager
*pounces_manager
= NULL
;
121 /**************************************************************************
123 **************************************************************************/
125 delete_win_cb(GtkWidget
*w
, GdkEventAny
*e
, PidginPounceDialog
*dialog
)
127 gtk_widget_destroy(dialog
->window
);
134 cancel_cb(GtkWidget
*w
, PidginPounceDialog
*dialog
)
136 delete_win_cb(NULL
, NULL
, dialog
);
140 pounce_update_entry_fields(void *user_data
, const char *filename
)
142 GtkWidget
*entry
= (GtkWidget
*)user_data
;
144 gtk_entry_set_text(GTK_ENTRY(entry
), filename
);
148 filesel(GtkWidget
*widget
, gpointer data
)
153 entry
= (GtkWidget
*)data
;
154 name
= gtk_entry_get_text(GTK_ENTRY(entry
));
156 purple_request_file(entry
, _("Select a file"), name
, FALSE
,
157 G_CALLBACK(pounce_update_entry_fields
), NULL
, NULL
, entry
);
158 g_signal_connect_swapped(G_OBJECT(entry
), "destroy",
159 G_CALLBACK(purple_request_close_with_handle
), entry
);
163 pounce_test_sound(GtkWidget
*w
, GtkWidget
*entry
)
165 const char *filename
;
168 temp_mute
= purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/sound/mute");
170 if (temp_mute
) purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/sound/mute", FALSE
);
172 filename
= gtk_entry_get_text(GTK_ENTRY(entry
));
174 if (filename
!= NULL
&& *filename
!= '\0' && strcmp(filename
, _("(default)")))
175 purple_sound_play_file(filename
, NULL
);
177 purple_sound_play_event(PURPLE_SOUND_POUNCE_DEFAULT
, NULL
);
179 if (temp_mute
) purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/sound/mute", TRUE
);
183 pounce_reset_sound(GtkWidget
*w
, GtkWidget
*entry
)
185 gtk_entry_set_text(GTK_ENTRY(entry
), _("(default)"));
189 add_pounce_to_treeview(GtkListStore
*model
, PurplePounce
*pounce
)
192 PurpleAccount
*account
;
198 account
= purple_pounce_get_pouncer(pounce
);
200 pixbuf
= pidgin_create_protocol_icon(account
, PIDGIN_PROTOCOL_ICON_MEDIUM
);
202 pouncer
= purple_account_get_username(account
);
203 pouncee
= purple_pounce_get_pouncee(pounce
);
204 recurring
= purple_pounce_get_save(pounce
);
206 gtk_list_store_append(model
, &iter
);
207 gtk_list_store_set(model
, &iter
,
208 POUNCES_MANAGER_COLUMN_POUNCE
, pounce
,
209 POUNCES_MANAGER_COLUMN_ICON
, pixbuf
,
210 POUNCES_MANAGER_COLUMN_TARGET
, pouncee
,
211 POUNCES_MANAGER_COLUMN_ACCOUNT
, pouncer
,
212 POUNCES_MANAGER_COLUMN_RECURRING
, recurring
,
216 g_object_unref(pixbuf
);
220 populate_pounces_list(PouncesManager
*dialog
)
224 gtk_list_store_clear(dialog
->model
);
226 for (pounces
= purple_pounces_get_all_for_ui(PIDGIN_UI
); pounces
!= NULL
;
227 pounces
= g_list_delete_link(pounces
, pounces
))
229 add_pounce_to_treeview(dialog
->model
, pounces
->data
);
236 /* Rebuild the pounces list if the pounces manager is open */
237 if (pounces_manager
!= NULL
)
239 populate_pounces_list(pounces_manager
);
244 signed_on_off_cb(PurpleConnection
*gc
, gpointer user_data
)
250 save_pounce_cb(GtkWidget
*w
, PidginPounceDialog
*dialog
)
253 const char *command
, *sound
, *reason
;
255 PurplePounceEvent events
= PURPLE_POUNCE_NONE
;
256 PurplePounceOption options
= PURPLE_POUNCE_OPTION_NONE
;
258 name
= gtk_entry_get_text(GTK_ENTRY(dialog
->buddy_entry
));
262 purple_notify_error(NULL
, NULL
, _("Please enter a buddy to "
263 "pounce."), NULL
, NULL
);
268 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->on_away
)))
269 options
|= PURPLE_POUNCE_OPTION_AWAY
;
272 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->signon
)))
273 events
|= PURPLE_POUNCE_SIGNON
;
275 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->signoff
)))
276 events
|= PURPLE_POUNCE_SIGNOFF
;
278 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->away
)))
279 events
|= PURPLE_POUNCE_AWAY
;
281 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->away_return
)))
282 events
|= PURPLE_POUNCE_AWAY_RETURN
;
284 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->idle
)))
285 events
|= PURPLE_POUNCE_IDLE
;
287 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->idle_return
)))
288 events
|= PURPLE_POUNCE_IDLE_RETURN
;
290 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->typing
)))
291 events
|= PURPLE_POUNCE_TYPING
;
293 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->typed
)))
294 events
|= PURPLE_POUNCE_TYPED
;
296 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->stop_typing
)))
297 events
|= PURPLE_POUNCE_TYPING_STOPPED
;
299 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->message_recv
)))
300 events
|= PURPLE_POUNCE_MESSAGE_RECEIVED
;
303 message
= pidgin_webview_get_body_html(PIDGIN_WEBVIEW(dialog
->send_msg_entry
));
304 command
= gtk_entry_get_text(GTK_ENTRY(dialog
->exec_cmd_entry
));
305 sound
= gtk_entry_get_text(GTK_ENTRY(dialog
->play_sound_entry
));
306 reason
= gtk_entry_get_text(GTK_ENTRY(dialog
->popup_entry
));
308 if (*reason
== '\0') reason
= NULL
;
309 if (*message
== '\0') {
313 if (*command
== '\0') command
= NULL
;
314 if (*sound
== '\0' || !strcmp(sound
, _("(default)"))) sound
= NULL
;
316 /* If the pounce has already been triggered, let's pretend it is a new one */
317 if (dialog
->pounce
!= NULL
318 && g_list_find(purple_pounces_get_all(), dialog
->pounce
) == NULL
) {
319 purple_debug_info("gtkpounce", "Saving pounce that no longer exists; creating new pounce.\n");
320 dialog
->pounce
= NULL
;
323 if (dialog
->pounce
== NULL
)
325 dialog
->pounce
= purple_pounce_new(PIDGIN_UI
, dialog
->account
,
326 name
, events
, options
);
329 purple_pounce_set_events(dialog
->pounce
, events
);
330 purple_pounce_set_options(dialog
->pounce
, options
);
331 purple_pounce_set_pouncer(dialog
->pounce
, dialog
->account
);
332 purple_pounce_set_pouncee(dialog
->pounce
, name
);
336 purple_pounce_action_set_enabled(dialog
->pounce
, "open-window",
337 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->open_win
)));
338 purple_pounce_action_set_enabled(dialog
->pounce
, "popup-notify",
339 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->popup
)));
340 purple_pounce_action_set_enabled(dialog
->pounce
, "send-message",
341 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
)));
342 purple_pounce_action_set_enabled(dialog
->pounce
, "execute-command",
343 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
)));
344 purple_pounce_action_set_enabled(dialog
->pounce
, "play-sound",
345 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
)));
347 purple_pounce_action_set_attribute(dialog
->pounce
, "send-message",
349 purple_pounce_action_set_attribute(dialog
->pounce
, "execute-command",
351 purple_pounce_action_set_attribute(dialog
->pounce
, "play-sound",
353 purple_pounce_action_set_attribute(dialog
->pounce
, "popup-notify",
356 /* Set the defaults for next time. */
357 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/open-window",
358 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->open_win
)));
359 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/popup-notify",
360 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->popup
)));
361 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/send-message",
362 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
)));
363 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/execute-command",
364 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
)));
365 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/play-sound",
366 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
)));
368 purple_pounce_set_save(dialog
->pounce
,
369 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->save_pounce
)));
374 delete_win_cb(NULL
, NULL
, dialog
);
378 entry_key_press_cb(GtkWidget
*widget
, GdkEventKey
*event
,
379 PidginPounceDialog
*dialog
)
381 if ((event
->keyval
== GDK_KEY_Return
)
382 || (event
->keyval
== GDK_KEY_KP_Enter
)) {
383 save_pounce_cb(widget
, dialog
);
391 pounce_choose_cb(GtkWidget
*item
, PurpleAccount
*account
,
392 PidginPounceDialog
*dialog
)
394 dialog
->account
= account
;
398 buddy_changed_cb(GtkEntry
*entry
, PidginPounceDialog
*dialog
)
400 if (dialog
->save_button
== NULL
)
403 gtk_widget_set_sensitive(dialog
->save_button
,
404 *gtk_entry_get_text(entry
) != '\0');
408 message_recv_toggle(GtkButton
*message_recv
, GtkWidget
*send_msg
)
410 gboolean active
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(message_recv
));
412 gtk_widget_set_sensitive(send_msg
, !active
);
414 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(send_msg
), FALSE
);
418 pounce_dnd_recv(GtkWidget
*widget
, GdkDragContext
*dc
, gint x
, gint y
,
419 GtkSelectionData
*sd
, guint info
, guint t
, gpointer data
)
421 PidginPounceDialog
*dialog
;
422 GdkAtom target
= gtk_selection_data_get_target(sd
);
423 const guchar
*sd_data
= gtk_selection_data_get_data(sd
);
425 if (target
== gdk_atom_intern("PURPLE_BLIST_NODE", FALSE
))
427 PurpleBlistNode
*node
= NULL
;
430 memcpy(&node
, sd_data
, sizeof(node
));
432 if (PURPLE_IS_CONTACT(node
))
433 buddy
= purple_contact_get_priority_buddy((PurpleContact
*)node
);
434 else if (PURPLE_IS_BUDDY(node
))
435 buddy
= (PurpleBuddy
*)node
;
439 dialog
= (PidginPounceDialog
*)data
;
441 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
), purple_buddy_get_name(buddy
));
442 dialog
->account
= purple_buddy_get_account(buddy
);
443 pidgin_account_option_menu_set_selected(dialog
->account_menu
, purple_buddy_get_account(buddy
));
445 gtk_drag_finish(dc
, TRUE
, (gdk_drag_context_get_actions(dc
) == GDK_ACTION_MOVE
), t
);
447 else if (target
== gdk_atom_intern("application/x-im-contact", FALSE
))
449 char *protocol
= NULL
;
450 char *username
= NULL
;
451 PurpleAccount
*account
;
453 if (pidgin_parse_x_im_contact((const char *)sd_data
, FALSE
, &account
,
454 &protocol
, &username
, NULL
))
458 purple_notify_error(NULL
, NULL
,
459 _("You are not currently signed on with an account that "
460 "can add that buddy."), NULL
, NULL
);
464 dialog
= (PidginPounceDialog
*)data
;
466 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
), username
);
467 dialog
->account
= account
;
468 pidgin_account_option_menu_set_selected(dialog
->account_menu
, account
);
475 gtk_drag_finish(dc
, TRUE
, (gdk_drag_context_get_actions(dc
) == GDK_ACTION_MOVE
), t
);
479 static const GtkTargetEntry dnd_targets
[] =
481 {"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP
, 0},
482 {"application/x-im-contact", 0, 1}
486 reset_send_msg_entry(PidginPounceDialog
*dialog
, GtkWidget
*dontcare
)
488 PurpleAccount
*account
= pidgin_account_option_menu_get_selected(dialog
->account_menu
);
489 pidgin_webview_setup_entry(PIDGIN_WEBVIEW(dialog
->send_msg_entry
),
490 (account
&& purple_account_get_connection(account
)) ? purple_connection_get_flags(purple_account_get_connection(account
)) : PURPLE_CONNECTION_FLAG_HTML
);
494 pidgin_pounce_editor_show(PurpleAccount
*account
, const char *name
,
495 PurplePounce
*cur_pounce
)
497 PidginPounceDialog
*dialog
;
500 GtkWidget
*vbox1
, *vbox2
;
506 GPtrArray
*sound_widgets
;
507 GPtrArray
*exec_widgets
;
508 GtkWidget
*send_msg_webview
;
510 g_return_if_fail((cur_pounce
!= NULL
) ||
512 (purple_accounts_get_all() != NULL
));
514 dialog
= g_new0(PidginPounceDialog
, 1);
516 if (cur_pounce
!= NULL
)
518 dialog
->pounce
= cur_pounce
;
519 dialog
->account
= purple_pounce_get_pouncer(cur_pounce
);
521 else if (account
!= NULL
)
523 dialog
->pounce
= NULL
;
524 dialog
->account
= account
;
528 GList
*connections
= purple_connections_get_all();
529 PurpleConnection
*gc
;
531 if (connections
!= NULL
)
533 gc
= (PurpleConnection
*)connections
->data
;
534 dialog
->account
= purple_connection_get_account(gc
);
537 dialog
->account
= purple_accounts_get_all()->data
;
539 dialog
->pounce
= NULL
;
542 sg
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
544 /* Create the window. */
545 dialog
->window
= window
= gtk_dialog_new();
546 gtk_window_set_title(GTK_WINDOW(window
), (cur_pounce
== NULL
? _("Add Buddy Pounce") : _("Modify Buddy Pounce")));
547 gtk_window_set_role(GTK_WINDOW(window
), "buddy_pounce");
549 g_signal_connect(G_OBJECT(window
), "delete_event",
550 G_CALLBACK(delete_win_cb
), dialog
);
552 /* Get the parent vbox for everything. */
553 vbox1
= gtk_dialog_get_content_area(GTK_DIALOG(window
));
555 /* Create the vbox that will contain all the prefs stuff. */
556 vbox2
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, PIDGIN_HIG_BOX_SPACE
);
557 gtk_box_pack_start(GTK_BOX(vbox1
), vbox2
, TRUE
, TRUE
, 0);
559 /* Create the "Pounce on Whom" frame. */
560 frame
= pidgin_make_frame(vbox2
, _("Pounce on Whom"));
563 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, PIDGIN_HIG_BOX_SPACE
);
564 gtk_box_pack_start(GTK_BOX(frame
), hbox
, FALSE
, FALSE
, 0);
565 gtk_widget_show(hbox
);
567 label
= gtk_label_new_with_mnemonic(_("_Account:"));
568 gtk_label_set_xalign(GTK_LABEL(label
), 0);
569 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
570 gtk_widget_show(label
);
571 gtk_size_group_add_widget(sg
, label
);
573 dialog
->account_menu
=
574 pidgin_account_option_menu_new(dialog
->account
, TRUE
,
575 G_CALLBACK(pounce_choose_cb
),
578 gtk_box_pack_start(GTK_BOX(hbox
), dialog
->account_menu
, FALSE
, FALSE
, 0);
579 gtk_widget_show(dialog
->account_menu
);
580 pidgin_set_accessible_label(dialog
->account_menu
, GTK_LABEL(label
));
583 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, PIDGIN_HIG_BOX_SPACE
);
584 gtk_box_pack_start(GTK_BOX(frame
), hbox
, FALSE
, FALSE
, 0);
585 gtk_widget_show(hbox
);
587 label
= gtk_label_new_with_mnemonic(_("_Buddy name:"));
588 gtk_label_set_xalign(GTK_LABEL(label
), 0);
589 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
590 gtk_widget_show(label
);
591 gtk_size_group_add_widget(sg
, label
);
593 dialog
->buddy_entry
= gtk_entry_new();
595 pidgin_setup_screenname_autocomplete(dialog
->buddy_entry
, dialog
->account_menu
, pidgin_screenname_autocomplete_default_filter
, GINT_TO_POINTER(FALSE
));
597 gtk_box_pack_start(GTK_BOX(hbox
), dialog
->buddy_entry
, TRUE
, TRUE
, 0);
598 gtk_widget_show(dialog
->buddy_entry
);
600 g_signal_connect(G_OBJECT(dialog
->buddy_entry
), "changed",
601 G_CALLBACK(buddy_changed_cb
), dialog
);
602 pidgin_set_accessible_label(dialog
->buddy_entry
, GTK_LABEL(label
));
604 if (cur_pounce
!= NULL
) {
605 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
),
606 purple_pounce_get_pouncee(cur_pounce
));
608 else if (name
!= NULL
) {
609 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
), name
);
612 /* Create the "Pounce When Buddy..." frame. */
613 frame
= pidgin_make_frame(vbox2
, _("Pounce When Buddy..."));
615 grid
= gtk_grid_new();
616 gtk_container_add(GTK_CONTAINER(frame
), grid
);
617 gtk_grid_set_column_spacing(GTK_GRID(grid
), PIDGIN_HIG_BORDER
);
618 gtk_widget_show(grid
);
621 gtk_check_button_new_with_mnemonic(_("Si_gns on"));
623 gtk_check_button_new_with_mnemonic(_("Signs o_ff"));
625 gtk_check_button_new_with_mnemonic(_("Goes a_way"));
626 dialog
->away_return
=
627 gtk_check_button_new_with_mnemonic(_("Ret_urns from away"));
629 gtk_check_button_new_with_mnemonic(_("Becomes _idle"));
630 dialog
->idle_return
=
631 gtk_check_button_new_with_mnemonic(_("Is no longer i_dle"));
633 gtk_check_button_new_with_mnemonic(_("Starts _typing"));
635 gtk_check_button_new_with_mnemonic(_("P_auses while typing"));
636 dialog
->stop_typing
=
637 gtk_check_button_new_with_mnemonic(_("Stops t_yping"));
638 dialog
->message_recv
=
639 gtk_check_button_new_with_mnemonic(_("Sends a _message"));
641 gtk_widget_set_valign(dialog
->message_recv
, GTK_ALIGN_CENTER
);
642 gtk_widget_set_valign(dialog
->signon
, GTK_ALIGN_CENTER
);
643 gtk_widget_set_valign(dialog
->signoff
, GTK_ALIGN_CENTER
);
644 gtk_widget_set_valign(dialog
->away
, GTK_ALIGN_CENTER
);
645 gtk_widget_set_valign(dialog
->away_return
, GTK_ALIGN_CENTER
);
646 gtk_widget_set_valign(dialog
->idle
, GTK_ALIGN_CENTER
);
647 gtk_widget_set_valign(dialog
->idle_return
, GTK_ALIGN_CENTER
);
648 gtk_widget_set_valign(dialog
->typing
, GTK_ALIGN_CENTER
);
649 gtk_widget_set_valign(dialog
->typed
, GTK_ALIGN_CENTER
);
650 gtk_widget_set_valign(dialog
->stop_typing
, GTK_ALIGN_CENTER
);
652 gtk_grid_attach(GTK_GRID(grid
), dialog
->message_recv
, 0, 0, 1, 1);
653 gtk_grid_attach(GTK_GRID(grid
), dialog
->signon
, 0, 1, 1, 1);
654 gtk_grid_attach(GTK_GRID(grid
), dialog
->signoff
, 0, 2, 1, 1);
655 gtk_grid_attach(GTK_GRID(grid
), dialog
->away
, 1, 0, 1, 1);
656 gtk_grid_attach(GTK_GRID(grid
), dialog
->away_return
, 1, 1, 1, 1);
657 gtk_grid_attach(GTK_GRID(grid
), dialog
->idle
, 1, 2, 1, 1);
658 gtk_grid_attach(GTK_GRID(grid
), dialog
->idle_return
, 2, 0, 1, 1);
659 gtk_grid_attach(GTK_GRID(grid
), dialog
->typing
, 2, 1, 1, 1);
660 gtk_grid_attach(GTK_GRID(grid
), dialog
->typed
, 2, 2, 1, 1);
661 gtk_grid_attach(GTK_GRID(grid
), dialog
->stop_typing
, 3, 0, 1, 1);
663 gtk_widget_show(dialog
->signon
);
664 gtk_widget_show(dialog
->signoff
);
665 gtk_widget_show(dialog
->away
);
666 gtk_widget_show(dialog
->away_return
);
667 gtk_widget_show(dialog
->idle
);
668 gtk_widget_show(dialog
->idle_return
);
669 gtk_widget_show(dialog
->typing
);
670 gtk_widget_show(dialog
->typed
);
671 gtk_widget_show(dialog
->stop_typing
);
672 gtk_widget_show(dialog
->message_recv
);
674 /* Create the "Action" frame. */
675 frame
= pidgin_make_frame(vbox2
, _("Action"));
677 grid
= gtk_grid_new();
678 gtk_container_add(GTK_CONTAINER(frame
), grid
);
679 gtk_grid_set_column_spacing(GTK_GRID(grid
), PIDGIN_HIG_BORDER
);
680 gtk_widget_show(grid
);
683 = gtk_check_button_new_with_mnemonic(_("Ope_n an IM window"));
685 = gtk_check_button_new_with_mnemonic(_("_Pop up a notification"));
687 = gtk_check_button_new_with_mnemonic(_("Send a _message"));
689 = gtk_check_button_new_with_mnemonic(_("E_xecute a command"));
691 = gtk_check_button_new_with_mnemonic(_("P_lay a sound"));
693 send_msg_webview
= pidgin_create_webview(TRUE
, &dialog
->send_msg_entry
, NULL
);
694 reset_send_msg_entry(dialog
, NULL
);
695 dialog
->exec_cmd_entry
= gtk_entry_new();
696 dialog
->popup_entry
= gtk_entry_new();
697 dialog
->exec_cmd_browse
= gtk_button_new_with_mnemonic(_("Brows_e..."));
698 dialog
->play_sound_entry
= gtk_entry_new();
699 gtk_entry_set_text(GTK_ENTRY(dialog
->play_sound_entry
), _("(default)"));
700 gtk_editable_set_editable(GTK_EDITABLE(dialog
->play_sound_entry
), FALSE
);
701 dialog
->play_sound_browse
= gtk_button_new_with_mnemonic(_("Br_owse..."));
702 dialog
->play_sound_test
= gtk_button_new_with_mnemonic(_("Pre_view"));
703 dialog
->play_sound_reset
= gtk_button_new_with_mnemonic(_("Reset"));
705 gtk_widget_set_sensitive(send_msg_webview
, FALSE
);
706 gtk_widget_set_sensitive(dialog
->exec_cmd_entry
, FALSE
);
707 gtk_widget_set_sensitive(dialog
->popup_entry
, FALSE
);
708 gtk_widget_set_sensitive(dialog
->exec_cmd_browse
, FALSE
);
709 gtk_widget_set_sensitive(dialog
->play_sound_entry
, FALSE
);
710 gtk_widget_set_sensitive(dialog
->play_sound_browse
, FALSE
);
711 gtk_widget_set_sensitive(dialog
->play_sound_test
, FALSE
);
712 gtk_widget_set_sensitive(dialog
->play_sound_reset
, FALSE
);
716 sg
= gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL
);
717 gtk_size_group_add_widget(sg
, dialog
->open_win
);
718 gtk_size_group_add_widget(sg
, dialog
->popup
);
719 gtk_size_group_add_widget(sg
, dialog
->popup_entry
);
720 gtk_size_group_add_widget(sg
, dialog
->exec_cmd
);
721 gtk_size_group_add_widget(sg
, dialog
->exec_cmd_entry
);
722 gtk_size_group_add_widget(sg
, dialog
->exec_cmd_browse
);
723 gtk_size_group_add_widget(sg
, dialog
->play_sound
);
724 gtk_size_group_add_widget(sg
, dialog
->play_sound_entry
);
725 gtk_size_group_add_widget(sg
, dialog
->play_sound_browse
);
726 gtk_size_group_add_widget(sg
, dialog
->play_sound_test
);
727 gtk_size_group_add_widget(sg
, dialog
->play_sound_reset
);
732 gtk_widget_set_valign(dialog
->open_win
, GTK_ALIGN_CENTER
);
733 gtk_widget_set_valign(dialog
->popup
, GTK_ALIGN_CENTER
);
734 gtk_widget_set_valign(dialog
->popup_entry
, GTK_ALIGN_CENTER
);
735 gtk_widget_set_valign(dialog
->send_msg
, GTK_ALIGN_CENTER
);
736 gtk_widget_set_valign(send_msg_webview
, GTK_ALIGN_CENTER
);
737 gtk_widget_set_valign(dialog
->exec_cmd
, GTK_ALIGN_CENTER
);
738 gtk_widget_set_valign(dialog
->exec_cmd_entry
, GTK_ALIGN_CENTER
);
739 gtk_widget_set_hexpand(dialog
->exec_cmd_browse
, TRUE
);
740 gtk_widget_set_valign(dialog
->exec_cmd_browse
, GTK_ALIGN_CENTER
);
741 gtk_widget_set_valign(dialog
->play_sound
, GTK_ALIGN_CENTER
);
742 gtk_widget_set_valign(dialog
->play_sound_entry
, GTK_ALIGN_CENTER
);
743 gtk_widget_set_hexpand(dialog
->play_sound_browse
, TRUE
);
744 gtk_widget_set_valign(dialog
->play_sound_browse
, GTK_ALIGN_CENTER
);
745 gtk_widget_set_hexpand(dialog
->play_sound_test
, TRUE
);
746 gtk_widget_set_valign(dialog
->play_sound_test
, GTK_ALIGN_CENTER
);
747 gtk_widget_set_hexpand(dialog
->play_sound_reset
, TRUE
);
748 gtk_widget_set_valign(dialog
->play_sound_reset
, GTK_ALIGN_CENTER
);
750 gtk_grid_attach(GTK_GRID(grid
), dialog
->open_win
, 0, 0, 1, 1);
751 gtk_grid_attach(GTK_GRID(grid
), dialog
->popup
, 0, 1, 1, 1);
752 gtk_grid_attach(GTK_GRID(grid
), dialog
->popup_entry
, 1, 1, 4, 1);
753 gtk_grid_attach(GTK_GRID(grid
), dialog
->send_msg
, 0, 2, 5, 1);
754 gtk_grid_attach(GTK_GRID(grid
), send_msg_webview
, 0, 3, 5, 1);
755 gtk_grid_attach(GTK_GRID(grid
), dialog
->exec_cmd
, 0, 4, 1, 1);
756 gtk_grid_attach(GTK_GRID(grid
), dialog
->exec_cmd_entry
, 1, 4, 1, 1);
757 gtk_grid_attach(GTK_GRID(grid
), dialog
->exec_cmd_browse
, 2, 4, 1, 1);
758 gtk_grid_attach(GTK_GRID(grid
), dialog
->play_sound
, 0, 5, 1, 1);
759 gtk_grid_attach(GTK_GRID(grid
), dialog
->play_sound_entry
, 1, 5, 1, 1);
760 gtk_grid_attach(GTK_GRID(grid
), dialog
->play_sound_browse
,2, 5, 1, 1);
761 gtk_grid_attach(GTK_GRID(grid
), dialog
->play_sound_test
, 3, 5, 1, 1);
762 gtk_grid_attach(GTK_GRID(grid
), dialog
->play_sound_reset
, 4, 5, 1, 1);
764 gtk_grid_set_row_spacing(GTK_GRID(grid
), PIDGIN_HIG_BOX_SPACE
/ 2);
766 gtk_widget_show(dialog
->open_win
);
767 gtk_widget_show(dialog
->popup
);
768 gtk_widget_show(dialog
->popup_entry
);
769 gtk_widget_show(dialog
->send_msg
);
770 gtk_widget_show(send_msg_webview
);
771 gtk_widget_show(dialog
->exec_cmd
);
772 gtk_widget_show(dialog
->exec_cmd_entry
);
773 gtk_widget_show(dialog
->exec_cmd_browse
);
774 gtk_widget_show(dialog
->play_sound
);
775 gtk_widget_show(dialog
->play_sound_entry
);
776 gtk_widget_show(dialog
->play_sound_browse
);
777 gtk_widget_show(dialog
->play_sound_test
);
778 gtk_widget_show(dialog
->play_sound_reset
);
780 g_signal_connect(G_OBJECT(dialog
->message_recv
), "clicked",
781 G_CALLBACK(message_recv_toggle
),
784 g_signal_connect(G_OBJECT(dialog
->send_msg
), "clicked",
785 G_CALLBACK(pidgin_toggle_sensitive
),
788 g_signal_connect(G_OBJECT(dialog
->popup
), "clicked",
789 G_CALLBACK(pidgin_toggle_sensitive
),
790 dialog
->popup_entry
);
792 exec_widgets
= g_ptr_array_new();
793 g_ptr_array_add(exec_widgets
,dialog
->exec_cmd_entry
);
794 g_ptr_array_add(exec_widgets
,dialog
->exec_cmd_browse
);
796 g_signal_connect(G_OBJECT(dialog
->exec_cmd
), "clicked",
797 G_CALLBACK(pidgin_toggle_sensitive_array
),
799 g_signal_connect(G_OBJECT(dialog
->exec_cmd_browse
), "clicked",
801 dialog
->exec_cmd_entry
);
802 g_object_set_data_full(G_OBJECT(dialog
->window
), "exec-widgets",
803 exec_widgets
, (GDestroyNotify
)g_ptr_array_free
);
805 sound_widgets
= g_ptr_array_new();
806 g_ptr_array_add(sound_widgets
,dialog
->play_sound_entry
);
807 g_ptr_array_add(sound_widgets
,dialog
->play_sound_browse
);
808 g_ptr_array_add(sound_widgets
,dialog
->play_sound_test
);
809 g_ptr_array_add(sound_widgets
,dialog
->play_sound_reset
);
811 g_signal_connect(G_OBJECT(dialog
->play_sound
), "clicked",
812 G_CALLBACK(pidgin_toggle_sensitive_array
),
814 g_signal_connect(G_OBJECT(dialog
->play_sound_browse
), "clicked",
816 dialog
->play_sound_entry
);
817 g_signal_connect(G_OBJECT(dialog
->play_sound_test
), "clicked",
818 G_CALLBACK(pounce_test_sound
),
819 dialog
->play_sound_entry
);
820 g_signal_connect(G_OBJECT(dialog
->play_sound_reset
), "clicked",
821 G_CALLBACK(pounce_reset_sound
),
822 dialog
->play_sound_entry
);
823 g_object_set_data_full(G_OBJECT(dialog
->window
), "sound-widgets",
824 sound_widgets
, (GDestroyNotify
)g_ptr_array_free
);
826 g_signal_connect_swapped(G_OBJECT(dialog
->send_msg_entry
), "format-cleared",
827 G_CALLBACK(reset_send_msg_entry
), dialog
);
828 g_signal_connect_swapped(G_OBJECT(dialog
->account_menu
), "changed",
829 G_CALLBACK(reset_send_msg_entry
), dialog
);
831 g_signal_connect(G_OBJECT(dialog
->send_msg_entry
), "key-press-event",
832 G_CALLBACK(entry_key_press_cb
), dialog
);
833 g_signal_connect(G_OBJECT(dialog
->popup_entry
), "activate",
834 G_CALLBACK(save_pounce_cb
), dialog
);
835 g_signal_connect(G_OBJECT(dialog
->exec_cmd_entry
), "activate",
836 G_CALLBACK(save_pounce_cb
), dialog
);
838 /* Create the "Options" frame. */
839 frame
= pidgin_make_frame(vbox2
, _("Options"));
841 grid
= gtk_grid_new();
842 gtk_container_add(GTK_CONTAINER(frame
), grid
);
843 gtk_grid_set_column_spacing(GTK_GRID(grid
), PIDGIN_HIG_BORDER
);
844 gtk_widget_show(grid
);
847 gtk_check_button_new_with_mnemonic(_("P_ounce only when my status is not Available"));
848 gtk_widget_set_valign(dialog
->on_away
, GTK_ALIGN_CENTER
);
849 gtk_grid_attach(GTK_GRID(grid
), dialog
->on_away
, 0, 0, 1, 1);
851 dialog
->save_pounce
= gtk_check_button_new_with_mnemonic(
853 gtk_widget_set_valign(dialog
->save_pounce
, GTK_ALIGN_CENTER
);
854 gtk_grid_attach(GTK_GRID(grid
), dialog
->save_pounce
, 0, 1, 1, 1);
856 gtk_widget_show(dialog
->on_away
);
857 gtk_widget_show(dialog
->save_pounce
);
860 button
= gtk_dialog_add_button(GTK_DIALOG(window
), GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
);
861 g_signal_connect(G_OBJECT(button
), "clicked",
862 G_CALLBACK(cancel_cb
), dialog
);
864 /* Save/Add button */
865 dialog
->save_button
= button
= gtk_dialog_add_button(GTK_DIALOG(window
),
866 (cur_pounce
== NULL
? GTK_STOCK_ADD
: GTK_STOCK_SAVE
),
868 g_signal_connect(G_OBJECT(button
), "clicked",
869 G_CALLBACK(save_pounce_cb
), dialog
);
871 if (*gtk_entry_get_text(GTK_ENTRY(dialog
->buddy_entry
)) == '\0')
872 gtk_widget_set_sensitive(button
, FALSE
);
874 /* Setup drag-and-drop */
875 gtk_drag_dest_set(window
,
876 GTK_DEST_DEFAULT_MOTION
|
877 GTK_DEST_DEFAULT_DROP
,
879 sizeof(dnd_targets
) / sizeof(GtkTargetEntry
),
881 gtk_drag_dest_set(dialog
->buddy_entry
,
882 GTK_DEST_DEFAULT_MOTION
|
883 GTK_DEST_DEFAULT_DROP
,
885 sizeof(dnd_targets
) / sizeof(GtkTargetEntry
),
888 g_signal_connect(G_OBJECT(window
), "drag_data_received",
889 G_CALLBACK(pounce_dnd_recv
), dialog
);
890 g_signal_connect(G_OBJECT(dialog
->buddy_entry
), "drag_data_received",
891 G_CALLBACK(pounce_dnd_recv
), dialog
);
893 /* Set the values of stuff. */
894 if (cur_pounce
!= NULL
)
896 PurplePounceEvent events
= purple_pounce_get_events(cur_pounce
);
897 PurplePounceOption options
= purple_pounce_get_options(cur_pounce
);
901 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->on_away
),
902 (options
& PURPLE_POUNCE_OPTION_AWAY
));
905 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->signon
),
906 (events
& PURPLE_POUNCE_SIGNON
));
907 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->signoff
),
908 (events
& PURPLE_POUNCE_SIGNOFF
));
909 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->away
),
910 (events
& PURPLE_POUNCE_AWAY
));
911 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->away_return
),
912 (events
& PURPLE_POUNCE_AWAY_RETURN
));
913 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->idle
),
914 (events
& PURPLE_POUNCE_IDLE
));
915 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->idle_return
),
916 (events
& PURPLE_POUNCE_IDLE_RETURN
));
917 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->typing
),
918 (events
& PURPLE_POUNCE_TYPING
));
919 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->typed
),
920 (events
& PURPLE_POUNCE_TYPED
));
921 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->stop_typing
),
922 (events
& PURPLE_POUNCE_TYPING_STOPPED
));
923 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->message_recv
),
924 (events
& PURPLE_POUNCE_MESSAGE_RECEIVED
));
927 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->open_win
),
928 purple_pounce_action_is_enabled(cur_pounce
, "open-window"));
929 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->popup
),
930 purple_pounce_action_is_enabled(cur_pounce
, "popup-notify"));
931 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
),
932 purple_pounce_action_is_enabled(cur_pounce
, "send-message"));
933 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
),
934 purple_pounce_action_is_enabled(cur_pounce
, "execute-command"));
935 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
),
936 purple_pounce_action_is_enabled(cur_pounce
, "play-sound"));
938 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->save_pounce
),
939 purple_pounce_get_save(cur_pounce
));
941 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
945 pidgin_webview_append_html(PIDGIN_WEBVIEW(dialog
->send_msg_entry
), value
);
948 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
952 gtk_entry_set_text(GTK_ENTRY(dialog
->popup_entry
), value
);
955 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
959 gtk_entry_set_text(GTK_ENTRY(dialog
->exec_cmd_entry
), value
);
962 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
964 "filename")) != NULL
)
966 gtk_entry_set_text(GTK_ENTRY(dialog
->play_sound_entry
), (value
&& *value
!= '\0') ? value
: _("(default)"));
971 PurpleBuddy
*buddy
= NULL
;
974 buddy
= purple_blist_find_buddy(account
, name
);
976 /* Set some defaults */
979 gtk_toggle_button_set_active(
980 GTK_TOGGLE_BUTTON(dialog
->signon
), TRUE
);
984 if (!PURPLE_BUDDY_IS_ONLINE(buddy
))
986 gtk_toggle_button_set_active(
987 GTK_TOGGLE_BUTTON(dialog
->signon
), TRUE
);
991 gboolean default_set
= FALSE
;
992 PurplePresence
*presence
= purple_buddy_get_presence(buddy
);
994 if (purple_presence_is_idle(presence
))
996 gtk_toggle_button_set_active(
997 GTK_TOGGLE_BUTTON(dialog
->idle_return
), TRUE
);
1002 if (!purple_presence_is_available(presence
))
1004 gtk_toggle_button_set_active(
1005 GTK_TOGGLE_BUTTON(dialog
->away_return
), TRUE
);
1012 gtk_toggle_button_set_active(
1013 GTK_TOGGLE_BUTTON(dialog
->signon
), TRUE
);
1018 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->open_win
),
1019 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/open-window"));
1020 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->popup
),
1021 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/popup-notify"));
1022 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
),
1023 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/send-message"));
1024 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
),
1025 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/execute-command"));
1026 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
),
1027 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/play-sound"));
1030 gtk_widget_show(vbox2
);
1031 gtk_widget_show(window
);
1035 pounces_manager_configure_cb(GtkWidget
*widget
, GdkEventConfigure
*event
, PouncesManager
*dialog
)
1037 if (gtk_widget_get_visible(widget
)) {
1038 purple_prefs_set_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/width", event
->width
);
1039 purple_prefs_set_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/height", event
->height
);
1046 pounces_manager_find_pounce(GtkTreeIter
*iter
, PurplePounce
*pounce
)
1048 GtkTreeModel
*model
= GTK_TREE_MODEL(pounces_manager
->model
);
1051 if (!gtk_tree_model_get_iter_first(model
, iter
))
1054 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &p
, -1);
1058 while (gtk_tree_model_iter_next(model
, iter
))
1060 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &p
, -1);
1069 pounces_manager_destroy_cb(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
)
1071 PouncesManager
*dialog
= user_data
;
1073 dialog
->window
= NULL
;
1074 pidgin_pounces_manager_hide();
1080 pounces_manager_connection_cb(PurpleConnection
*gc
, GtkWidget
*add_button
)
1082 gtk_widget_set_sensitive(add_button
, (purple_connections_get_all() != NULL
));
1086 pounces_manager_add_cb(GtkButton
*button
, gpointer user_data
)
1088 pidgin_pounce_editor_show(NULL
, NULL
, NULL
);
1092 pounces_manager_modify_foreach(GtkTreeModel
*model
, GtkTreePath
*path
,
1093 GtkTreeIter
*iter
, gpointer user_data
)
1095 PurplePounce
*pounce
;
1097 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
, -1);
1098 pidgin_pounce_editor_show(NULL
, NULL
, pounce
);
1102 pounces_manager_modify_cb(GtkButton
*button
, gpointer user_data
)
1104 PouncesManager
*dialog
= user_data
;
1105 GtkTreeSelection
*selection
;
1107 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->treeview
));
1109 gtk_tree_selection_selected_foreach(selection
, pounces_manager_modify_foreach
, user_data
);
1113 pounces_manager_delete_confirm_cb(PurplePounce
*pounce
)
1117 if (pounces_manager
&& pounces_manager_find_pounce(&iter
, pounce
))
1118 gtk_list_store_remove(pounces_manager
->model
, &iter
);
1120 purple_request_close_with_handle(pounce
);
1121 purple_pounce_destroy(pounce
);
1125 pounces_manager_delete_foreach(GtkTreeModel
*model
, GtkTreePath
*path
,
1126 GtkTreeIter
*iter
, gpointer user_data
)
1128 PurplePounce
*pounce
;
1129 PurpleAccount
*account
;
1130 const char *pouncer
, *pouncee
;
1133 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
, -1);
1134 account
= purple_pounce_get_pouncer(pounce
);
1135 pouncer
= purple_account_get_username(account
);
1136 pouncee
= purple_pounce_get_pouncee(pounce
);
1138 buf
= g_strdup_printf(_("Are you sure you want to delete the pounce on %s for %s?"), pouncee
, pouncer
);
1139 purple_request_action(pounce
, NULL
, buf
, NULL
, 0,
1140 purple_request_cpar_from_account(account
),
1141 pounce
, 2, _("Delete"), pounces_manager_delete_confirm_cb
,
1147 pounces_manager_delete_cb(GtkButton
*button
, gpointer user_data
)
1149 PouncesManager
*dialog
= user_data
;
1150 GtkTreeSelection
*selection
;
1152 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->treeview
));
1154 gtk_tree_selection_selected_foreach(selection
, pounces_manager_delete_foreach
, user_data
);
1158 pounces_manager_close_cb(GtkButton
*button
, gpointer user_data
)
1160 pidgin_pounces_manager_hide();
1164 pounce_selected_cb(GtkTreeSelection
*sel
, gpointer user_data
)
1166 PouncesManager
*dialog
= user_data
;
1167 int num_selected
= 0;
1169 num_selected
= gtk_tree_selection_count_selected_rows(sel
);
1171 gtk_widget_set_sensitive(dialog
->modify_button
, (num_selected
> 0));
1172 gtk_widget_set_sensitive(dialog
->delete_button
, (num_selected
> 0));
1176 pounce_double_click_cb(GtkTreeView
*treeview
, GdkEventButton
*event
, gpointer user_data
)
1178 PouncesManager
*dialog
= user_data
;
1181 PurplePounce
*pounce
;
1183 /* Figure out which node was clicked */
1184 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(dialog
->treeview
), event
->x
, event
->y
, &path
, NULL
, NULL
, NULL
))
1186 gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog
->model
), &iter
, path
);
1187 gtk_tree_path_free(path
);
1188 gtk_tree_model_get(GTK_TREE_MODEL(dialog
->model
), &iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
, -1);
1190 if ((pounce
!= NULL
) && (event
->button
== 1) &&
1191 (event
->type
== GDK_2BUTTON_PRESS
))
1193 pidgin_pounce_editor_show(NULL
, NULL
, pounce
);
1201 pounces_manager_recurring_cb(GtkCellRendererToggle
*renderer
, gchar
*path_str
,
1204 PouncesManager
*dialog
= user_data
;
1205 PurplePounce
*pounce
;
1207 GtkTreeModel
*model
= GTK_TREE_MODEL(dialog
->model
);
1210 gtk_tree_model_get_iter_from_string(model
, &iter
, path_str
);
1211 gtk_tree_model_get(model
, &iter
,
1212 POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
,
1213 POUNCES_MANAGER_COLUMN_RECURRING
, &recurring
,
1216 purple_pounce_set_save(pounce
, !recurring
);
1222 search_func(GtkTreeModel
*model
, gint column
, const gchar
*key
, GtkTreeIter
*iter
, gpointer search_data
)
1227 gtk_tree_model_get(model
, iter
, column
, &haystack
, -1);
1229 result
= (purple_strcasestr(haystack
, key
) == NULL
);
1237 create_pounces_list(PouncesManager
*dialog
)
1239 GtkWidget
*treeview
;
1240 GtkTreeSelection
*sel
;
1241 GtkTreeViewColumn
*column
;
1242 GtkCellRenderer
*renderer
;
1244 /* Create the list model */
1245 dialog
->model
= gtk_list_store_new(POUNCES_MANAGER_NUM_COLUMNS
,
1253 /* Create the treeview */
1254 treeview
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog
->model
));
1255 g_object_unref(G_OBJECT(dialog
->model
));
1256 dialog
->treeview
= treeview
;
1257 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview
), TRUE
);
1259 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
));
1260 gtk_tree_selection_set_mode(sel
, GTK_SELECTION_MULTIPLE
);
1261 g_signal_connect(G_OBJECT(sel
), "changed",
1262 G_CALLBACK(pounce_selected_cb
), dialog
);
1264 /* Handle double-clicking */
1265 g_signal_connect(G_OBJECT(treeview
), "button_press_event",
1266 G_CALLBACK(pounce_double_click_cb
), dialog
);
1267 gtk_widget_show(treeview
);
1269 /* Pouncee Column */
1270 column
= gtk_tree_view_column_new();
1271 gtk_tree_view_column_set_title(column
, _("Pounce Target"));
1272 gtk_tree_view_column_set_resizable(column
, TRUE
);
1273 gtk_tree_view_column_set_min_width(column
, 200);
1274 gtk_tree_view_column_set_sort_column_id(column
,
1275 POUNCES_MANAGER_COLUMN_TARGET
);
1276 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
1279 renderer
= gtk_cell_renderer_pixbuf_new();
1280 gtk_tree_view_column_pack_start(column
, renderer
, FALSE
);
1281 gtk_tree_view_column_add_attribute(column
, renderer
, "pixbuf",
1282 POUNCES_MANAGER_COLUMN_ICON
);
1285 renderer
= gtk_cell_renderer_text_new();
1286 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1287 gtk_tree_view_column_add_attribute(column
, renderer
, "text",
1288 POUNCES_MANAGER_COLUMN_TARGET
);
1291 /* Account Column */
1292 column
= gtk_tree_view_column_new();
1293 gtk_tree_view_column_set_title(column
, _("Account"));
1294 gtk_tree_view_column_set_resizable(column
, TRUE
);
1295 gtk_tree_view_column_set_min_width(column
, 200);
1296 gtk_tree_view_column_set_sort_column_id(column
,
1297 POUNCES_MANAGER_COLUMN_ACCOUNT
);
1298 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
1299 renderer
= gtk_cell_renderer_text_new();
1300 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1301 gtk_tree_view_column_add_attribute(column
, renderer
, "text",
1302 POUNCES_MANAGER_COLUMN_ACCOUNT
);
1304 /* Recurring Column */
1305 renderer
= gtk_cell_renderer_toggle_new();
1306 column
= gtk_tree_view_column_new_with_attributes(_("Recurring"), renderer
,
1307 "active", POUNCES_MANAGER_COLUMN_RECURRING
, NULL
);
1308 gtk_tree_view_column_set_sort_column_id(column
,
1309 POUNCES_MANAGER_COLUMN_RECURRING
);
1310 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
1311 g_signal_connect(G_OBJECT(renderer
), "toggled",
1312 G_CALLBACK(pounces_manager_recurring_cb
), dialog
);
1314 /* Enable CTRL+F searching */
1315 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview
), POUNCES_MANAGER_COLUMN_TARGET
);
1316 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(treeview
), search_func
, NULL
, NULL
);
1318 /* Sort the pouncee column by default */
1319 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog
->model
),
1320 POUNCES_MANAGER_COLUMN_TARGET
,
1321 GTK_SORT_ASCENDING
);
1324 populate_pounces_list(dialog
);
1326 return pidgin_make_scrollable(treeview
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
, GTK_SHADOW_IN
, -1, -1);
1330 pidgin_pounces_manager_show(void)
1332 PouncesManager
*dialog
;
1339 if (pounces_manager
!= NULL
) {
1340 gtk_window_present(GTK_WINDOW(pounces_manager
->window
));
1344 pounces_manager
= dialog
= g_new0(PouncesManager
, 1);
1346 width
= purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/width");
1347 height
= purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/height");
1349 dialog
->window
= win
= pidgin_create_dialog(_("Buddy Pounces"), 0, "pounces", TRUE
);
1351 gtk_window_set_default_size(GTK_WINDOW(win
), width
, height
);
1353 g_signal_connect(G_OBJECT(win
), "delete_event",
1354 G_CALLBACK(pounces_manager_destroy_cb
), dialog
);
1355 g_signal_connect(G_OBJECT(win
), "configure_event",
1356 G_CALLBACK(pounces_manager_configure_cb
), dialog
);
1358 /* Setup the vbox */
1359 vbox
= pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win
), FALSE
, PIDGIN_HIG_BORDER
);
1361 /* List of saved buddy pounces */
1362 list
= create_pounces_list(dialog
);
1363 gtk_box_pack_start(GTK_BOX(vbox
), list
, TRUE
, TRUE
, 0);
1366 button
= pidgin_dialog_add_button(GTK_DIALOG(win
), PIDGIN_STOCK_ADD
, G_CALLBACK(pounces_manager_add_cb
), dialog
);
1367 gtk_widget_set_sensitive(button
, (purple_accounts_get_all() != NULL
));
1369 purple_signal_connect(purple_connections_get_handle(), "signed-on",
1370 pounces_manager
, PURPLE_CALLBACK(pounces_manager_connection_cb
), button
);
1371 purple_signal_connect(purple_connections_get_handle(), "signed-off",
1372 pounces_manager
, PURPLE_CALLBACK(pounces_manager_connection_cb
), button
);
1375 button
= pidgin_dialog_add_button(GTK_DIALOG(win
), PIDGIN_STOCK_MODIFY
, G_CALLBACK(pounces_manager_modify_cb
), dialog
);
1376 gtk_widget_set_sensitive(button
, FALSE
);
1377 dialog
->modify_button
= button
;
1380 button
= pidgin_dialog_add_button(GTK_DIALOG(win
), GTK_STOCK_DELETE
, G_CALLBACK(pounces_manager_delete_cb
), dialog
);
1381 gtk_widget_set_sensitive(button
, FALSE
);
1382 dialog
->delete_button
= button
;
1385 pidgin_dialog_add_button(GTK_DIALOG(win
), GTK_STOCK_CLOSE
, G_CALLBACK(pounces_manager_close_cb
), dialog
);
1387 gtk_widget_show(win
);
1391 pidgin_pounces_manager_hide(void)
1393 if (pounces_manager
== NULL
)
1396 if (pounces_manager
->window
!= NULL
)
1397 gtk_widget_destroy(pounces_manager
->window
);
1399 purple_signals_disconnect_by_handle(pounces_manager
);
1401 g_free(pounces_manager
);
1402 pounces_manager
= NULL
;
1406 pounce_cb(PurplePounce
*pounce
, PurplePounceEvent events
, void *data
)
1408 PurpleIMConversation
*im
;
1409 PurpleAccount
*account
;
1411 const char *pouncee
;
1414 pouncee
= purple_pounce_get_pouncee(pounce
);
1415 account
= purple_pounce_get_pouncer(pounce
);
1417 buddy
= purple_blist_find_buddy(account
, pouncee
);
1420 alias
= purple_buddy_get_alias(buddy
);
1427 if (purple_pounce_action_is_enabled(pounce
, "open-window"))
1429 if (!purple_conversations_find_im_with_account(pouncee
, account
))
1430 purple_im_conversation_new(account
, pouncee
);
1433 if (purple_pounce_action_is_enabled(pounce
, "popup-notify"))
1437 reason
= purple_pounce_action_get_attribute(pounce
, "popup-notify",
1441 * Here we place the protocol name in the pounce dialog to lessen
1442 * confusion about what protocol a pounce is for.
1445 (events
& PURPLE_POUNCE_TYPING
) ?
1446 _("Started typing") :
1447 (events
& PURPLE_POUNCE_TYPED
) ?
1448 _("Paused while typing") :
1449 (events
& PURPLE_POUNCE_SIGNON
) ?
1451 (events
& PURPLE_POUNCE_IDLE_RETURN
) ?
1452 _("Returned from being idle") :
1453 (events
& PURPLE_POUNCE_AWAY_RETURN
) ?
1454 _("Returned from being away") :
1455 (events
& PURPLE_POUNCE_TYPING_STOPPED
) ?
1456 _("Stopped typing") :
1457 (events
& PURPLE_POUNCE_SIGNOFF
) ?
1459 (events
& PURPLE_POUNCE_IDLE
) ?
1461 (events
& PURPLE_POUNCE_AWAY
) ?
1463 (events
& PURPLE_POUNCE_MESSAGE_RECEIVED
) ?
1464 _("Sent a message") :
1465 _("Unknown.... Please report this!")
1468 pidgin_notify_pounce_add(account
, pounce
, alias
, tmp
, reason
,
1469 purple_date_format_full(NULL
));
1474 if (purple_pounce_action_is_enabled(pounce
, "send-message"))
1476 const char *message
;
1478 message
= purple_pounce_action_get_attribute(pounce
, "send-message",
1481 if (message
!= NULL
)
1483 PurpleMessage
*pmsg
;
1485 im
= purple_conversations_find_im_with_account(pouncee
, account
);
1488 im
= purple_im_conversation_new(account
, pouncee
);
1490 pmsg
= purple_message_new_outgoing(pouncee
, message
, 0);
1491 purple_serv_send_im(purple_account_get_connection(account
), pmsg
);
1492 purple_conversation_write_message(PURPLE_CONVERSATION(im
), pmsg
);
1496 if (purple_pounce_action_is_enabled(pounce
, "execute-command"))
1498 const char *command
;
1500 command
= purple_pounce_action_get_attribute(pounce
,
1501 "execute-command", "command");
1503 if (command
!= NULL
)
1505 GError
*error
= NULL
;
1506 if (!g_spawn_command_line_async(command
, &error
)) {
1507 purple_debug_error("gtkpounce",
1508 "pounce command could not be launched: %s\n",
1510 g_error_free(error
);
1515 if (purple_pounce_action_is_enabled(pounce
, "play-sound"))
1519 sound
= purple_pounce_action_get_attribute(pounce
,
1520 "play-sound", "filename");
1523 purple_sound_play_file(sound
, account
);
1525 purple_sound_play_event(PURPLE_SOUND_POUNCE_DEFAULT
, account
);
1530 free_pounce(PurplePounce
*pounce
)
1536 new_pounce(PurplePounce
*pounce
)
1538 purple_pounce_action_register(pounce
, "open-window");
1539 purple_pounce_action_register(pounce
, "popup-notify");
1540 purple_pounce_action_register(pounce
, "send-message");
1541 purple_pounce_action_register(pounce
, "execute-command");
1542 purple_pounce_action_register(pounce
, "play-sound");
1548 pidgin_pounces_get_handle() {
1555 pidgin_pounces_init(void)
1557 purple_pounces_register_handler(PIDGIN_UI
, pounce_cb
, new_pounce
,
1560 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/pounces");
1561 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/pounces/default_actions");
1562 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/open-window",
1564 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/popup-notify",
1566 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/send-message",
1568 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/execute-command",
1570 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/play-sound",
1572 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/pounces/dialog");
1573 purple_prefs_add_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/width", 520);
1574 purple_prefs_add_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/height", 321);
1576 purple_signal_connect(purple_connections_get_handle(), "signed-on",
1577 pidgin_pounces_get_handle(),
1578 PURPLE_CALLBACK(signed_on_off_cb
), NULL
);
1579 purple_signal_connect(purple_connections_get_handle(), "signed-off",
1580 pidgin_pounces_get_handle(),
1581 PURPLE_CALLBACK(signed_on_off_cb
), NULL
);