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"
33 #include "pidginaccountchooser.h"
35 #include "gtk3compat.h"
43 GtkWidget
*add_button
;
44 GtkWidget
*remove_button
;
45 GtkWidget
*removeall_button
;
46 GtkWidget
*close_button
;
48 GtkWidget
*button_box
;
49 GtkWidget
*allow_widget
;
50 GtkWidget
*block_widget
;
52 GtkListStore
*allow_store
;
53 GtkListStore
*block_store
;
55 GtkWidget
*allow_list
;
56 GtkWidget
*block_list
;
58 gboolean in_allow_list
;
60 PurpleAccount
*account
;
62 } PidginPrivacyDialog
;
66 PurpleAccount
*account
;
70 } PidginPrivacyRequestData
;
75 PurpleAccountPrivacyType type
;
77 } const menu_entries
[] =
79 { N_("Allow all users to contact me"), PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
},
80 { N_("Allow only the users on my buddy list"), PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST
},
81 { N_("Allow only the users below"), PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
},
82 { N_("Block all users"), PURPLE_ACCOUNT_PRIVACY_DENY_ALL
},
83 { N_("Block only the users below"), PURPLE_ACCOUNT_PRIVACY_DENY_USERS
}
86 static const size_t menu_entry_count
= sizeof(menu_entries
) / sizeof(*menu_entries
);
88 static PidginPrivacyDialog
*privacy_dialog
= NULL
;
91 rebuild_allow_list(PidginPrivacyDialog
*dialog
)
96 gtk_list_store_clear(dialog
->allow_store
);
98 for (l
= purple_account_privacy_get_permitted(dialog
->account
); l
!= NULL
; l
= l
->next
) {
99 gtk_list_store_append(dialog
->allow_store
, &iter
);
100 gtk_list_store_set(dialog
->allow_store
, &iter
, 0, l
->data
, -1);
105 rebuild_block_list(PidginPrivacyDialog
*dialog
)
110 gtk_list_store_clear(dialog
->block_store
);
112 for (l
= purple_account_privacy_get_denied(dialog
->account
); l
!= NULL
; l
= l
->next
) {
113 gtk_list_store_append(dialog
->block_store
, &iter
);
114 gtk_list_store_set(dialog
->block_store
, &iter
, 0, l
->data
, -1);
119 user_selected_cb(GtkTreeSelection
*sel
, PidginPrivacyDialog
*dialog
)
121 gtk_widget_set_sensitive(dialog
->remove_button
, TRUE
);
125 build_list(PidginPrivacyDialog
*dialog
, GtkListStore
*model
,
126 GtkWidget
**ret_treeview
)
130 GtkCellRenderer
*rend
;
131 GtkTreeViewColumn
*column
;
132 GtkTreeSelection
*sel
;
134 treeview
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(model
));
135 *ret_treeview
= treeview
;
137 rend
= gtk_cell_renderer_text_new();
139 column
= gtk_tree_view_column_new_with_attributes(NULL
, rend
,
142 gtk_tree_view_column_set_clickable(GTK_TREE_VIEW_COLUMN(column
), TRUE
);
143 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
144 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview
), FALSE
);
145 sw
= pidgin_make_scrollable(treeview
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
, GTK_SHADOW_IN
, -1, 200);
147 gtk_widget_show(treeview
);
149 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
));
151 g_signal_connect(G_OBJECT(sel
), "changed",
152 G_CALLBACK(user_selected_cb
), dialog
);
158 build_allow_list(PidginPrivacyDialog
*dialog
)
163 dialog
->allow_store
= gtk_list_store_new(1, G_TYPE_STRING
);
165 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog
->allow_store
), 0, GTK_SORT_ASCENDING
);
167 widget
= build_list(dialog
, dialog
->allow_store
, &list
);
169 dialog
->allow_list
= list
;
171 rebuild_allow_list(dialog
);
177 build_block_list(PidginPrivacyDialog
*dialog
)
182 dialog
->block_store
= gtk_list_store_new(1, G_TYPE_STRING
);
184 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog
->block_store
), 0, GTK_SORT_ASCENDING
);
186 widget
= build_list(dialog
, dialog
->block_store
, &list
);
188 dialog
->block_list
= list
;
190 rebuild_block_list(dialog
);
196 destroy_cb(GtkWidget
*w
, GdkEvent
*event
, PidginPrivacyDialog
*dialog
)
198 pidgin_privacy_dialog_hide();
204 select_account_cb(GtkWidget
*chooser
, PidginPrivacyDialog
*dialog
)
206 PurpleAccount
*account
= pidgin_account_chooser_get_selected(chooser
);
209 dialog
->account
= account
;
211 for (i
= 0; i
< menu_entry_count
; i
++) {
212 if (menu_entries
[i
].type
== purple_account_get_privacy_type(account
)) {
213 gtk_combo_box_set_active(GTK_COMBO_BOX(dialog
->type_menu
), i
);
218 rebuild_allow_list(dialog
);
219 rebuild_block_list(dialog
);
223 * TODO: Setting the permit/deny setting needs to go through privacy.c
224 * Even better: the privacy API needs to not suck.
227 type_changed_cb(GtkComboBox
*combo
, PidginPrivacyDialog
*dialog
)
229 PurpleAccountPrivacyType new_type
=
230 menu_entries
[gtk_combo_box_get_active(combo
)].type
;
232 purple_account_set_privacy_type(dialog
->account
, new_type
);
233 purple_serv_set_permit_deny(purple_account_get_connection(dialog
->account
));
235 gtk_widget_hide(dialog
->allow_widget
);
236 gtk_widget_hide(dialog
->block_widget
);
237 gtk_widget_hide(dialog
->button_box
);
239 if (new_type
== PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
) {
240 gtk_widget_show(dialog
->allow_widget
);
241 gtk_widget_show_all(dialog
->button_box
);
242 dialog
->in_allow_list
= TRUE
;
244 else if (new_type
== PURPLE_ACCOUNT_PRIVACY_DENY_USERS
) {
245 gtk_widget_show(dialog
->block_widget
);
246 gtk_widget_show_all(dialog
->button_box
);
247 dialog
->in_allow_list
= FALSE
;
250 gtk_widget_show_all(dialog
->close_button
);
251 gtk_widget_show(dialog
->button_box
);
253 purple_blist_schedule_save();
254 pidgin_blist_refresh(purple_blist_get_default());
258 add_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
260 if (dialog
->in_allow_list
)
261 pidgin_request_add_permit(dialog
->account
, NULL
);
263 pidgin_request_add_block(dialog
->account
, NULL
);
267 remove_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
271 GtkTreeSelection
*sel
;
274 if (dialog
->in_allow_list
&& dialog
->allow_store
== NULL
)
277 if (!dialog
->in_allow_list
&& dialog
->block_store
== NULL
)
280 if (dialog
->in_allow_list
) {
281 model
= GTK_TREE_MODEL(dialog
->allow_store
);
282 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->allow_list
));
285 model
= GTK_TREE_MODEL(dialog
->block_store
);
286 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->block_list
));
289 if (gtk_tree_selection_get_selected(sel
, NULL
, &iter
))
290 gtk_tree_model_get(model
, &iter
, 0, &name
, -1);
294 if (dialog
->in_allow_list
)
295 purple_account_privacy_permit_remove(dialog
->account
, name
, FALSE
);
297 purple_account_privacy_deny_remove(dialog
->account
, name
, FALSE
);
303 removeall_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
306 if (dialog
->in_allow_list
)
307 l
= purple_account_privacy_get_permitted(dialog
->account
);
309 l
= purple_account_privacy_get_denied(dialog
->account
);
314 if (dialog
->in_allow_list
)
315 purple_account_privacy_permit_remove(dialog
->account
, user
, FALSE
);
317 purple_account_privacy_deny_remove(dialog
->account
, user
, FALSE
);
322 close_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
324 gtk_widget_destroy(dialog
->win
);
326 pidgin_privacy_dialog_hide();
329 static PidginPrivacyDialog
*
330 privacy_dialog_new(void)
332 PidginPrivacyDialog
*dialog
;
337 gssize selected
= -1;
340 dialog
= g_new0(PidginPrivacyDialog
, 1);
342 dialog
->win
= pidgin_create_dialog(_("Privacy"), PIDGIN_HIG_BORDER
, "privacy", TRUE
);
344 g_signal_connect(G_OBJECT(dialog
->win
), "delete_event",
345 G_CALLBACK(destroy_cb
), dialog
);
348 vbox
= pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(dialog
->win
), FALSE
, PIDGIN_HIG_BORDER
);
350 /* Description label */
351 label
= gtk_label_new(
352 _("Changes to privacy settings take effect immediately."));
354 gtk_box_pack_start(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
355 gtk_label_set_xalign(GTK_LABEL(label
), 0);
356 gtk_widget_show(label
);
358 /* Accounts drop-down */
359 dropdown
= pidgin_account_chooser_new(NULL
, FALSE
);
360 pidgin_add_widget_to_vbox(GTK_BOX(vbox
), _("Set privacy for:"), NULL
, dropdown
, TRUE
, NULL
);
361 g_signal_connect(dropdown
, "changed", G_CALLBACK(select_account_cb
),
363 dialog
->account
= pidgin_account_chooser_get_selected(dropdown
);
365 /* Add the drop-down list with the allow/block types. */
366 dialog
->type_menu
= gtk_combo_box_text_new();
367 gtk_box_pack_start(GTK_BOX(vbox
), dialog
->type_menu
, FALSE
, FALSE
, 0);
368 gtk_widget_show(dialog
->type_menu
);
370 for (i
= 0; i
< menu_entry_count
; i
++) {
371 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(dialog
->type_menu
),
372 _(menu_entries
[i
].text
));
374 if (menu_entries
[i
].type
== purple_account_get_privacy_type(dialog
->account
))
375 selected
= (gssize
)i
;
378 gtk_combo_box_set_active(GTK_COMBO_BOX(dialog
->type_menu
), selected
);
380 g_signal_connect(G_OBJECT(dialog
->type_menu
), "changed",
381 G_CALLBACK(type_changed_cb
), dialog
);
383 /* Build the treeview for the allow list. */
384 dialog
->allow_widget
= build_allow_list(dialog
);
385 gtk_box_pack_start(GTK_BOX(vbox
), dialog
->allow_widget
, TRUE
, TRUE
, 0);
387 /* Build the treeview for the block list. */
388 dialog
->block_widget
= build_block_list(dialog
);
389 gtk_box_pack_start(GTK_BOX(vbox
), dialog
->block_widget
, TRUE
, TRUE
, 0);
391 /* Add the button box for Add, Remove, Remove All */
392 dialog
->button_box
= pidgin_dialog_get_action_area(GTK_DIALOG(dialog
->win
));
395 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), GTK_STOCK_ADD
, G_CALLBACK(add_cb
), dialog
);
396 dialog
->add_button
= button
;
399 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), GTK_STOCK_REMOVE
, G_CALLBACK(remove_cb
), dialog
);
400 dialog
->remove_button
= button
;
401 /* TODO: This button should be sensitive/invisitive more cleverly */
402 gtk_widget_set_sensitive(button
, FALSE
);
404 /* Remove All button */
405 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), _("Remove Al_l"), G_CALLBACK(removeall_cb
), dialog
);
406 dialog
->removeall_button
= button
;
409 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), GTK_STOCK_CLOSE
, G_CALLBACK(close_cb
), dialog
);
410 dialog
->close_button
= button
;
412 type_changed_cb(GTK_COMBO_BOX(dialog
->type_menu
), dialog
);
414 if (purple_account_get_privacy_type(dialog
->account
) == PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
) {
415 gtk_widget_show(dialog
->allow_widget
);
416 gtk_widget_show(dialog
->button_box
);
417 dialog
->in_allow_list
= TRUE
;
419 else if (purple_account_get_privacy_type(dialog
->account
) == PURPLE_ACCOUNT_PRIVACY_DENY_USERS
) {
420 gtk_widget_show(dialog
->block_widget
);
421 gtk_widget_show(dialog
->button_box
);
422 dialog
->in_allow_list
= FALSE
;
429 pidgin_privacy_dialog_show(void)
431 g_return_if_fail(purple_connections_get_all() != NULL
);
433 if (privacy_dialog
== NULL
)
434 privacy_dialog
= privacy_dialog_new();
436 gtk_widget_show(privacy_dialog
->win
);
437 gdk_window_raise(gtk_widget_get_window(privacy_dialog
->win
));
441 pidgin_privacy_dialog_hide(void)
443 if (privacy_dialog
== NULL
)
446 g_object_unref(G_OBJECT(privacy_dialog
->allow_store
));
447 g_object_unref(G_OBJECT(privacy_dialog
->block_store
));
448 g_free(privacy_dialog
);
449 privacy_dialog
= NULL
;
453 destroy_request_data(PidginPrivacyRequestData
*data
)
460 confirm_permit_block_cb(PidginPrivacyRequestData
*data
, int option
)
463 purple_account_privacy_deny(data
->account
, data
->name
);
465 purple_account_privacy_allow(data
->account
, data
->name
);
467 destroy_request_data(data
);
471 add_permit_block_cb(PidginPrivacyRequestData
*data
, const char *name
)
473 data
->name
= g_strdup(name
);
475 confirm_permit_block_cb(data
, 0);
479 pidgin_request_add_permit(PurpleAccount
*account
, const char *name
)
481 PidginPrivacyRequestData
*data
;
483 g_return_if_fail(account
!= NULL
);
485 data
= g_new0(PidginPrivacyRequestData
, 1);
486 data
->account
= account
;
487 data
->name
= g_strdup(name
);
491 purple_request_input(account
, _("Permit User"),
492 _("Type a user you permit to contact you."),
493 _("Please enter the name of the user you wish to be "
494 "able to contact you."),
495 NULL
, FALSE
, FALSE
, NULL
,
496 _("_Permit"), G_CALLBACK(add_permit_block_cb
),
497 _("Cancel"), G_CALLBACK(destroy_request_data
),
498 purple_request_cpar_from_account(account
),
502 char *primary
= g_strdup_printf(_("Allow %s to contact you?"), name
);
504 g_strdup_printf(_("Are you sure you wish to allow "
505 "%s to contact you?"), name
);
508 purple_request_action(account
, _("Permit User"), primary
,
509 secondary
, 0, purple_request_cpar_from_account(account
),
511 _("_Permit"), G_CALLBACK(confirm_permit_block_cb
),
512 _("Cancel"), G_CALLBACK(destroy_request_data
));
520 pidgin_request_add_block(PurpleAccount
*account
, const char *name
)
522 PidginPrivacyRequestData
*data
;
524 g_return_if_fail(account
!= NULL
);
526 data
= g_new0(PidginPrivacyRequestData
, 1);
527 data
->account
= account
;
528 data
->name
= g_strdup(name
);
532 purple_request_input(account
, _("Block User"),
533 _("Type a user to block."),
534 _("Please enter the name of the user you wish to block."),
535 NULL
, FALSE
, FALSE
, NULL
,
536 _("_Block"), G_CALLBACK(add_permit_block_cb
),
537 _("Cancel"), G_CALLBACK(destroy_request_data
),
538 purple_request_cpar_from_account(account
),
542 char *primary
= g_strdup_printf(_("Block %s?"), name
);
544 g_strdup_printf(_("Are you sure you want to block %s?"), name
);
546 purple_request_action(account
, _("Block User"), primary
,
547 secondary
, 0, purple_request_cpar_from_account(account
),
549 _("_Block"), G_CALLBACK(confirm_permit_block_cb
),
550 _("Cancel"), G_CALLBACK(destroy_request_data
));
558 pidgin_permit_added_removed(PurpleAccount
*account
, const char *name
)
560 if (privacy_dialog
!= NULL
)
561 rebuild_allow_list(privacy_dialog
);
565 pidgin_deny_added_removed(PurpleAccount
*account
, const char *name
)
567 if (privacy_dialog
!= NULL
)
568 rebuild_block_list(privacy_dialog
);
572 pidgin_privacy_init(void)
574 PurpleAccountUiOps
*ops
= pidgin_accounts_get_ui_ops();
576 ops
->permit_added
= ops
->permit_removed
= pidgin_permit_added_removed
;
577 ops
->deny_added
= ops
->deny_removed
= pidgin_deny_added_removed
;