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"
41 #include "gtkdialogs.h"
42 #include "gtkimhtml.h"
43 #include "gtkpounce.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' && strcmp(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
;
197 PurplePounceEvent events
;
203 account
= purple_pounce_get_pouncer(pounce
);
205 events
= purple_pounce_get_events(pounce
);
207 pixbuf
= pidgin_create_prpl_icon(account
, PIDGIN_PRPL_ICON_MEDIUM
);
209 pouncer
= purple_account_get_username(account
);
210 pouncee
= purple_pounce_get_pouncee(pounce
);
211 recurring
= purple_pounce_get_save(pounce
);
213 gtk_list_store_append(model
, &iter
);
214 gtk_list_store_set(model
, &iter
,
215 POUNCES_MANAGER_COLUMN_POUNCE
, pounce
,
216 POUNCES_MANAGER_COLUMN_ICON
, pixbuf
,
217 POUNCES_MANAGER_COLUMN_TARGET
, pouncee
,
218 POUNCES_MANAGER_COLUMN_ACCOUNT
, pouncer
,
219 POUNCES_MANAGER_COLUMN_RECURRING
, recurring
,
223 g_object_unref(pixbuf
);
227 populate_pounces_list(PouncesManager
*dialog
)
231 gtk_list_store_clear(dialog
->model
);
233 for (pounces
= purple_pounces_get_all_for_ui(PIDGIN_UI
); pounces
!= NULL
;
234 pounces
= g_list_delete_link(pounces
, pounces
))
236 add_pounce_to_treeview(dialog
->model
, pounces
->data
);
243 /* Rebuild the pounces list if the pounces manager is open */
244 if (pounces_manager
!= NULL
)
246 populate_pounces_list(pounces_manager
);
251 signed_on_off_cb(PurpleConnection
*gc
, gpointer user_data
)
257 save_pounce_cb(GtkWidget
*w
, PidginPounceDialog
*dialog
)
260 const char *command
, *sound
, *reason
;
262 PurplePounceEvent events
= PURPLE_POUNCE_NONE
;
263 PurplePounceOption options
= PURPLE_POUNCE_OPTION_NONE
;
265 name
= gtk_entry_get_text(GTK_ENTRY(dialog
->buddy_entry
));
269 purple_notify_error(NULL
, NULL
,
270 _("Please enter a buddy to pounce."), NULL
);
275 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->on_away
)))
276 options
|= PURPLE_POUNCE_OPTION_AWAY
;
279 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->signon
)))
280 events
|= PURPLE_POUNCE_SIGNON
;
282 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->signoff
)))
283 events
|= PURPLE_POUNCE_SIGNOFF
;
285 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->away
)))
286 events
|= PURPLE_POUNCE_AWAY
;
288 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->away_return
)))
289 events
|= PURPLE_POUNCE_AWAY_RETURN
;
291 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->idle
)))
292 events
|= PURPLE_POUNCE_IDLE
;
294 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->idle_return
)))
295 events
|= PURPLE_POUNCE_IDLE_RETURN
;
297 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->typing
)))
298 events
|= PURPLE_POUNCE_TYPING
;
300 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->typed
)))
301 events
|= PURPLE_POUNCE_TYPED
;
303 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->stop_typing
)))
304 events
|= PURPLE_POUNCE_TYPING_STOPPED
;
306 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->message_recv
)))
307 events
|= PURPLE_POUNCE_MESSAGE_RECEIVED
;
310 message
= gtk_imhtml_get_markup(GTK_IMHTML(dialog
->send_msg_entry
));
311 command
= gtk_entry_get_text(GTK_ENTRY(dialog
->exec_cmd_entry
));
312 sound
= gtk_entry_get_text(GTK_ENTRY(dialog
->play_sound_entry
));
313 reason
= gtk_entry_get_text(GTK_ENTRY(dialog
->popup_entry
));
315 if (*reason
== '\0') reason
= NULL
;
316 if (*message
== '\0') {
320 if (*command
== '\0') command
= NULL
;
321 if (*sound
== '\0' || !strcmp(sound
, _("(default)"))) sound
= NULL
;
323 /* If the pounce has already been triggered, let's pretend it is a new one */
324 if (dialog
->pounce
!= NULL
325 && g_list_find(purple_pounces_get_all(), dialog
->pounce
) == NULL
) {
326 purple_debug_info("gtkpounce", "Saving pounce that no longer exists; creating new pounce.\n");
327 dialog
->pounce
= NULL
;
330 if (dialog
->pounce
== NULL
)
332 dialog
->pounce
= purple_pounce_new(PIDGIN_UI
, dialog
->account
,
333 name
, events
, options
);
336 purple_pounce_set_events(dialog
->pounce
, events
);
337 purple_pounce_set_options(dialog
->pounce
, options
);
338 purple_pounce_set_pouncer(dialog
->pounce
, dialog
->account
);
339 purple_pounce_set_pouncee(dialog
->pounce
, name
);
343 purple_pounce_action_set_enabled(dialog
->pounce
, "open-window",
344 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->open_win
)));
345 purple_pounce_action_set_enabled(dialog
->pounce
, "popup-notify",
346 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->popup
)));
347 purple_pounce_action_set_enabled(dialog
->pounce
, "send-message",
348 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
)));
349 purple_pounce_action_set_enabled(dialog
->pounce
, "execute-command",
350 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
)));
351 purple_pounce_action_set_enabled(dialog
->pounce
, "play-sound",
352 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
)));
354 purple_pounce_action_set_attribute(dialog
->pounce
, "send-message",
356 purple_pounce_action_set_attribute(dialog
->pounce
, "execute-command",
358 purple_pounce_action_set_attribute(dialog
->pounce
, "play-sound",
360 purple_pounce_action_set_attribute(dialog
->pounce
, "popup-notify",
363 /* Set the defaults for next time. */
364 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/open-window",
365 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->open_win
)));
366 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/popup-notify",
367 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->popup
)));
368 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/send-message",
369 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
)));
370 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/execute-command",
371 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
)));
372 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/play-sound",
373 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
)));
375 purple_pounce_set_save(dialog
->pounce
,
376 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog
->save_pounce
)));
381 delete_win_cb(NULL
, NULL
, dialog
);
385 pounce_choose_cb(GtkWidget
*item
, PurpleAccount
*account
,
386 PidginPounceDialog
*dialog
)
388 dialog
->account
= account
;
392 buddy_changed_cb(GtkEntry
*entry
, PidginPounceDialog
*dialog
)
394 if (dialog
->save_button
== NULL
)
397 gtk_widget_set_sensitive(dialog
->save_button
,
398 *gtk_entry_get_text(entry
) != '\0');
402 message_recv_toggle(GtkButton
*message_recv
, GtkWidget
*send_msg
)
404 gboolean active
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(message_recv
));
406 gtk_widget_set_sensitive(send_msg
, !active
);
408 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(send_msg
), FALSE
);
412 pounce_dnd_recv(GtkWidget
*widget
, GdkDragContext
*dc
, gint x
, gint y
,
413 GtkSelectionData
*sd
, guint info
, guint t
, gpointer data
)
415 PidginPounceDialog
*dialog
;
417 if (sd
->target
== gdk_atom_intern("PURPLE_BLIST_NODE", FALSE
))
419 PurpleBlistNode
*node
= NULL
;
422 memcpy(&node
, sd
->data
, sizeof(node
));
424 if (PURPLE_BLIST_NODE_IS_CONTACT(node
))
425 buddy
= purple_contact_get_priority_buddy((PurpleContact
*)node
);
426 else if (PURPLE_BLIST_NODE_IS_BUDDY(node
))
427 buddy
= (PurpleBuddy
*)node
;
431 dialog
= (PidginPounceDialog
*)data
;
433 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
), buddy
->name
);
434 dialog
->account
= buddy
->account
;
435 pidgin_account_option_menu_set_selected(dialog
->account_menu
, buddy
->account
);
437 gtk_drag_finish(dc
, TRUE
, (dc
->action
== GDK_ACTION_MOVE
), t
);
439 else if (sd
->target
== gdk_atom_intern("application/x-im-contact", FALSE
))
441 char *protocol
= NULL
;
442 char *username
= NULL
;
443 PurpleAccount
*account
;
445 if (pidgin_parse_x_im_contact((const char *)sd
->data
, FALSE
, &account
,
446 &protocol
, &username
, NULL
))
450 purple_notify_error(NULL
, NULL
,
451 _("You are not currently signed on with an account that "
452 "can add that buddy."), NULL
);
456 dialog
= (PidginPounceDialog
*)data
;
458 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
), username
);
459 dialog
->account
= account
;
460 pidgin_account_option_menu_set_selected(dialog
->account_menu
, account
);
467 gtk_drag_finish(dc
, TRUE
, (dc
->action
== GDK_ACTION_MOVE
), t
);
471 static const GtkTargetEntry dnd_targets
[] =
473 {"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP
, 0},
474 {"application/x-im-contact", 0, 1}
478 reset_send_msg_entry(PidginPounceDialog
*dialog
, GtkWidget
*dontcare
)
480 PurpleAccount
*account
= pidgin_account_option_menu_get_selected(dialog
->account_menu
);
481 gtk_imhtml_setup_entry(GTK_IMHTML(dialog
->send_msg_entry
),
482 (account
&& account
->gc
) ? account
->gc
->flags
: PURPLE_CONNECTION_HTML
);
486 pidgin_pounce_editor_show(PurpleAccount
*account
, const char *name
,
487 PurplePounce
*cur_pounce
)
489 PidginPounceDialog
*dialog
;
492 GtkWidget
*vbox1
, *vbox2
;
498 GPtrArray
*sound_widgets
;
499 GPtrArray
*exec_widgets
;
500 GtkWidget
*send_msg_imhtml
;
502 g_return_if_fail((cur_pounce
!= NULL
) ||
504 (purple_accounts_get_all() != NULL
));
506 dialog
= g_new0(PidginPounceDialog
, 1);
508 if (cur_pounce
!= NULL
)
510 dialog
->pounce
= cur_pounce
;
511 dialog
->account
= purple_pounce_get_pouncer(cur_pounce
);
513 else if (account
!= NULL
)
515 dialog
->pounce
= NULL
;
516 dialog
->account
= account
;
520 GList
*connections
= purple_connections_get_all();
521 PurpleConnection
*gc
;
523 if (connections
!= NULL
)
525 gc
= (PurpleConnection
*)connections
->data
;
526 dialog
->account
= purple_connection_get_account(gc
);
529 dialog
->account
= purple_accounts_get_all()->data
;
531 dialog
->pounce
= NULL
;
534 sg
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
536 /* Create the window. */
537 dialog
->window
= window
= gtk_dialog_new();
538 gtk_window_set_title(GTK_WINDOW(window
), (cur_pounce
== NULL
? _("New Buddy Pounce") : _("Edit Buddy Pounce")));
539 gtk_window_set_role(GTK_WINDOW(window
), "buddy_pounce");
540 gtk_container_set_border_width(GTK_CONTAINER(dialog
->window
), PIDGIN_HIG_BORDER
);
542 g_signal_connect(G_OBJECT(window
), "delete_event",
543 G_CALLBACK(delete_win_cb
), dialog
);
545 /* Create the parent vbox for everything. */
546 vbox1
= GTK_DIALOG(window
)->vbox
;
548 /* Create the vbox that will contain all the prefs stuff. */
549 vbox2
= gtk_vbox_new(FALSE
, PIDGIN_HIG_BOX_SPACE
);
550 gtk_box_pack_start(GTK_BOX(vbox1
), vbox2
, TRUE
, TRUE
, 0);
552 /* Create the "Pounce on Whom" frame. */
553 frame
= pidgin_make_frame(vbox2
, _("Pounce on Whom"));
556 hbox
= gtk_hbox_new(FALSE
, PIDGIN_HIG_BOX_SPACE
);
557 gtk_box_pack_start(GTK_BOX(frame
), hbox
, FALSE
, FALSE
, 0);
558 gtk_widget_show(hbox
);
560 label
= gtk_label_new_with_mnemonic(_("_Account:"));
561 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
562 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
563 gtk_widget_show(label
);
564 gtk_size_group_add_widget(sg
, label
);
566 dialog
->account_menu
=
567 pidgin_account_option_menu_new(dialog
->account
, TRUE
,
568 G_CALLBACK(pounce_choose_cb
),
571 gtk_box_pack_start(GTK_BOX(hbox
), dialog
->account_menu
, FALSE
, FALSE
, 0);
572 gtk_widget_show(dialog
->account_menu
);
573 pidgin_set_accessible_label (dialog
->account_menu
, label
);
576 hbox
= gtk_hbox_new(FALSE
, PIDGIN_HIG_BOX_SPACE
);
577 gtk_box_pack_start(GTK_BOX(frame
), hbox
, FALSE
, FALSE
, 0);
578 gtk_widget_show(hbox
);
580 label
= gtk_label_new_with_mnemonic(_("_Buddy name:"));
581 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
582 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
583 gtk_widget_show(label
);
584 gtk_size_group_add_widget(sg
, label
);
586 dialog
->buddy_entry
= gtk_entry_new();
588 pidgin_setup_screenname_autocomplete_with_filter(dialog
->buddy_entry
, dialog
->account_menu
, pidgin_screenname_autocomplete_default_filter
, GINT_TO_POINTER(FALSE
));
590 gtk_box_pack_start(GTK_BOX(hbox
), dialog
->buddy_entry
, TRUE
, TRUE
, 0);
591 gtk_widget_show(dialog
->buddy_entry
);
593 g_signal_connect(G_OBJECT(dialog
->buddy_entry
), "changed",
594 G_CALLBACK(buddy_changed_cb
), dialog
);
595 pidgin_set_accessible_label (dialog
->buddy_entry
, label
);
597 if (cur_pounce
!= NULL
) {
598 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
),
599 purple_pounce_get_pouncee(cur_pounce
));
601 else if (name
!= NULL
) {
602 gtk_entry_set_text(GTK_ENTRY(dialog
->buddy_entry
), name
);
605 /* Create the "Pounce When Buddy..." frame. */
606 frame
= pidgin_make_frame(vbox2
, _("Pounce When Buddy..."));
608 table
= gtk_table_new(5, 2, FALSE
);
609 gtk_container_add(GTK_CONTAINER(frame
), table
);
610 gtk_table_set_col_spacings(GTK_TABLE(table
), PIDGIN_HIG_BORDER
);
611 gtk_widget_show(table
);
614 gtk_check_button_new_with_mnemonic(_("Si_gns on"));
616 gtk_check_button_new_with_mnemonic(_("Signs o_ff"));
618 gtk_check_button_new_with_mnemonic(_("Goes a_way"));
619 dialog
->away_return
=
620 gtk_check_button_new_with_mnemonic(_("Ret_urns from away"));
622 gtk_check_button_new_with_mnemonic(_("Becomes _idle"));
623 dialog
->idle_return
=
624 gtk_check_button_new_with_mnemonic(_("Is no longer i_dle"));
626 gtk_check_button_new_with_mnemonic(_("Starts _typing"));
628 gtk_check_button_new_with_mnemonic(_("P_auses while typing"));
629 dialog
->stop_typing
=
630 gtk_check_button_new_with_mnemonic(_("Stops t_yping"));
631 dialog
->message_recv
=
632 gtk_check_button_new_with_mnemonic(_("Sends a _message"));
634 gtk_table_attach(GTK_TABLE(table
), dialog
->message_recv
, 0, 1, 0, 1,
636 gtk_table_attach(GTK_TABLE(table
), dialog
->signon
, 0, 1, 1, 2,
638 gtk_table_attach(GTK_TABLE(table
), dialog
->signoff
, 0, 1, 2, 3,
640 gtk_table_attach(GTK_TABLE(table
), dialog
->away
, 0, 1, 3, 4,
642 gtk_table_attach(GTK_TABLE(table
), dialog
->away_return
, 0, 1, 4, 5,
644 gtk_table_attach(GTK_TABLE(table
), dialog
->idle
, 1, 2, 0, 1,
646 gtk_table_attach(GTK_TABLE(table
), dialog
->idle_return
, 1, 2, 1, 2,
648 gtk_table_attach(GTK_TABLE(table
), dialog
->typing
, 1, 2, 2, 3,
650 gtk_table_attach(GTK_TABLE(table
), dialog
->typed
, 1, 2, 3, 4,
652 gtk_table_attach(GTK_TABLE(table
), dialog
->stop_typing
, 1, 2, 4, 5,
655 gtk_widget_show(dialog
->signon
);
656 gtk_widget_show(dialog
->signoff
);
657 gtk_widget_show(dialog
->away
);
658 gtk_widget_show(dialog
->away_return
);
659 gtk_widget_show(dialog
->idle
);
660 gtk_widget_show(dialog
->idle_return
);
661 gtk_widget_show(dialog
->typing
);
662 gtk_widget_show(dialog
->typed
);
663 gtk_widget_show(dialog
->stop_typing
);
664 gtk_widget_show(dialog
->message_recv
);
666 /* Create the "Action" frame. */
667 frame
= pidgin_make_frame(vbox2
, _("Action"));
669 table
= gtk_table_new(3, 6, FALSE
);
670 gtk_container_add(GTK_CONTAINER(frame
), table
);
671 gtk_table_set_col_spacings(GTK_TABLE(table
), PIDGIN_HIG_BORDER
);
672 gtk_widget_show(table
);
675 = gtk_check_button_new_with_mnemonic(_("Ope_n an IM window"));
677 = gtk_check_button_new_with_mnemonic(_("_Pop up a notification"));
679 = gtk_check_button_new_with_mnemonic(_("Send a _message"));
681 = gtk_check_button_new_with_mnemonic(_("E_xecute a command"));
683 = gtk_check_button_new_with_mnemonic(_("P_lay a sound"));
685 send_msg_imhtml
= pidgin_create_imhtml(TRUE
, &dialog
->send_msg_entry
, NULL
, NULL
);
686 reset_send_msg_entry(dialog
, NULL
);
687 dialog
->exec_cmd_entry
= gtk_entry_new();
688 dialog
->popup_entry
= gtk_entry_new();
689 dialog
->exec_cmd_browse
= gtk_button_new_with_mnemonic(_("Brows_e..."));
690 dialog
->play_sound_entry
= gtk_entry_new();
691 gtk_entry_set_text(GTK_ENTRY(dialog
->play_sound_entry
), _("(default)"));
692 gtk_editable_set_editable(GTK_EDITABLE(dialog
->play_sound_entry
), FALSE
);
693 dialog
->play_sound_browse
= gtk_button_new_with_mnemonic(_("Br_owse..."));
694 dialog
->play_sound_test
= gtk_button_new_with_mnemonic(_("Pre_view"));
695 dialog
->play_sound_reset
= gtk_button_new_with_mnemonic(_("Reset"));
697 gtk_widget_set_sensitive(send_msg_imhtml
, FALSE
);
698 gtk_widget_set_sensitive(dialog
->exec_cmd_entry
, FALSE
);
699 gtk_widget_set_sensitive(dialog
->popup_entry
, FALSE
);
700 gtk_widget_set_sensitive(dialog
->exec_cmd_browse
, FALSE
);
701 gtk_widget_set_sensitive(dialog
->play_sound_entry
, FALSE
);
702 gtk_widget_set_sensitive(dialog
->play_sound_browse
, FALSE
);
703 gtk_widget_set_sensitive(dialog
->play_sound_test
, FALSE
);
704 gtk_widget_set_sensitive(dialog
->play_sound_reset
, FALSE
);
708 sg
= gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL
);
709 gtk_size_group_add_widget(sg
, dialog
->open_win
);
710 gtk_size_group_add_widget(sg
, dialog
->popup
);
711 gtk_size_group_add_widget(sg
, dialog
->popup_entry
);
712 gtk_size_group_add_widget(sg
, dialog
->exec_cmd
);
713 gtk_size_group_add_widget(sg
, dialog
->exec_cmd_entry
);
714 gtk_size_group_add_widget(sg
, dialog
->exec_cmd_browse
);
715 gtk_size_group_add_widget(sg
, dialog
->play_sound
);
716 gtk_size_group_add_widget(sg
, dialog
->play_sound_entry
);
717 gtk_size_group_add_widget(sg
, dialog
->play_sound_browse
);
718 gtk_size_group_add_widget(sg
, dialog
->play_sound_test
);
719 gtk_size_group_add_widget(sg
, dialog
->play_sound_reset
);
724 gtk_table_attach(GTK_TABLE(table
), dialog
->open_win
, 0, 1, 0, 1,
726 gtk_table_attach(GTK_TABLE(table
), dialog
->popup
, 0, 1, 1, 2,
728 gtk_table_attach(GTK_TABLE(table
), dialog
->popup_entry
, 1, 5, 1, 2,
730 gtk_table_attach(GTK_TABLE(table
), dialog
->send_msg
, 0, 5, 2, 3,
732 gtk_table_attach(GTK_TABLE(table
), send_msg_imhtml
, 0, 5, 3, 4,
734 gtk_table_attach(GTK_TABLE(table
), dialog
->exec_cmd
, 0, 1, 4, 5,
736 gtk_table_attach(GTK_TABLE(table
), dialog
->exec_cmd_entry
, 1, 2, 4, 5,
738 gtk_table_attach(GTK_TABLE(table
), dialog
->exec_cmd_browse
, 2, 3, 4, 5,
739 GTK_FILL
| GTK_EXPAND
, 0, 0, 0);
740 gtk_table_attach(GTK_TABLE(table
), dialog
->play_sound
, 0, 1, 5, 6,
742 gtk_table_attach(GTK_TABLE(table
), dialog
->play_sound_entry
, 1, 2, 5, 6,
744 gtk_table_attach(GTK_TABLE(table
), dialog
->play_sound_browse
,2, 3, 5, 6,
745 GTK_FILL
| GTK_EXPAND
, 0, 0, 0);
746 gtk_table_attach(GTK_TABLE(table
), dialog
->play_sound_test
, 3, 4, 5, 6,
747 GTK_FILL
| GTK_EXPAND
, 0, 0, 0);
748 gtk_table_attach(GTK_TABLE(table
), dialog
->play_sound_reset
, 4, 5, 5, 6,
749 GTK_FILL
| GTK_EXPAND
, 0, 0, 0);
751 gtk_table_set_row_spacings(GTK_TABLE(table
), PIDGIN_HIG_BOX_SPACE
/ 2);
753 gtk_widget_show(dialog
->open_win
);
754 gtk_widget_show(dialog
->popup
);
755 gtk_widget_show(dialog
->popup_entry
);
756 gtk_widget_show(dialog
->send_msg
);
757 gtk_widget_show(send_msg_imhtml
);
758 gtk_widget_show(dialog
->exec_cmd
);
759 gtk_widget_show(dialog
->exec_cmd_entry
);
760 gtk_widget_show(dialog
->exec_cmd_browse
);
761 gtk_widget_show(dialog
->play_sound
);
762 gtk_widget_show(dialog
->play_sound_entry
);
763 gtk_widget_show(dialog
->play_sound_browse
);
764 gtk_widget_show(dialog
->play_sound_test
);
765 gtk_widget_show(dialog
->play_sound_reset
);
767 g_signal_connect(G_OBJECT(dialog
->message_recv
), "clicked",
768 G_CALLBACK(message_recv_toggle
),
771 g_signal_connect(G_OBJECT(dialog
->send_msg
), "clicked",
772 G_CALLBACK(pidgin_toggle_sensitive
),
775 g_signal_connect(G_OBJECT(dialog
->popup
), "clicked",
776 G_CALLBACK(pidgin_toggle_sensitive
),
777 dialog
->popup_entry
);
779 exec_widgets
= g_ptr_array_new();
780 g_ptr_array_add(exec_widgets
,dialog
->exec_cmd_entry
);
781 g_ptr_array_add(exec_widgets
,dialog
->exec_cmd_browse
);
783 g_signal_connect(G_OBJECT(dialog
->exec_cmd
), "clicked",
784 G_CALLBACK(pidgin_toggle_sensitive_array
),
786 g_signal_connect(G_OBJECT(dialog
->exec_cmd_browse
), "clicked",
788 dialog
->exec_cmd_entry
);
789 g_object_set_data_full(G_OBJECT(dialog
->window
), "exec-widgets",
790 exec_widgets
, (GDestroyNotify
)g_ptr_array_free
);
792 sound_widgets
= g_ptr_array_new();
793 g_ptr_array_add(sound_widgets
,dialog
->play_sound_entry
);
794 g_ptr_array_add(sound_widgets
,dialog
->play_sound_browse
);
795 g_ptr_array_add(sound_widgets
,dialog
->play_sound_test
);
796 g_ptr_array_add(sound_widgets
,dialog
->play_sound_reset
);
798 g_signal_connect(G_OBJECT(dialog
->play_sound
), "clicked",
799 G_CALLBACK(pidgin_toggle_sensitive_array
),
801 g_signal_connect(G_OBJECT(dialog
->play_sound_browse
), "clicked",
803 dialog
->play_sound_entry
);
804 g_signal_connect(G_OBJECT(dialog
->play_sound_test
), "clicked",
805 G_CALLBACK(pounce_test_sound
),
806 dialog
->play_sound_entry
);
807 g_signal_connect(G_OBJECT(dialog
->play_sound_reset
), "clicked",
808 G_CALLBACK(pounce_reset_sound
),
809 dialog
->play_sound_entry
);
810 g_object_set_data_full(G_OBJECT(dialog
->window
), "sound-widgets",
811 sound_widgets
, (GDestroyNotify
)g_ptr_array_free
);
813 g_signal_connect_swapped(G_OBJECT(dialog
->send_msg_entry
), "format_function_clear",
814 G_CALLBACK(reset_send_msg_entry
), dialog
);
815 g_signal_connect_swapped(G_OBJECT(dialog
->account_menu
), "changed",
816 G_CALLBACK(reset_send_msg_entry
), dialog
);
818 g_signal_connect(G_OBJECT(dialog
->send_msg_entry
), "message_send",
819 G_CALLBACK(save_pounce_cb
), dialog
);
820 g_signal_connect(G_OBJECT(dialog
->popup_entry
), "activate",
821 G_CALLBACK(save_pounce_cb
), dialog
);
822 g_signal_connect(G_OBJECT(dialog
->exec_cmd_entry
), "activate",
823 G_CALLBACK(save_pounce_cb
), dialog
);
825 /* Create the "Options" frame. */
826 frame
= pidgin_make_frame(vbox2
, _("Options"));
828 table
= gtk_table_new(2, 1, FALSE
);
829 gtk_container_add(GTK_CONTAINER(frame
), table
);
830 gtk_table_set_col_spacings(GTK_TABLE(table
), PIDGIN_HIG_BORDER
);
831 gtk_widget_show(table
);
834 gtk_check_button_new_with_mnemonic(_("P_ounce only when my status is not Available"));
835 gtk_table_attach(GTK_TABLE(table
), dialog
->on_away
, 0, 1, 0, 1,
838 dialog
->save_pounce
= gtk_check_button_new_with_mnemonic(
840 gtk_table_attach(GTK_TABLE(table
), dialog
->save_pounce
, 0, 1, 1, 2,
843 gtk_widget_show(dialog
->on_away
);
844 gtk_widget_show(dialog
->save_pounce
);
847 button
= gtk_dialog_add_button(GTK_DIALOG(window
), GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
);
848 g_signal_connect(G_OBJECT(button
), "clicked",
849 G_CALLBACK(cancel_cb
), dialog
);
851 /* Save/Add button */
852 dialog
->save_button
= button
= gtk_dialog_add_button(GTK_DIALOG(window
),
853 (cur_pounce
== NULL
? GTK_STOCK_ADD
: GTK_STOCK_SAVE
),
855 g_signal_connect(G_OBJECT(button
), "clicked",
856 G_CALLBACK(save_pounce_cb
), dialog
);
858 if (*gtk_entry_get_text(GTK_ENTRY(dialog
->buddy_entry
)) == '\0')
859 gtk_widget_set_sensitive(button
, FALSE
);
861 /* Setup drag-and-drop */
862 gtk_drag_dest_set(window
,
863 GTK_DEST_DEFAULT_MOTION
|
864 GTK_DEST_DEFAULT_DROP
,
866 sizeof(dnd_targets
) / sizeof(GtkTargetEntry
),
868 gtk_drag_dest_set(dialog
->buddy_entry
,
869 GTK_DEST_DEFAULT_MOTION
|
870 GTK_DEST_DEFAULT_DROP
,
872 sizeof(dnd_targets
) / sizeof(GtkTargetEntry
),
875 g_signal_connect(G_OBJECT(window
), "drag_data_received",
876 G_CALLBACK(pounce_dnd_recv
), dialog
);
877 g_signal_connect(G_OBJECT(dialog
->buddy_entry
), "drag_data_received",
878 G_CALLBACK(pounce_dnd_recv
), dialog
);
880 /* Set the values of stuff. */
881 if (cur_pounce
!= NULL
)
883 PurplePounceEvent events
= purple_pounce_get_events(cur_pounce
);
884 PurplePounceOption options
= purple_pounce_get_options(cur_pounce
);
888 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->on_away
),
889 (options
& PURPLE_POUNCE_OPTION_AWAY
));
892 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->signon
),
893 (events
& PURPLE_POUNCE_SIGNON
));
894 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->signoff
),
895 (events
& PURPLE_POUNCE_SIGNOFF
));
896 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->away
),
897 (events
& PURPLE_POUNCE_AWAY
));
898 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->away_return
),
899 (events
& PURPLE_POUNCE_AWAY_RETURN
));
900 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->idle
),
901 (events
& PURPLE_POUNCE_IDLE
));
902 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->idle_return
),
903 (events
& PURPLE_POUNCE_IDLE_RETURN
));
904 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->typing
),
905 (events
& PURPLE_POUNCE_TYPING
));
906 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->typed
),
907 (events
& PURPLE_POUNCE_TYPED
));
908 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->stop_typing
),
909 (events
& PURPLE_POUNCE_TYPING_STOPPED
));
910 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->message_recv
),
911 (events
& PURPLE_POUNCE_MESSAGE_RECEIVED
));
914 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->open_win
),
915 purple_pounce_action_is_enabled(cur_pounce
, "open-window"));
916 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->popup
),
917 purple_pounce_action_is_enabled(cur_pounce
, "popup-notify"));
918 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
),
919 purple_pounce_action_is_enabled(cur_pounce
, "send-message"));
920 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
),
921 purple_pounce_action_is_enabled(cur_pounce
, "execute-command"));
922 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
),
923 purple_pounce_action_is_enabled(cur_pounce
, "play-sound"));
925 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->save_pounce
),
926 purple_pounce_get_save(cur_pounce
));
928 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
932 gtk_imhtml_append_text(GTK_IMHTML(dialog
->send_msg_entry
), value
, 0);
935 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
939 gtk_entry_set_text(GTK_ENTRY(dialog
->popup_entry
), value
);
942 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
946 gtk_entry_set_text(GTK_ENTRY(dialog
->exec_cmd_entry
), value
);
949 if ((value
= purple_pounce_action_get_attribute(cur_pounce
,
951 "filename")) != NULL
)
953 gtk_entry_set_text(GTK_ENTRY(dialog
->play_sound_entry
), (value
&& *value
!= '\0') ? value
: _("(default)"));
958 PurpleBuddy
*buddy
= NULL
;
961 buddy
= purple_find_buddy(account
, name
);
963 /* Set some defaults */
966 gtk_toggle_button_set_active(
967 GTK_TOGGLE_BUTTON(dialog
->signon
), TRUE
);
971 if (!PURPLE_BUDDY_IS_ONLINE(buddy
))
973 gtk_toggle_button_set_active(
974 GTK_TOGGLE_BUTTON(dialog
->signon
), TRUE
);
978 gboolean default_set
= FALSE
;
979 PurplePresence
*presence
= purple_buddy_get_presence(buddy
);
981 if (purple_presence_is_idle(presence
))
983 gtk_toggle_button_set_active(
984 GTK_TOGGLE_BUTTON(dialog
->idle_return
), TRUE
);
989 if (!purple_presence_is_available(presence
))
991 gtk_toggle_button_set_active(
992 GTK_TOGGLE_BUTTON(dialog
->away_return
), TRUE
);
999 gtk_toggle_button_set_active(
1000 GTK_TOGGLE_BUTTON(dialog
->signon
), TRUE
);
1005 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->open_win
),
1006 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/open-window"));
1007 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->popup
),
1008 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/popup-notify"));
1009 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->send_msg
),
1010 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/send-message"));
1011 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->exec_cmd
),
1012 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/execute-command"));
1013 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog
->play_sound
),
1014 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/play-sound"));
1017 gtk_widget_show(vbox2
);
1018 gtk_widget_show(window
);
1022 pounces_manager_configure_cb(GtkWidget
*widget
, GdkEventConfigure
*event
, PouncesManager
*dialog
)
1024 if (GTK_WIDGET_VISIBLE(widget
)) {
1025 purple_prefs_set_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/width", event
->width
);
1026 purple_prefs_set_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/height", event
->height
);
1033 pounces_manager_find_pounce(GtkTreeIter
*iter
, PurplePounce
*pounce
)
1035 GtkTreeModel
*model
= GTK_TREE_MODEL(pounces_manager
->model
);
1038 if (!gtk_tree_model_get_iter_first(model
, iter
))
1041 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &p
, -1);
1045 while (gtk_tree_model_iter_next(model
, iter
))
1047 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &p
, -1);
1056 pounces_manager_destroy_cb(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
)
1058 PouncesManager
*dialog
= user_data
;
1060 dialog
->window
= NULL
;
1061 pidgin_pounces_manager_hide();
1066 #if !GTK_CHECK_VERSION(2,2,0)
1068 count_selected_helper(GtkTreeModel
*model
, GtkTreePath
*path
,
1069 GtkTreeIter
*iter
, gpointer user_data
)
1071 (*(gint
*)user_data
)++;
1076 pounces_manager_connection_cb(PurpleConnection
*gc
, GtkWidget
*add_button
)
1078 gtk_widget_set_sensitive(add_button
, (purple_connections_get_all() != NULL
));
1082 pounces_manager_add_cb(GtkButton
*button
, gpointer user_data
)
1084 pidgin_pounce_editor_show(NULL
, NULL
, NULL
);
1088 pounces_manager_modify_foreach(GtkTreeModel
*model
, GtkTreePath
*path
,
1089 GtkTreeIter
*iter
, gpointer user_data
)
1091 PurplePounce
*pounce
;
1093 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
, -1);
1094 pidgin_pounce_editor_show(NULL
, NULL
, pounce
);
1098 pounces_manager_modify_cb(GtkButton
*button
, gpointer user_data
)
1100 PouncesManager
*dialog
= user_data
;
1101 GtkTreeSelection
*selection
;
1103 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->treeview
));
1105 gtk_tree_selection_selected_foreach(selection
, pounces_manager_modify_foreach
, user_data
);
1109 pounces_manager_delete_confirm_cb(PurplePounce
*pounce
)
1113 if (pounces_manager
&& pounces_manager_find_pounce(&iter
, pounce
))
1114 gtk_list_store_remove(pounces_manager
->model
, &iter
);
1116 purple_request_close_with_handle(pounce
);
1117 purple_pounce_destroy(pounce
);
1121 pounces_manager_delete_foreach(GtkTreeModel
*model
, GtkTreePath
*path
,
1122 GtkTreeIter
*iter
, gpointer user_data
)
1124 PurplePounce
*pounce
;
1125 PurpleAccount
*account
;
1126 const char *pouncer
, *pouncee
;
1129 gtk_tree_model_get(model
, iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
, -1);
1130 account
= purple_pounce_get_pouncer(pounce
);
1131 pouncer
= purple_account_get_username(account
);
1132 pouncee
= purple_pounce_get_pouncee(pounce
);
1134 buf
= g_strdup_printf(_("Are you sure you want to delete the pounce on %s for %s?"), pouncee
, pouncer
);
1135 purple_request_action(pounce
, NULL
, buf
, NULL
, 0,
1136 account
, pouncee
, NULL
,
1138 _("Delete"), pounces_manager_delete_confirm_cb
,
1144 pounces_manager_delete_cb(GtkButton
*button
, gpointer user_data
)
1146 PouncesManager
*dialog
= user_data
;
1147 GtkTreeSelection
*selection
;
1149 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->treeview
));
1151 gtk_tree_selection_selected_foreach(selection
, pounces_manager_delete_foreach
, user_data
);
1155 pounces_manager_close_cb(GtkButton
*button
, gpointer user_data
)
1157 pidgin_pounces_manager_hide();
1161 pounce_selected_cb(GtkTreeSelection
*sel
, gpointer user_data
)
1163 PouncesManager
*dialog
= user_data
;
1164 int num_selected
= 0;
1166 #if GTK_CHECK_VERSION(2,2,0)
1167 num_selected
= gtk_tree_selection_count_selected_rows(sel
);
1169 gtk_tree_selection_selected_foreach(sel
, count_selected_helper
, &num_selected
);
1172 gtk_widget_set_sensitive(dialog
->modify_button
, (num_selected
> 0));
1173 gtk_widget_set_sensitive(dialog
->delete_button
, (num_selected
> 0));
1177 pounce_double_click_cb(GtkTreeView
*treeview
, GdkEventButton
*event
, gpointer user_data
)
1179 PouncesManager
*dialog
= user_data
;
1182 PurplePounce
*pounce
;
1184 /* Figure out which node was clicked */
1185 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(dialog
->treeview
), event
->x
, event
->y
, &path
, NULL
, NULL
, NULL
))
1187 gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog
->model
), &iter
, path
);
1188 gtk_tree_path_free(path
);
1189 gtk_tree_model_get(GTK_TREE_MODEL(dialog
->model
), &iter
, POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
, -1);
1191 if ((pounce
!= NULL
) && (event
->button
== 1) &&
1192 (event
->type
== GDK_2BUTTON_PRESS
))
1194 pidgin_pounce_editor_show(NULL
, NULL
, pounce
);
1202 pounces_manager_recurring_cb(GtkCellRendererToggle
*renderer
, gchar
*path_str
,
1205 PouncesManager
*dialog
= user_data
;
1206 PurplePounce
*pounce
;
1208 GtkTreeModel
*model
= GTK_TREE_MODEL(dialog
->model
);
1211 gtk_tree_model_get_iter_from_string(model
, &iter
, path_str
);
1212 gtk_tree_model_get(model
, &iter
,
1213 POUNCES_MANAGER_COLUMN_POUNCE
, &pounce
,
1214 POUNCES_MANAGER_COLUMN_RECURRING
, &recurring
,
1217 purple_pounce_set_save(pounce
, !recurring
);
1223 search_func(GtkTreeModel
*model
, gint column
, const gchar
*key
, GtkTreeIter
*iter
, gpointer search_data
)
1228 gtk_tree_model_get(model
, iter
, column
, &haystack
, -1);
1230 result
= (purple_strcasestr(haystack
, key
) == NULL
);
1238 create_pounces_list(PouncesManager
*dialog
)
1241 GtkWidget
*treeview
;
1242 GtkTreeSelection
*sel
;
1243 GtkTreeViewColumn
*column
;
1244 GtkCellRenderer
*renderer
;
1246 /* Create the scrolled window */
1247 sw
= gtk_scrolled_window_new(0, 0);
1248 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw
),
1249 GTK_POLICY_AUTOMATIC
,
1250 GTK_POLICY_AUTOMATIC
);
1251 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw
),
1253 gtk_widget_show(sw
);
1255 /* Create the list model */
1256 dialog
->model
= gtk_list_store_new(POUNCES_MANAGER_NUM_COLUMNS
,
1264 /* Create the treeview */
1265 treeview
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog
->model
));
1266 g_object_unref(G_OBJECT(dialog
->model
));
1267 dialog
->treeview
= treeview
;
1268 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview
), TRUE
);
1270 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
));
1271 gtk_tree_selection_set_mode(sel
, GTK_SELECTION_MULTIPLE
);
1272 g_signal_connect(G_OBJECT(sel
), "changed",
1273 G_CALLBACK(pounce_selected_cb
), dialog
);
1275 /* Handle double-clicking */
1276 g_signal_connect(G_OBJECT(treeview
), "button_press_event",
1277 G_CALLBACK(pounce_double_click_cb
), dialog
);
1279 gtk_container_add(GTK_CONTAINER(sw
), treeview
);
1280 gtk_widget_show(treeview
);
1282 /* Pouncee Column */
1283 column
= gtk_tree_view_column_new();
1284 gtk_tree_view_column_set_title(column
, _("Pounce Target"));
1285 gtk_tree_view_column_set_resizable(column
, TRUE
);
1286 gtk_tree_view_column_set_min_width(column
, 200);
1287 gtk_tree_view_column_set_sort_column_id(column
,
1288 POUNCES_MANAGER_COLUMN_TARGET
);
1289 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
1292 renderer
= gtk_cell_renderer_pixbuf_new();
1293 gtk_tree_view_column_pack_start(column
, renderer
, FALSE
);
1294 gtk_tree_view_column_add_attribute(column
, renderer
, "pixbuf",
1295 POUNCES_MANAGER_COLUMN_ICON
);
1298 renderer
= gtk_cell_renderer_text_new();
1299 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1300 gtk_tree_view_column_add_attribute(column
, renderer
, "text",
1301 POUNCES_MANAGER_COLUMN_TARGET
);
1304 /* Account Column */
1305 column
= gtk_tree_view_column_new();
1306 gtk_tree_view_column_set_title(column
, _("Account"));
1307 gtk_tree_view_column_set_resizable(column
, TRUE
);
1308 gtk_tree_view_column_set_min_width(column
, 200);
1309 gtk_tree_view_column_set_sort_column_id(column
,
1310 POUNCES_MANAGER_COLUMN_ACCOUNT
);
1311 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
1312 renderer
= gtk_cell_renderer_text_new();
1313 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1314 gtk_tree_view_column_add_attribute(column
, renderer
, "text",
1315 POUNCES_MANAGER_COLUMN_ACCOUNT
);
1317 /* Recurring Column */
1318 renderer
= gtk_cell_renderer_toggle_new();
1319 column
= gtk_tree_view_column_new_with_attributes(_("Recurring"), renderer
,
1320 "active", POUNCES_MANAGER_COLUMN_RECURRING
, NULL
);
1321 gtk_tree_view_column_set_sort_column_id(column
,
1322 POUNCES_MANAGER_COLUMN_RECURRING
);
1323 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
1324 g_signal_connect(G_OBJECT(renderer
), "toggled",
1325 G_CALLBACK(pounces_manager_recurring_cb
), dialog
);
1327 /* Enable CTRL+F searching */
1328 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview
), POUNCES_MANAGER_COLUMN_TARGET
);
1329 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(treeview
), search_func
, NULL
, NULL
);
1331 /* Sort the pouncee column by default */
1332 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog
->model
),
1333 POUNCES_MANAGER_COLUMN_TARGET
,
1334 GTK_SORT_ASCENDING
);
1337 populate_pounces_list(dialog
);
1343 pidgin_pounces_manager_show(void)
1345 PouncesManager
*dialog
;
1352 if (pounces_manager
!= NULL
) {
1353 gtk_window_present(GTK_WINDOW(pounces_manager
->window
));
1357 pounces_manager
= dialog
= g_new0(PouncesManager
, 1);
1359 width
= purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/width");
1360 height
= purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/height");
1362 dialog
->window
= win
= pidgin_create_dialog(_("Buddy Pounces"), PIDGIN_HIG_BORDER
, "pounces", TRUE
);
1363 gtk_window_set_default_size(GTK_WINDOW(win
), width
, height
);
1365 g_signal_connect(G_OBJECT(win
), "delete_event",
1366 G_CALLBACK(pounces_manager_destroy_cb
), dialog
);
1367 g_signal_connect(G_OBJECT(win
), "configure_event",
1368 G_CALLBACK(pounces_manager_configure_cb
), dialog
);
1370 /* Setup the vbox */
1371 vbox
= pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win
), FALSE
, PIDGIN_HIG_BORDER
);
1373 /* List of saved buddy pounces */
1374 list
= create_pounces_list(dialog
);
1375 gtk_box_pack_start(GTK_BOX(vbox
), list
, TRUE
, TRUE
, 0);
1378 button
= pidgin_dialog_add_button(GTK_DIALOG(win
), PIDGIN_STOCK_ADD
, G_CALLBACK(pounces_manager_add_cb
), dialog
);
1379 gtk_widget_set_sensitive(button
, (purple_accounts_get_all() != NULL
));
1381 purple_signal_connect(purple_connections_get_handle(), "signed-on",
1382 pounces_manager
, PURPLE_CALLBACK(pounces_manager_connection_cb
), button
);
1383 purple_signal_connect(purple_connections_get_handle(), "signed-off",
1384 pounces_manager
, PURPLE_CALLBACK(pounces_manager_connection_cb
), button
);
1387 button
= pidgin_dialog_add_button(GTK_DIALOG(win
), PIDGIN_STOCK_MODIFY
, G_CALLBACK(pounces_manager_modify_cb
), dialog
);
1388 gtk_widget_set_sensitive(button
, FALSE
);
1389 dialog
->modify_button
= button
;
1392 button
= pidgin_dialog_add_button(GTK_DIALOG(win
), GTK_STOCK_DELETE
, G_CALLBACK(pounces_manager_delete_cb
), dialog
);
1393 gtk_widget_set_sensitive(button
, FALSE
);
1394 dialog
->delete_button
= button
;
1397 pidgin_dialog_add_button(GTK_DIALOG(win
), GTK_STOCK_CLOSE
, G_CALLBACK(pounces_manager_close_cb
), dialog
);
1399 gtk_widget_show(win
);
1403 pidgin_pounces_manager_hide(void)
1405 if (pounces_manager
== NULL
)
1408 if (pounces_manager
->window
!= NULL
)
1409 gtk_widget_destroy(pounces_manager
->window
);
1411 purple_signals_disconnect_by_handle(pounces_manager
);
1413 g_free(pounces_manager
);
1414 pounces_manager
= NULL
;
1418 pounce_cb(PurplePounce
*pounce
, PurplePounceEvent events
, void *data
)
1420 PurpleConversation
*conv
;
1421 PurpleAccount
*account
;
1423 const char *pouncee
;
1426 pouncee
= purple_pounce_get_pouncee(pounce
);
1427 account
= purple_pounce_get_pouncer(pounce
);
1429 buddy
= purple_find_buddy(account
, pouncee
);
1432 alias
= purple_buddy_get_alias(buddy
);
1439 if (purple_pounce_action_is_enabled(pounce
, "open-window"))
1441 conv
= purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM
, pouncee
, account
);
1444 conv
= purple_conversation_new(PURPLE_CONV_TYPE_IM
, account
, pouncee
);
1447 if (purple_pounce_action_is_enabled(pounce
, "popup-notify"))
1450 const char *name_shown
;
1452 reason
= purple_pounce_action_get_attribute(pounce
, "popup-notify",
1456 * Here we place the protocol name in the pounce dialog to lessen
1457 * confusion about what protocol a pounce is for.
1459 tmp
= g_strdup_printf(
1460 (events
& PURPLE_POUNCE_TYPING
) ?
1461 _("%s has started typing to you (%s)") :
1462 (events
& PURPLE_POUNCE_TYPED
) ?
1463 _("%s has paused while typing to you (%s)") :
1464 (events
& PURPLE_POUNCE_SIGNON
) ?
1465 _("%s has signed on (%s)") :
1466 (events
& PURPLE_POUNCE_IDLE_RETURN
) ?
1467 _("%s has returned from being idle (%s)") :
1468 (events
& PURPLE_POUNCE_AWAY_RETURN
) ?
1469 _("%s has returned from being away (%s)") :
1470 (events
& PURPLE_POUNCE_TYPING_STOPPED
) ?
1471 _("%s has stopped typing to you (%s)") :
1472 (events
& PURPLE_POUNCE_SIGNOFF
) ?
1473 _("%s has signed off (%s)") :
1474 (events
& PURPLE_POUNCE_IDLE
) ?
1475 _("%s has become idle (%s)") :
1476 (events
& PURPLE_POUNCE_AWAY
) ?
1477 _("%s has gone away. (%s)") :
1478 (events
& PURPLE_POUNCE_MESSAGE_RECEIVED
) ?
1479 _("%s has sent you a message. (%s)") :
1480 _("Unknown pounce event. Please report this!"),
1481 alias
, purple_account_get_protocol_name(account
));
1484 * Ok here is where I change the second argument, title, from
1485 * NULL to the account alias if we have it or the account
1486 * name if that's all we have
1488 if ((name_shown
= purple_account_get_alias(account
)) == NULL
)
1489 name_shown
= purple_account_get_username(account
);
1493 purple_notify_info(NULL
, name_shown
, tmp
, purple_date_format_full(NULL
));
1497 char *tmp2
= g_strdup_printf("%s\n\n%s", reason
, purple_date_format_full(NULL
));
1498 purple_notify_info(NULL
, name_shown
, tmp
, tmp2
);
1504 if (purple_pounce_action_is_enabled(pounce
, "send-message"))
1506 const char *message
;
1508 message
= purple_pounce_action_get_attribute(pounce
, "send-message",
1511 if (message
!= NULL
)
1513 conv
= purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM
, pouncee
, account
);
1516 conv
= purple_conversation_new(PURPLE_CONV_TYPE_IM
, account
, pouncee
);
1518 purple_conversation_write(conv
, NULL
, message
,
1519 PURPLE_MESSAGE_SEND
, time(NULL
));
1521 serv_send_im(account
->gc
, (char *)pouncee
, (char *)message
, 0);
1525 if (purple_pounce_action_is_enabled(pounce
, "execute-command"))
1527 const char *command
;
1529 command
= purple_pounce_action_get_attribute(pounce
,
1530 "execute-command", "command");
1532 if (command
!= NULL
)
1535 char *localecmd
= g_locale_from_utf8(command
, -1, NULL
,
1538 if (localecmd
!= NULL
)
1547 args
[2] = (char *)localecmd
;
1550 execvp(args
[0], args
);
1557 PROCESS_INFORMATION pi
;
1559 gchar
*message
= NULL
;
1561 memset(&pi
, 0, sizeof(pi
));
1563 if (G_WIN32_HAVE_WIDECHAR_API ()) {
1565 wchar_t *wc_cmd
= g_utf8_to_utf16(command
,
1566 -1, NULL
, NULL
, NULL
);
1568 memset(&si
, 0 , sizeof(si
));
1571 retval
= CreateProcessW(NULL
, wc_cmd
, NULL
,
1572 NULL
, 0, 0, NULL
, NULL
,
1577 char *l_cmd
= g_locale_from_utf8(command
,
1578 -1, NULL
, NULL
, NULL
);
1580 memset(&si
, 0 , sizeof(si
));
1583 retval
= CreateProcessA(NULL
, l_cmd
, NULL
,
1584 NULL
, 0, 0, NULL
, NULL
,
1590 CloseHandle(pi
.hProcess
);
1591 CloseHandle(pi
.hThread
);
1593 message
= g_win32_error_message(GetLastError());
1596 purple_debug_info("pounce",
1597 "Pounce execute command called for: "
1600 retval
? "" : "Error: ",
1601 retval
? "" : message
,
1602 retval
? "" : "\n");
1604 #endif /* !_WIN32 */
1608 if (purple_pounce_action_is_enabled(pounce
, "play-sound"))
1612 sound
= purple_pounce_action_get_attribute(pounce
,
1613 "play-sound", "filename");
1616 purple_sound_play_file(sound
, account
);
1618 purple_sound_play_event(PURPLE_SOUND_POUNCE_DEFAULT
, account
);
1623 free_pounce(PurplePounce
*pounce
)
1629 new_pounce(PurplePounce
*pounce
)
1631 purple_pounce_action_register(pounce
, "open-window");
1632 purple_pounce_action_register(pounce
, "popup-notify");
1633 purple_pounce_action_register(pounce
, "send-message");
1634 purple_pounce_action_register(pounce
, "execute-command");
1635 purple_pounce_action_register(pounce
, "play-sound");
1641 pidgin_pounces_get_handle() {
1648 pidgin_pounces_init(void)
1650 purple_pounces_register_handler(PIDGIN_UI
, pounce_cb
, new_pounce
,
1653 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/pounces");
1654 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/pounces/default_actions");
1655 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/open-window",
1657 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/popup-notify",
1659 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/send-message",
1661 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/execute-command",
1663 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/pounces/default_actions/play-sound",
1665 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/pounces/dialog");
1666 purple_prefs_add_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/width", 520);
1667 purple_prefs_add_int(PIDGIN_PREFS_ROOT
"/pounces/dialog/height", 321);
1669 purple_signal_connect(purple_connections_get_handle(), "signed-on",
1670 pidgin_pounces_get_handle(),
1671 PURPLE_CALLBACK(signed_on_off_cb
), NULL
);
1672 purple_signal_connect(purple_connections_get_handle(), "signed-off",
1673 pidgin_pounces_get_handle(),
1674 PURPLE_CALLBACK(signed_on_off_cb
), NULL
);