[evolution-ews] I#6 - Add 'Subscribe to folder of other EWS user' into File menu



commit f26fb7da86aa05e58b4a923e35afdb82f410ac25
Author: Milan Crha <mcrha redhat com>
Date:   Mon Jul 2 14:31:42 2018 +0200

    I#6 - Add 'Subscribe to folder of other EWS user' into File menu
    
    Closes https://gitlab.gnome.org/GNOME/evolution-ews/issues/6

 src/configuration/e-ews-config-utils.c             | 162 +++++++++++++++++++--
 src/configuration/e-ews-subscribe-foreign-folder.c | 158 ++++++++++++++++----
 2 files changed, 284 insertions(+), 36 deletions(-)
---
diff --git a/src/configuration/e-ews-config-utils.c b/src/configuration/e-ews-config-utils.c
index 5a2a5dfc..467097a2 100644
--- a/src/configuration/e-ews-config-utils.c
+++ b/src/configuration/e-ews-config-utils.c
@@ -799,6 +799,97 @@ e_ews_config_utils_run_folder_sizes_dialog (GtkWindow *parent,
        gtk_widget_show (GTK_WIDGET (dialog));
 }
 
+static void
+action_global_subscribe_foreign_folder_cb (GtkAction *action,
+                                          EShellView *shell_view)
+{
+       EShell *shell;
+       EShellBackend *shell_backend;
+       EShellWindow *shell_window;
+       EClientCache *client_cache;
+       CamelSession *session = NULL;
+
+       g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
+
+       shell_window = e_shell_view_get_shell_window (shell_view);
+       shell = e_shell_window_get_shell (shell_window);
+       shell_backend = e_shell_get_backend_by_name (shell, "mail");
+
+       if (shell_backend)
+               g_object_get (G_OBJECT (shell_backend), "session", &session, NULL);
+
+       if (!session)
+               return;
+
+       client_cache = e_shell_get_client_cache (shell);
+
+       e_ews_subscribe_foreign_folder (GTK_WINDOW (shell_window), session, NULL, client_cache);
+
+       g_object_unref (session);
+}
+
+static GtkActionEntry global_ews_entries[] = {
+       { "ews-global-subscribe-foreign-folder",
+         NULL,
+         N_("Subscribe to folder of other EWS user…"),
+         NULL,
+         NULL,  /* XXX Add a tooltip! */
+         G_CALLBACK (action_global_subscribe_foreign_folder_cb) }
+};
+
+static gboolean
+ews_ui_has_ews_account (EShellView *shell_view,
+                       CamelSession *in_session)
+{
+       CamelSession *session = in_session;
+       EShell *shell;
+       gboolean has_any = FALSE;
+
+       g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE);
+       if (in_session)
+               g_return_val_if_fail (CAMEL_IS_SESSION (in_session), FALSE);
+
+       shell = e_shell_window_get_shell (e_shell_view_get_shell_window (shell_view));
+
+       if (!session) {
+               EShellBackend *shell_backend;
+
+               shell_backend = e_shell_get_backend_by_name (shell, "mail");
+
+               if (shell_backend) {
+                       g_object_get (G_OBJECT (shell_backend), "session", &session, NULL);
+               }
+       }
+
+       if (session) {
+               ESourceRegistry *registry;
+               GList *services, *link;
+
+               registry = e_shell_get_registry (shell);
+               services = camel_session_list_services (session);
+
+               for (link = services; link && !has_any; link = g_list_next (link)) {
+                       CamelService *service = link->data;
+
+                       if (CAMEL_IS_EWS_STORE (service)) {
+                               ESource *source;
+
+                               source = e_source_registry_ref_source (registry, camel_service_get_uid 
(service));
+                               has_any = source && e_source_registry_check_enabled (registry, source);
+
+                               g_clear_object (&source);
+                       }
+               }
+
+               g_list_free_full (services, g_object_unref);
+       }
+
+       if (session && session != in_session)
+               g_object_unref (session);
+
+       return has_any;
+}
+
 static gboolean
 get_ews_store_from_folder_tree (EShellView *shell_view,
                                 gchar **pfolder_path,
@@ -1021,6 +1112,13 @@ static GtkActionEntry mail_folder_context_entries[] = {
 };
 
 static const gchar *ews_ui_mail_def =
+       "<menubar name='main-menu'>\n"
+       "  <menu action='file-menu'>\n"
+       "    <placeholder name='long-running-actions'>\n"
+       "      <menuitem action=\"ews-global-subscribe-foreign-folder\"/>\n"
+       "    </placeholder>\n"
+       "  </menu>\n"
+       "</menubar>\n"
        "<popup name=\"mail-folder-popup\">\n"
        "  <placeholder name=\"mail-folder-popup-actions\">\n"
        "    <menuitem action=\"mail-ews-folder-sizes\"/>\n"
@@ -1034,6 +1132,8 @@ ews_ui_update_actions_mail_cb (EShellView *shell_view,
                                GtkActionEntry *entries)
 {
        EShellWindow *shell_window;
+       EShellBackend *backend;
+       CamelSession *session = NULL;
        GtkActionGroup *action_group;
        GtkUIManager *ui_manager;
        EShellSidebar *shell_sidebar;
@@ -1041,7 +1141,7 @@ ews_ui_update_actions_mail_cb (EShellView *shell_view,
        CamelStore *selected_store = NULL;
        gchar *selected_path = NULL;
        gboolean account_node = FALSE, folder_node = FALSE;
-       gboolean online = FALSE;
+       gboolean online, has_ews_account;
 
        shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
        g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
@@ -1066,21 +1166,19 @@ ews_ui_update_actions_mail_cb (EShellView *shell_view,
        ui_manager = e_shell_window_get_ui_manager (shell_window);
        action_group = e_lookup_action_group (ui_manager, "mail");
 
-       if (account_node || folder_node) {
-               EShellBackend *backend;
-               CamelSession *session = NULL;
+       backend = e_shell_view_get_shell_backend (shell_view);
+       g_object_get (G_OBJECT (backend), "session", &session, NULL);
 
-               backend = e_shell_view_get_shell_backend (shell_view);
-               g_object_get (G_OBJECT (backend), "session", &session, NULL);
+       online = session && camel_session_get_online (session);
 
-               online = session && camel_session_get_online (session);
+       has_ews_account = account_node || folder_node || ews_ui_has_ews_account (shell_view, session);
 
-               if (session)
-                       g_object_unref (session);
-       }
+       if (session)
+               g_object_unref (session);
 
        ews_ui_enable_actions (action_group, mail_account_context_entries, G_N_ELEMENTS 
(mail_account_context_entries), account_node, online);
        ews_ui_enable_actions (action_group, mail_folder_context_entries, G_N_ELEMENTS 
(mail_folder_context_entries), folder_node, online);
+       ews_ui_enable_actions (action_group, global_ews_entries, G_N_ELEMENTS (global_ews_entries), 
has_ews_account, online);
 }
 
 static void
@@ -1106,6 +1204,11 @@ ews_ui_init_mail (GtkUIManager *ui_manager,
                action_group, GETTEXT_PACKAGE,
                mail_folder_context_entries, G_N_ELEMENTS (mail_folder_context_entries), shell_view);
 
+       /* Add global actions */
+       e_action_group_add_actions_localized (
+               action_group, GETTEXT_PACKAGE,
+               global_ews_entries, G_N_ELEMENTS (global_ews_entries), shell_view);
+
        /* Decide whether we want this option to be visible or not */
        g_signal_connect (
                shell_view, "update-actions",
@@ -1234,6 +1337,8 @@ update_ews_source_entries_cb (EShellView *shell_view,
        action_group = e_shell_window_get_action_group (shell_window, group);
 
        ews_ui_enable_actions (action_group, entries, EWS_ESOURCE_NUM_ENTRIES, is_ews_source, is_online);
+       ews_ui_enable_actions (action_group, global_ews_entries, G_N_ELEMENTS (global_ews_entries),
+               ews_ui_has_ews_account (shell_view, NULL), is_online);
 }
 
 static void
@@ -1243,6 +1348,7 @@ setup_ews_source_actions (EShellView *shell_view,
                           guint n_entries)
 {
        EShellWindow *shell_window;
+       GtkActionGroup *action_group;
        const gchar *group;
 
        g_return_if_fail (shell_view != NULL);
@@ -1263,11 +1369,17 @@ setup_ews_source_actions (EShellView *shell_view,
                g_return_if_reached ();
 
        shell_window = e_shell_view_get_shell_window (shell_view);
+       action_group = e_shell_window_get_action_group (shell_window, group);
 
        e_action_group_add_actions_localized (
-               e_shell_window_get_action_group (shell_window, group), GETTEXT_PACKAGE,
+               action_group, GETTEXT_PACKAGE,
                entries, EWS_ESOURCE_NUM_ENTRIES, shell_view);
 
+       /* Add global actions */
+       e_action_group_add_actions_localized (
+               action_group, GETTEXT_PACKAGE,
+               global_ews_entries, G_N_ELEMENTS (global_ews_entries), shell_view);
+
        g_signal_connect (shell_view, "update-actions", G_CALLBACK (update_ews_source_entries_cb), entries);
 }
 
@@ -1336,6 +1448,13 @@ static GtkActionEntry calendar_context_entries[] = {
 };
 
 static const gchar *ews_ui_cal_def =
+       "<menubar name='main-menu'>\n"
+       "  <menu action='file-menu'>\n"
+       "    <placeholder name='long-running-actions'>\n"
+       "      <menuitem action=\"ews-global-subscribe-foreign-folder\"/>\n"
+       "    </placeholder>\n"
+       "  </menu>\n"
+       "</menubar>\n"
        "<popup name=\"calendar-popup\">\n"
        "  <placeholder name=\"calendar-popup-actions\">\n"
        "    <menuitem action=\"calendar-ews-folder-permissions\"/>\n"
@@ -1367,6 +1486,13 @@ static GtkActionEntry tasks_context_entries[] = {
 };
 
 static const gchar *ews_ui_task_def =
+       "<menubar name='main-menu'>\n"
+       "  <menu action='file-menu'>\n"
+       "    <placeholder name='long-running-actions'>\n"
+       "      <menuitem action=\"ews-global-subscribe-foreign-folder\"/>\n"
+       "    </placeholder>\n"
+       "  </menu>\n"
+       "</menubar>\n"
        "<popup name=\"task-list-popup\">\n"
        "  <placeholder name=\"task-list-popup-actions\">\n"
        "    <menuitem action=\"tasks-ews-folder-permissions\"/>\n"
@@ -1398,6 +1524,13 @@ static GtkActionEntry memos_context_entries[] = {
 };
 
 static const gchar *ews_ui_memo_def =
+       "<menubar name='main-menu'>\n"
+       "  <menu action='file-menu'>\n"
+       "    <placeholder name='long-running-actions'>\n"
+       "      <menuitem action=\"ews-global-subscribe-foreign-folder\"/>\n"
+       "    </placeholder>\n"
+       "  </menu>\n"
+       "</menubar>\n"
        "<popup name=\"memo-list-popup\">\n"
        "  <placeholder name=\"memo-list-popup-actions\">\n"
        "    <menuitem action=\"memos-ews-folder-permissions\"/>\n"
@@ -1429,6 +1562,13 @@ static GtkActionEntry contacts_context_entries[] = {
 };
 
 static const gchar *ews_ui_book_def =
+       "<menubar name='main-menu'>\n"
+       "  <menu action='file-menu'>\n"
+       "    <placeholder name='long-running-actions'>\n"
+       "      <menuitem action=\"ews-global-subscribe-foreign-folder\"/>\n"
+       "    </placeholder>\n"
+       "  </menu>\n"
+       "</menubar>\n"
        "<popup name=\"address-book-popup\">\n"
        "  <placeholder name=\"address-book-popup-actions\">\n"
        "    <menuitem action=\"contacts-ews-folder-permissions\"/>\n"
diff --git a/src/configuration/e-ews-subscribe-foreign-folder.c 
b/src/configuration/e-ews-subscribe-foreign-folder.c
index 76c5d4a5..98d74405 100644
--- a/src/configuration/e-ews-subscribe-foreign-folder.c
+++ b/src/configuration/e-ews-subscribe-foreign-folder.c
@@ -38,13 +38,19 @@
 #include "e-ews-search-user.h"
 #include "e-ews-subscribe-foreign-folder.h"
 
+#define STR_ACCOUNTS_COMBO             "e-ews-accounts-combo"
 #define STR_USER_NAME_SELECTOR_ENTRY   "e-ews-name-selector-entry"
 #define STR_FOLDER_NAME_COMBO          "e-ews-folder-name-combo"
 #define STR_SUBFOLDERS_CHECK           "e-ews-subfolders-check"
 #define STR_EWS_CAMEL_SESSION          "e-ews-camel-session"
-#define STR_EWS_CAMEL_STORE            "e-ews-camel-store"
 #define STR_EWS_DIRECT_EMAIL           "e-ews-direct-email"
 
+enum {
+       COLUMN_UID = 0,
+       COLUMN_DISPLAY_NAME,
+       COLUMN_STORE
+};
+
 static void
 announce_new_folder (CamelEwsStore *ews_store,
                      const gchar *fid)
@@ -272,7 +278,7 @@ check_foreign_folder_thread (GObject *with_object,
        if (!conn) {
                g_set_error_literal (
                        perror, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_NORESPONSE,
-                       _("Cannot test foreign folder availability while in offline mode"));
+                       _("Cannot test foreign folder availability when the account is offline"));
                return;
        }
 
@@ -289,9 +295,17 @@ check_foreign_folder_thread (GObject *with_object,
                if (!e_ews_connection_resolve_names_sync (conn, G_PRIORITY_DEFAULT,
                        cffd->email, EWS_SEARCH_AD, NULL, FALSE,
                        &mailboxes, NULL, &includes_last_item,
-                       cancellable, perror)) {
-                       g_object_unref (conn);
-                       return;
+                       cancellable, &local_error)) {
+                       if (g_error_matches (local_error, EWS_CONNECTION_ERROR, 
EWS_CONNECTION_ERROR_NAMERESOLUTIONNORESULTS) ||
+                           g_error_matches (local_error, EWS_CONNECTION_ERROR, 
EWS_CONNECTION_ERROR_NAMERESOLUTIONNOMAILBOX)) {
+                               g_clear_error (&local_error);
+                               mailboxes = NULL;
+                       } else {
+                               if (local_error)
+                                       g_propagate_error (perror, local_error);
+                               g_object_unref (conn);
+                               return;
+                       }
                }
 
                if (!mailboxes) {
@@ -490,6 +504,24 @@ check_foreign_folder_idle (GObject *with_object,
        g_object_unref (settings);
 }
 
+static gpointer
+ref_selected_store (GObject *dialog)
+{
+       GtkComboBox *combo_box;
+       CamelStore *store = NULL;
+       GtkTreeIter iter;
+
+       combo_box = g_object_get_data (dialog, STR_ACCOUNTS_COMBO);
+       g_return_val_if_fail (combo_box != NULL, NULL);
+
+       if (gtk_combo_box_get_active_iter (combo_box, &iter)) {
+               gtk_tree_model_get (gtk_combo_box_get_model (combo_box), &iter,
+                       COLUMN_STORE, &store, -1);
+       }
+
+       return store;
+}
+
 static void
 subscribe_foreign_response_cb (GObject *dialog,
                                gint response_id)
@@ -514,9 +546,10 @@ subscribe_foreign_response_cb (GObject *dialog,
        entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
        combo_text = g_object_get_data (dialog, STR_FOLDER_NAME_COMBO);
        subfolders_check = g_object_get_data (dialog, STR_SUBFOLDERS_CHECK);
-       cstore = g_object_get_data (dialog, STR_EWS_CAMEL_STORE);
 
        g_return_if_fail (entry != NULL);
+
+       cstore = ref_selected_store (dialog);
        g_return_if_fail (cstore != NULL);
 
        username = NULL;
@@ -587,6 +620,7 @@ subscribe_foreign_response_cb (GObject *dialog,
 
        g_free (description);
        g_free (show_foldername);
+       g_object_unref (cstore);
 }
 
 static void
@@ -601,19 +635,18 @@ pick_gal_user_clicked_cb (GtkButton *button,
        g_return_if_fail (dialog != NULL);
 
        entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
-       ews_store = g_object_get_data (dialog, STR_EWS_CAMEL_STORE);
 
        g_return_if_fail (entry != NULL);
+
+       ews_store = ref_selected_store (dialog);
        g_return_if_fail (ews_store != NULL);
 
        text = g_strstrip (g_strdup (gtk_entry_get_text (entry)));
        conn = camel_ews_store_ref_connection (ews_store);
 
-       if (e_ews_search_user_modal (GTK_WINDOW (dialog),
-                                    conn,
-                                    text,
-                                    &display_name,
-                                    &email)) {
+       if (!conn) {
+               e_notice (dialog, GTK_MESSAGE_ERROR, "%s", _("Cannot search for user when the account is 
offline"));
+       } else if (e_ews_search_user_modal (GTK_WINDOW (dialog), conn, text, &display_name, &email)) {
                if (display_name && email && *email) {
                        gtk_entry_set_text (entry, display_name);
                        g_object_set_data_full (G_OBJECT (entry), STR_EWS_DIRECT_EMAIL, g_strdup (email), 
g_free);
@@ -623,7 +656,86 @@ pick_gal_user_clicked_cb (GtkButton *button,
        g_free (text);
        g_free (display_name);
        g_free (email);
-       g_object_unref (conn);
+       g_object_unref (ews_store);
+       g_clear_object (&conn);
+}
+
+static gint
+sort_accounts_by_display_name_cb (gconstpointer ptr1,
+                                 gconstpointer ptr2)
+{
+       CamelService *service1 = (CamelService *) ptr1;
+       CamelService *service2 = (CamelService *) ptr2;
+
+       return g_utf8_collate (camel_service_get_display_name (service1), camel_service_get_display_name 
(service2));
+}
+
+static GtkWidget *
+create_accounts_combo (CamelSession *session,
+                      EClientCache *client_cache,
+                      CamelStore *store)
+{
+       GtkListStore *list_store;
+       GtkTreeIter iter;
+       GtkComboBox *combo_box;
+       ESourceRegistry *registry;
+       GList *services, *link, *accounts = NULL;
+       GtkCellRenderer *renderer;
+
+       list_store = gtk_list_store_new (3,
+               G_TYPE_STRING,          /* COLUMN_UID - UID of the CamelEwsStore */
+               G_TYPE_STRING,          /* COLUMN_DISPLAY_NAME */
+               CAMEL_TYPE_EWS_STORE);  /* COLUMN_STORE */
+
+       registry = e_client_cache_ref_registry (client_cache);
+       services = camel_session_list_services (session);
+
+       for (link = services; link; link = g_list_next (link)) {
+               CamelService *service = link->data;
+
+               if (CAMEL_IS_EWS_STORE (service)) {
+                       ESource *source;
+
+                       source = e_source_registry_ref_source (registry, camel_service_get_uid (service));
+                       if (source && e_source_registry_check_enabled (registry, source)) {
+                               accounts = g_list_prepend (accounts, service);
+                       }
+
+                       g_clear_object (&source);
+               }
+       }
+
+       accounts = g_list_sort (accounts, sort_accounts_by_display_name_cb);
+
+       for (link = accounts; link; link = g_list_next (link)) {
+               CamelService *service = link->data;
+
+               gtk_list_store_append (list_store, &iter);
+               gtk_list_store_set (list_store, &iter,
+                       COLUMN_UID, camel_service_get_uid (service),
+                       COLUMN_DISPLAY_NAME, camel_service_get_display_name (service),
+                       COLUMN_STORE, service,
+                       -1);
+       }
+
+       g_list_free_full (services, g_object_unref);
+       g_list_free (accounts);
+       g_clear_object (&registry);
+
+       combo_box = GTK_COMBO_BOX (gtk_combo_box_new_with_model (GTK_TREE_MODEL (list_store)));
+       g_object_unref (list_store);
+
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
+       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer, "text", COLUMN_DISPLAY_NAME, 
NULL);
+
+       gtk_combo_box_set_id_column (combo_box, COLUMN_UID);
+       if (store)
+               gtk_combo_box_set_active_id (combo_box, camel_service_get_uid (CAMEL_SERVICE (store)));
+       else if (accounts)
+               gtk_combo_box_set_active (combo_box, 0);
+
+       return GTK_WIDGET (combo_box);
 }
 
 /* Opens dialog to subscribe to folders of other
@@ -634,20 +746,20 @@ e_ews_subscribe_foreign_folder (GtkWindow *parent,
                                 CamelStore *store,
                                 EClientCache *client_cache)
 {
-       PangoAttrList *attrs;
        ENameSelector *name_selector;
        ENameSelectorModel *name_selector_model;
        ENameSelectorDialog *name_selector_dialog;
        GObject *dialog;
        GtkWidget *content;
-       GtkWidget *label, *widget, *entry, *check;
+       GtkWidget *label, *widget, *entry, *check, *accounts_combo;
        GtkGrid *grid;
        GtkComboBoxText *combo_text;
        gint row;
 
        g_return_if_fail (session != NULL);
-       g_return_if_fail (store != NULL);
-       g_return_if_fail (CAMEL_IS_EWS_STORE (store));
+       if (store)
+               g_return_if_fail (CAMEL_IS_EWS_STORE (store));
+       g_return_if_fail (E_IS_CLIENT_CACHE (client_cache));
 
        dialog = G_OBJECT (gtk_dialog_new_with_buttons (
                _("Subscribe to folder of other EWS user..."),
@@ -680,19 +792,14 @@ e_ews_subscribe_foreign_folder (GtkWindow *parent,
                "halign", GTK_ALIGN_START,
                NULL);
 
-       attrs = pango_attr_list_new ();
-       pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
-       widget = gtk_label_new (camel_service_get_display_name (CAMEL_SERVICE (store)));
+       widget = create_accounts_combo (session, client_cache, store);
        g_object_set (
                G_OBJECT (widget),
                "hexpand", TRUE,
                "vexpand", FALSE,
-               "use-underline", FALSE,
-               "attributes", attrs,
-               "xalign", 0.0,
                "halign", GTK_ALIGN_START,
                NULL);
-       pango_attr_list_unref (attrs);
+       accounts_combo = widget;
 
        gtk_grid_attach (grid, label, 0, row, 1, 1);
        gtk_grid_attach (grid, widget, 1, row, 2, 1);
@@ -774,15 +881,16 @@ e_ews_subscribe_foreign_folder (GtkWindow *parent,
        gtk_grid_attach (grid, check, 1, row, 2, 1);
 
        /* remember widgets for later use */
+       g_object_set_data (dialog, STR_ACCOUNTS_COMBO, accounts_combo);
        g_object_set_data (dialog, STR_USER_NAME_SELECTOR_ENTRY, entry);
        g_object_set_data (dialog, STR_FOLDER_NAME_COMBO, widget);
        g_object_set_data (dialog, STR_SUBFOLDERS_CHECK, check);
 
        g_object_set_data_full (dialog, STR_EWS_CAMEL_SESSION, g_object_ref (session), g_object_unref);
-       g_object_set_data_full (dialog, STR_EWS_CAMEL_STORE, g_object_ref (store), g_object_unref);
 
        g_signal_connect_swapped (entry, "changed", G_CALLBACK (name_entry_changed_cb), dialog);
        g_signal_connect_swapped (combo_text, "changed", G_CALLBACK (folder_name_combo_changed_cb), dialog);
+       g_signal_connect_swapped (accounts_combo, "changed", G_CALLBACK (name_entry_changed_cb), dialog);
 
        name_entry_changed_cb (dialog);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]