/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Copyright (C) 2002-2004 Novell, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "exchange-permissions-dialog.h"
#include "exchange-hierarchy.h"
#include "exchange-user-dialog.h"
#include "e2k-context.h"
#include "e2k-global-catalog.h"
#include "e2k-propnames.h"
#include "e2k-sid.h"
#include "e2k-security-descriptor.h"
#include "e2k-uri.h"
#include "e2k-utils.h"
#include "e-folder-exchange.h"
#include "exchange-account.h"
#include "exchange-operations.h"
#include <e-util/e-dialog-utils.h>
#include <e-util/e-error.h>
#include <glade/glade-xml.h>
struct _ExchangePermissionsDialogPrivate {
ExchangeAccount *account;
char *base_uri, *folder_path;
E2kSecurityDescriptor *sd;
gboolean changed;
gboolean frozen;
/* The user list */
GtkTreeView *list_view;
GtkListStore *list_store;
GtkTreeSelection *list_selection;
E2kSid *selected_sid;
/* The Role menu */
GtkComboBox *role_optionmenu;
/* Custom label is added or not */
gboolean custom_added;
GtkWidget *separator, *custom;
E2kPermissionsRole selected_role;
/* The toggles */
GtkToggleButton *read_items_check, *create_items_check;
GtkToggleButton *create_subfolders_check, *folder_visible_check;
GtkToggleButton *folder_owner_check, *folder_contact_check;
GtkToggleButton *edit_none_radio, *edit_own_radio, *edit_all_radio;
GtkToggleButton *delete_none_radio, *delete_own_radio, *delete_all_radio;
guint32 selected_perms;
};
enum {
EXCHANGE_PERMISSIONS_DIALOG_NAME_COLUMN,
EXCHANGE_PERMISSIONS_DIALOG_ROLE_COLUMN,
EXCHANGE_PERMISSIONS_DIALOG_SID_COLUMN,
EXCHANGE_PERMISSIONS_DIALOG_NUM_COLUMNS
};
#define PARENT_TYPE GTK_TYPE_DIALOG
static GtkDialogClass *parent_class = NULL;
static void
finalize (GObject *object)
{
ExchangePermissionsDialog *dialog =
EXCHANGE_PERMISSIONS_DIALOG (object);
g_free (dialog->priv->base_uri);
g_free (dialog->priv->folder_path);
if (dialog->priv->sd)
g_object_unref (dialog->priv->sd);
g_free (dialog->priv);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
class_init (GObjectClass *object_class)
{
parent_class = g_type_class_ref (PARENT_TYPE);
/* virtual method override */
object_class->finalize = finalize;
}
static void
init (GObject *object)
{
ExchangePermissionsDialog *dialog =
EXCHANGE_PERMISSIONS_DIALOG (object);
dialog->priv = g_new0 (ExchangePermissionsDialogPrivate, 1);
}
E2K_MAKE_TYPE (exchange_permissions_dialog, ExchangePermissionsDialog, class_init, init, PARENT_TYPE)
static void get_widgets (ExchangePermissionsDialog *dialog,
GladeXML *xml);
static void setup_user_list (ExchangePermissionsDialog *dialog);
static void display_permissions (ExchangePermissionsDialog *dialog);
static void dialog_response (ExchangePermissionsDialog *dialog,
int response, gpointer user_data);
static const char *sd_props[] = {
E2K_PR_EXCHANGE_SD_BINARY,
E2K_PR_EXCHANGE_SD_XML
};
static const int n_sd_props = sizeof (sd_props) / sizeof (sd_props[0]);
/**
* exchange_permissions_dialog_new:
* @account: an account
* @folder: the folder whose permissions are to be editted
* @parent: a widget in the dialog's parent window
*
* Creates and displays a modeless permissions editor dialog for @folder.
**/
void
exchange_permissions_dialog_new (ExchangeAccount *account,
EFolder *folder,
GtkWidget *parent)
{
ExchangePermissionsDialog *dialog;
const char *base_uri, *folder_uri, *folder_path;
E2kContext *ctx;
ExchangeHierarchy *hier;
GladeXML *xml;
GtkWidget *box;
char *title;
E2kHTTPStatus status;
E2kResult *results;
int nresults = 0;
xmlNode *xml_form;
GByteArray *binary_form;
g_return_if_fail (folder);
ctx = exchange_account_get_context (account);
g_return_if_fail (ctx);
xml = glade_xml_new (
CONNECTOR_GLADEDIR "/exchange-permissions-dialog.glade",
"permissions_vbox", PACKAGE);
g_return_if_fail (xml != NULL);
/* Create the dialog */
dialog = g_object_new (EXCHANGE_TYPE_PERMISSIONS_DIALOG, NULL);
title = g_strdup_printf (_("Permissions for %s"),
e_folder_get_name (folder));
gtk_window_set_title (GTK_WINDOW (dialog), title);
g_free (title);
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
g_signal_connect (dialog, "response",
G_CALLBACK (dialog_response), NULL);
dialog->priv->changed = FALSE;
/* Put the widgets from the glade file into it */
box = glade_xml_get_widget (xml, "permissions_vbox");
g_object_ref (box);
gtk_widget_unparent (box);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
box, TRUE, TRUE, 0);
g_object_unref (box);
get_widgets (dialog, xml);
g_object_unref (xml);
dialog->priv->account = account;
g_object_ref (account);
hier = e_folder_exchange_get_hierarchy (folder);
base_uri = e_folder_exchange_get_internal_uri (hier->toplevel);
dialog->priv->base_uri = g_strdup (base_uri);
folder_uri = e_folder_exchange_get_internal_uri (folder);
folder_path = e2k_uri_relative (dialog->priv->base_uri, folder_uri);
dialog->priv->folder_path = g_strdup (folder_path);
/* And fetch the security descriptor */
status = e2k_context_propfind (ctx, NULL, folder_uri,
sd_props, n_sd_props,
&results, &nresults);
if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status) || nresults < 1) {
lose:
e_error_run (GTK_WINDOW (parent), ERROR_DOMAIN ":perm-read-error", NULL);
gtk_widget_destroy (GTK_WIDGET (dialog));
if (nresults)
e2k_results_free (results, nresults);
return;
}
xml_form = e2k_properties_get_prop (results[0].props,
E2K_PR_EXCHANGE_SD_XML);
binary_form = e2k_properties_get_prop (results[0].props,
E2K_PR_EXCHANGE_SD_BINARY);
if (!xml_form || !binary_form)
goto lose;
dialog->priv->sd = e2k_security_descriptor_new (xml_form, binary_form);
if (!dialog->priv->sd)
goto lose;
setup_user_list (dialog);
gtk_widget_show (GTK_WIDGET (dialog));
if (nresults)
e2k_results_free (results, nresults);
}
static void
dialog_response (ExchangePermissionsDialog *dialog, int response,
gpointer user_data)
{
E2kContext *ctx;
GByteArray *binsd;
E2kProperties *props;
E2kResultIter *iter;
E2kResult *result;
E2kHTTPStatus status;
if (response != GTK_RESPONSE_OK || !dialog->priv->changed) {
gtk_widget_destroy (GTK_WIDGET (dialog));
return;
}
ctx = exchange_account_get_context (dialog->priv->account);
g_return_if_fail (ctx != NULL);
binsd = e2k_security_descriptor_to_binary (dialog->priv->sd);
if (!binsd) {
e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":perm-update-error", "", NULL);
return;
}
gtk_widget_set_sensitive (GTK_WIDGET (dialog), FALSE);
props = e2k_properties_new ();
e2k_properties_set_binary (props, E2K_PR_EXCHANGE_SD_BINARY, binsd);
/* We use BPROPPATCH here instead of PROPPATCH, because
* PROPPATCH seems to mysteriously fail in someone else's
* folder hierarchy. #29726
*/
iter = e2k_context_bproppatch_start (ctx, NULL, dialog->priv->base_uri,
(const char **)&dialog->priv->folder_path, 1,
props, FALSE);
e2k_properties_free (props);
result = e2k_result_iter_next (iter);
if (result) {
status = result->status;
e2k_result_iter_free (iter);
} else
status = e2k_result_iter_free (iter);
gtk_widget_set_sensitive (GTK_WIDGET (dialog), TRUE);
if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":perm-update-error",
status == E2K_HTTP_UNAUTHORIZED ?
_("(Permission denied.)") : "", NULL);
return;
}
if (response == GTK_RESPONSE_OK)
gtk_widget_destroy (GTK_WIDGET (dialog));
}
static void
set_permissions (ExchangePermissionsDialog *dialog, guint32 perms)
{
dialog->priv->selected_perms = perms;
dialog->priv->selected_role = e2k_permissions_role_find (perms);
e2k_security_descriptor_set_permissions (dialog->priv->sd,
dialog->priv->selected_sid,
dialog->priv->selected_perms);
dialog->priv->changed = TRUE;
}
/* User list functions */
static void
list_view_selection_changed (GtkTreeSelection *selection, gpointer user_data)
{
ExchangePermissionsDialog *dialog = user_data;
GtkTreeModel *model;
GtkTreeIter iter;
E2kSid *sid;
if (!gtk_tree_selection_get_selected (selection, &model, &iter))
return;
gtk_tree_model_get (model, &iter,
EXCHANGE_PERMISSIONS_DIALOG_SID_COLUMN, &sid,
-1);
dialog->priv->selected_sid = sid;
dialog->priv->selected_perms =
e2k_security_descriptor_get_permissions (dialog->priv->sd, sid);
dialog->priv->selected_role =
e2k_permissions_role_find (dialog->priv->selected_perms);
/* "Default" or "Anonymous" can't be a Folder contact, but any
* real person can.
*/
gtk_widget_set_sensitive (GTK_WIDGET (dialog->priv->folder_contact_check),
e2k_sid_get_sid_type (sid) != E2K_SID_TYPE_WELL_KNOWN_GROUP);
/* Update role menu and permissions checkboxes */
display_permissions (dialog);
}
static void
add_user_to_list (ExchangePermissionsDialog *dialog, E2kSid *sid, gboolean select)
{
guint32 perms;
E2kPermissionsRole role;
GtkTreeIter iter;
perms = e2k_security_descriptor_get_permissions (dialog->priv->sd,
sid);
role = e2k_permissions_role_find (perms);
if (e2k_sid_get_sid_type (sid) == E2K_SID_TYPE_WELL_KNOWN_GROUP)
gtk_list_store_insert (dialog->priv->list_store, &iter, 1);
else
gtk_list_store_append (dialog->priv->list_store, &iter);
gtk_list_store_set (dialog->priv->list_store, &iter,
EXCHANGE_PERMISSIONS_DIALOG_NAME_COLUMN,
e2k_sid_get_display_name (sid),
EXCHANGE_PERMISSIONS_DIALOG_ROLE_COLUMN,
e2k_permissions_role_get_name (role),
EXCHANGE_PERMISSIONS_DIALOG_SID_COLUMN,
sid,
-1);
if (select)
gtk_tree_selection_select_iter (dialog->priv->list_selection, &iter);
}
static void
add_clicked (GtkButton *button, gpointer user_data)
{
ExchangePermissionsDialog *dialog = user_data;
E2kGlobalCatalog *gc;
E2kGlobalCatalogStatus status;
E2kGlobalCatalogEntry *entry;
E2kSid *sid2;
GtkTreeIter iter;
GtkWidget *user_dialog;
const guint8 *bsid, *bsid2;
GList *email_list = NULL;
GList *l = NULL;
char *email = NULL;
gboolean valid;
gint result;
gc = exchange_account_get_global_catalog (dialog->priv->account);
if (!gc) {
e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":acl-no-gcs-error",
NULL);
return;
}
user_dialog = e2k_user_dialog_new (GTK_WIDGET (dialog), _("Add User:"), _("Add User"));
result = gtk_dialog_run (GTK_DIALOG (user_dialog));
if (result == GTK_RESPONSE_OK)
email_list = e2k_user_dialog_get_user_list (E2K_USER_DIALOG (user_dialog));
gtk_widget_destroy (user_dialog);
if (email_list == NULL)
return;
for (l = email_list; l; l = g_list_next (l)) {
email = l->data;
status = e2k_global_catalog_lookup (
gc, NULL, /* FIXME: cancellable */
E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL, email,
E2K_GLOBAL_CATALOG_LOOKUP_SID, &entry);
switch (status) {
case E2K_GLOBAL_CATALOG_OK:
break;
case E2K_GLOBAL_CATALOG_NO_SUCH_USER:
e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":no-user-error", email, NULL);
break;
case E2K_GLOBAL_CATALOG_NO_DATA:
e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":acl-add-error", email, NULL);
break;
default:
e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":perm-unknown-error", email, NULL);
break;
}
if (status != E2K_GLOBAL_CATALOG_OK)
return;
/* Make sure the user isn't already there. */
bsid = e2k_sid_get_binary_sid (entry->sid);
valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dialog->priv->list_store), &iter);
while (valid) {
gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->list_store), &iter,
EXCHANGE_PERMISSIONS_DIALOG_SID_COLUMN, &sid2,
-1);
bsid2 = e2k_sid_get_binary_sid (sid2);
if (e2k_sid_binary_sid_equal (bsid, bsid2)) {
e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":perm-existing-error",
entry->display_name, NULL);
e2k_global_catalog_entry_free (gc, entry);
gtk_tree_selection_select_iter (dialog->priv->list_selection, &iter);
return;
}
valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (dialog->priv->list_store), &iter);
}
add_user_to_list (dialog, entry->sid, TRUE);
/* Calling set_permissions will cause the sd to take a
* ref on the sid, allowing us to unref it.
*/
set_permissions (dialog, 0);
e2k_global_catalog_entry_free (gc, entry);
}
g_list_free (email_list);
}
static void
remove_clicked (GtkButton *button, gpointer user_data)
{
ExchangePermissionsDialog *dialog = user_data;
E2kSid *sid;
GdkModifierType modifiers;
GtkTreeModel *model;
GtkTreeIter iter;
if (!gtk_tree_selection_get_selected (dialog->priv->list_selection,
&model, &iter))
return;
gtk_tree_model_get (model, &iter,
EXCHANGE_PERMISSIONS_DIALOG_SID_COLUMN, &sid,
-1);
gdk_window_get_pointer (NULL, NULL, NULL, &modifiers);
if (e2k_sid_get_sid_type (sid) == E2K_SID_TYPE_WELL_KNOWN_GROUP &&
!(modifiers & GDK_SHIFT_MASK)) {
/* You shouldn't normally delete "Default" or "Anonymous". */
set_permissions (dialog, 0);
} else {
gtk_list_store_remove (dialog->priv->list_store, &iter);
e2k_security_descriptor_remove_sid (dialog->priv->sd, sid);
if (!gtk_list_store_iter_is_valid (dialog->priv->list_store, &iter)) {
/* Select the new last row. Love that API... */
gtk_tree_model_iter_nth_child (model, &iter, NULL,
gtk_tree_model_iter_n_children (model, NULL) - 1);
}
gtk_tree_selection_select_iter (dialog->priv->list_selection, &iter);
dialog->priv->changed = TRUE;
}
}
static void
setup_user_list (ExchangePermissionsDialog *dialog)
{
E2kSecurityDescriptor *sd = dialog->priv->sd;
E2kSid *default_entry;
GList *sids;
/* FIXME */
/* gtk_clist_freeze (dialog->priv->clist); */
/* Always put "Default" first. */
default_entry = e2k_security_descriptor_get_default (sd);
add_user_to_list (dialog, default_entry, TRUE);
sids = e2k_security_descriptor_get_sids (sd);
while (sids) {
if (sids->data != default_entry)
add_user_to_list (dialog, sids->data, FALSE);
sids = sids->next;
}
g_list_free (sids);
/* gtk_clist_thaw (dialog->priv->clist); */
}
/* Role option menu functions */
static void
role_changed (GtkWidget *role_combo, gpointer user_data)
{
ExchangePermissionsDialog *dialog = user_data;
int role;
if (dialog->priv->frozen)
return;
role = gtk_combo_box_get_active (GTK_COMBO_BOX (role_combo));
if (role == dialog->priv->selected_role)
return;
if (role >= E2K_PERMISSIONS_ROLE_NUM_ROLES) {
/* The user selected "Custom". Since "Custom" will
* only be there to select when it's already
* selected, this is a no-op.
*/
return;
}
set_permissions (dialog, e2k_permissions_role_get_perms (role));
display_permissions (dialog);
}
static void
display_role (ExchangePermissionsDialog *dialog)
{
int role = dialog->priv->selected_role;
GtkTreeModel *model;
GtkTreeIter iter;
if (!gtk_tree_selection_get_selected (dialog->priv->list_selection,
&model, &iter))
return;
gtk_list_store_set (dialog->priv->list_store, &iter,
EXCHANGE_PERMISSIONS_DIALOG_ROLE_COLUMN,
e2k_permissions_role_get_name (role),
-1);
if (role == E2K_PERMISSIONS_ROLE_CUSTOM) {
if (dialog->priv->custom_added == FALSE) {
gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->priv->role_optionmenu), _("Custom"));
dialog->priv->custom_added = TRUE;
}
role = E2K_PERMISSIONS_ROLE_NUM_ROLES;
}
else {
if (dialog->priv->custom_added) {
gtk_combo_box_remove_text (GTK_COMBO_BOX (dialog->priv->role_optionmenu), E2K_PERMISSIONS_ROLE_NUM_ROLES);
dialog->priv->custom_added = FALSE;
}
}
gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->priv->role_optionmenu), role);
}
/* Toggle buttons */
static void
check_toggled (GtkToggleButton *toggle, gpointer user_data)
{
ExchangePermissionsDialog *dialog = user_data;
ExchangePermissionsDialogPrivate *priv = dialog->priv;
guint32 new_perms, value;
if (dialog->priv->frozen)
return;
value = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (toggle), "mapi_permission"));
if (gtk_toggle_button_get_active (toggle))
new_perms = priv->selected_perms | value;
else
new_perms = priv->selected_perms & ~value;
if (new_perms == priv->selected_perms)
return;
set_permissions (dialog, new_perms);
display_role (dialog);
}
static void
radio_toggled (GtkToggleButton *toggle, gpointer user_data)
{
ExchangePermissionsDialog *dialog = user_data;
ExchangePermissionsDialogPrivate *priv = dialog->priv;
guint32 new_perms, value, mask;
if (dialog->priv->frozen || !gtk_toggle_button_get_active (toggle))
return;
value = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (toggle), "mapi_permission"));
mask = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (toggle), "mapi_mask"));
new_perms = (priv->selected_perms & ~mask) | value;
if (new_perms == priv->selected_perms)
return;
set_permissions (dialog, new_perms);
display_role (dialog);
}
static void
rv_toggle (GtkToggleButton *toggled, gpointer user_data)
{
ExchangePermissionsDialog *dialog = user_data;
GtkToggleButton *visible = dialog->priv->folder_visible_check;
GtkToggleButton *read = dialog->priv->read_items_check;
if (dialog->priv->frozen)
return;
/* If you turn off "Folder visible", then "Read items" turns
* off too. Contrariwise, if you turn on "Read items", then
* "Folder visible" turns on too.
*/
if (toggled == visible && !gtk_toggle_button_get_active (toggled))
gtk_toggle_button_set_active (read, FALSE);
else if (toggled == read && gtk_toggle_button_get_active (toggled))
gtk_toggle_button_set_active (visible, TRUE);
}
static void
display_permissions (ExchangePermissionsDialog *dialog)
{
GtkToggleButton *radio;
guint32 perms = dialog->priv->selected_perms;
dialog->priv->frozen = TRUE;
/* Set up check boxes */
gtk_toggle_button_set_active (dialog->priv->read_items_check,
perms & E2K_PERMISSION_READ_ANY);
gtk_toggle_button_set_active (dialog->priv->create_items_check,
perms & E2K_PERMISSION_CREATE);
gtk_toggle_button_set_active (dialog->priv->create_subfolders_check,
perms & E2K_PERMISSION_CREATE_SUBFOLDER);
gtk_toggle_button_set_active (dialog->priv->folder_owner_check,
perms & E2K_PERMISSION_OWNER);
gtk_toggle_button_set_active (dialog->priv->folder_contact_check,
(perms & E2K_PERMISSION_CONTACT) &&
GTK_WIDGET_SENSITIVE (dialog->priv->folder_contact_check));
gtk_toggle_button_set_active (dialog->priv->folder_visible_check,
perms & E2K_PERMISSION_FOLDER_VISIBLE);
/* Set up radio buttons */
if (perms & E2K_PERMISSION_EDIT_ANY)
radio = dialog->priv->edit_all_radio;
else if (perms & E2K_PERMISSION_EDIT_OWNED)
radio = dialog->priv->edit_own_radio;
else
radio = dialog->priv->edit_none_radio;
gtk_toggle_button_set_active (radio, TRUE);
if (perms & E2K_PERMISSION_DELETE_ANY)
radio = dialog->priv->delete_all_radio;
else if (perms & E2K_PERMISSION_DELETE_OWNED)
radio = dialog->priv->delete_own_radio;
else
radio = dialog->priv->delete_none_radio;
gtk_toggle_button_set_active (radio, TRUE);
/* And role menu */
display_role (dialog);
dialog->priv->frozen = FALSE;
}
static void
get_widgets (ExchangePermissionsDialog *dialog, GladeXML *xml)
{
GtkWidget *button;
GtkTreeViewColumn *column;
#define GET_WIDGET(name, type) dialog->priv->name = type (glade_xml_get_widget (xml, #name))
GET_WIDGET (list_view, GTK_TREE_VIEW);
column = gtk_tree_view_column_new_with_attributes (
_("Name"), gtk_cell_renderer_text_new (),
"text", EXCHANGE_PERMISSIONS_DIALOG_NAME_COLUMN, NULL);
gtk_tree_view_append_column (dialog->priv->list_view, column);
column = gtk_tree_view_column_new_with_attributes (
_("Role"), gtk_cell_renderer_text_new (),
"text", EXCHANGE_PERMISSIONS_DIALOG_ROLE_COLUMN, NULL);
gtk_tree_view_append_column (dialog->priv->list_view, column);
dialog->priv->list_selection = gtk_tree_view_get_selection (dialog->priv->list_view);
gtk_tree_selection_set_mode (dialog->priv->list_selection,
GTK_SELECTION_SINGLE);
g_signal_connect (dialog->priv->list_selection, "changed",
G_CALLBACK (list_view_selection_changed), dialog);
dialog->priv->list_store = gtk_list_store_new (
EXCHANGE_PERMISSIONS_DIALOG_NUM_COLUMNS,
G_TYPE_STRING, G_TYPE_STRING, E2K_TYPE_SID);
gtk_tree_view_set_model (dialog->priv->list_view,
GTK_TREE_MODEL (dialog->priv->list_store));
button = glade_xml_get_widget (xml, "add_button");
g_signal_connect (button, "clicked",
G_CALLBACK (add_clicked), dialog);
button = glade_xml_get_widget (xml, "remove_button");
g_signal_connect (button, "clicked",
G_CALLBACK (remove_clicked), dialog);
GET_WIDGET (role_optionmenu, GTK_COMBO_BOX);
g_signal_connect (dialog->priv->role_optionmenu, "changed",
G_CALLBACK (role_changed), dialog);
dialog->priv->custom_added = FALSE;
#define GET_TOGGLE(name, value, callback) \
GET_WIDGET (name, GTK_TOGGLE_BUTTON); \
g_object_set_data (G_OBJECT (dialog->priv->name), \
"mapi_permission", \
GUINT_TO_POINTER (value)); \
g_signal_connect (dialog->priv->name, "toggled", \
G_CALLBACK (callback), dialog)
#define GET_CHECK(name, value) \
GET_TOGGLE (name, value, check_toggled)
#define GET_RADIO(name, value, mask) \
GET_TOGGLE (name, value, radio_toggled); \
g_object_set_data (G_OBJECT (dialog->priv->name), \
"mapi_mask", \
GUINT_TO_POINTER (mask))
GET_CHECK (read_items_check, E2K_PERMISSION_READ_ANY);
GET_CHECK (create_items_check, E2K_PERMISSION_CREATE);
GET_RADIO (edit_none_radio, 0, E2K_PERMISSION_EDIT_MASK);
GET_RADIO (delete_none_radio, 0, E2K_PERMISSION_DELETE_MASK);
GET_RADIO (edit_own_radio, E2K_PERMISSION_EDIT_OWNED, E2K_PERMISSION_EDIT_MASK);
GET_RADIO (delete_own_radio, E2K_PERMISSION_DELETE_OWNED, E2K_PERMISSION_DELETE_MASK);
GET_RADIO (edit_all_radio, (E2K_PERMISSION_EDIT_ANY | E2K_PERMISSION_EDIT_OWNED), E2K_PERMISSION_EDIT_MASK);
GET_RADIO (delete_all_radio, (E2K_PERMISSION_DELETE_ANY | E2K_PERMISSION_DELETE_OWNED), E2K_PERMISSION_DELETE_MASK);
GET_CHECK (create_subfolders_check, E2K_PERMISSION_CREATE_SUBFOLDER);
GET_CHECK (folder_owner_check, E2K_PERMISSION_OWNER);
GET_CHECK (folder_contact_check, E2K_PERMISSION_CONTACT);
GET_CHECK (folder_visible_check, E2K_PERMISSION_FOLDER_VISIBLE);
g_signal_connect (dialog->priv->folder_visible_check,
"toggled", G_CALLBACK (rv_toggle), dialog);
g_signal_connect (dialog->priv->read_items_check,
"toggled", G_CALLBACK (rv_toggle), dialog);
}
GtkWidget *exchange_permissions_role_optionmenu_new (char *widget_name, char *string1, char *string2, int int1, int int2);
GtkWidget *
exchange_permissions_role_optionmenu_new (char *widget_name, char *string1, char *string2, int int1, int int2)
{
GtkWidget *menu;
const char **roles;
int role;
menu = gtk_combo_box_new_text ();
roles = g_new (const char *, E2K_PERMISSIONS_ROLE_NUM_ROLES + 1);
for (role = 0; role < E2K_PERMISSIONS_ROLE_NUM_ROLES; role++) {
roles[role] = e2k_permissions_role_get_name (role);
gtk_combo_box_append_text (GTK_COMBO_BOX (menu), roles[role]);
}
roles[role] = NULL;
g_free (roles);
gtk_widget_show (menu);
return menu;
}