"Fossies" - the Fresh Open Source Software Archive 
Member "evolution-mapi-3.46.1/src/configuration/e-mapi-config-utils.c" (2 Dec 2022, 56569 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-config-utils.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
3.44.0_vs_3.44.1.
1 /*
2 * e-mapi-config-utils.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 */
18
19 #include "evolution-mapi-config.h"
20
21 #include <string.h>
22 #include <unistd.h>
23 #include <glib/gi18n-lib.h>
24
25 #include <gtk/gtk.h>
26 #include <libedataserver/libedataserver.h>
27 #include <libedataserverui/libedataserverui.h>
28
29 #include <e-util/e-util.h>
30
31 #include <mail/em-folder-tree.h>
32 #include <shell/e-shell.h>
33 #include <shell/e-shell-sidebar.h>
34 #include <shell/e-shell-view.h>
35 #include <shell/e-shell-window.h>
36
37 #include "e-mapi-folder.h"
38 #include "e-mapi-connection.h"
39 #include "e-mapi-utils.h"
40 #include "e-source-mapi-folder.h"
41
42 #include "e-mapi-subscribe-foreign-folder.h"
43 #include "e-mapi-edit-folder-permissions.h"
44
45 #include "camel/camel-mapi-store.h"
46 #include "camel/camel-mapi-store-summary.h"
47
48 #include "e-mapi-config-utils.h"
49
50 struct RunWithFeedbackData
51 {
52 GtkWindow *parent;
53 GtkWidget *dialog;
54 GCancellable *cancellable;
55 GObject *with_object;
56 EMapiSetupFunc thread_func;
57 EMapiSetupFunc idle_func;
58 gpointer user_data;
59 GDestroyNotify free_user_data;
60 GError *error;
61 gboolean run_modal;
62 };
63
64 static void
65 free_run_with_feedback_data (gpointer ptr)
66 {
67 struct RunWithFeedbackData *rfd = ptr;
68
69 if (!rfd)
70 return;
71
72 if (rfd->dialog)
73 gtk_widget_destroy (rfd->dialog);
74
75 g_object_unref (rfd->cancellable);
76 g_object_unref (rfd->with_object);
77
78 if (rfd->free_user_data)
79 rfd->free_user_data (rfd->user_data);
80
81 g_clear_error (&rfd->error);
82
83 g_slice_free (struct RunWithFeedbackData, rfd);
84 }
85
86 static gboolean
87 run_with_feedback_idle (gpointer user_data)
88 {
89 struct RunWithFeedbackData *rfd = user_data;
90 gboolean was_cancelled = FALSE;
91
92 g_return_val_if_fail (rfd != NULL, FALSE);
93
94 if (!g_cancellable_is_cancelled (rfd->cancellable)) {
95 if (rfd->idle_func && !rfd->error)
96 rfd->idle_func (rfd->with_object, rfd->user_data, rfd->cancellable, &rfd->error);
97
98 was_cancelled = g_cancellable_is_cancelled (rfd->cancellable);
99
100 if (rfd->dialog) {
101 gtk_widget_destroy (rfd->dialog);
102 rfd->dialog = NULL;
103 }
104 } else {
105 was_cancelled = TRUE;
106 }
107
108 if (!was_cancelled) {
109 if (rfd->error)
110 e_notice (rfd->parent, GTK_MESSAGE_ERROR, "%s", rfd->error->message);
111 }
112
113 free_run_with_feedback_data (rfd);
114
115 return FALSE;
116 }
117
118 static gpointer
119 run_with_feedback_thread (gpointer user_data)
120 {
121 struct RunWithFeedbackData *rfd = user_data;
122
123 g_return_val_if_fail (rfd != NULL, NULL);
124 g_return_val_if_fail (rfd->thread_func != NULL, NULL);
125
126 if (!g_cancellable_is_cancelled (rfd->cancellable))
127 rfd->thread_func (rfd->with_object, rfd->user_data, rfd->cancellable, &rfd->error);
128
129 g_idle_add (run_with_feedback_idle, rfd);
130
131 return NULL;
132 }
133
134 static void
135 run_with_feedback_response_cb (GtkWidget *dialog,
136 gint resonse_id,
137 struct RunWithFeedbackData *rfd)
138 {
139 g_return_if_fail (rfd != NULL);
140
141 rfd->dialog = NULL;
142
143 g_cancellable_cancel (rfd->cancellable);
144
145 gtk_widget_destroy (dialog);
146 }
147
148 static void
149 e_mapi_config_utils_run_in_thread_with_feedback_general (GtkWindow *parent,
150 GObject *with_object,
151 const gchar *description,
152 EMapiSetupFunc thread_func,
153 EMapiSetupFunc idle_func,
154 gpointer user_data,
155 GDestroyNotify free_user_data,
156 gboolean run_modal)
157 {
158 GtkWidget *dialog, *label, *content, *spinner, *box;
159 struct RunWithFeedbackData *rfd;
160
161 g_return_if_fail (with_object != NULL);
162 g_return_if_fail (description != NULL);
163 g_return_if_fail (thread_func != NULL);
164
165 dialog = gtk_dialog_new_with_buttons ("",
166 parent,
167 GTK_DIALOG_MODAL,
168 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
169 NULL);
170
171 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
172
173 spinner = e_spinner_new ();
174 e_spinner_start (E_SPINNER (spinner));
175 gtk_box_pack_start (GTK_BOX (box), spinner, FALSE, FALSE, 0);
176
177 label = gtk_label_new (description);
178 gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
179
180 gtk_widget_show_all (box);
181
182 content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
183
184 gtk_container_add (GTK_CONTAINER (content), box);
185 gtk_container_set_border_width (GTK_CONTAINER (content), 12);
186
187 rfd = g_slice_new0 (struct RunWithFeedbackData);
188 rfd->parent = parent;
189 rfd->dialog = dialog;
190 rfd->cancellable = g_cancellable_new ();
191 rfd->with_object = g_object_ref (with_object);
192 rfd->thread_func = thread_func;
193 rfd->idle_func = idle_func;
194 rfd->user_data = user_data;
195 rfd->free_user_data = free_user_data;
196 rfd->error = NULL;
197 rfd->run_modal = run_modal;
198
199 g_signal_connect (dialog, "response", G_CALLBACK (run_with_feedback_response_cb), rfd);
200
201 if (run_modal) {
202 GThread *thread;
203 GCancellable *cancellable;
204
205 cancellable = g_object_ref (rfd->cancellable);
206
207 thread = g_thread_new (NULL, run_with_feedback_thread, rfd);
208 g_thread_unref (thread);
209
210 gtk_dialog_run (GTK_DIALOG (dialog));
211
212 g_cancellable_cancel (cancellable);
213 g_object_unref (cancellable);
214 } else {
215 GThread *thread;
216
217 gtk_widget_show (dialog);
218
219 thread = g_thread_new (NULL, run_with_feedback_thread, rfd);
220 g_thread_unref (thread);
221 }
222 }
223
224 void
225 e_mapi_config_utils_run_in_thread_with_feedback (GtkWindow *parent,
226 GObject *with_object,
227 const gchar *description,
228 EMapiSetupFunc thread_func,
229 EMapiSetupFunc idle_func,
230 gpointer user_data,
231 GDestroyNotify free_user_data)
232 {
233 e_mapi_config_utils_run_in_thread_with_feedback_general (parent, with_object, description, thread_func, idle_func, user_data, free_user_data, FALSE);
234 }
235
236 void
237 e_mapi_config_utils_run_in_thread_with_feedback_modal (GtkWindow *parent,
238 GObject *with_object,
239 const gchar *description,
240 EMapiSetupFunc thread_func,
241 EMapiSetupFunc idle_func,
242 gpointer user_data,
243 GDestroyNotify free_user_data)
244 {
245 e_mapi_config_utils_run_in_thread_with_feedback_general (parent, with_object, description, thread_func, idle_func, user_data, free_user_data, TRUE);
246 }
247
248 typedef struct _TryCredentialsData {
249 ESourceRegistry *registry;
250 CamelMapiSettings *mapi_settings;
251 EMapiConnection *conn;
252 } TryCredentialsData;
253
254 static gboolean
255 mapi_config_utils_try_credentials_sync (ECredentialsPrompter *prompter,
256 ESource *source,
257 const ENamedParameters *credentials,
258 gboolean *out_authenticated,
259 gpointer user_data,
260 GCancellable *cancellable,
261 GError **error)
262 {
263 TryCredentialsData *data = user_data;
264 EMapiProfileData empd = { 0 };
265 CamelNetworkSettings *network_settings;
266 GError *mapi_error = NULL;
267
268 network_settings = CAMEL_NETWORK_SETTINGS (data->mapi_settings);
269
270 empd.server = camel_network_settings_get_host (network_settings);
271 empd.username = camel_network_settings_get_user (network_settings);
272 e_mapi_util_profiledata_from_settings (&empd, data->mapi_settings);
273
274 data->conn = e_mapi_connection_new (
275 data->registry,
276 camel_mapi_settings_get_profile (data->mapi_settings),
277 credentials, cancellable, &mapi_error);
278
279 if (mapi_error) {
280 g_warn_if_fail (!data->conn);
281 data->conn = NULL;
282
283 g_propagate_error (error, mapi_error);
284
285 return FALSE;
286 }
287
288 g_warn_if_fail (data->conn);
289 *out_authenticated = TRUE;
290
291 return TRUE;
292 }
293
294 EMapiConnection *
295 e_mapi_config_utils_open_connection_for (GtkWindow *parent,
296 ESourceRegistry *registry,
297 ESource *source,
298 CamelMapiSettings *mapi_settings,
299 GCancellable *cancellable,
300 GError **perror)
301 {
302 const gchar *profile;
303 EMapiConnection *conn = NULL;
304 EMapiProfileData empd = { 0 };
305 CamelNetworkSettings *network_settings;
306 GError *local_error = NULL;
307
308 g_return_val_if_fail (registry != NULL, NULL);
309 g_return_val_if_fail (source != NULL, NULL);
310 g_return_val_if_fail (mapi_settings != NULL, NULL);
311
312 profile = camel_mapi_settings_get_profile (mapi_settings);
313
314 /* use the one from mailer, if there, otherwise open new */
315 conn = e_mapi_connection_find (profile);
316 if (conn)
317 return conn;
318
319 network_settings = CAMEL_NETWORK_SETTINGS (mapi_settings);
320
321 empd.server = camel_network_settings_get_host (network_settings);
322 empd.username = camel_network_settings_get_user (network_settings);
323 e_mapi_util_profiledata_from_settings (&empd, mapi_settings);
324
325 if (empd.krb_sso)
326 conn = e_mapi_connection_new (registry, profile, NULL, cancellable, &local_error);
327
328 while (!conn && !g_cancellable_is_cancelled (cancellable) && !local_error) {
329 if (empd.krb_sso) {
330 GError *krb_error = NULL;
331
332 e_mapi_util_trigger_krb_auth (&empd, &krb_error);
333
334 conn = e_mapi_connection_new (registry, profile, NULL, cancellable, &local_error);
335
336 if (!conn && krb_error) {
337 if (local_error) {
338 GError *new_error = g_error_new (local_error->domain, local_error->code,
339 /* Translators: the first '%s' is replaced with a generic error message,
340 the second '%s' is replaced with additional error information. */
341 C_("gssapi_error", "%s (%s)"), local_error->message, krb_error->message);
342 g_clear_error (&local_error);
343 local_error = new_error;
344 } else {
345 local_error = krb_error;
346 krb_error = NULL;
347 }
348 }
349
350 g_clear_error (&krb_error);
351 } else {
352 EShell *shell;
353 TryCredentialsData data;
354
355 shell = e_shell_get_default ();
356
357 data.mapi_settings = g_object_ref (mapi_settings);
358 data.registry = g_object_ref (registry);
359 data.conn = NULL;
360
361 e_credentials_prompter_loop_prompt_sync (e_shell_get_credentials_prompter (shell),
362 source, E_CREDENTIALS_PROMPTER_PROMPT_FLAG_ALLOW_SOURCE_SAVE,
363 mapi_config_utils_try_credentials_sync, &data, cancellable, &local_error);
364
365 if (data.conn)
366 conn = g_object_ref (data.conn);
367
368 g_clear_object (&data.mapi_settings);
369 g_clear_object (&data.registry);
370 g_clear_object (&data.conn);
371 }
372 }
373
374 if (local_error)
375 g_propagate_error (perror, local_error);
376
377 return conn;
378 }
379
380 #define FOLDERSIZE_MENU_ITEM 0
381
382 enum {
383 COL_FOLDERSIZE_NAME = 0,
384 COL_FOLDERSIZE_SIZE,
385 COL_FOLDERSIZE_MAX
386 };
387
388 typedef struct
389 {
390 GtkDialog *dialog;
391 GtkGrid *spinner_grid;
392
393 ESourceRegistry *registry;
394 ESource *source;
395 CamelMapiSettings *mapi_settings;
396
397 GSList *folder_list;
398 GCancellable *cancellable;
399 GError *error;
400 } FolderSizeDialogData;
401
402 static gboolean
403 mapi_settings_get_folder_size_idle (gpointer user_data)
404 {
405 GtkWidget *widget;
406 GtkCellRenderer *renderer;
407 GtkListStore *store;
408 GtkTreeIter iter;
409 GtkBox *content_area;
410 FolderSizeDialogData *fsd = user_data;
411
412 g_return_val_if_fail (fsd != NULL, FALSE);
413
414 if (g_cancellable_is_cancelled (fsd->cancellable))
415 goto cleanup;
416
417 /* Hide progress bar. Set status*/
418 gtk_widget_destroy (GTK_WIDGET (fsd->spinner_grid));
419
420 if (fsd->folder_list) {
421 GtkWidget *scrolledwindow, *tree_view;
422 GSList *fiter;
423
424 scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
425 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
426 gtk_widget_show (scrolledwindow);
427
428 /*Tree View */
429 tree_view = gtk_tree_view_new ();
430 renderer = gtk_cell_renderer_text_new ();
431 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),-1,
432 _("Folder"), renderer, "text", COL_FOLDERSIZE_NAME,
433 NULL);
434
435 renderer = gtk_cell_renderer_text_new ();
436 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),-1,
437 _("Size"), renderer, "text", COL_FOLDERSIZE_SIZE,
438 NULL);
439 /* Model for TreeView */
440 store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
441 gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (store));
442
443 /* Populate model with data */
444 for (fiter = fsd->folder_list; fiter; fiter = fiter->next) {
445 EMapiFolder *folder = fiter->data;
446 gchar *folder_size = g_format_size_full (folder->size, G_FORMAT_SIZE_IEC_UNITS);
447
448 gtk_list_store_append (store, &iter);
449 gtk_list_store_set (store, &iter,
450 COL_FOLDERSIZE_NAME, folder->folder_name,
451 COL_FOLDERSIZE_SIZE, folder_size,
452 -1);
453
454 g_free (folder_size);
455 }
456
457 gtk_container_add (GTK_CONTAINER (scrolledwindow), tree_view);
458 widget = scrolledwindow;
459 } else if (fsd->error) {
460 gchar *msg = g_strconcat (_("Unable to retrieve folder size information"), "\n", fsd->error->message, NULL);
461 widget = gtk_label_new (msg);
462 g_free (msg);
463 } else {
464 widget = gtk_label_new (_("Unable to retrieve folder size information"));
465 }
466
467 gtk_widget_show_all (widget);
468
469 /* Pack into content_area */
470 content_area = GTK_BOX (gtk_dialog_get_content_area (fsd->dialog));
471 gtk_box_pack_start (content_area, widget, TRUE, TRUE, 6);
472
473 cleanup:
474 e_mapi_folder_free_list (fsd->folder_list);
475 g_object_unref (fsd->registry);
476 g_object_unref (fsd->source);
477 g_object_unref (fsd->mapi_settings);
478 g_object_unref (fsd->cancellable);
479 g_clear_error (&fsd->error);
480 g_slice_free (FolderSizeDialogData, fsd);
481
482 return FALSE;
483 }
484
485 static gpointer
486 mapi_settings_get_folder_size_thread (gpointer user_data)
487 {
488 FolderSizeDialogData *fsd = user_data;
489 EMapiConnection *conn;
490
491 g_return_val_if_fail (fsd != NULL, NULL);
492
493 fsd->folder_list = NULL;
494 conn = e_mapi_config_utils_open_connection_for (GTK_WINDOW (fsd->dialog),
495 fsd->registry,
496 fsd->source,
497 fsd->mapi_settings,
498 fsd->cancellable,
499 &fsd->error);
500
501 if (conn && e_mapi_connection_connected (conn)) {
502 fsd->folder_list = NULL;
503 e_mapi_connection_get_folders_list (conn,
504 &fsd->folder_list,
505 NULL, NULL,
506 fsd->cancellable, &fsd->error);
507 }
508
509 if (conn)
510 g_object_unref (conn);
511
512 g_idle_add (mapi_settings_get_folder_size_idle, fsd);
513
514 return NULL;
515 }
516
517 void
518 e_mapi_config_utils_run_folder_size_dialog (ESourceRegistry *registry,
519 ESource *source,
520 CamelMapiSettings *mapi_settings)
521 {
522 GtkBox *content_area;
523 GtkWidget *spinner, *alignment, *dialog;
524 GtkWidget *spinner_label;
525 GCancellable *cancellable;
526 GThread *thread;
527 FolderSizeDialogData *fsd;
528
529 g_return_if_fail (mapi_settings != NULL);
530
531 dialog = gtk_dialog_new_with_buttons (_("Folder Size"), NULL,
532 GTK_DIALOG_DESTROY_WITH_PARENT,
533 GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
534 NULL);
535
536 fsd = g_slice_new0 (FolderSizeDialogData);
537 fsd->dialog = GTK_DIALOG (dialog);
538
539 gtk_window_set_default_size (GTK_WINDOW (fsd->dialog), 250, 300);
540
541 content_area = GTK_BOX (gtk_dialog_get_content_area (fsd->dialog));
542
543 spinner = e_spinner_new ();
544 e_spinner_start (E_SPINNER (spinner));
545 spinner_label = gtk_label_new (_("Fetching folder list…"));
546
547 fsd->spinner_grid = GTK_GRID (gtk_grid_new ());
548 gtk_grid_set_column_spacing (fsd->spinner_grid, 6);
549 gtk_grid_set_column_homogeneous (fsd->spinner_grid, FALSE);
550 gtk_orientable_set_orientation (GTK_ORIENTABLE (fsd->spinner_grid), GTK_ORIENTATION_HORIZONTAL);
551
552 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 1.0);
553 gtk_container_add (GTK_CONTAINER (alignment), spinner);
554 gtk_misc_set_alignment (GTK_MISC (spinner_label), 0.0, 0.5);
555
556 gtk_container_add (GTK_CONTAINER (fsd->spinner_grid), alignment);
557 gtk_container_add (GTK_CONTAINER (fsd->spinner_grid), spinner_label);
558
559 /* Pack the TreeView into dialog's content area */
560 gtk_box_pack_start (content_area, GTK_WIDGET (fsd->spinner_grid), TRUE, TRUE, 6);
561 gtk_widget_show_all (GTK_WIDGET (fsd->dialog));
562
563 cancellable = g_cancellable_new ();
564 fsd->registry = g_object_ref (registry);
565 fsd->source = g_object_ref (source);
566 fsd->mapi_settings = g_object_ref (mapi_settings);
567 fsd->cancellable = g_object_ref (cancellable);
568
569 thread = g_thread_new (NULL, mapi_settings_get_folder_size_thread, fsd);
570 g_thread_unref (thread);
571
572 /* Start the dialog */
573 gtk_dialog_run (GTK_DIALOG (dialog));
574
575 g_cancellable_cancel (cancellable);
576 g_object_unref (cancellable);
577 gtk_widget_destroy (GTK_WIDGET (dialog));
578 }
579
580 static void
581 action_global_subscribe_foreign_folder_cb (GtkAction *action,
582 EShellView *shell_view)
583 {
584 EShell *shell;
585 EShellBackend *shell_backend;
586 EShellWindow *shell_window;
587 EClientCache *client_cache;
588 CamelSession *session = NULL;
589
590 g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
591
592 shell_window = e_shell_view_get_shell_window (shell_view);
593 shell = e_shell_window_get_shell (shell_window);
594 shell_backend = e_shell_get_backend_by_name (shell, "mail");
595
596 if (shell_backend)
597 g_object_get (G_OBJECT (shell_backend), "session", &session, NULL);
598
599 if (!session)
600 return;
601
602 client_cache = e_shell_get_client_cache (shell);
603
604 e_mapi_subscribe_foreign_folder (GTK_WINDOW (shell_window), session, NULL, client_cache);
605
606 g_object_unref (session);
607 }
608
609 static GtkActionEntry global_mapi_entries[] = {
610 { "mapi-global-subscribe-foreign-folder",
611 NULL,
612 N_("Subscribe to folder of other MAPI user…"),
613 NULL,
614 NULL, /* XXX Add a tooltip! */
615 G_CALLBACK (action_global_subscribe_foreign_folder_cb) }
616 };
617
618 static gboolean
619 mapi_ui_has_mapi_account (EShellView *shell_view,
620 CamelSession *in_session)
621 {
622 CamelSession *session = in_session;
623 EShell *shell;
624 gboolean has_any = FALSE;
625
626 g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE);
627 if (in_session)
628 g_return_val_if_fail (CAMEL_IS_SESSION (in_session), FALSE);
629
630 shell = e_shell_window_get_shell (e_shell_view_get_shell_window (shell_view));
631
632 if (!session) {
633 EShellBackend *shell_backend;
634
635 shell_backend = e_shell_get_backend_by_name (shell, "mail");
636
637 if (shell_backend) {
638 g_object_get (G_OBJECT (shell_backend), "session", &session, NULL);
639 }
640 }
641
642 if (session) {
643 ESourceRegistry *registry;
644 GList *services, *link;
645
646 registry = e_shell_get_registry (shell);
647 services = camel_session_list_services (session);
648
649 for (link = services; link && !has_any; link = g_list_next (link)) {
650 CamelService *service = link->data;
651
652 if (CAMEL_IS_MAPI_STORE (service)) {
653 ESource *source;
654
655 source = e_source_registry_ref_source (registry, camel_service_get_uid (service));
656 has_any = source && e_source_registry_check_enabled (registry, source);
657
658 g_clear_object (&source);
659 }
660 }
661
662 g_list_free_full (services, g_object_unref);
663 }
664
665 if (session && session != in_session)
666 g_object_unref (session);
667
668 return has_any;
669 }
670
671 static gchar *
672 get_profile_name_from_folder_tree (EShellView *shell_view,
673 gchar **pfolder_path,
674 CamelStore **pstore)
675 {
676 EShellSidebar *shell_sidebar;
677 EMFolderTree *folder_tree;
678 gchar *profile = NULL, *selected_path = NULL;
679 CamelStore *selected_store = NULL;
680
681 /* Get hold of Folder Tree */
682 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
683 g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
684 if (em_folder_tree_get_selected (folder_tree, &selected_store, &selected_path) ||
685 em_folder_tree_store_root_selected (folder_tree, &selected_store)) {
686 if (selected_store) {
687 CamelProvider *provider = camel_service_get_provider (CAMEL_SERVICE (selected_store));
688
689 if (provider && g_ascii_strcasecmp (provider->protocol, "mapi") == 0) {
690 CamelService *service;
691 CamelSettings *settings;
692
693 service = CAMEL_SERVICE (selected_store);
694
695 settings = camel_service_ref_settings (service);
696 g_object_get (settings, "profile", &profile, NULL);
697 g_object_unref (settings);
698
699 if (pstore && profile)
700 *pstore = g_object_ref (selected_store);
701
702 if (pfolder_path)
703 *pfolder_path = selected_path;
704 else
705 g_free (selected_path);
706
707 selected_path = NULL;
708 }
709
710 g_object_unref (selected_store);
711 }
712
713 g_free (selected_path);
714 }
715
716 g_object_unref (folder_tree);
717
718 return profile;
719 }
720
721 static void
722 action_folder_size_cb (GtkAction *action,
723 EShellView *shell_view)
724 {
725 gchar *profile;
726 CamelSession *session;
727 CamelStore *store = NULL;
728
729 profile = get_profile_name_from_folder_tree (shell_view, NULL, &store);
730 if (profile && store) {
731 CamelSettings *settings;
732 ESourceRegistry *registry;
733 ESource *source;
734
735 session = camel_service_ref_session (CAMEL_SERVICE (store));
736 registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
737 source = e_source_registry_ref_source (registry, camel_service_get_uid (CAMEL_SERVICE (store)));
738
739 settings = camel_service_ref_settings (CAMEL_SERVICE (store));
740
741 e_mapi_config_utils_run_folder_size_dialog (
742 registry, source, CAMEL_MAPI_SETTINGS (settings));
743
744 g_object_unref (settings);
745
746 g_object_unref (source);
747
748 g_object_unref (session);
749 }
750
751 g_free (profile);
752 if (store)
753 g_object_unref (store);
754 }
755
756 static void
757 action_subscribe_foreign_folder_cb (GtkAction *action,
758 EShellView *shell_view)
759 {
760 gchar *profile;
761 GtkWindow *parent;
762 EShell *shell;
763 EShellBackend *backend;
764 EClientCache *client_cache;
765 CamelSession *session = NULL;
766 CamelStore *store = NULL;
767
768 profile = get_profile_name_from_folder_tree (shell_view, NULL, &store);
769 if (!profile)
770 return;
771
772 parent = GTK_WINDOW (e_shell_view_get_shell_window (shell_view));
773 backend = e_shell_view_get_shell_backend (shell_view);
774 g_object_get (G_OBJECT (backend), "session", &session, NULL);
775
776 shell = e_shell_backend_get_shell (backend);
777 client_cache = e_shell_get_client_cache (shell);
778
779 e_mapi_subscribe_foreign_folder (parent, session, store, client_cache);
780
781 g_object_unref (session);
782 g_object_unref (store);
783 g_free (profile);
784 }
785
786 static void
787 action_folder_permissions_mail_cb (GtkAction *action,
788 EShellView *shell_view)
789 {
790 gchar *profile, *folder_path = NULL;
791 EShellWindow *shell_window;
792 GtkWindow *parent;
793 CamelStore *store = NULL;
794 CamelMapiStore *mapi_store;
795 CamelStoreInfo *si;
796
797 profile = get_profile_name_from_folder_tree (shell_view, &folder_path, &store);
798 if (!profile)
799 return;
800
801 mapi_store = CAMEL_MAPI_STORE (store);
802 g_return_if_fail (mapi_store != NULL);
803 g_return_if_fail (folder_path != NULL);
804
805 shell_window = e_shell_view_get_shell_window (shell_view);
806 parent = GTK_WINDOW (shell_window);
807
808 si = camel_store_summary_path (mapi_store->summary, folder_path);
809 if (!si) {
810 e_notice (parent, GTK_MESSAGE_ERROR, _("Cannot edit permissions of folder “%s”, choose other folder."), folder_path);
811 } else {
812 CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) si;
813 ESourceRegistry *registry = e_shell_get_registry (e_shell_window_get_shell (shell_window));
814 ESource *source;
815 CamelSettings *settings;
816
817 source = e_source_registry_ref_source (registry, camel_service_get_uid (CAMEL_SERVICE (store)));
818 g_return_if_fail (source != NULL);
819
820 settings = camel_service_ref_settings (CAMEL_SERVICE (store));
821
822 e_mapi_edit_folder_permissions (parent,
823 registry,
824 source,
825 CAMEL_MAPI_SETTINGS (settings),
826 camel_service_get_display_name (CAMEL_SERVICE (store)),
827 folder_path,
828 msi->folder_id,
829 (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0 ? E_MAPI_FOLDER_CATEGORY_FOREIGN :
830 (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ? E_MAPI_FOLDER_CATEGORY_PUBLIC :
831 E_MAPI_FOLDER_CATEGORY_PERSONAL,
832 msi->foreign_username,
833 FALSE);
834
835 g_object_unref (settings);
836
837 g_object_unref (source);
838 }
839
840 g_object_unref (store);
841 g_free (folder_path);
842 }
843
844 static void
845 mapi_ui_enable_actions (GtkActionGroup *action_group,
846 const GtkActionEntry *entries,
847 guint n_entries,
848 gboolean can_show,
849 gboolean is_online)
850 {
851 gint ii;
852
853 g_return_if_fail (action_group != NULL);
854 g_return_if_fail (entries != NULL);
855
856 for (ii = 0; ii < n_entries; ii++) {
857 GtkAction *action;
858
859 action = gtk_action_group_get_action (action_group, entries[ii].name);
860 if (!action)
861 continue;
862
863 gtk_action_set_visible (action, can_show);
864 if (can_show)
865 gtk_action_set_sensitive (action, is_online);
866 }
867 }
868
869 static GtkActionEntry mail_account_context_entries[] = {
870
871 { "mail-mapi-folder-size",
872 NULL,
873 N_("Folder size…"),
874 NULL,
875 NULL, /* XXX Add a tooltip! */
876 G_CALLBACK (action_folder_size_cb) },
877
878 { "mail-mapi-subscribe-foreign-folder",
879 NULL,
880 N_("Subscribe to folder of other user…"),
881 NULL,
882 NULL, /* XXX Add a tooltip! */
883 G_CALLBACK (action_subscribe_foreign_folder_cb) }
884 };
885
886 static GtkActionEntry mail_folder_context_entries[] = {
887 { "mail-mapi-folder-permissions",
888 "folder-new",
889 N_("Permissions…"),
890 NULL,
891 N_("Edit MAPI folder permissions"),
892 G_CALLBACK (action_folder_permissions_mail_cb) }
893 };
894
895 static const gchar *mapi_ui_mail_def =
896 "<menubar name='main-menu'>\n"
897 " <menu action='file-menu'>\n"
898 " <placeholder name='long-running-actions'>\n"
899 " <menuitem action=\"mapi-global-subscribe-foreign-folder\"/>\n"
900 " </placeholder>\n"
901 " </menu>\n"
902 "</menubar>\n"
903 "<popup name=\"mail-folder-popup\">\n"
904 " <placeholder name=\"mail-folder-popup-actions\">\n"
905 " <menuitem action=\"mail-mapi-folder-size\"/>\n"
906 " <menuitem action=\"mail-mapi-subscribe-foreign-folder\"/>\n"
907 " <menuitem action=\"mail-mapi-folder-permissions\"/>\n"
908 " </placeholder>\n"
909 "</popup>\n";
910
911 static void
912 mapi_ui_update_actions_mail_cb (EShellView *shell_view,
913 GtkActionEntry *entries)
914 {
915 EShellWindow *shell_window;
916 EShellBackend *backend;
917 CamelSession *session = NULL;
918 GtkActionGroup *action_group;
919 GtkUIManager *ui_manager;
920 EShellSidebar *shell_sidebar;
921 EMFolderTree *folder_tree;
922 CamelStore *selected_store = NULL;
923 gchar *selected_path = NULL;
924 gboolean account_node = FALSE, folder_node = FALSE;
925 gboolean online, has_mapi_account;
926
927 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
928 g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
929 if (em_folder_tree_get_selected (folder_tree, &selected_store, &selected_path) ||
930 em_folder_tree_store_root_selected (folder_tree, &selected_store)) {
931 if (selected_store) {
932 CamelProvider *provider = camel_service_get_provider (CAMEL_SERVICE (selected_store));
933
934 if (provider && g_ascii_strcasecmp (provider->protocol, "mapi") == 0) {
935 account_node = !selected_path || !*selected_path;
936 folder_node = !account_node;
937 }
938
939 g_object_unref (selected_store);
940 }
941 }
942 g_object_unref (folder_tree);
943
944 g_free (selected_path);
945
946 shell_window = e_shell_view_get_shell_window (shell_view);
947 ui_manager = e_shell_window_get_ui_manager (shell_window);
948 action_group = e_lookup_action_group (ui_manager, "mail");
949
950 backend = e_shell_view_get_shell_backend (shell_view);
951 g_object_get (G_OBJECT (backend), "session", &session, NULL);
952
953 online = session && camel_session_get_online (session);
954
955 has_mapi_account = account_node || folder_node || mapi_ui_has_mapi_account (shell_view, session);
956
957 if (session)
958 g_object_unref (session);
959
960 mapi_ui_enable_actions (action_group, mail_account_context_entries, G_N_ELEMENTS (mail_account_context_entries), account_node, online);
961 mapi_ui_enable_actions (action_group, mail_folder_context_entries, G_N_ELEMENTS (mail_folder_context_entries), folder_node, online);
962 mapi_ui_enable_actions (action_group, global_mapi_entries, G_N_ELEMENTS (global_mapi_entries), has_mapi_account, online);
963 }
964
965 static void
966 mapi_ui_init_mail (GtkUIManager *ui_manager,
967 EShellView *shell_view,
968 gchar **ui_definition)
969 {
970 EShellWindow *shell_window;
971 GtkActionGroup *action_group;
972
973 g_return_if_fail (ui_definition != NULL);
974
975 *ui_definition = g_strdup (mapi_ui_mail_def);
976
977 shell_window = e_shell_view_get_shell_window (shell_view);
978 action_group = e_shell_window_get_action_group (shell_window, "mail");
979
980 /* Add actions to the "mail" action group. */
981 e_action_group_add_actions_localized (action_group, GETTEXT_PACKAGE,
982 mail_account_context_entries, G_N_ELEMENTS (mail_account_context_entries), shell_view);
983 e_action_group_add_actions_localized (action_group, GETTEXT_PACKAGE,
984 mail_folder_context_entries, G_N_ELEMENTS (mail_folder_context_entries), shell_view);
985
986 /* Add global actions */
987 e_action_group_add_actions_localized (
988 action_group, GETTEXT_PACKAGE,
989 global_mapi_entries, G_N_ELEMENTS (global_mapi_entries), shell_view);
990
991 /* Decide whether we want this option to be visible or not */
992 g_signal_connect (shell_view, "update-actions",
993 G_CALLBACK (mapi_ui_update_actions_mail_cb),
994 shell_view);
995 }
996
997 static gboolean
998 get_selected_mapi_source (EShellView *shell_view,
999 ESource **selected_source,
1000 ESourceRegistry **registry)
1001 {
1002 ESource *source;
1003 EShellSidebar *shell_sidebar;
1004 ESourceSelector *selector = NULL;
1005
1006 g_return_val_if_fail (shell_view != NULL, FALSE);
1007
1008 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
1009 g_return_val_if_fail (shell_sidebar != NULL, FALSE);
1010
1011 g_object_get (shell_sidebar, "selector", &selector, NULL);
1012 g_return_val_if_fail (selector != NULL, FALSE);
1013
1014 source = e_source_selector_ref_primary_selection (selector);
1015 if (source) {
1016 ESourceBackend *backend_ext = NULL;
1017
1018 if (e_source_has_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK))
1019 backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK);
1020 else if (e_source_has_extension (source, E_SOURCE_EXTENSION_CALENDAR))
1021 backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR);
1022 else if (e_source_has_extension (source, E_SOURCE_EXTENSION_MEMO_LIST))
1023 backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_MEMO_LIST);
1024 else if (e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST))
1025 backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_TASK_LIST);
1026 else if (e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_ACCOUNT))
1027 backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_MAIL_ACCOUNT);
1028
1029 if (!backend_ext ||
1030 g_strcmp0 (e_source_backend_get_backend_name (backend_ext), "mapi") != 0) {
1031 g_object_unref (source);
1032 source = NULL;
1033 }
1034 }
1035
1036 if (source && registry)
1037 *registry = g_object_ref (e_source_selector_get_registry (selector));
1038
1039 g_object_unref (selector);
1040
1041 if (selected_source)
1042 *selected_source = source;
1043 else if (source)
1044 g_object_unref (source);
1045
1046 return source != NULL;
1047 }
1048
1049 /* how many menu entries are defined; all calendar/tasks/memos/contacts
1050 actions should have same count */
1051 #define MAPI_ESOURCE_NUM_ENTRIES 1
1052
1053 static void
1054 update_mapi_source_entries_cb (EShellView *shell_view,
1055 GtkActionEntry *entries)
1056 {
1057 GtkActionGroup *action_group;
1058 EShell *shell;
1059 EShellWindow *shell_window;
1060 ESource *source = NULL;
1061 const gchar *group;
1062 gboolean is_mapi_source, is_online;
1063
1064 g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1065 g_return_if_fail (entries != NULL);
1066
1067 if (strstr (entries->name, "calendar"))
1068 group = "calendar";
1069 else if (strstr (entries->name, "tasks"))
1070 group = "tasks";
1071 else if (strstr (entries->name, "memos"))
1072 group = "memos";
1073 else if (strstr (entries->name, "contacts"))
1074 group = "contacts";
1075 else
1076 g_return_if_reached ();
1077
1078 is_mapi_source = get_selected_mapi_source (shell_view, &source, NULL);
1079
1080 if (is_mapi_source) {
1081 ESource *clicked_source = NULL;
1082
1083 g_object_get (G_OBJECT (shell_view), "clicked-source", &clicked_source, NULL);
1084
1085 if (clicked_source && clicked_source != source)
1086 is_mapi_source = FALSE;
1087
1088 g_clear_object (&clicked_source);
1089 }
1090
1091 g_clear_object (&source);
1092
1093 shell_window = e_shell_view_get_shell_window (shell_view);
1094 shell = e_shell_window_get_shell (shell_window);
1095
1096 is_online = shell && e_shell_get_online (shell);
1097 action_group = e_shell_window_get_action_group (shell_window, group);
1098
1099 mapi_ui_enable_actions (action_group, entries, MAPI_ESOURCE_NUM_ENTRIES, is_mapi_source, is_online);
1100 mapi_ui_enable_actions (action_group, global_mapi_entries, G_N_ELEMENTS (global_mapi_entries),
1101 mapi_ui_has_mapi_account (shell_view, NULL), is_online);
1102 }
1103
1104 static void
1105 setup_mapi_source_actions (EShellView *shell_view,
1106 GtkUIManager *ui_manager,
1107 GtkActionEntry *entries,
1108 guint n_entries)
1109 {
1110 EShellWindow *shell_window;
1111 GtkActionGroup *action_group;
1112 const gchar *group;
1113
1114 g_return_if_fail (shell_view != NULL);
1115 g_return_if_fail (ui_manager != NULL);
1116 g_return_if_fail (entries != NULL);
1117 g_return_if_fail (n_entries > 0);
1118 g_return_if_fail (n_entries == MAPI_ESOURCE_NUM_ENTRIES);
1119
1120 if (strstr (entries->name, "calendar"))
1121 group = "calendar";
1122 else if (strstr (entries->name, "tasks"))
1123 group = "tasks";
1124 else if (strstr (entries->name, "memos"))
1125 group = "memos";
1126 else if (strstr (entries->name, "contacts"))
1127 group = "contacts";
1128 else
1129 g_return_if_reached ();
1130
1131 shell_window = e_shell_view_get_shell_window (shell_view);
1132 action_group = e_shell_window_get_action_group (shell_window, group);
1133
1134 e_action_group_add_actions_localized (
1135 action_group, GETTEXT_PACKAGE,
1136 entries, MAPI_ESOURCE_NUM_ENTRIES, shell_view);
1137
1138 /* Add global actions */
1139 e_action_group_add_actions_localized (
1140 action_group, GETTEXT_PACKAGE,
1141 global_mapi_entries, G_N_ELEMENTS (global_mapi_entries), shell_view);
1142
1143 g_signal_connect (shell_view, "update-actions", G_CALLBACK (update_mapi_source_entries_cb), entries);
1144 }
1145
1146 static void
1147 action_folder_permissions_source_cb (GtkAction *action,
1148 EShellView *shell_view)
1149 {
1150 ESourceRegistry *registry = NULL;
1151 ESource *source = NULL, *parent_source;
1152 ESourceMapiFolder *folder_ext;
1153 mapi_id_t folder_id = 0;
1154 const gchar *foreign_username;
1155 gboolean is_public;
1156 ESourceCamel *extension;
1157 CamelSettings *settings;
1158 const gchar *extension_name;
1159
1160 g_return_if_fail (action != NULL);
1161 g_return_if_fail (shell_view != NULL);
1162 g_return_if_fail (get_selected_mapi_source (shell_view, &source, ®istry));
1163 g_return_if_fail (source != NULL);
1164 g_return_if_fail (e_source_has_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER));
1165 g_return_if_fail (gtk_action_get_name (action) != NULL);
1166
1167 folder_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
1168 folder_id = e_source_mapi_folder_get_id (folder_ext);
1169 g_return_if_fail (folder_id != 0);
1170
1171 foreign_username = e_source_mapi_folder_get_foreign_username (folder_ext);
1172 is_public = !foreign_username && e_source_mapi_folder_is_public (folder_ext);
1173
1174 parent_source = e_source_registry_ref_source (registry, e_source_get_parent (source));
1175
1176 extension_name = e_source_camel_get_extension_name ("mapi");
1177 extension = e_source_get_extension (parent_source, extension_name);
1178
1179 settings = e_source_camel_get_settings (extension);
1180
1181 e_mapi_edit_folder_permissions (NULL,
1182 registry,
1183 source,
1184 CAMEL_MAPI_SETTINGS (settings),
1185 e_source_get_display_name (parent_source),
1186 e_source_get_display_name (source),
1187 folder_id,
1188 foreign_username ? E_MAPI_FOLDER_CATEGORY_FOREIGN :
1189 is_public ? E_MAPI_FOLDER_CATEGORY_PUBLIC :
1190 E_MAPI_FOLDER_CATEGORY_PERSONAL,
1191 foreign_username,
1192 strstr (gtk_action_get_name (action), "calendar") != NULL);
1193
1194 g_object_unref (source);
1195 g_object_unref (parent_source);
1196 g_object_unref (registry);
1197 }
1198
1199 static GtkActionEntry calendar_context_entries[] = {
1200
1201 { "calendar-mapi-folder-permissions",
1202 "folder-new",
1203 N_("Permissions…"),
1204 NULL,
1205 N_("Edit MAPI calendar permissions"),
1206 G_CALLBACK (action_folder_permissions_source_cb) }
1207 };
1208
1209 static const gchar *mapi_ui_cal_def =
1210 "<menubar name='main-menu'>\n"
1211 " <menu action='file-menu'>\n"
1212 " <placeholder name='long-running-actions'>\n"
1213 " <menuitem action=\"mapi-global-subscribe-foreign-folder\"/>\n"
1214 " </placeholder>\n"
1215 " </menu>\n"
1216 "</menubar>\n"
1217 "<popup name=\"calendar-popup\">\n"
1218 " <placeholder name=\"calendar-popup-actions\">\n"
1219 " <menuitem action=\"calendar-mapi-folder-permissions\"/>\n"
1220 " </placeholder>\n"
1221 "</popup>\n";
1222
1223 static void
1224 mapi_ui_init_calendar (GtkUIManager *ui_manager,
1225 EShellView *shell_view,
1226 gchar **ui_definition)
1227 {
1228 g_return_if_fail (ui_definition != NULL);
1229
1230 *ui_definition = g_strdup (mapi_ui_cal_def);
1231
1232 setup_mapi_source_actions (shell_view, ui_manager,
1233 calendar_context_entries, G_N_ELEMENTS (calendar_context_entries));
1234 }
1235
1236 static GtkActionEntry tasks_context_entries[] = {
1237
1238 { "tasks-mapi-folder-permissions",
1239 "folder-new",
1240 N_("Permissions…"),
1241 NULL,
1242 N_("Edit MAPI tasks permissions"),
1243 G_CALLBACK (action_folder_permissions_source_cb) }
1244 };
1245
1246 static const gchar *mapi_ui_task_def =
1247 "<menubar name='main-menu'>\n"
1248 " <menu action='file-menu'>\n"
1249 " <placeholder name='long-running-actions'>\n"
1250 " <menuitem action=\"mapi-global-subscribe-foreign-folder\"/>\n"
1251 " </placeholder>\n"
1252 " </menu>\n"
1253 "</menubar>\n"
1254 "<popup name=\"task-list-popup\">\n"
1255 " <placeholder name=\"task-list-popup-actions\">\n"
1256 " <menuitem action=\"tasks-mapi-folder-permissions\"/>\n"
1257 " </placeholder>\n"
1258 "</popup>\n";
1259
1260 static void
1261 mapi_ui_init_tasks (GtkUIManager *ui_manager,
1262 EShellView *shell_view,
1263 gchar **ui_definition)
1264 {
1265 g_return_if_fail (ui_definition != NULL);
1266
1267 *ui_definition = g_strdup (mapi_ui_task_def);
1268
1269 setup_mapi_source_actions (shell_view, ui_manager,
1270 tasks_context_entries, G_N_ELEMENTS (tasks_context_entries));
1271 }
1272
1273 static GtkActionEntry memos_context_entries[] = {
1274
1275 { "memos-mapi-folder-permissions",
1276 "folder-new",
1277 N_("Permissions…"),
1278 NULL,
1279 N_("Edit MAPI memos permissions"),
1280 G_CALLBACK (action_folder_permissions_source_cb) }
1281 };
1282
1283 static const gchar *mapi_ui_memo_def =
1284 "<menubar name='main-menu'>\n"
1285 " <menu action='file-menu'>\n"
1286 " <placeholder name='long-running-actions'>\n"
1287 " <menuitem action=\"mapi-global-subscribe-foreign-folder\"/>\n"
1288 " </placeholder>\n"
1289 " </menu>\n"
1290 "</menubar>\n"
1291 "<popup name=\"memo-list-popup\">\n"
1292 " <placeholder name=\"memo-list-popup-actions\">\n"
1293 " <menuitem action=\"memos-mapi-folder-permissions\"/>\n"
1294 " </placeholder>\n"
1295 "</popup>\n";
1296
1297 static void
1298 mapi_ui_init_memos (GtkUIManager *ui_manager,
1299 EShellView *shell_view,
1300 gchar **ui_definition)
1301 {
1302 g_return_if_fail (ui_definition != NULL);
1303
1304 *ui_definition = g_strdup (mapi_ui_memo_def);
1305
1306 setup_mapi_source_actions (shell_view, ui_manager,
1307 memos_context_entries, G_N_ELEMENTS (memos_context_entries));
1308 }
1309
1310 static GtkActionEntry contacts_context_entries[] = {
1311
1312 { "contacts-mapi-folder-permissions",
1313 "folder-new",
1314 N_("Permissions…"),
1315 NULL,
1316 N_("Edit MAPI contacts permissions"),
1317 G_CALLBACK (action_folder_permissions_source_cb) }
1318 };
1319
1320 static const gchar *mapi_ui_book_def =
1321 "<menubar name='main-menu'>\n"
1322 " <menu action='file-menu'>\n"
1323 " <placeholder name='long-running-actions'>\n"
1324 " <menuitem action=\"mapi-global-subscribe-foreign-folder\"/>\n"
1325 " </placeholder>\n"
1326 " </menu>\n"
1327 "</menubar>\n"
1328 "<popup name=\"address-book-popup\">\n"
1329 " <placeholder name=\"address-book-popup-actions\">\n"
1330 " <menuitem action=\"contacts-mapi-folder-permissions\"/>\n"
1331 " </placeholder>\n"
1332 "</popup>\n";
1333
1334 static void
1335 mapi_ui_init_contacts (GtkUIManager *ui_manager,
1336 EShellView *shell_view,
1337 gchar **ui_definition)
1338 {
1339 g_return_if_fail (ui_definition != NULL);
1340
1341 *ui_definition = g_strdup (mapi_ui_book_def);
1342
1343 setup_mapi_source_actions (shell_view, ui_manager,
1344 contacts_context_entries, G_N_ELEMENTS (contacts_context_entries));
1345 }
1346
1347 void
1348 e_mapi_config_utils_init_ui (EShellView *shell_view,
1349 const gchar *ui_manager_id,
1350 gchar **ui_definition)
1351 {
1352 EShellWindow *shell_window;
1353 GtkUIManager *ui_manager;
1354
1355 g_return_if_fail (shell_view != NULL);
1356 g_return_if_fail (ui_manager_id != NULL);
1357 g_return_if_fail (ui_definition != NULL);
1358
1359 shell_window = e_shell_view_get_shell_window (shell_view);
1360 ui_manager = e_shell_window_get_ui_manager (shell_window);
1361
1362 if (g_strcmp0 (ui_manager_id, "org.gnome.evolution.mail") == 0)
1363 mapi_ui_init_mail (ui_manager, shell_view, ui_definition);
1364 else if (g_strcmp0 (ui_manager_id, "org.gnome.evolution.calendars") == 0)
1365 mapi_ui_init_calendar (ui_manager, shell_view, ui_definition);
1366 else if (g_strcmp0 (ui_manager_id, "org.gnome.evolution.tasks") == 0)
1367 mapi_ui_init_tasks (ui_manager, shell_view, ui_definition);
1368 else if (g_strcmp0 (ui_manager_id, "org.gnome.evolution.memos") == 0)
1369 mapi_ui_init_memos (ui_manager, shell_view, ui_definition);
1370 else if (g_strcmp0 (ui_manager_id, "org.gnome.evolution.contacts") == 0)
1371 mapi_ui_init_contacts (ui_manager, shell_view, ui_definition);
1372 }
1373
1374 gboolean
1375 e_mapi_config_utils_is_online (void)
1376 {
1377 EShell *shell;
1378
1379 shell = e_shell_get_default ();
1380
1381 return shell && e_shell_get_online (shell);
1382 }
1383
1384 GtkWindow *
1385 e_mapi_config_utils_get_widget_toplevel_window (GtkWidget *widget)
1386 {
1387 if (!widget)
1388 return NULL;
1389
1390 if (!GTK_IS_WINDOW (widget))
1391 widget = gtk_widget_get_toplevel (widget);
1392
1393 if (GTK_IS_WINDOW (widget))
1394 return GTK_WINDOW (widget);
1395
1396 return NULL;
1397 }
1398
1399 enum {
1400 NAME_COL,
1401 FID_COL,
1402 FOLDER_COL,
1403 NUM_COLS
1404 };
1405
1406 static gboolean
1407 check_node (GtkTreeStore *ts, EMapiFolder *folder, GtkTreeIter iter)
1408 {
1409 GtkTreeModel *ts_model;
1410 mapi_id_t fid;
1411
1412 ts_model = GTK_TREE_MODEL (ts);
1413
1414 gtk_tree_model_get (ts_model, &iter, 1, &fid, -1);
1415 if (fid && folder->parent_folder_id == fid) {
1416 /* Do something */
1417 GtkTreeIter node;
1418 gtk_tree_store_append (ts, &node, &iter);
1419 gtk_tree_store_set (ts, &node, NAME_COL, folder->folder_name, FID_COL, folder->folder_id, FOLDER_COL, folder,-1);
1420 return TRUE;
1421 }
1422
1423 if (gtk_tree_model_iter_has_child (ts_model, &iter)) {
1424 GtkTreeIter child;
1425 gtk_tree_model_iter_children (ts_model, &child, &iter);
1426 if (check_node (ts, folder, child))
1427 return TRUE;
1428 }
1429
1430 if (gtk_tree_model_iter_next (ts_model, &iter)) {
1431 return check_node (ts, folder, iter);
1432 }
1433
1434 return FALSE;
1435 }
1436
1437 static void
1438 add_to_store (GtkTreeStore *ts, EMapiFolder *folder)
1439 {
1440 GtkTreeModel *ts_model;
1441 GtkTreeIter iter;
1442
1443 ts_model = GTK_TREE_MODEL (ts);
1444
1445 g_return_if_fail (gtk_tree_model_get_iter_first (ts_model, &iter));
1446 if (!check_node (ts, folder, iter)) {
1447 GtkTreeIter node;
1448 gtk_tree_store_append (ts, &node, &iter);
1449 gtk_tree_store_set (ts, &node, NAME_COL, folder->folder_name, FID_COL, folder->folder_id, FOLDER_COL, folder, -1);
1450 }
1451 }
1452
1453 static void
1454 traverse_tree (GtkTreeModel *model, GtkTreeIter iter, EMapiFolderType folder_type, gboolean *pany_sub_used)
1455 {
1456 gboolean any_sub_used = FALSE;
1457 gboolean has_next = TRUE;
1458
1459 do {
1460 gboolean sub_used = FALSE;
1461 GtkTreeIter next = iter;
1462 EMapiFolder *folder = NULL;
1463
1464 has_next = gtk_tree_model_iter_next (model, &next);
1465
1466 if (gtk_tree_model_iter_has_child (model, &iter)) {
1467 GtkTreeIter child;
1468
1469 gtk_tree_model_iter_children (model, &child, &iter);
1470 traverse_tree (model, child, folder_type, &sub_used);
1471 }
1472
1473 gtk_tree_model_get (model, &iter, FOLDER_COL, &folder, -1);
1474 if (folder && (e_mapi_folder_get_type (folder) == folder_type || (folder_type == E_MAPI_FOLDER_TYPE_MEMO && e_mapi_folder_get_type (folder) == E_MAPI_FOLDER_TYPE_JOURNAL))) {
1475 sub_used = TRUE;
1476 }
1477
1478 if (sub_used)
1479 any_sub_used = TRUE;
1480 else if (pany_sub_used && folder)
1481 gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
1482
1483 iter = next;
1484 } while (has_next);
1485
1486 if (pany_sub_used && any_sub_used)
1487 *pany_sub_used = TRUE;
1488 }
1489
1490 static void
1491 add_folders (GSList *folders, GtkTreeStore *ts, EMapiFolderType folder_type)
1492 {
1493 GSList *tmp = folders;
1494 GtkTreeIter iter;
1495 GtkTreeModel *model = GTK_TREE_MODEL (ts);
1496 gchar *node = _("Personal Folders");
1497
1498 /* add all... */
1499 gtk_tree_store_append (ts, &iter, NULL);
1500 gtk_tree_store_set (ts, &iter, NAME_COL, node, -1);
1501 while (tmp) {
1502 EMapiFolder *folder = tmp->data;
1503 add_to_store (ts, folder);
1504 tmp = tmp->next;
1505 }
1506
1507 /* ... then remove those which don't belong to folder_type */
1508 if (gtk_tree_model_get_iter_first (model, &iter)) {
1509 traverse_tree (model, iter, folder_type, NULL);
1510 }
1511 }
1512
1513 static void
1514 select_folder (GtkTreeModel *model,
1515 mapi_id_t fid,
1516 GtkWidget *tree_view)
1517 {
1518 GtkTreeIter iter, next;
1519 gboolean found = FALSE, can = TRUE;
1520
1521 g_return_if_fail (model != NULL);
1522 g_return_if_fail (tree_view != NULL);
1523
1524 if (!gtk_tree_model_get_iter_first (model, &iter))
1525 return;
1526
1527 while (!found && can) {
1528 EMapiFolder *folder = NULL;
1529
1530 gtk_tree_model_get (model, &iter, FOLDER_COL, &folder, -1);
1531
1532 if (folder && e_mapi_folder_get_id (folder) == fid) {
1533 gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)), &iter);
1534 found = TRUE;
1535 break;
1536 }
1537
1538 can = FALSE;
1539 if (gtk_tree_model_iter_children (model, &next, &iter)) {
1540 iter = next;
1541 can = TRUE;
1542 }
1543
1544 next = iter;
1545 if (!can && gtk_tree_model_iter_next (model, &next)) {
1546 iter = next;
1547 can = TRUE;
1548 }
1549
1550 if (!can && gtk_tree_model_iter_parent (model, &next, &iter)) {
1551 while (!can) {
1552 iter = next;
1553
1554 if (gtk_tree_model_iter_next (model, &iter)) {
1555 can = TRUE;
1556 break;
1557 }
1558
1559 iter = next;
1560 if (!gtk_tree_model_iter_parent (model, &next, &iter))
1561 break;
1562 }
1563 }
1564 }
1565 }
1566
1567 static void
1568 e_mapi_cursor_change (GtkTreeView *treeview,
1569 ESource *source)
1570 {
1571 ESourceMapiFolder *folder_ext;
1572 GtkTreeSelection *selection;
1573 GtkTreeModel *model;
1574 GtkTreeIter iter;
1575 mapi_id_t pfid;
1576
1577 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
1578 if (!selection)
1579 return;
1580
1581 if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
1582 gtk_tree_model_get (model, &iter, FID_COL, &pfid, -1);
1583 } else {
1584 pfid = 0;
1585 }
1586
1587 folder_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
1588 e_source_mapi_folder_set_parent_id (folder_ext, pfid);
1589 }
1590
1591 struct EMapiFolderStructureData
1592 {
1593 EMapiFolderType folder_type;
1594 GSList *folders;
1595 GtkWidget *tree_view;
1596 ESource *source;
1597 ESource *child_source;
1598 ESourceRegistry *registry;
1599 ESourceConfig *config;
1600 };
1601
1602 static void
1603 e_mapi_folder_structure_data_free (gpointer ptr)
1604 {
1605 struct EMapiFolderStructureData *fsd = ptr;
1606
1607 if (!fsd)
1608 return;
1609
1610 e_mapi_folder_free_list (fsd->folders);
1611 g_object_unref (fsd->tree_view);
1612 if (fsd->source)
1613 g_object_unref (fsd->source);
1614 if (fsd->config)
1615 g_object_unref (fsd->config);
1616 g_object_unref (fsd->child_source);
1617 g_object_unref (fsd->registry);
1618 g_slice_free (struct EMapiFolderStructureData, fsd);
1619 }
1620
1621 static void
1622 e_mapi_download_folder_structure_idle (GObject *source_obj,
1623 gpointer user_data,
1624 GCancellable *cancellable,
1625 GError **perror)
1626 {
1627 struct EMapiFolderStructureData *fsd = user_data;
1628 ESourceMapiFolder *folder_ext;
1629 GtkTreeStore *tree_store;
1630
1631 g_return_if_fail (fsd != NULL);
1632 g_return_if_fail (fsd->tree_view != NULL);
1633 g_return_if_fail (source_obj != NULL);
1634 g_return_if_fail (E_IS_SOURCE (source_obj));
1635
1636 tree_store = GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fsd->tree_view)));
1637 g_return_if_fail (tree_store != NULL);
1638
1639 add_folders (fsd->folders, tree_store, fsd->folder_type);
1640 gtk_tree_view_expand_all (GTK_TREE_VIEW (fsd->tree_view));
1641
1642 folder_ext = e_source_get_extension (fsd->child_source, E_SOURCE_EXTENSION_MAPI_FOLDER);
1643 if (e_source_mapi_folder_get_id (folder_ext)) {
1644 select_folder (GTK_TREE_MODEL (tree_store),
1645 e_source_mapi_folder_get_id (folder_ext),
1646 fsd->tree_view);
1647 }
1648 }
1649
1650 static void
1651 e_mapi_download_folder_structure_thread (GObject *source_obj,
1652 gpointer user_data,
1653 GCancellable *cancellable,
1654 GError **perror)
1655 {
1656 struct EMapiFolderStructureData *fsd = user_data;
1657 const gchar *extension_name;
1658 ESource *source;
1659 ESourceCamel *extension;
1660 EMapiConnection *conn;
1661 CamelSettings *settings;
1662
1663 g_return_if_fail (fsd != NULL);
1664 g_return_if_fail (fsd->tree_view != NULL);
1665 g_return_if_fail (source_obj != NULL);
1666 g_return_if_fail (E_IS_SOURCE (source_obj));
1667
1668 source = E_SOURCE (source_obj);
1669
1670 extension_name = e_source_camel_get_extension_name ("mapi");
1671 g_return_if_fail (e_source_has_extension (source, extension_name));
1672
1673 extension = e_source_get_extension (source, extension_name);
1674
1675 settings = e_source_camel_get_settings (extension);
1676
1677 conn = e_mapi_config_utils_open_connection_for (NULL,
1678 fsd->registry,
1679 source,
1680 CAMEL_MAPI_SETTINGS (settings),
1681 cancellable,
1682 perror);
1683
1684 if (!conn)
1685 return;
1686
1687 if (conn && e_mapi_connection_connected (conn)) {
1688 fsd->folders = e_mapi_connection_peek_folders_list (conn);
1689 if (fsd->folders)
1690 fsd->folders = e_mapi_folder_copy_list (fsd->folders);
1691 }
1692
1693 if (conn)
1694 g_object_unref (conn);
1695 }
1696
1697 static void
1698 tree_view_mapped_cb (GObject *tree_view)
1699 {
1700 const struct EMapiFolderStructureData *old_fsd = g_object_get_data (tree_view, "mapi-fsd-pointer");
1701 struct EMapiFolderStructureData *fsd;
1702 GtkTreeViewColumn *column;
1703 ESource *parent_source;
1704
1705 g_return_if_fail (old_fsd != NULL);
1706
1707 parent_source = e_source_config_get_collection_source (old_fsd->config);
1708 if (!parent_source)
1709 parent_source = e_source_registry_find_extension (
1710 old_fsd->registry, old_fsd->child_source, E_SOURCE_EXTENSION_COLLECTION);
1711
1712 g_return_if_fail (parent_source != NULL);
1713
1714 fsd = g_slice_new0 (struct EMapiFolderStructureData);
1715 fsd->folder_type = old_fsd->folder_type;
1716 fsd->folders = NULL;
1717 fsd->tree_view = g_object_ref (old_fsd->tree_view);
1718 fsd->source = g_object_ref (parent_source);
1719 fsd->child_source = g_object_ref (old_fsd->child_source);
1720 fsd->registry = g_object_ref (old_fsd->registry);
1721
1722 column = gtk_tree_view_get_column (GTK_TREE_VIEW (tree_view), 0);
1723 gtk_tree_view_column_set_title (column, e_source_get_display_name (parent_source));
1724
1725 e_mapi_config_utils_run_in_thread_with_feedback (e_mapi_config_utils_get_widget_toplevel_window (fsd->tree_view),
1726 G_OBJECT (fsd->source),
1727 _("Searching remote MAPI folder structure, please wait…"),
1728 e_mapi_download_folder_structure_thread,
1729 e_mapi_download_folder_structure_idle,
1730 fsd,
1731 e_mapi_folder_structure_data_free);
1732 }
1733
1734 void
1735 e_mapi_config_utils_insert_widgets (ESourceConfigBackend *backend,
1736 ESource *scratch_source)
1737 {
1738 ESourceBackend *backend_ext = NULL;
1739 ESourceMapiFolder *folder_ext;
1740 ESourceConfig *config;
1741 GtkWidget *widget;
1742 gboolean is_new_source;
1743 EMapiFolderType folder_type = E_MAPI_FOLDER_TYPE_UNKNOWN;
1744
1745 g_return_if_fail (backend != NULL);
1746 g_return_if_fail (scratch_source != NULL);
1747
1748 if (e_source_has_extension (scratch_source, E_SOURCE_EXTENSION_ADDRESS_BOOK)) {
1749 backend_ext = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_ADDRESS_BOOK);
1750 folder_type = E_MAPI_FOLDER_TYPE_CONTACT;
1751 } else if (e_source_has_extension (scratch_source, E_SOURCE_EXTENSION_CALENDAR)) {
1752 backend_ext = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_CALENDAR);
1753 folder_type = E_MAPI_FOLDER_TYPE_APPOINTMENT;
1754 } else if (e_source_has_extension (scratch_source, E_SOURCE_EXTENSION_TASK_LIST)) {
1755 backend_ext = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_TASK_LIST);
1756 folder_type = E_MAPI_FOLDER_TYPE_TASK;
1757 } else if (e_source_has_extension (scratch_source, E_SOURCE_EXTENSION_MEMO_LIST)) {
1758 backend_ext = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_MEMO_LIST);
1759 folder_type = E_MAPI_FOLDER_TYPE_MEMO;
1760 }
1761
1762 if (!backend_ext || g_strcmp0 (e_source_backend_get_backend_name (backend_ext), "mapi") != 0)
1763 return;
1764
1765 folder_ext = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_MAPI_FOLDER);
1766 g_return_if_fail (folder_ext != NULL);
1767
1768 config = e_source_config_backend_get_config (backend);
1769 if (E_IS_BOOK_SOURCE_CONFIG (config))
1770 e_book_source_config_add_offline_toggle (E_BOOK_SOURCE_CONFIG (config), scratch_source);
1771 else if (E_IS_CAL_SOURCE_CONFIG (config))
1772 e_cal_source_config_add_offline_toggle (E_CAL_SOURCE_CONFIG (config), scratch_source);
1773
1774 widget = gtk_check_button_new_with_mnemonic (_("Lis_ten for server notifications"));
1775 e_source_config_insert_widget (config, scratch_source, NULL, widget);
1776 gtk_widget_show (widget);
1777
1778 e_binding_bind_property (
1779 folder_ext, "server-notification",
1780 widget, "active",
1781 G_BINDING_BIDIRECTIONAL |
1782 G_BINDING_SYNC_CREATE);
1783
1784 /* no extra options for subscribed folders */
1785 if (e_source_mapi_folder_is_public (folder_ext) ||
1786 e_source_mapi_folder_get_foreign_username (folder_ext)) {
1787 e_source_config_add_refresh_interval (config, scratch_source);
1788 return;
1789 }
1790
1791 is_new_source = e_source_mapi_folder_get_id (folder_ext) == 0;
1792 if (is_new_source && !e_mapi_config_utils_is_online ()) {
1793 const gchar *msg;
1794
1795 switch (folder_type) {
1796 case E_MAPI_FOLDER_TYPE_APPOINTMENT:
1797 msg = _("Cannot create MAPI calendar in offline mode");
1798 break;
1799 case E_MAPI_FOLDER_TYPE_TASK:
1800 msg = _("Cannot create MAPI task list in offline mode");
1801 break;
1802 case E_MAPI_FOLDER_TYPE_MEMO:
1803 msg = _("Cannot create MAPI memo list in offline mode");
1804 break;
1805 case E_MAPI_FOLDER_TYPE_CONTACT:
1806 msg = _("Cannot create MAPI address book in offline mode");
1807 break;
1808 /* coverity[dead_error_begin] */
1809 default:
1810 g_warn_if_reached ();
1811 msg = _("Cannot create MAPI source in offline mode");
1812 break;
1813 }
1814
1815 widget = gtk_label_new (msg);
1816 gtk_widget_show (widget);
1817 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
1818
1819 e_source_config_insert_widget (config, scratch_source, NULL, widget);
1820 } else {
1821 GtkGrid *content_grid;
1822 GtkCellRenderer *renderer;
1823 GtkTreeViewColumn *column;
1824 GtkTreeStore *tree_store;
1825 GtkWidget *tree_view, *scrolled_window;
1826
1827 content_grid = GTK_GRID (gtk_grid_new ());
1828 gtk_grid_set_row_spacing (content_grid, 2);
1829 gtk_grid_set_column_spacing (content_grid, 6);
1830
1831 widget = gtk_label_new_with_mnemonic (_("_Location:"));
1832 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
1833 gtk_widget_set_hexpand (widget, TRUE);
1834 gtk_grid_attach (content_grid, widget, 0, 0, 1, 1);
1835
1836 tree_store = gtk_tree_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_POINTER);
1837
1838 renderer = gtk_cell_renderer_text_new ();
1839 column = gtk_tree_view_column_new_with_attributes ("", renderer, "text", NAME_COL, NULL);
1840 tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (tree_store));
1841 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
1842 g_object_set (tree_view, "expander-column", column, "headers-visible", TRUE, NULL);
1843 gtk_widget_set_sensitive (tree_view, is_new_source);
1844 g_object_unref (tree_store);
1845
1846 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
1847 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1848 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
1849 g_object_set (scrolled_window, "height-request", 150, NULL);
1850 gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
1851 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), scrolled_window);
1852 g_signal_connect (G_OBJECT (tree_view), "cursor-changed", G_CALLBACK (e_mapi_cursor_change), scratch_source);
1853 gtk_widget_show_all (scrolled_window);
1854
1855 gtk_grid_attach (content_grid, scrolled_window, 0, 1, 1, 1);
1856
1857 if (e_mapi_config_utils_is_online ()) {
1858 struct EMapiFolderStructureData *fsd;
1859
1860 fsd = g_slice_new0 (struct EMapiFolderStructureData);
1861 fsd->folder_type = folder_type;
1862 fsd->folders = NULL;
1863 fsd->tree_view = g_object_ref (tree_view);
1864 fsd->config = g_object_ref (config);
1865 fsd->child_source = g_object_ref (scratch_source);
1866 fsd->registry = g_object_ref (e_source_config_get_registry (config));
1867
1868 g_signal_connect_after (tree_view, "map", G_CALLBACK (tree_view_mapped_cb), NULL);
1869 g_object_set_data_full (G_OBJECT (tree_view), "mapi-fsd-pointer", fsd, e_mapi_folder_structure_data_free);
1870 }
1871
1872 gtk_widget_set_hexpand (GTK_WIDGET (content_grid), TRUE);
1873 gtk_widget_set_vexpand (GTK_WIDGET (content_grid), TRUE);
1874 gtk_widget_show_all (GTK_WIDGET (content_grid));
1875
1876 e_source_config_insert_widget (config, scratch_source, NULL, GTK_WIDGET (content_grid));
1877 }
1878
1879 e_source_config_add_refresh_interval (config, scratch_source);
1880 }
1881
1882 gboolean
1883 e_mapi_config_utils_check_complete (ESource *scratch_source)
1884 {
1885 ESourceBackend *backend_ext = NULL;
1886 ESourceMapiFolder *folder_ext;
1887
1888 g_return_val_if_fail (scratch_source != NULL, FALSE);
1889
1890 if (e_source_has_extension (scratch_source, E_SOURCE_EXTENSION_ADDRESS_BOOK)) {
1891 backend_ext = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_ADDRESS_BOOK);
1892 } else if (e_source_has_extension (scratch_source, E_SOURCE_EXTENSION_CALENDAR)) {
1893 backend_ext = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_CALENDAR);
1894 } else if (e_source_has_extension (scratch_source, E_SOURCE_EXTENSION_TASK_LIST)) {
1895 backend_ext = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_TASK_LIST);
1896 } else if (e_source_has_extension (scratch_source, E_SOURCE_EXTENSION_MEMO_LIST)) {
1897 backend_ext = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_MEMO_LIST);
1898 }
1899
1900 if (!backend_ext || g_strcmp0 (e_source_backend_get_backend_name (backend_ext), "mapi") != 0)
1901 return TRUE;
1902
1903 folder_ext = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_MAPI_FOLDER);
1904 if (!folder_ext)
1905 return FALSE;
1906
1907 if (!e_source_mapi_folder_get_id (folder_ext) &&
1908 !e_mapi_config_utils_is_online ())
1909 return FALSE;
1910
1911 /* does not have a parent-fid which is needed for folder creation on server */
1912 return e_source_mapi_folder_get_parent_id (folder_ext) ||
1913 e_source_mapi_folder_get_foreign_username (folder_ext) ||
1914 e_source_mapi_folder_is_public (folder_ext);
1915 }