2 * @file gtkprivacy.c GTK+ Privacy UI
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
29 #include "connection.h"
36 #include "gtkprivacy.h"
45 GtkWidget
*add_button
;
46 GtkWidget
*remove_button
;
47 GtkWidget
*removeall_button
;
48 GtkWidget
*close_button
;
50 GtkWidget
*button_box
;
51 GtkWidget
*allow_widget
;
52 GtkWidget
*block_widget
;
54 GtkListStore
*allow_store
;
55 GtkListStore
*block_store
;
57 GtkWidget
*allow_list
;
58 GtkWidget
*block_list
;
60 gboolean in_allow_list
;
62 PurpleAccount
*account
;
64 } PidginPrivacyDialog
;
68 PurpleAccount
*account
;
72 } PidginPrivacyRequestData
;
79 } const menu_entries
[] =
81 { N_("Allow all users to contact me"), PURPLE_PRIVACY_ALLOW_ALL
},
82 { N_("Allow only the users on my buddy list"), PURPLE_PRIVACY_ALLOW_BUDDYLIST
},
83 { N_("Allow only the users below"), PURPLE_PRIVACY_ALLOW_USERS
},
84 { N_("Block all users"), PURPLE_PRIVACY_DENY_ALL
},
85 { N_("Block only the users below"), PURPLE_PRIVACY_DENY_USERS
}
88 static const size_t menu_entry_count
= sizeof(menu_entries
) / sizeof(*menu_entries
);
90 static PidginPrivacyDialog
*privacy_dialog
= NULL
;
93 rebuild_allow_list(PidginPrivacyDialog
*dialog
)
98 gtk_list_store_clear(dialog
->allow_store
);
100 for (l
= dialog
->account
->permit
; l
!= NULL
; l
= l
->next
) {
101 gtk_list_store_append(dialog
->allow_store
, &iter
);
102 gtk_list_store_set(dialog
->allow_store
, &iter
, 0, l
->data
, -1);
107 rebuild_block_list(PidginPrivacyDialog
*dialog
)
112 gtk_list_store_clear(dialog
->block_store
);
114 for (l
= dialog
->account
->deny
; l
!= NULL
; l
= l
->next
) {
115 gtk_list_store_append(dialog
->block_store
, &iter
);
116 gtk_list_store_set(dialog
->block_store
, &iter
, 0, l
->data
, -1);
121 user_selected_cb(GtkTreeSelection
*sel
, PidginPrivacyDialog
*dialog
)
123 gtk_widget_set_sensitive(dialog
->remove_button
, TRUE
);
127 build_list(PidginPrivacyDialog
*dialog
, GtkListStore
*model
,
128 GtkWidget
**ret_treeview
)
132 GtkCellRenderer
*rend
;
133 GtkTreeViewColumn
*column
;
134 GtkTreeSelection
*sel
;
136 sw
= gtk_scrolled_window_new(NULL
, NULL
);
137 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw
),
138 GTK_POLICY_AUTOMATIC
,
139 GTK_POLICY_AUTOMATIC
);
140 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw
), GTK_SHADOW_IN
);
142 treeview
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(model
));
143 *ret_treeview
= treeview
;
145 rend
= gtk_cell_renderer_text_new();
147 column
= gtk_tree_view_column_new_with_attributes(NULL
, rend
,
150 gtk_tree_view_column_set_clickable(GTK_TREE_VIEW_COLUMN(column
), TRUE
);
151 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview
), column
);
152 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview
), FALSE
);
153 gtk_container_add(GTK_CONTAINER(sw
), treeview
);
155 gtk_widget_show(treeview
);
157 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
));
159 g_signal_connect(G_OBJECT(sel
), "changed",
160 G_CALLBACK(user_selected_cb
), dialog
);
162 gtk_widget_set_size_request(sw
, -1, 200);
168 build_allow_list(PidginPrivacyDialog
*dialog
)
173 dialog
->allow_store
= gtk_list_store_new(1, G_TYPE_STRING
);
175 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog
->allow_store
), 0, GTK_SORT_ASCENDING
);
177 widget
= build_list(dialog
, dialog
->allow_store
, &list
);
179 dialog
->allow_list
= list
;
181 rebuild_allow_list(dialog
);
187 build_block_list(PidginPrivacyDialog
*dialog
)
192 dialog
->block_store
= gtk_list_store_new(1, G_TYPE_STRING
);
194 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog
->block_store
), 0, GTK_SORT_ASCENDING
);
196 widget
= build_list(dialog
, dialog
->block_store
, &list
);
198 dialog
->block_list
= list
;
200 rebuild_block_list(dialog
);
206 destroy_cb(GtkWidget
*w
, GdkEvent
*event
, PidginPrivacyDialog
*dialog
)
208 pidgin_privacy_dialog_hide();
214 select_account_cb(GtkWidget
*dropdown
, PurpleAccount
*account
,
215 PidginPrivacyDialog
*dialog
)
219 dialog
->account
= account
;
221 for (i
= 0; i
< menu_entry_count
; i
++) {
222 if (menu_entries
[i
].num
== account
->perm_deny
) {
223 gtk_combo_box_set_active(GTK_COMBO_BOX(dialog
->type_menu
), i
);
228 rebuild_allow_list(dialog
);
229 rebuild_block_list(dialog
);
233 * TODO: Setting the permit/deny setting needs to go through privacy.c
234 * Even better: the privacy API needs to not suck.
237 type_changed_cb(GtkComboBox
*combo
, PidginPrivacyDialog
*dialog
)
239 int new_type
= menu_entries
[gtk_combo_box_get_active(combo
)].num
;
241 dialog
->account
->perm_deny
= new_type
;
242 serv_set_permit_deny(purple_account_get_connection(dialog
->account
));
244 gtk_widget_hide(dialog
->allow_widget
);
245 gtk_widget_hide(dialog
->block_widget
);
246 gtk_widget_hide_all(dialog
->button_box
);
248 if (new_type
== PURPLE_PRIVACY_ALLOW_USERS
) {
249 gtk_widget_show(dialog
->allow_widget
);
250 gtk_widget_show_all(dialog
->button_box
);
251 dialog
->in_allow_list
= TRUE
;
253 else if (new_type
== PURPLE_PRIVACY_DENY_USERS
) {
254 gtk_widget_show(dialog
->block_widget
);
255 gtk_widget_show_all(dialog
->button_box
);
256 dialog
->in_allow_list
= FALSE
;
259 gtk_widget_show_all(dialog
->close_button
);
260 gtk_widget_show(dialog
->button_box
);
262 purple_blist_schedule_save();
263 pidgin_blist_refresh(purple_get_blist());
267 add_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
269 if (dialog
->in_allow_list
)
270 pidgin_request_add_permit(dialog
->account
, NULL
);
272 pidgin_request_add_block(dialog
->account
, NULL
);
276 remove_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
280 GtkTreeSelection
*sel
;
283 if (dialog
->in_allow_list
&& dialog
->allow_store
== NULL
)
286 if (!dialog
->in_allow_list
&& dialog
->block_store
== NULL
)
289 if (dialog
->in_allow_list
) {
290 model
= GTK_TREE_MODEL(dialog
->allow_store
);
291 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->allow_list
));
294 model
= GTK_TREE_MODEL(dialog
->block_store
);
295 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog
->block_list
));
298 if (gtk_tree_selection_get_selected(sel
, NULL
, &iter
))
299 gtk_tree_model_get(model
, &iter
, 0, &name
, -1);
303 if (dialog
->in_allow_list
)
304 purple_privacy_permit_remove(dialog
->account
, name
, FALSE
);
306 purple_privacy_deny_remove(dialog
->account
, name
, FALSE
);
312 removeall_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
315 if (dialog
->in_allow_list
)
316 l
= dialog
->account
->permit
;
318 l
= dialog
->account
->deny
;
323 if (dialog
->in_allow_list
)
324 purple_privacy_permit_remove(dialog
->account
, user
, FALSE
);
326 purple_privacy_deny_remove(dialog
->account
, user
, FALSE
);
331 close_cb(GtkWidget
*button
, PidginPrivacyDialog
*dialog
)
333 gtk_widget_destroy(dialog
->win
);
335 pidgin_privacy_dialog_hide();
338 static PidginPrivacyDialog
*
339 privacy_dialog_new(void)
341 PidginPrivacyDialog
*dialog
;
349 dialog
= g_new0(PidginPrivacyDialog
, 1);
351 dialog
->win
= pidgin_create_dialog(_("Privacy"), PIDGIN_HIG_BORDER
, "privacy", TRUE
);
353 g_signal_connect(G_OBJECT(dialog
->win
), "delete_event",
354 G_CALLBACK(destroy_cb
), dialog
);
357 vbox
= pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(dialog
->win
), FALSE
, PIDGIN_HIG_BORDER
);
359 /* Description label */
360 label
= gtk_label_new(
361 _("Changes to privacy settings take effect immediately."));
363 gtk_box_pack_start(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
364 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
365 gtk_widget_show(label
);
367 /* Accounts drop-down */
368 dropdown
= pidgin_account_option_menu_new(NULL
, FALSE
,
369 G_CALLBACK(select_account_cb
), NULL
, dialog
);
370 pidgin_add_widget_to_vbox(GTK_BOX(vbox
), _("Set privacy for:"), NULL
, dropdown
, TRUE
, NULL
);
371 dialog
->account
= pidgin_account_option_menu_get_selected(dropdown
);
373 /* Add the drop-down list with the allow/block types. */
374 dialog
->type_menu
= gtk_combo_box_new_text();
375 gtk_box_pack_start(GTK_BOX(vbox
), dialog
->type_menu
, FALSE
, FALSE
, 0);
376 gtk_widget_show(dialog
->type_menu
);
378 for (i
= 0; i
< menu_entry_count
; i
++) {
379 gtk_combo_box_append_text(GTK_COMBO_BOX(dialog
->type_menu
),
380 _(menu_entries
[i
].text
));
382 if (menu_entries
[i
].num
== dialog
->account
->perm_deny
)
386 gtk_combo_box_set_active(GTK_COMBO_BOX(dialog
->type_menu
), selected
);
388 g_signal_connect(G_OBJECT(dialog
->type_menu
), "changed",
389 G_CALLBACK(type_changed_cb
), dialog
);
391 /* Build the treeview for the allow list. */
392 dialog
->allow_widget
= build_allow_list(dialog
);
393 gtk_box_pack_start(GTK_BOX(vbox
), dialog
->allow_widget
, TRUE
, TRUE
, 0);
395 /* Build the treeview for the block list. */
396 dialog
->block_widget
= build_block_list(dialog
);
397 gtk_box_pack_start(GTK_BOX(vbox
), dialog
->block_widget
, TRUE
, TRUE
, 0);
399 /* Add the button box for Add, Remove, Remove All */
400 dialog
->button_box
= pidgin_dialog_get_action_area(GTK_DIALOG(dialog
->win
));
403 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), GTK_STOCK_ADD
, G_CALLBACK(add_cb
), dialog
);
404 dialog
->add_button
= button
;
407 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), GTK_STOCK_REMOVE
, G_CALLBACK(remove_cb
), dialog
);
408 dialog
->remove_button
= button
;
409 /* TODO: This button should be sensitive/invisitive more cleverly */
410 gtk_widget_set_sensitive(button
, FALSE
);
412 /* Remove All button */
413 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), _("Remove Al_l"), G_CALLBACK(removeall_cb
), dialog
);
414 dialog
->removeall_button
= button
;
417 button
= pidgin_dialog_add_button(GTK_DIALOG(dialog
->win
), GTK_STOCK_CLOSE
, G_CALLBACK(close_cb
), dialog
);
418 dialog
->close_button
= button
;
420 type_changed_cb(GTK_COMBO_BOX(dialog
->type_menu
), dialog
);
422 if (dialog
->account
->perm_deny
== PURPLE_PRIVACY_ALLOW_USERS
) {
423 gtk_widget_show(dialog
->allow_widget
);
424 gtk_widget_show(dialog
->button_box
);
425 dialog
->in_allow_list
= TRUE
;
427 else if (dialog
->account
->perm_deny
== PURPLE_PRIVACY_DENY_USERS
) {
428 gtk_widget_show(dialog
->block_widget
);
429 gtk_widget_show(dialog
->button_box
);
430 dialog
->in_allow_list
= FALSE
;
437 pidgin_privacy_dialog_show(void)
439 g_return_if_fail(purple_connections_get_all() != NULL
);
441 if (privacy_dialog
== NULL
)
442 privacy_dialog
= privacy_dialog_new();
444 gtk_widget_show(privacy_dialog
->win
);
445 gdk_window_raise(privacy_dialog
->win
->window
);
449 pidgin_privacy_dialog_hide(void)
451 if (privacy_dialog
== NULL
)
454 g_object_unref(G_OBJECT(privacy_dialog
->allow_store
));
455 g_object_unref(G_OBJECT(privacy_dialog
->block_store
));
456 g_free(privacy_dialog
);
457 privacy_dialog
= NULL
;
461 destroy_request_data(PidginPrivacyRequestData
*data
)
468 confirm_permit_block_cb(PidginPrivacyRequestData
*data
, int option
)
471 purple_privacy_deny(data
->account
, data
->name
, FALSE
, FALSE
);
473 purple_privacy_allow(data
->account
, data
->name
, FALSE
, FALSE
);
475 destroy_request_data(data
);
479 add_permit_block_cb(PidginPrivacyRequestData
*data
, const char *name
)
481 data
->name
= g_strdup(name
);
483 confirm_permit_block_cb(data
, 0);
487 pidgin_request_add_permit(PurpleAccount
*account
, const char *name
)
489 PidginPrivacyRequestData
*data
;
491 g_return_if_fail(account
!= NULL
);
493 data
= g_new0(PidginPrivacyRequestData
, 1);
494 data
->account
= account
;
495 data
->name
= g_strdup(name
);
499 purple_request_input(account
, _("Permit User"),
500 _("Type a user you permit to contact you."),
501 _("Please enter the name of the user you wish to be "
502 "able to contact you."),
503 NULL
, FALSE
, FALSE
, NULL
,
504 _("_Permit"), G_CALLBACK(add_permit_block_cb
),
505 _("Cancel"), G_CALLBACK(destroy_request_data
),
510 char *primary
= g_strdup_printf(_("Allow %s to contact you?"), name
);
512 g_strdup_printf(_("Are you sure you wish to allow "
513 "%s to contact you?"), name
);
516 purple_request_action(account
, _("Permit User"), primary
, secondary
,
520 _("_Permit"), G_CALLBACK(confirm_permit_block_cb
),
521 _("Cancel"), G_CALLBACK(destroy_request_data
));
529 pidgin_request_add_block(PurpleAccount
*account
, const char *name
)
531 PidginPrivacyRequestData
*data
;
533 g_return_if_fail(account
!= NULL
);
535 data
= g_new0(PidginPrivacyRequestData
, 1);
536 data
->account
= account
;
537 data
->name
= g_strdup(name
);
541 purple_request_input(account
, _("Block User"),
542 _("Type a user to block."),
543 _("Please enter the name of the user you wish to block."),
544 NULL
, FALSE
, FALSE
, NULL
,
545 _("_Block"), G_CALLBACK(add_permit_block_cb
),
546 _("Cancel"), G_CALLBACK(destroy_request_data
),
551 char *primary
= g_strdup_printf(_("Block %s?"), name
);
553 g_strdup_printf(_("Are you sure you want to block %s?"), name
);
555 purple_request_action(account
, _("Block User"), primary
, secondary
,
559 _("_Block"), G_CALLBACK(confirm_permit_block_cb
),
560 _("Cancel"), G_CALLBACK(destroy_request_data
));
568 pidgin_permit_added_removed(PurpleAccount
*account
, const char *name
)
570 if (privacy_dialog
!= NULL
)
571 rebuild_allow_list(privacy_dialog
);
575 pidgin_deny_added_removed(PurpleAccount
*account
, const char *name
)
577 if (privacy_dialog
!= NULL
)
578 rebuild_block_list(privacy_dialog
);
581 static PurplePrivacyUiOps privacy_ops
=
583 pidgin_permit_added_removed
,
584 pidgin_permit_added_removed
,
585 pidgin_deny_added_removed
,
586 pidgin_deny_added_removed
,
594 pidgin_privacy_get_ui_ops(void)
600 pidgin_privacy_init(void)