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
24 #include "connection.h"
29 #include "gtkaccount.h"
31 #include "gtkprivacy.h"
34 #include "gtk3compat.h"
42 GtkWidget
*add_button
;
43 GtkWidget
*remove_button
;
44 GtkWidget
*removeall_button
;
45 GtkWidget
*close_button
;
47 GtkWidget
*button_box
;
48 GtkWidget
*allow_widget
;
49 GtkWidget
*block_widget
;
51 GtkListStore
*allow_store
;
52 GtkListStore
*block_store
;
54 GtkWidget
*allow_list
;
55 GtkWidget
*block_list
;
57 gboolean in_allow_list
;
59 PurpleAccount
*account
;
61 } PidginPrivacyDialog
;
65 PurpleAccount
*account
;
69 } PidginPrivacyRequestData
;
74 PurpleAccountPrivacyType type
;
76 } const menu_entries
[] =
78 { N_("Allow all users to contact me"), PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
},
79 { N_("Allow only the users on my buddy list"), PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST
},
80 { N_("Allow only the users below"), PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
},
81 { N_("Block all users"), PURPLE_ACCOUNT_PRIVACY_DENY_ALL
},
82 { N_("Block only the users below"), PURPLE_ACCOUNT_PRIVACY_DENY_USERS
}
85 static const size_t menu_entry_count
= sizeof(menu_entries
) / sizeof(*menu_entries
);
87 static PidginPrivacyDialog
*privacy_dialog
= NULL
;
90 rebuild_allow_list(PidginPrivacyDialog
*dialog
)
95 gtk_list_store_clear(dialog
->allow_store
);
97 for (l
= purple_account_privacy_get_permitted(dialog
->account
); l
!= NULL
; l
= l
->next
) {
98 gtk_list_store_append(dialog
->allow_store
, &iter
);
99 gtk_list_store_set(dialog
->allow_store
, &iter
, 0, l
->data
, -1);
104 rebuild_block_list(PidginPrivacyDialog
*dialog
)
109 gtk_list_store_clear(dialog
->block_store
);
111 for (l
= purple_account_privacy_get_denied(dialog
->account
); l
!= NULL
; l
= l
->next
) {
112 gtk_list_store_append(dialog
->block_store
, &iter
);
113 gtk_list_store_set(dialog
->block_store
, &iter
, 0, l
->data
, -1);
118 user_selected_cb(GtkTreeSelection
*sel
, PidginPrivacyDialog
*dialog
)
120 gtk_widget_set_sensitive(dialog
->remove_button
, TRUE
);
124 build_list(PidginPrivacyDialog
*dialog
, GtkListStore
*model
,
125 GtkWidget
**ret_treeview
)
129 GtkCellRenderer
*rend
;
130 GtkTreeViewColumn
*column
;
131 GtkTreeSelection
*sel
;
133 treeview
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(model
));
134 *ret_treeview
= treeview
;
136 rend
= gtk_cell_renderer_text_new();
138 column
= gtk_tree_view_column_new_with_attributes(NULL
, rend
,
141 gtk_tree_view_column_set_clickable(GTK_TREE_VIEW_COLUMN(column
), TRUE
);
142 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
143 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview
), FALSE
);
144 sw
= pidgin_make_scrollable(treeview
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
, GTK_SHADOW_IN
, -1, 200);
146 gtk_widget_show(treeview
);
148 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
));
150 g_signal_connect(G_OBJECT(sel
), "changed",
151 G_CALLBACK(user_selected_cb
), dialog
);
157 build_allow_list(PidginPrivacyDialog
*dialog
)
162 dialog
->allow_store
= gtk_list_store_new(1, G_TYPE_STRING
);
164 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog
->allow_store
), 0, GTK_SORT_ASCENDING
);
166 widget
= build_list(dialog
, dialog
->allow_store
, &list
);
168 dialog
->allow_list
= list
;
170 rebuild_allow_list(dialog
);
176 build_block_list(PidginPrivacyDialog
*dialog
)
181 dialog
->block_store
= gtk_list_store_new(1, G_TYPE_STRING
);
183 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog
->block_store
), 0, GTK_SORT_ASCENDING
);
185 widget
= build_list(dialog
, dialog
->block_store
, &list
);
187 dialog
->block_list
= list
;
189 rebuild_block_list(dialog
);
195 destroy_cb(GtkWidget
*w
, GdkEvent
*event
, PidginPrivacyDialog
*dialog
)
197 pidgin_privacy_dialog_hide();
203 select_account_cb(GtkWidget
*dropdown
, PurpleAccount
*account
,
204 PidginPrivacyDialog
*dialog
)
208 dialog
->account
= account
;
210 for (i
= 0; i
< menu_entry_count
; i
++) {
211 if (menu_entries
[i
].type
== purple_account_get_privacy_type(account
)) {
212 gtk_combo_box_set_active(GTK_COMBO_BOX(dialog
->type_menu
), i
);
217 rebuild_allow_list(dialog
);
218 rebuild_block_list(dialog
);
222 * TODO: Setting the permit/deny setting needs to go through privacy.c
223 * Even better: the privacy API needs to not suck.
226 type_changed_cb(GtkComboBox
*combo
, PidginPrivacyDialog
*dialog
)
228 PurpleAccountPrivacyType new_type
=
229 menu_entries
[gtk_combo_box_get_active(combo
)].type
;
231 purple_account_set_privacy_type(dialog
->account
, new_type
);
232 purple_serv_set_permit_deny(purple_account_get_connection(dialog
->account
));
234 gtk_widget_hide(dialog
->allow_widget
);
235 gtk_widget_hide(dialog
->block_widget
);
236 gtk_widget_hide(dialog
->button_box
);
238 if (new_type
== PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
) {
239 gtk_widget_show(dialog
->allow_widget
);
240 gtk_widget_show_all(dialog
->button_box
);
241 dialog
->in_allow_list
= TRUE
;
243 else if (new_type
== PURPLE_ACCOUNT_PRIVACY_DENY_USERS
) {
244 gtk_widget_show(dialog
->block_widget
);
245 gtk_widget_show_all(dialog
->button_box
);
246 dialog
->in_allow_list
= FALSE
;
249 gtk_widget_show_all(dialog
->close_button
);
250 gtk_widget_show(dialog
->button_box
);
252 purple_blist_schedule_save();
253 pidgin_blist_refresh(purple_blist_get_buddy_list());
257 add_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
259 if (dialog
->in_allow_list
)
260 pidgin_request_add_permit(dialog
->account
, NULL
);
262 pidgin_request_add_block(dialog
->account
, NULL
);
266 remove_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
270 GtkTreeSelection
*sel
;
273 if (dialog
->in_allow_list
&& dialog
->allow_store
== NULL
)
276 if (!dialog
->in_allow_list
&& dialog
->block_store
== NULL
)
279 if (dialog
->in_allow_list
) {
280 model
= GTK_TREE_MODEL(dialog
->allow_store
);
281 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->allow_list
));
284 model
= GTK_TREE_MODEL(dialog
->block_store
);
285 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->block_list
));
288 if (gtk_tree_selection_get_selected(sel
, NULL
, &iter
))
289 gtk_tree_model_get(model
, &iter
, 0, &name
, -1);
293 if (dialog
->in_allow_list
)
294 purple_account_privacy_permit_remove(dialog
->account
, name
, FALSE
);
296 purple_account_privacy_deny_remove(dialog
->account
, name
, FALSE
);
302 removeall_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
305 if (dialog
->in_allow_list
)
306 l
= purple_account_privacy_get_permitted(dialog
->account
);
308 l
= purple_account_privacy_get_denied(dialog
->account
);
313 if (dialog
->in_allow_list
)
314 purple_account_privacy_permit_remove(dialog
->account
, user
, FALSE
);
316 purple_account_privacy_deny_remove(dialog
->account
, user
, FALSE
);
321 close_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
323 gtk_widget_destroy(dialog
->win
);
325 pidgin_privacy_dialog_hide();
328 static PidginPrivacyDialog
*
329 privacy_dialog_new(void)
331 PidginPrivacyDialog
*dialog
;
336 gssize selected
= -1;
339 dialog
= g_new0(PidginPrivacyDialog
, 1);
341 dialog
->win
= pidgin_create_dialog(_("Privacy"), PIDGIN_HIG_BORDER
, "privacy", TRUE
);
343 g_signal_connect(G_OBJECT(dialog
->win
), "delete_event",
344 G_CALLBACK(destroy_cb
), dialog
);
347 vbox
= pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(dialog
->win
), FALSE
, PIDGIN_HIG_BORDER
);
349 /* Description label */
350 label
= gtk_label_new(
351 _("Changes to privacy settings take effect immediately."));
353 gtk_box_pack_start(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
354 gtk_label_set_xalign(GTK_LABEL(label
), 0);
355 gtk_widget_show(label
);
357 /* Accounts drop-down */
358 dropdown
= pidgin_account_option_menu_new(NULL
, FALSE
,
359 G_CALLBACK(select_account_cb
), NULL
, dialog
);
360 pidgin_add_widget_to_vbox(GTK_BOX(vbox
), _("Set privacy for:"), NULL
, dropdown
, TRUE
, NULL
);
361 dialog
->account
= pidgin_account_option_menu_get_selected(dropdown
);
363 /* Add the drop-down list with the allow/block types. */
364 dialog
->type_menu
= gtk_combo_box_text_new();
365 gtk_box_pack_start(GTK_BOX(vbox
), dialog
->type_menu
, FALSE
, FALSE
, 0);
366 gtk_widget_show(dialog
->type_menu
);
368 for (i
= 0; i
< menu_entry_count
; i
++) {
369 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(dialog
->type_menu
),
370 _(menu_entries
[i
].text
));
372 if (menu_entries
[i
].type
== purple_account_get_privacy_type(dialog
->account
))
373 selected
= (gssize
)i
;
376 gtk_combo_box_set_active(GTK_COMBO_BOX(dialog
->type_menu
), selected
);
378 g_signal_connect(G_OBJECT(dialog
->type_menu
), "changed",
379 G_CALLBACK(type_changed_cb
), dialog
);
381 /* Build the treeview for the allow list. */
382 dialog
->allow_widget
= build_allow_list(dialog
);
383 gtk_box_pack_start(GTK_BOX(vbox
), dialog
->allow_widget
, TRUE
, TRUE
, 0);
385 /* Build the treeview for the block list. */
386 dialog
->block_widget
= build_block_list(dialog
);
387 gtk_box_pack_start(GTK_BOX(vbox
), dialog
->block_widget
, TRUE
, TRUE
, 0);
389 /* Add the button box for Add, Remove, Remove All */
390 dialog
->button_box
= pidgin_dialog_get_action_area(GTK_DIALOG(dialog
->win
));
393 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), GTK_STOCK_ADD
, G_CALLBACK(add_cb
), dialog
);
394 dialog
->add_button
= button
;
397 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), GTK_STOCK_REMOVE
, G_CALLBACK(remove_cb
), dialog
);
398 dialog
->remove_button
= button
;
399 /* TODO: This button should be sensitive/invisitive more cleverly */
400 gtk_widget_set_sensitive(button
, FALSE
);
402 /* Remove All button */
403 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), _("Remove Al_l"), G_CALLBACK(removeall_cb
), dialog
);
404 dialog
->removeall_button
= button
;
407 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), GTK_STOCK_CLOSE
, G_CALLBACK(close_cb
), dialog
);
408 dialog
->close_button
= button
;
410 type_changed_cb(GTK_COMBO_BOX(dialog
->type_menu
), dialog
);
412 if (purple_account_get_privacy_type(dialog
->account
) == PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
) {
413 gtk_widget_show(dialog
->allow_widget
);
414 gtk_widget_show(dialog
->button_box
);
415 dialog
->in_allow_list
= TRUE
;
417 else if (purple_account_get_privacy_type(dialog
->account
) == PURPLE_ACCOUNT_PRIVACY_DENY_USERS
) {
418 gtk_widget_show(dialog
->block_widget
);
419 gtk_widget_show(dialog
->button_box
);
420 dialog
->in_allow_list
= FALSE
;
427 pidgin_privacy_dialog_show(void)
429 g_return_if_fail(purple_connections_get_all() != NULL
);
431 if (privacy_dialog
== NULL
)
432 privacy_dialog
= privacy_dialog_new();
434 gtk_widget_show(privacy_dialog
->win
);
435 gdk_window_raise(gtk_widget_get_window(privacy_dialog
->win
));
439 pidgin_privacy_dialog_hide(void)
441 if (privacy_dialog
== NULL
)
444 g_object_unref(G_OBJECT(privacy_dialog
->allow_store
));
445 g_object_unref(G_OBJECT(privacy_dialog
->block_store
));
446 g_free(privacy_dialog
);
447 privacy_dialog
= NULL
;
451 destroy_request_data(PidginPrivacyRequestData
*data
)
458 confirm_permit_block_cb(PidginPrivacyRequestData
*data
, int option
)
461 purple_account_privacy_deny(data
->account
, data
->name
);
463 purple_account_privacy_allow(data
->account
, data
->name
);
465 destroy_request_data(data
);
469 add_permit_block_cb(PidginPrivacyRequestData
*data
, const char *name
)
471 data
->name
= g_strdup(name
);
473 confirm_permit_block_cb(data
, 0);
477 pidgin_request_add_permit(PurpleAccount
*account
, const char *name
)
479 PidginPrivacyRequestData
*data
;
481 g_return_if_fail(account
!= NULL
);
483 data
= g_new0(PidginPrivacyRequestData
, 1);
484 data
->account
= account
;
485 data
->name
= g_strdup(name
);
489 purple_request_input(account
, _("Permit User"),
490 _("Type a user you permit to contact you."),
491 _("Please enter the name of the user you wish to be "
492 "able to contact you."),
493 NULL
, FALSE
, FALSE
, NULL
,
494 _("_Permit"), G_CALLBACK(add_permit_block_cb
),
495 _("Cancel"), G_CALLBACK(destroy_request_data
),
496 purple_request_cpar_from_account(account
),
500 char *primary
= g_strdup_printf(_("Allow %s to contact you?"), name
);
502 g_strdup_printf(_("Are you sure you wish to allow "
503 "%s to contact you?"), name
);
506 purple_request_action(account
, _("Permit User"), primary
,
507 secondary
, 0, purple_request_cpar_from_account(account
),
509 _("_Permit"), G_CALLBACK(confirm_permit_block_cb
),
510 _("Cancel"), G_CALLBACK(destroy_request_data
));
518 pidgin_request_add_block(PurpleAccount
*account
, const char *name
)
520 PidginPrivacyRequestData
*data
;
522 g_return_if_fail(account
!= NULL
);
524 data
= g_new0(PidginPrivacyRequestData
, 1);
525 data
->account
= account
;
526 data
->name
= g_strdup(name
);
530 purple_request_input(account
, _("Block User"),
531 _("Type a user to block."),
532 _("Please enter the name of the user you wish to block."),
533 NULL
, FALSE
, FALSE
, NULL
,
534 _("_Block"), G_CALLBACK(add_permit_block_cb
),
535 _("Cancel"), G_CALLBACK(destroy_request_data
),
536 purple_request_cpar_from_account(account
),
540 char *primary
= g_strdup_printf(_("Block %s?"), name
);
542 g_strdup_printf(_("Are you sure you want to block %s?"), name
);
544 purple_request_action(account
, _("Block User"), primary
,
545 secondary
, 0, purple_request_cpar_from_account(account
),
547 _("_Block"), G_CALLBACK(confirm_permit_block_cb
),
548 _("Cancel"), G_CALLBACK(destroy_request_data
));
556 pidgin_permit_added_removed(PurpleAccount
*account
, const char *name
)
558 if (privacy_dialog
!= NULL
)
559 rebuild_allow_list(privacy_dialog
);
563 pidgin_deny_added_removed(PurpleAccount
*account
, const char *name
)
565 if (privacy_dialog
!= NULL
)
566 rebuild_block_list(privacy_dialog
);
570 pidgin_privacy_init(void)
572 PurpleAccountUiOps
*ops
= pidgin_accounts_get_ui_ops();
574 ops
->permit_added
= ops
->permit_removed
= pidgin_permit_added_removed
;
575 ops
->deny_added
= ops
->deny_removed
= pidgin_deny_added_removed
;