"Fossies" - the Fresh Open Source Software Archive

Member "evolution-mapi-3.46.1/src/configuration/e-mapi-edit-folder-permissions.c" (2 Dec 2022, 43761 Bytes) of package /linux/misc/evolution-mapi-3.46.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "e-mapi-edit-folder-permissions.c" see the Fossies "Dox" file reference documentation.

    1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
    2 /*
    3  * This program is free software; you can redistribute it and/or
    4  * modify it under the terms of the GNU Lesser General Public
    5  * License as published by the Free Software Foundation; either
    6  * version 2 of the License, or (at your option) version 3.
    7  *
    8  * This program is distributed in the hope that it will be useful,
    9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   11  * Lesser General Public License for more details.
   12  *
   13  * You should have received a copy of the GNU Lesser General Public
   14  * License along with the program; if not, see <http://www.gnu.org/licenses/>
   15  *
   16  *
   17  * Authors:
   18  *    Milan Crha <mcrha@redhat.com>
   19  *
   20  * Copyright (C) 2012 Red Hat, Inc. (www.redhat.com)
   21  *
   22  */
   23 
   24 #include "evolution-mapi-config.h"
   25 
   26 #include <glib/gi18n-lib.h>
   27 #include <gtk/gtk.h>
   28 
   29 #include "e-mapi-config-utils.h"
   30 #include "e-mapi-edit-folder-permissions.h"
   31 #include "e-mapi-search-gal-user.h"
   32 #include "e-mapi-utils.h"
   33 
   34 #define E_MAPI_PERM_DLG_WIDGETS "e-mapi-perm-dlg-widgets"
   35 
   36 enum {
   37     COL_NAME = 0,
   38     COL_PERMISSION_LEVEL,
   39     COL_E_MAPI_PERMISSION_ENTRY,
   40     COL_E_MAPI_GAL_USER_TYPE,
   41     COL_IS_NEW
   42 };
   43 
   44 struct EMapiPermissionsDialogWidgets
   45 {
   46     ESourceRegistry *registry;
   47     ESource *source;
   48     CamelMapiSettings *mapi_settings;
   49     mapi_id_t folder_id;
   50     EMapiFolderCategory folder_category;
   51     gchar *foreign_username;
   52 
   53     EMapiConnection *conn;
   54 
   55     gboolean updating;
   56 
   57     GtkWidget *dialog;
   58     GtkWidget *tree_view;
   59 
   60     GtkWidget *add_button;
   61     GtkWidget *remove_button;
   62     GtkWidget *level_combo;
   63 
   64     GtkWidget *read_none_radio;
   65     GtkWidget *read_full_radio;
   66     GtkWidget *read_fb_simple_check;
   67     GtkWidget *read_fb_detail_check;
   68 
   69     GtkWidget *write_create_items_check;
   70     GtkWidget *write_create_subfolders_check;
   71     GtkWidget *write_edit_own_check;
   72     GtkWidget *write_edit_all_check;
   73 
   74     GtkWidget *delete_none_radio;
   75     GtkWidget *delete_own_radio;
   76     GtkWidget *delete_all_radio;
   77 
   78     GtkWidget *other_folder_owner_check;
   79     GtkWidget *other_folder_contact_check;
   80     GtkWidget *other_folder_visible_check;
   81 };
   82 
   83 static const struct EMapiPredefinedLevels {
   84     const gchar *name;
   85     uint32_t rights;
   86 } predefined_levels[] = {
   87     { NC_("PermissionsLevel", "None"), 0 },
   88     { NC_("PermissionsLevel", "Owner"),     E_MAPI_PERMISSION_BIT_READ_ANY |
   89                         E_MAPI_PERMISSION_BIT_CREATE |
   90                         E_MAPI_PERMISSION_BIT_CREATE_SUBFOLDER |
   91                         E_MAPI_PERMISSION_BIT_EDIT_OWNED |
   92                         E_MAPI_PERMISSION_BIT_EDIT_ANY |
   93                         E_MAPI_PERMISSION_BIT_DELETE_OWNED |
   94                         E_MAPI_PERMISSION_BIT_DELETE_ANY |
   95                         E_MAPI_PERMISSION_BIT_FOLDER_OWNER |
   96                         E_MAPI_PERMISSION_BIT_FOLDER_CONTACT |
   97                         E_MAPI_PERMISSION_BIT_FOLDER_VISIBLE },
   98     { NC_("PermissionsLevel", "Publishing Editor"),
   99                         E_MAPI_PERMISSION_BIT_READ_ANY |
  100                         E_MAPI_PERMISSION_BIT_CREATE |
  101                         E_MAPI_PERMISSION_BIT_CREATE_SUBFOLDER |
  102                         E_MAPI_PERMISSION_BIT_EDIT_OWNED |
  103                         E_MAPI_PERMISSION_BIT_EDIT_ANY |
  104                         E_MAPI_PERMISSION_BIT_DELETE_OWNED |
  105                         E_MAPI_PERMISSION_BIT_DELETE_ANY |
  106                         E_MAPI_PERMISSION_BIT_FOLDER_VISIBLE  },
  107     { NC_("PermissionsLevel", "Editor"),
  108                         E_MAPI_PERMISSION_BIT_READ_ANY |
  109                         E_MAPI_PERMISSION_BIT_CREATE |
  110                         E_MAPI_PERMISSION_BIT_EDIT_OWNED |
  111                         E_MAPI_PERMISSION_BIT_EDIT_ANY |
  112                         E_MAPI_PERMISSION_BIT_DELETE_OWNED |
  113                         E_MAPI_PERMISSION_BIT_DELETE_ANY |
  114                         E_MAPI_PERMISSION_BIT_FOLDER_VISIBLE  },
  115     { NC_("PermissionsLevel", "Publishing Author"),
  116                         E_MAPI_PERMISSION_BIT_READ_ANY |
  117                         E_MAPI_PERMISSION_BIT_CREATE |
  118                         E_MAPI_PERMISSION_BIT_CREATE_SUBFOLDER |
  119                         E_MAPI_PERMISSION_BIT_EDIT_OWNED |
  120                         E_MAPI_PERMISSION_BIT_DELETE_OWNED |
  121                         E_MAPI_PERMISSION_BIT_FOLDER_VISIBLE  },
  122     { NC_("PermissionsLevel", "Author"),
  123                         E_MAPI_PERMISSION_BIT_READ_ANY |
  124                         E_MAPI_PERMISSION_BIT_CREATE |
  125                         E_MAPI_PERMISSION_BIT_EDIT_OWNED |
  126                         E_MAPI_PERMISSION_BIT_DELETE_OWNED |
  127                         E_MAPI_PERMISSION_BIT_FOLDER_VISIBLE  },
  128     { NC_("PermissionsLevel", "Nonediting Author"),
  129                         E_MAPI_PERMISSION_BIT_READ_ANY |
  130                         E_MAPI_PERMISSION_BIT_CREATE |
  131                         E_MAPI_PERMISSION_BIT_DELETE_OWNED |
  132                         E_MAPI_PERMISSION_BIT_FOLDER_VISIBLE  },
  133     { NC_("PermissionsLevel", "Reviewer"),
  134                         E_MAPI_PERMISSION_BIT_READ_ANY |
  135                         E_MAPI_PERMISSION_BIT_FOLDER_VISIBLE  },
  136     { NC_("PermissionsLevel", "Contributor"),
  137                         E_MAPI_PERMISSION_BIT_CREATE |
  138                         E_MAPI_PERMISSION_BIT_FOLDER_VISIBLE  },
  139     { NC_("PermissionsLevel", "Custom"), ~0 } /* make sure 'Custom' is always the last */
  140 };
  141 
  142 static void
  143 edit_permissions_widgets_free (gpointer ptr)
  144 {
  145     struct EMapiPermissionsDialogWidgets *widgets = ptr;
  146 
  147     if (!widgets)
  148         return;
  149 
  150     g_object_unref (widgets->registry);
  151     g_object_unref (widgets->source);
  152     g_object_unref (widgets->mapi_settings);
  153     g_free (widgets->foreign_username);
  154     if (widgets->conn)
  155         e_mapi_utils_unref_in_thread (G_OBJECT (widgets->conn));
  156     g_free (widgets);
  157 }
  158 
  159 static void
  160 folder_permissions_clear_all_entries (GObject *dialog)
  161 {
  162     struct EMapiPermissionsDialogWidgets *widgets;
  163     GtkTreeModel *model;
  164     GtkTreeIter iter;
  165 
  166     g_return_if_fail (dialog != NULL);
  167 
  168     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  169     g_return_if_fail (widgets != NULL);
  170     g_return_if_fail (widgets->tree_view != NULL);
  171 
  172     model = gtk_tree_view_get_model (GTK_TREE_VIEW (widgets->tree_view));
  173     g_return_if_fail (model != NULL);
  174 
  175     if (!gtk_tree_model_get_iter_first (model, &iter))
  176         return;
  177 
  178     do {
  179         EMapiPermissionEntry *pem = NULL;
  180 
  181         gtk_tree_model_get (model, &iter, COL_E_MAPI_PERMISSION_ENTRY, &pem, -1);
  182 
  183         e_mapi_permission_entry_free (pem);
  184     } while (gtk_tree_model_iter_next (model, &iter));
  185 
  186     gtk_list_store_clear (GTK_LIST_STORE (model));
  187 }
  188 
  189 static void
  190 write_folder_permissions_thread (GObject *dialog,
  191                  gpointer user_data,
  192                  GCancellable *cancellable,
  193                  GError **perror)
  194 {
  195     struct EMapiPermissionsDialogWidgets *widgets;
  196     mapi_object_t obj_folder;
  197     gboolean opened;
  198     const GSList *entries = user_data;
  199 
  200     g_return_if_fail (dialog != NULL);
  201 
  202     if (g_cancellable_is_cancelled (cancellable))
  203         return;
  204 
  205     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  206     g_return_if_fail (widgets != NULL);
  207     g_return_if_fail (widgets->conn != NULL);
  208 
  209     if (widgets->folder_category == E_MAPI_FOLDER_CATEGORY_FOREIGN)
  210         opened = e_mapi_connection_open_foreign_folder (widgets->conn, widgets->foreign_username, widgets->folder_id, &obj_folder, cancellable, perror);
  211     else if (widgets->folder_category == E_MAPI_FOLDER_CATEGORY_PUBLIC)
  212         opened = e_mapi_connection_open_public_folder (widgets->conn, widgets->folder_id, &obj_folder, cancellable, perror);
  213     else
  214         opened = e_mapi_connection_open_personal_folder (widgets->conn, widgets->folder_id, &obj_folder, cancellable, perror);
  215 
  216     if (opened) {
  217         e_mapi_connection_set_permissions (widgets->conn, &obj_folder, widgets->read_fb_simple_check != NULL, entries, cancellable, perror);
  218         e_mapi_connection_close_folder (widgets->conn, &obj_folder, cancellable, perror);
  219     }
  220 }
  221 
  222 static void
  223 write_folder_permissions_idle (GObject *dialog,
  224                    gpointer user_data,
  225                    GCancellable *cancellable,
  226                    GError **perror)
  227 {
  228     /* does this only if no error was raised from the thread function */
  229     folder_permissions_clear_all_entries (dialog);
  230     gtk_widget_destroy (GTK_WIDGET (dialog));
  231 }
  232 
  233 static void
  234 edit_permissions_response_cb (GObject *dialog,
  235                   gint response_id)
  236 {
  237     struct EMapiPermissionsDialogWidgets *widgets;
  238     GSList *write_entries = NULL;
  239     GtkTreeModel *model;
  240     GtkTreeIter iter;
  241 
  242     g_return_if_fail (dialog != NULL);
  243 
  244     if (response_id != GTK_RESPONSE_OK) {
  245         folder_permissions_clear_all_entries (dialog);
  246         gtk_widget_destroy (GTK_WIDGET (dialog));
  247         return;
  248     }
  249 
  250     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  251     g_return_if_fail (widgets != NULL);
  252     g_return_if_fail (widgets->tree_view != NULL);
  253     g_return_if_fail (widgets->conn != NULL);
  254 
  255     model = gtk_tree_view_get_model (GTK_TREE_VIEW (widgets->tree_view));
  256     g_return_if_fail (model != NULL);
  257 
  258     if (gtk_tree_model_get_iter_first (model, &iter)) {
  259         do {
  260             EMapiPermissionEntry *pem = NULL;
  261 
  262             gtk_tree_model_get (model, &iter, COL_E_MAPI_PERMISSION_ENTRY, &pem, -1);
  263 
  264             if (pem)
  265                 write_entries = g_slist_prepend (write_entries, pem);
  266         } while (gtk_tree_model_iter_next (model, &iter));
  267 
  268         write_entries = g_slist_reverse (write_entries);
  269     }
  270 
  271     e_mapi_config_utils_run_in_thread_with_feedback (GTK_WINDOW (dialog), dialog,
  272         _("Writing folder permissions, please wait…"),
  273         write_folder_permissions_thread,
  274         write_folder_permissions_idle,
  275         write_entries, (GDestroyNotify) g_slist_free);
  276 }
  277 
  278 static void
  279 enable_all_widgets (struct EMapiPermissionsDialogWidgets *widgets,
  280             gboolean enabled)
  281 {
  282     g_return_if_fail (widgets != NULL);
  283 
  284     gtk_widget_set_sensitive (widgets->add_button, enabled || gtk_widget_get_sensitive (widgets->tree_view));
  285     gtk_widget_set_sensitive (widgets->remove_button, enabled);
  286     gtk_widget_set_sensitive (widgets->level_combo, enabled);
  287     gtk_widget_set_sensitive (widgets->read_none_radio, enabled);
  288     gtk_widget_set_sensitive (widgets->read_full_radio, enabled);
  289     if (widgets->read_fb_simple_check)
  290         gtk_widget_set_sensitive (widgets->read_fb_simple_check, enabled);
  291     if (widgets->read_fb_detail_check)
  292         gtk_widget_set_sensitive (widgets->read_fb_detail_check, enabled);
  293     gtk_widget_set_sensitive (widgets->write_create_items_check, enabled);
  294     gtk_widget_set_sensitive (widgets->write_create_subfolders_check, enabled);
  295     gtk_widget_set_sensitive (widgets->write_edit_own_check, enabled);
  296     gtk_widget_set_sensitive (widgets->write_edit_all_check, enabled);
  297     gtk_widget_set_sensitive (widgets->delete_none_radio, enabled);
  298     gtk_widget_set_sensitive (widgets->delete_own_radio, enabled);
  299     gtk_widget_set_sensitive (widgets->delete_all_radio, enabled);
  300     gtk_widget_set_sensitive (widgets->other_folder_owner_check, enabled);
  301     gtk_widget_set_sensitive (widgets->other_folder_contact_check, enabled);
  302     gtk_widget_set_sensitive (widgets->other_folder_visible_check, enabled);
  303 }
  304 
  305 static uint32_t
  306 folder_permissions_dialog_to_rights (GObject *dialog)
  307 {
  308     struct EMapiPermissionsDialogWidgets *widgets;
  309     uint32_t rights;
  310 
  311     g_return_val_if_fail (dialog != NULL, 0);
  312 
  313     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  314     g_return_val_if_fail (widgets != NULL, 0);
  315 
  316     #define set_bit_by_active(x, bt) G_STMT_START {                 \
  317         if (widgets->x &&                           \
  318             gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->x)) &&    \
  319             gtk_widget_get_sensitive (widgets->x)) {                \
  320             rights |= bt;                           \
  321         } } G_STMT_END
  322 
  323     rights = 0;
  324 
  325     set_bit_by_active (read_none_radio, 0);
  326     set_bit_by_active (read_full_radio, E_MAPI_PERMISSION_BIT_READ_ANY);
  327     set_bit_by_active (read_fb_simple_check, E_MAPI_PERMISSION_BIT_FREE_BUSY_SIMPLE);
  328     set_bit_by_active (read_fb_detail_check, E_MAPI_PERMISSION_BIT_FREE_BUSY_DETAILED);
  329     set_bit_by_active (write_create_items_check, E_MAPI_PERMISSION_BIT_CREATE);
  330     set_bit_by_active (write_create_subfolders_check, E_MAPI_PERMISSION_BIT_CREATE_SUBFOLDER);
  331     set_bit_by_active (write_edit_own_check, E_MAPI_PERMISSION_BIT_EDIT_OWNED);
  332     set_bit_by_active (write_edit_all_check, E_MAPI_PERMISSION_BIT_EDIT_ANY | E_MAPI_PERMISSION_BIT_EDIT_OWNED);
  333     set_bit_by_active (delete_none_radio, 0);
  334     set_bit_by_active (delete_own_radio, E_MAPI_PERMISSION_BIT_DELETE_OWNED);
  335     set_bit_by_active (delete_all_radio, E_MAPI_PERMISSION_BIT_DELETE_ANY | E_MAPI_PERMISSION_BIT_DELETE_OWNED);
  336     set_bit_by_active (other_folder_owner_check, E_MAPI_PERMISSION_BIT_FOLDER_OWNER);
  337     set_bit_by_active (other_folder_contact_check, E_MAPI_PERMISSION_BIT_FOLDER_CONTACT);
  338     set_bit_by_active (other_folder_visible_check, E_MAPI_PERMISSION_BIT_FOLDER_VISIBLE);
  339 
  340     #undef set_bit_by_active
  341 
  342     return rights;
  343 }
  344 
  345 static void
  346 update_folder_permissions_sensitivity (GObject *dialog,
  347                        gboolean member_valid,
  348                        EMapiGalUserType user_type)
  349 {
  350     struct EMapiPermissionsDialogWidgets *widgets;
  351 
  352     g_return_if_fail (dialog != NULL);
  353 
  354     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  355     g_return_if_fail (widgets != NULL);
  356 
  357     enable_all_widgets (widgets, member_valid);
  358 
  359     if (user_type == E_MAPI_GAL_USER_DEFAULT ||
  360         user_type == E_MAPI_GAL_USER_ANONYMOUS)
  361         gtk_widget_set_sensitive (widgets->other_folder_contact_check, FALSE);
  362 
  363     if (member_valid)
  364         gtk_widget_set_sensitive (widgets->remove_button,
  365             user_type != E_MAPI_GAL_USER_DEFAULT &&
  366             user_type != E_MAPI_GAL_USER_ANONYMOUS);
  367 
  368     if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->write_edit_all_check))) {
  369         gtk_widget_set_sensitive (widgets->write_edit_own_check, FALSE);
  370         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widgets->write_edit_own_check), TRUE);
  371     }
  372 }
  373 
  374 static void
  375 update_folder_permissions_by_rights (GObject *dialog,
  376                      uint32_t rights)
  377 {
  378     struct EMapiPermissionsDialogWidgets *widgets;
  379 
  380     g_return_if_fail (dialog != NULL);
  381 
  382     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  383     g_return_if_fail (widgets != NULL);
  384 
  385     #define set_active(x, act) G_STMT_START { if (widgets->x) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widgets->x), act); } G_STMT_END
  386     #define set_active_by_bit(x, bt) set_active (x, (rights & (bt)) != 0)
  387 
  388     widgets->updating = TRUE;
  389 
  390     set_active (read_none_radio, TRUE);
  391     set_active_by_bit (read_full_radio, E_MAPI_PERMISSION_BIT_READ_ANY);
  392     set_active_by_bit (read_fb_simple_check, E_MAPI_PERMISSION_BIT_FREE_BUSY_SIMPLE);
  393     set_active_by_bit (read_fb_detail_check, E_MAPI_PERMISSION_BIT_FREE_BUSY_DETAILED);
  394     set_active_by_bit (write_create_items_check, E_MAPI_PERMISSION_BIT_CREATE);
  395     set_active_by_bit (write_create_subfolders_check, E_MAPI_PERMISSION_BIT_CREATE_SUBFOLDER);
  396     set_active_by_bit (write_edit_own_check, E_MAPI_PERMISSION_BIT_EDIT_OWNED | E_MAPI_PERMISSION_BIT_EDIT_ANY);
  397     set_active_by_bit (write_edit_all_check, E_MAPI_PERMISSION_BIT_EDIT_ANY);
  398     set_active (delete_none_radio, TRUE);
  399     set_active_by_bit (delete_own_radio, E_MAPI_PERMISSION_BIT_DELETE_OWNED);
  400     set_active_by_bit (delete_all_radio, E_MAPI_PERMISSION_BIT_DELETE_ANY);
  401     set_active_by_bit (other_folder_owner_check, E_MAPI_PERMISSION_BIT_FOLDER_OWNER);
  402     set_active_by_bit (other_folder_contact_check, E_MAPI_PERMISSION_BIT_FOLDER_CONTACT);
  403     set_active_by_bit (other_folder_visible_check, E_MAPI_PERMISSION_BIT_FOLDER_VISIBLE);
  404 
  405     if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->write_edit_all_check)) &&
  406         gtk_widget_get_sensitive (widgets->write_edit_all_check)) {
  407         gtk_widget_set_sensitive (widgets->write_edit_own_check, TRUE);
  408     } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->write_edit_all_check))) {
  409         gtk_widget_set_sensitive (widgets->write_edit_own_check, FALSE);
  410         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widgets->write_edit_own_check), TRUE);
  411     }
  412 
  413     if (widgets->read_fb_simple_check && widgets->read_fb_detail_check) {
  414         if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->read_fb_detail_check)) &&
  415             gtk_widget_get_sensitive (widgets->read_fb_detail_check)) {
  416             gtk_widget_set_sensitive (widgets->read_fb_simple_check, TRUE);
  417         } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->read_fb_detail_check))) {
  418             gtk_widget_set_sensitive (widgets->read_fb_simple_check, FALSE);
  419             gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widgets->read_fb_simple_check), TRUE);
  420         }
  421     }
  422 
  423     widgets->updating = FALSE;
  424 
  425     #undef set_active_by_bit
  426     #undef set_active
  427 }
  428 
  429 static void
  430 update_folder_permissions_tree_view (GObject *dialog,
  431                      struct EMapiPermissionsDialogWidgets *widgets)
  432 {
  433     GtkTreeSelection *selection;
  434     GtkTreeModel *model;
  435     GtkTreeIter iter;
  436     uint32_t rights;
  437 
  438     g_return_if_fail (dialog != NULL);
  439     g_return_if_fail (widgets != NULL);
  440 
  441     selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widgets->tree_view));
  442     if (selection && gtk_tree_selection_get_selected (selection, &model, &iter)) {
  443         gchar *combo_text;
  444         EMapiPermissionEntry *pem = NULL;
  445 
  446         combo_text = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (widgets->level_combo));
  447         rights = folder_permissions_dialog_to_rights (dialog);
  448 
  449         gtk_tree_model_get (model, &iter, COL_E_MAPI_PERMISSION_ENTRY, &pem, -1);
  450 
  451         if (pem) {
  452             if (!widgets->read_fb_simple_check)
  453                 rights = rights | (pem->member_rights & (E_MAPI_PERMISSION_BIT_FREE_BUSY_DETAILED | E_MAPI_PERMISSION_BIT_FREE_BUSY_SIMPLE));
  454 
  455             pem->member_rights = rights;
  456 
  457             gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_PERMISSION_LEVEL, combo_text, -1);
  458         }
  459 
  460         g_free (combo_text);
  461     }
  462 }
  463 
  464 static void
  465 update_permission_level_combo_by_dialog (GObject *dialog)
  466 {
  467     struct EMapiPermissionsDialogWidgets *widgets;
  468     uint32_t rights;
  469     gint ii;
  470 
  471     g_return_if_fail (dialog != NULL);
  472 
  473     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  474     g_return_if_fail (widgets != NULL);
  475 
  476     if (widgets->updating)
  477         return;
  478 
  479     rights = folder_permissions_dialog_to_rights (dialog);
  480     rights = rights & ~(E_MAPI_PERMISSION_BIT_FREE_BUSY_DETAILED |
  481         E_MAPI_PERMISSION_BIT_FREE_BUSY_SIMPLE);
  482 
  483     for (ii = 0; ii < G_N_ELEMENTS (predefined_levels) - 1; ii++) {
  484         if (predefined_levels[ii].rights == rights) {
  485             break;
  486         }
  487     }
  488 
  489     /* ii points to the matched or the last item, which is 'Custom' */
  490     widgets->updating = TRUE;
  491     gtk_combo_box_set_active (GTK_COMBO_BOX (widgets->level_combo), ii);
  492 
  493     if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->write_edit_all_check)) &&
  494         gtk_widget_get_sensitive (widgets->write_edit_all_check)) {
  495         gtk_widget_set_sensitive (widgets->write_edit_own_check, TRUE);
  496         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->write_edit_own_check))) {
  497             rights |= E_MAPI_PERMISSION_BIT_EDIT_OWNED;
  498 
  499             for (ii = 0; ii < G_N_ELEMENTS (predefined_levels) - 1; ii++) {
  500                 if (predefined_levels[ii].rights == rights) {
  501                     break;
  502                 }
  503             }
  504 
  505             gtk_combo_box_set_active (GTK_COMBO_BOX (widgets->level_combo), ii);
  506         }
  507     } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->write_edit_all_check))) {
  508         gtk_widget_set_sensitive (widgets->write_edit_own_check, FALSE);
  509         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widgets->write_edit_own_check), TRUE);
  510     }
  511 
  512     if (widgets->read_fb_simple_check && widgets->read_fb_detail_check) {
  513         if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->read_fb_detail_check)) &&
  514             gtk_widget_get_sensitive (widgets->read_fb_detail_check)) {
  515             gtk_widget_set_sensitive (widgets->read_fb_simple_check, TRUE);
  516         } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widgets->read_fb_detail_check))) {
  517             gtk_widget_set_sensitive (widgets->read_fb_simple_check, FALSE);
  518             gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widgets->read_fb_simple_check), TRUE);
  519         }
  520     }
  521 
  522     update_folder_permissions_tree_view (dialog, widgets);
  523 
  524     widgets->updating = FALSE;
  525 }
  526 
  527 static void
  528 update_permission_dialog_by_level_combo (GObject *dialog)
  529 {
  530     struct EMapiPermissionsDialogWidgets *widgets;
  531     uint32_t rights;
  532     gint ii;
  533 
  534     g_return_if_fail (dialog != NULL);
  535 
  536     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  537     g_return_if_fail (widgets != NULL);
  538 
  539     if (widgets->updating)
  540         return;
  541 
  542     ii = gtk_combo_box_get_active (GTK_COMBO_BOX (widgets->level_combo));
  543     if (ii < 0 || ii >= G_N_ELEMENTS (predefined_levels) - 1)
  544         return;
  545 
  546     if (!predefined_levels[ii].rights) {
  547         rights = predefined_levels[ii].rights;
  548     } else {
  549         rights = folder_permissions_dialog_to_rights (dialog);
  550         rights = predefined_levels[ii].rights | (rights & (E_MAPI_PERMISSION_BIT_FREE_BUSY_DETAILED |
  551             E_MAPI_PERMISSION_BIT_FREE_BUSY_SIMPLE));
  552     }
  553 
  554     widgets->updating = TRUE;
  555     update_folder_permissions_by_rights (dialog, rights);
  556     update_folder_permissions_tree_view (dialog, widgets);
  557     widgets->updating = FALSE;
  558 }
  559 
  560 static void
  561 add_button_clicked_cb (GObject *dialog)
  562 {
  563     struct EMapiPermissionsDialogWidgets *widgets;
  564     gchar *display_name = NULL;
  565     struct SBinary_short *entry_id = NULL;
  566     EMapiGalUserType user_type = E_MAPI_GAL_USER_NONE;
  567     GtkTreeModel *model;
  568     GtkTreeIter iter;
  569 
  570     g_return_if_fail (dialog != NULL);
  571 
  572     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  573     g_return_if_fail (widgets != NULL);
  574 
  575     if (widgets->updating)
  576         return;
  577 
  578     g_return_if_fail (widgets->tree_view != NULL);
  579 
  580     model = gtk_tree_view_get_model (GTK_TREE_VIEW (widgets->tree_view));
  581     g_return_if_fail (model != NULL);
  582 
  583     if (e_mapi_search_gal_user_modal (GTK_WINDOW (dialog), widgets->conn, NULL, &user_type, &display_name, NULL, NULL, &entry_id)) {
  584         EMapiPermissionEntry *pem;
  585         GtkTreeSelection *selection;
  586         gboolean found = FALSE;
  587 
  588         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widgets->tree_view));
  589         g_return_if_fail (selection != NULL);
  590 
  591         if (gtk_tree_model_get_iter_first (model, &iter)) {
  592             do {
  593                 EMapiGalUserType ut = E_MAPI_GAL_USER_NONE;
  594 
  595                 pem = NULL;
  596 
  597                 gtk_tree_model_get (model, &iter,
  598                     COL_E_MAPI_PERMISSION_ENTRY, &pem,
  599                     COL_E_MAPI_GAL_USER_TYPE, &ut,
  600                     -1);
  601 
  602                 if ((ut != E_MAPI_GAL_USER_REGULAR && ut == user_type) ||
  603                     (ut == E_MAPI_GAL_USER_REGULAR && pem && e_mapi_util_recip_entryid_equal (&pem->entry_id, entry_id))) {
  604                     gtk_tree_selection_select_iter (selection, &iter);
  605                     found = TRUE;
  606                     break;
  607                 }
  608             } while (gtk_tree_model_iter_next (model, &iter));
  609         }
  610 
  611         if (!found) {
  612             GtkListStore *store = GTK_LIST_STORE (model);
  613 
  614             pem = e_mapi_permission_entry_new (display_name, entry_id,
  615                 user_type == E_MAPI_GAL_USER_ANONYMOUS ? E_MAPI_PERMISSION_MEMBER_ID_ANONYMOUS_CLIENT :
  616                 user_type == E_MAPI_GAL_USER_DEFAULT ? E_MAPI_PERMISSION_MEMBER_ID_DEFAULT_USER : 0,
  617                 user_type == E_MAPI_GAL_USER_ANONYMOUS ? 0 : E_MAPI_PERMISSION_BIT_FREE_BUSY_SIMPLE);
  618 
  619             gtk_list_store_append (store, &iter);
  620             gtk_list_store_set (store, &iter,
  621                 COL_NAME, pem->username,
  622                 COL_PERMISSION_LEVEL, g_dpgettext2 (GETTEXT_PACKAGE, "PermissionsLevel", predefined_levels[0].name),
  623                 COL_E_MAPI_PERMISSION_ENTRY, pem,
  624                 COL_E_MAPI_GAL_USER_TYPE, user_type,
  625                 COL_IS_NEW, TRUE,
  626                 -1);
  627 
  628             gtk_tree_selection_select_iter (selection, &iter);
  629         }
  630     }
  631 
  632     g_free (display_name);
  633     if (entry_id) {
  634         g_free (entry_id->lpb);
  635         g_free (entry_id);
  636     }
  637 }
  638 
  639 static void
  640 remove_button_clicked_cb (GObject *dialog)
  641 {
  642     struct EMapiPermissionsDialogWidgets *widgets;
  643     GtkTreeSelection *selection;
  644     GtkTreeModel *model = NULL;
  645     GtkTreeIter iter;
  646 
  647     g_return_if_fail (dialog != NULL);
  648 
  649     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  650     g_return_if_fail (widgets != NULL);
  651 
  652     if (widgets->updating)
  653         return;
  654 
  655     selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widgets->tree_view));
  656     if (selection && gtk_tree_selection_get_selected (selection, &model, &iter)) {
  657         GtkTreeIter select;
  658         gboolean can_select = FALSE;
  659         EMapiPermissionEntry *pem = NULL;
  660 
  661         select = iter;
  662         can_select = gtk_tree_model_iter_next (model, &select);
  663         if (!can_select) {
  664             select = iter;
  665             can_select = gtk_tree_model_iter_previous (model, &select);
  666         }
  667 
  668         if (can_select)
  669             gtk_tree_selection_select_iter (selection, &select);
  670 
  671         gtk_tree_model_get (model, &iter, COL_E_MAPI_PERMISSION_ENTRY, &pem, -1);
  672 
  673         if (gtk_list_store_remove (GTK_LIST_STORE (model), &iter))
  674             e_mapi_permission_entry_free (pem);
  675     }
  676 }
  677 
  678 static void
  679 folder_permissions_free_found_entries (gpointer ptr)
  680 {
  681     GSList **entries = ptr;
  682 
  683     if (!entries)
  684         return;
  685 
  686     g_slist_free_full (*entries, (GDestroyNotify) e_mapi_permission_entry_free);
  687     *entries = NULL;
  688     g_free (entries);
  689 }
  690 
  691 static void
  692 read_folder_permissions_thread (GObject *dialog,
  693                 gpointer user_data,
  694                 GCancellable *cancellable,
  695                 GError **perror)
  696 {
  697     struct EMapiPermissionsDialogWidgets *widgets;
  698     mapi_object_t obj_folder;
  699     gboolean opened;
  700     GSList **pentries = user_data;
  701 
  702     g_return_if_fail (dialog != NULL);
  703     g_return_if_fail (pentries != NULL);
  704 
  705     if (g_cancellable_is_cancelled (cancellable))
  706         return;
  707 
  708     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  709     g_return_if_fail (widgets != NULL);
  710     g_return_if_fail (widgets->registry != NULL);
  711     g_return_if_fail (widgets->source != NULL);
  712     g_return_if_fail (widgets->mapi_settings != NULL);
  713 
  714     widgets->conn = e_mapi_config_utils_open_connection_for (GTK_WINDOW (dialog),
  715         widgets->registry,
  716         widgets->source,
  717         widgets->mapi_settings,
  718         cancellable,
  719         perror);
  720 
  721     if (!widgets->conn)
  722         g_cancellable_cancel (cancellable);
  723 
  724     if (g_cancellable_is_cancelled (cancellable))
  725         return;
  726 
  727     if (widgets->folder_category == E_MAPI_FOLDER_CATEGORY_FOREIGN)
  728         opened = e_mapi_connection_open_foreign_folder (widgets->conn, widgets->foreign_username, widgets->folder_id, &obj_folder, cancellable, perror);
  729     else if (widgets->folder_category == E_MAPI_FOLDER_CATEGORY_PUBLIC)
  730         opened = e_mapi_connection_open_public_folder (widgets->conn, widgets->folder_id, &obj_folder, cancellable, perror);
  731     else
  732         opened = e_mapi_connection_open_personal_folder (widgets->conn, widgets->folder_id, &obj_folder, cancellable, perror);
  733 
  734     if (opened) {
  735         e_mapi_connection_get_permissions (widgets->conn, &obj_folder, widgets->read_fb_simple_check != NULL, pentries, cancellable, perror);
  736         e_mapi_connection_close_folder (widgets->conn, &obj_folder, cancellable, perror);
  737     }
  738 }
  739 
  740 static void
  741 read_folder_permissions_idle (GObject *dialog,
  742                   gpointer user_data,
  743                   GCancellable *cancellable,
  744                   GError **perror)
  745 {
  746     struct EMapiPermissionsDialogWidgets *widgets;
  747     GSList **pentries = user_data;
  748     GSList *entry;
  749     GtkListStore *store;
  750     GtkTreeIter iter;
  751 
  752     g_return_if_fail (dialog != NULL);
  753     g_return_if_fail (pentries != NULL);
  754 
  755     if (g_cancellable_is_cancelled (cancellable))
  756         return;
  757 
  758     widgets = g_object_get_data (dialog, E_MAPI_PERM_DLG_WIDGETS);
  759     g_return_if_fail (widgets != NULL);
  760     g_return_if_fail (widgets->tree_view != NULL);
  761 
  762     store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (widgets->tree_view)));
  763     g_return_if_fail (store != NULL);
  764 
  765     for (entry = *pentries; entry; entry = entry->next) {
  766         EMapiPermissionEntry *pem = entry->data;
  767         EMapiGalUserType user_type;
  768         const gchar *perm_level;
  769         uint32_t rights;
  770         gint ii;
  771 
  772         if (!pem)
  773             continue;
  774 
  775         /* steal the pem */
  776         entry->data = NULL;
  777 
  778         if (!pem->username || !*pem->username) {
  779             g_free (pem->username);
  780 
  781             if (pem->member_id == E_MAPI_PERMISSION_MEMBER_ID_ANONYMOUS_CLIENT)
  782                 pem->username = g_strdup (C_("User", "Anonymous"));
  783             else if (pem->member_id == E_MAPI_PERMISSION_MEMBER_ID_DEFAULT_USER)
  784                 pem->username = g_strdup (C_("User", "Default"));
  785             else
  786                 pem->username = g_strdup (C_("User", "Unknown"));
  787         }
  788 
  789         rights = pem->member_rights;
  790         rights = rights & ~(E_MAPI_PERMISSION_BIT_FREE_BUSY_DETAILED |
  791             E_MAPI_PERMISSION_BIT_FREE_BUSY_SIMPLE);
  792 
  793         for (ii = 0; ii < G_N_ELEMENTS (predefined_levels) - 1; ii++) {
  794             if (predefined_levels[ii].rights == rights) {
  795                 break;
  796             }
  797         }
  798 
  799         perm_level = g_dpgettext2 (GETTEXT_PACKAGE, "PermissionsLevel", predefined_levels[ii].name);
  800 
  801         user_type = E_MAPI_GAL_USER_REGULAR;
  802         if (pem->member_id == E_MAPI_PERMISSION_MEMBER_ID_ANONYMOUS_CLIENT)
  803             user_type = E_MAPI_GAL_USER_ANONYMOUS;
  804         else if (pem->member_id == E_MAPI_PERMISSION_MEMBER_ID_DEFAULT_USER)
  805             user_type = E_MAPI_GAL_USER_DEFAULT;
  806 
  807         gtk_list_store_append (store, &iter);
  808         gtk_list_store_set (store, &iter,
  809             COL_NAME, pem->username,
  810             COL_PERMISSION_LEVEL, perm_level,
  811             COL_E_MAPI_PERMISSION_ENTRY, pem,
  812             COL_E_MAPI_GAL_USER_TYPE, user_type,
  813             COL_IS_NEW, FALSE,
  814             -1);
  815     }
  816 
  817     gtk_widget_set_sensitive (widgets->add_button, TRUE);
  818     gtk_dialog_set_response_sensitive (GTK_DIALOG (widgets->dialog), GTK_RESPONSE_OK, TRUE);
  819 }
  820 
  821 static void
  822 folder_permissions_tree_selection_changed_cb (GtkTreeSelection *selection,
  823                           struct EMapiPermissionsDialogWidgets *widgets)
  824 {
  825     GObject *dialog;
  826     GtkTreeModel *model = NULL;
  827     GtkTreeIter iter;
  828     gboolean has_selected;
  829 
  830     g_return_if_fail (selection != NULL);
  831     g_return_if_fail (widgets != NULL);
  832     g_return_if_fail (widgets->dialog != NULL);
  833     g_return_if_fail (widgets->add_button != NULL);
  834     g_return_if_fail (widgets->remove_button != NULL);
  835 
  836     dialog = G_OBJECT (widgets->dialog);
  837     has_selected = gtk_tree_selection_get_selected (selection, &model, &iter);
  838 
  839     gtk_widget_set_sensitive (widgets->add_button, TRUE);
  840     gtk_widget_set_sensitive (widgets->remove_button, has_selected);
  841 
  842     if (has_selected) {
  843         EMapiGalUserType user_type = E_MAPI_GAL_USER_NONE;
  844         EMapiPermissionEntry *pem = NULL;
  845 
  846         gtk_tree_model_get (model, &iter,
  847             COL_E_MAPI_PERMISSION_ENTRY, &pem,
  848             COL_E_MAPI_GAL_USER_TYPE, &user_type,
  849             -1);
  850 
  851         update_folder_permissions_sensitivity (dialog, pem != NULL, user_type);
  852         update_folder_permissions_by_rights (dialog, pem ? pem->member_rights : 0);
  853     } else {
  854         update_folder_permissions_sensitivity (dialog, FALSE, E_MAPI_GAL_USER_NONE);
  855         update_folder_permissions_by_rights (dialog, 0);
  856     }
  857 
  858     update_permission_level_combo_by_dialog (dialog);
  859 }
  860 
  861 static GtkWidget *
  862 create_permissions_tree_view (GObject *dialog,
  863                   struct EMapiPermissionsDialogWidgets *widgets)
  864 {
  865     GtkTreeView *tree_view;
  866     GtkTreeModel *model;
  867     GtkTreeSelection *selection;
  868     GtkCellRenderer *renderer;
  869     GtkTreeViewColumn *column;
  870     gint pos;
  871 
  872     g_return_val_if_fail (widgets != NULL, NULL);
  873 
  874     model = GTK_TREE_MODEL (gtk_list_store_new (5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_BOOLEAN));
  875     tree_view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (model));
  876     g_object_unref (model);
  877 
  878     renderer = gtk_cell_renderer_text_new ();
  879     g_object_set (renderer, "editable", FALSE, NULL);
  880     pos = gtk_tree_view_insert_column_with_attributes (tree_view, -1, _("Name"), renderer, "text", COL_NAME, NULL);
  881     column = gtk_tree_view_get_column (tree_view, pos - 1);
  882     gtk_tree_view_column_set_expand (column, TRUE);
  883 
  884     renderer = gtk_cell_renderer_text_new ();
  885     g_object_set (renderer, "editable", FALSE, NULL);
  886     gtk_tree_view_insert_column_with_attributes (tree_view, -1, _("Permission level"), renderer, "text", COL_PERMISSION_LEVEL, NULL);
  887 
  888     selection = gtk_tree_view_get_selection (tree_view);
  889     gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
  890     g_signal_connect (selection, "changed", G_CALLBACK (folder_permissions_tree_selection_changed_cb), widgets);
  891 
  892     widgets->tree_view = GTK_WIDGET (tree_view);
  893 
  894     return widgets->tree_view;
  895 }
  896 
  897 /* Opens dialog to subscribe to folders of other
  898    users in the given store */
  899 void
  900 e_mapi_edit_folder_permissions (GtkWindow *parent,
  901                 ESourceRegistry *registry,
  902                 ESource *source,
  903                 CamelMapiSettings *mapi_settings,
  904                 const gchar *account_name,
  905                 const gchar *folder_name,
  906                 mapi_id_t folder_id,
  907                 EMapiFolderCategory folder_category,
  908                 const gchar *foreign_username,
  909                 gboolean with_freebusy)
  910 {
  911     struct EMapiPermissionsDialogWidgets *widgets;
  912     PangoAttrList *attrs;
  913     GObject *dialog;
  914     GtkWidget *content;
  915     GtkWidget *label, *widget, *button, *frame, *hvbox;
  916     GtkScrolledWindow *scrolled_window;
  917     GtkComboBoxText *combo_text;
  918     GtkGrid *grid;
  919     GSList *radio_group, **found_entries;
  920     gchar *str;
  921     gint row, ii;
  922 
  923     g_return_if_fail (registry != NULL);
  924     g_return_if_fail (source != NULL);
  925     g_return_if_fail (mapi_settings != NULL);
  926     g_return_if_fail (account_name != NULL);
  927     g_return_if_fail (folder_name != NULL);
  928     g_return_if_fail (folder_id != 0);
  929 
  930     widgets = g_new0 (struct EMapiPermissionsDialogWidgets, 1);
  931     widgets->registry = g_object_ref (registry);
  932     widgets->source = g_object_ref (source);
  933     widgets->mapi_settings = g_object_ref (mapi_settings);
  934     widgets->folder_id = folder_id;
  935     widgets->folder_category = folder_category;
  936     widgets->foreign_username = g_strdup (foreign_username);
  937 
  938     widgets->dialog = gtk_dialog_new_with_buttons (
  939         _("Edit MAPI folder permissions…"),
  940         parent,
  941         GTK_DIALOG_DESTROY_WITH_PARENT,
  942         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  943         GTK_STOCK_OK, GTK_RESPONSE_OK,
  944         NULL);
  945 
  946     dialog = G_OBJECT (widgets->dialog);
  947     g_signal_connect (dialog, "response", G_CALLBACK (edit_permissions_response_cb), NULL);
  948     g_object_set_data_full (dialog, E_MAPI_PERM_DLG_WIDGETS, widgets, edit_permissions_widgets_free);
  949 
  950     gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
  951 
  952     content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
  953 
  954     grid = GTK_GRID (gtk_grid_new ());
  955     gtk_grid_set_row_homogeneous (grid, FALSE);
  956     gtk_grid_set_row_spacing (grid, 6);
  957     gtk_grid_set_column_homogeneous (grid, FALSE);
  958     gtk_grid_set_column_spacing (grid, 6);
  959     gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
  960     gtk_container_add (GTK_CONTAINER (content), GTK_WIDGET (grid));
  961 
  962     row = 0;
  963 
  964     label = gtk_label_new (_("Account:"));
  965     g_object_set (G_OBJECT (label),
  966         "hexpand", FALSE,
  967         "vexpand", FALSE,
  968         "xalign", 0.0,
  969         "halign", GTK_ALIGN_START,
  970         NULL);
  971 
  972     attrs = pango_attr_list_new ();
  973     pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
  974     widget = gtk_label_new (account_name);
  975     g_object_set (G_OBJECT (widget),
  976         "hexpand", TRUE,
  977         "vexpand", FALSE,
  978         "use-underline", FALSE,
  979         "attributes", attrs,
  980         "xalign", 0.0,
  981         "halign", GTK_ALIGN_START,
  982         NULL);
  983     pango_attr_list_unref (attrs);
  984 
  985     gtk_grid_attach (grid, label, 0, row, 1, 1);
  986     gtk_grid_attach (grid, widget, 1, row, 1, 1);
  987 
  988     row++;
  989 
  990     label = gtk_label_new (_("Folder name:"));
  991     g_object_set (G_OBJECT (label),
  992         "hexpand", FALSE,
  993         "vexpand", FALSE,
  994         "xalign", 0.0,
  995         NULL);
  996 
  997     widget = gtk_label_new (folder_name);
  998     gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_MIDDLE);
  999     gtk_widget_set_tooltip_text (widget, folder_name);
 1000     g_object_set (G_OBJECT (widget),
 1001         "hexpand", TRUE,
 1002         "vexpand", FALSE,
 1003         "xalign", 0.0,
 1004         NULL);
 1005 
 1006     gtk_grid_attach (grid, label, 0, row, 1, 1);
 1007     gtk_grid_attach (grid, widget, 1, row, 1, 1);
 1008 
 1009     row++;
 1010 
 1011     label = gtk_label_new (_("Folder ID:"));
 1012     g_object_set (G_OBJECT (label),
 1013         "hexpand", FALSE,
 1014         "vexpand", FALSE,
 1015         "xalign", 0.0,
 1016         NULL);
 1017 
 1018     str = e_mapi_util_mapi_id_to_string (folder_id);
 1019     widget = gtk_label_new (str);
 1020     g_free (str);
 1021     g_object_set (G_OBJECT (widget),
 1022         "hexpand", TRUE,
 1023         "vexpand", FALSE,
 1024         "xalign", 0.0,
 1025         "selectable", TRUE,
 1026         NULL);
 1027 
 1028     gtk_grid_attach (grid, label, 0, row, 1, 1);
 1029     gtk_grid_attach (grid, widget, 1, row, 1, 1);
 1030 
 1031     row++;
 1032 
 1033     widget = gtk_scrolled_window_new (NULL, NULL);
 1034     scrolled_window = GTK_SCROLLED_WINDOW (widget);
 1035     gtk_scrolled_window_set_min_content_width (scrolled_window, 120);
 1036     gtk_scrolled_window_set_min_content_height (scrolled_window, 120);
 1037     gtk_container_add (GTK_CONTAINER (widget), create_permissions_tree_view (dialog, widgets));
 1038     g_object_set (G_OBJECT (widget),
 1039         "hexpand", TRUE,
 1040         "vexpand", TRUE,
 1041         "shadow-type", GTK_SHADOW_IN,
 1042         NULL);
 1043 
 1044     gtk_grid_attach (grid, widget, 0, row, 2, 1);
 1045 
 1046     row++;
 1047 
 1048     hvbox = gtk_grid_new ();
 1049     gtk_orientable_set_orientation (GTK_ORIENTABLE (hvbox), GTK_ORIENTATION_HORIZONTAL);
 1050     gtk_grid_set_column_spacing (GTK_GRID (hvbox), 6);
 1051     gtk_grid_set_column_homogeneous (GTK_GRID (hvbox), TRUE);
 1052     g_object_set (G_OBJECT (hvbox),
 1053         "hexpand", FALSE,
 1054         "vexpand", FALSE,
 1055         "halign", GTK_ALIGN_END,
 1056         NULL);
 1057 
 1058     button = gtk_button_new_from_stock (GTK_STOCK_ADD);
 1059     widgets->add_button = button;
 1060     gtk_container_add (GTK_CONTAINER (hvbox), button);
 1061 
 1062     button = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
 1063     widgets->remove_button = button;
 1064     gtk_container_add (GTK_CONTAINER (hvbox), button);
 1065 
 1066     gtk_grid_attach (grid, hvbox, 0, row, 2, 1);
 1067 
 1068     row++;
 1069 
 1070     widget = gtk_frame_new (_("Permissions"));
 1071     g_object_set (G_OBJECT (widget),
 1072         "hexpand", TRUE,
 1073         "vexpand", FALSE,
 1074         NULL);
 1075     gtk_grid_attach (grid, widget, 0, row, 2, 1);
 1076 
 1077     grid = GTK_GRID (gtk_grid_new ());
 1078     gtk_grid_set_row_homogeneous (grid, FALSE);
 1079     gtk_grid_set_row_spacing (grid, 6);
 1080     gtk_grid_set_column_homogeneous (grid, FALSE);
 1081     gtk_grid_set_column_spacing (grid, 6);
 1082     gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
 1083     gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (grid));
 1084 
 1085     row = 0;
 1086 
 1087     hvbox = gtk_grid_new ();
 1088     gtk_orientable_set_orientation (GTK_ORIENTABLE (hvbox), GTK_ORIENTATION_HORIZONTAL);
 1089     gtk_grid_set_column_spacing (GTK_GRID (hvbox), 6);
 1090 
 1091     label = gtk_label_new_with_mnemonic (_("Permi_ssion level:"));
 1092     g_object_set (G_OBJECT (label),
 1093         "hexpand", FALSE,
 1094         "vexpand", FALSE,
 1095         "xalign", 0.0,
 1096         NULL);
 1097 
 1098     widget = GTK_WIDGET (g_object_new (gtk_combo_box_text_get_type (),
 1099         "has-entry", FALSE,
 1100         "entry-text-column", 0,
 1101         "hexpand", TRUE,
 1102         "vexpand", FALSE,
 1103         NULL));
 1104     widgets->level_combo = widget;
 1105 
 1106     combo_text = GTK_COMBO_BOX_TEXT (widget);
 1107     for (ii = 0; ii < G_N_ELEMENTS (predefined_levels); ii++)
 1108         gtk_combo_box_text_append_text (combo_text, g_dpgettext2 (GETTEXT_PACKAGE, "PermissionsLevel", predefined_levels[ii].name));
 1109     gtk_combo_box_set_active (GTK_COMBO_BOX (combo_text), 0);
 1110 
 1111     gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
 1112     gtk_container_add (GTK_CONTAINER (hvbox), label);
 1113     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1114 
 1115     gtk_grid_attach (grid, hvbox, 0, row, 2, 1);
 1116 
 1117     row++;
 1118 
 1119     frame = gtk_frame_new (C_("Permissions", "Read"));
 1120     g_object_set (G_OBJECT (frame),
 1121         "hexpand", FALSE,
 1122         "vexpand", FALSE,
 1123         NULL);
 1124 
 1125     hvbox = gtk_grid_new ();
 1126     gtk_orientable_set_orientation (GTK_ORIENTABLE (hvbox), GTK_ORIENTATION_VERTICAL);
 1127     gtk_grid_set_column_spacing (GTK_GRID (hvbox), 2);
 1128     gtk_container_add (GTK_CONTAINER (frame), hvbox);
 1129 
 1130     widget = gtk_radio_button_new_with_label (NULL, C_("Permissions", "None"));
 1131     widgets->read_none_radio = widget;
 1132     radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
 1133     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1134 
 1135     widget = gtk_radio_button_new_with_label (radio_group, C_("Permissions", "Full Details"));
 1136     widgets->read_full_radio = widget;
 1137     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1138 
 1139     if (with_freebusy) {
 1140         widget = gtk_check_button_new_with_label (C_("Permissions", "Simple Free/Busy"));
 1141         widgets->read_fb_simple_check = widget;
 1142         gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1143 
 1144         widget = gtk_check_button_new_with_label (C_("Permissions", "Detailed Free/Busy"));
 1145         widgets->read_fb_detail_check = widget;
 1146         gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1147     }
 1148 
 1149     gtk_grid_attach (grid, frame, 0, row, 1, 1);
 1150 
 1151     frame = gtk_frame_new (C_("Permissions", "Write"));
 1152     g_object_set (G_OBJECT (frame),
 1153         "hexpand", FALSE,
 1154         "vexpand", FALSE,
 1155         NULL);
 1156 
 1157     hvbox = gtk_grid_new ();
 1158     gtk_orientable_set_orientation (GTK_ORIENTABLE (hvbox), GTK_ORIENTATION_VERTICAL);
 1159     gtk_grid_set_column_spacing (GTK_GRID (hvbox), 2);
 1160     gtk_container_add (GTK_CONTAINER (frame), hvbox);
 1161 
 1162     widget = gtk_check_button_new_with_label (C_("Permissions", "Create items"));
 1163     widgets->write_create_items_check = widget;
 1164     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1165 
 1166     widget = gtk_check_button_new_with_label (C_("Permissions", "Create subfolders"));
 1167     widgets->write_create_subfolders_check = widget;
 1168     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1169 
 1170     widget = gtk_check_button_new_with_label (C_("Permissions", "Edit own"));
 1171     widgets->write_edit_own_check = widget;
 1172     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1173 
 1174     widget = gtk_check_button_new_with_label (C_("Permissions", "Edit all"));
 1175     widgets->write_edit_all_check = widget;
 1176     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1177 
 1178     gtk_grid_attach (grid, frame, 1, row, 1, 1);
 1179 
 1180     row++;
 1181 
 1182     frame = gtk_frame_new (C_("Permissions", "Delete items"));
 1183     g_object_set (G_OBJECT (frame),
 1184         "hexpand", FALSE,
 1185         "vexpand", FALSE,
 1186         NULL);
 1187 
 1188     hvbox = gtk_grid_new ();
 1189     gtk_orientable_set_orientation (GTK_ORIENTABLE (hvbox), GTK_ORIENTATION_VERTICAL);
 1190     gtk_grid_set_column_spacing (GTK_GRID (hvbox), 2);
 1191     gtk_container_add (GTK_CONTAINER (frame), hvbox);
 1192 
 1193     widget = gtk_radio_button_new_with_label (NULL, C_("Permissions", "None"));
 1194     widgets->delete_none_radio = widget;
 1195     radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
 1196     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1197 
 1198     widget = gtk_radio_button_new_with_label (radio_group, C_("Permissions", "Own"));
 1199     widgets->delete_own_radio = widget;
 1200     radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
 1201     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1202 
 1203     widget = gtk_radio_button_new_with_label (radio_group, C_("Permissions", "All"));
 1204     widgets->delete_all_radio = widget;
 1205     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1206 
 1207     gtk_grid_attach (grid, frame, 0, row, 1, 1);
 1208 
 1209     frame = gtk_frame_new (C_("Permissions", "Other"));
 1210     g_object_set (G_OBJECT (frame),
 1211         "hexpand", FALSE,
 1212         "vexpand", FALSE,
 1213         NULL);
 1214 
 1215     hvbox = gtk_grid_new ();
 1216     gtk_orientable_set_orientation (GTK_ORIENTABLE (hvbox), GTK_ORIENTATION_VERTICAL);
 1217     gtk_grid_set_column_spacing (GTK_GRID (hvbox), 2);
 1218     gtk_container_add (GTK_CONTAINER (frame), hvbox);
 1219 
 1220     widget = gtk_check_button_new_with_label (C_("Permissions", "Folder owner"));
 1221     widgets->other_folder_owner_check = widget;
 1222     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1223 
 1224     widget = gtk_check_button_new_with_label (C_("Permissions", "Folder contact"));
 1225     widgets->other_folder_contact_check = widget;
 1226     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1227 
 1228     widget = gtk_check_button_new_with_label (C_("Permissions", "Folder visible"));
 1229     widgets->other_folder_visible_check = widget;
 1230     gtk_container_add (GTK_CONTAINER (hvbox), widget);
 1231 
 1232     gtk_grid_attach (grid, frame, 1, row, 1, 1);
 1233 
 1234     row++;
 1235 
 1236     g_signal_connect_swapped (widgets->add_button,
 1237         "clicked", G_CALLBACK (add_button_clicked_cb), dialog);
 1238     g_signal_connect_swapped (widgets->remove_button,
 1239         "clicked", G_CALLBACK (remove_button_clicked_cb), dialog);
 1240     g_signal_connect_swapped (widgets->level_combo,
 1241         "changed", G_CALLBACK (update_permission_dialog_by_level_combo), dialog);
 1242     g_signal_connect_swapped (widgets->read_none_radio,
 1243         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1244     g_signal_connect_swapped (widgets->read_full_radio,
 1245         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1246     if (widgets->read_fb_simple_check)
 1247         g_signal_connect_swapped (widgets->read_fb_simple_check,
 1248             "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1249     if (widgets->read_fb_detail_check)
 1250         g_signal_connect_swapped (widgets->read_fb_detail_check,
 1251             "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1252     g_signal_connect_swapped (widgets->write_create_items_check,
 1253         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1254     g_signal_connect_swapped (widgets->write_create_subfolders_check,
 1255         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1256     g_signal_connect_swapped (widgets->write_edit_own_check,
 1257         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1258     g_signal_connect_swapped (widgets->write_edit_all_check,
 1259         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1260     g_signal_connect_swapped (widgets->delete_none_radio,
 1261         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1262     g_signal_connect_swapped (widgets->delete_own_radio,
 1263         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1264     g_signal_connect_swapped (widgets->delete_all_radio,
 1265         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1266     g_signal_connect_swapped (widgets->other_folder_owner_check,
 1267         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1268     g_signal_connect_swapped (widgets->other_folder_contact_check,
 1269         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1270     g_signal_connect_swapped (widgets->other_folder_visible_check,
 1271         "toggled", G_CALLBACK (update_permission_level_combo_by_dialog), dialog);
 1272 
 1273     enable_all_widgets (widgets, FALSE);
 1274 
 1275     gtk_dialog_set_response_sensitive (GTK_DIALOG (widgets->dialog), GTK_RESPONSE_OK, FALSE);
 1276 
 1277     gtk_widget_show_all (content);
 1278     gtk_widget_show (GTK_WIDGET (dialog));
 1279 
 1280     found_entries = g_new0 (GSList *, 1);
 1281 
 1282     e_mapi_config_utils_run_in_thread_with_feedback (GTK_WINDOW (dialog), dialog,
 1283         _("Reading folder permissions, please wait…"),
 1284         read_folder_permissions_thread,
 1285         read_folder_permissions_idle,
 1286         found_entries, folder_permissions_free_found_entries);
 1287 }