evolution-3.6.4/mail/e-mail-config-notebook.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-mail-config-notebook.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-mail-config-notebook.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /*
  2  * e-mail-config-notebook.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 "e-mail-config-notebook.h"
 20 
 21 #include <libebackend/libebackend.h>
 22 
 23 #include <mail/e-mail-config-defaults-page.h>
 24 #include <mail/e-mail-config-identity-page.h>
 25 #include <mail/e-mail-config-provider-page.h>
 26 #include <mail/e-mail-config-receiving-page.h>
 27 #include <mail/e-mail-config-security-page.h>
 28 #include <mail/e-mail-config-sending-page.h>
 29 
 30 #define E_MAIL_CONFIG_NOTEBOOK_GET_PRIVATE(obj) \
 31 	(G_TYPE_INSTANCE_GET_PRIVATE \
 32 	((obj), E_TYPE_MAIL_CONFIG_NOTEBOOK, EMailConfigNotebookPrivate))
 33 
 34 typedef struct _AsyncContext AsyncContext;
 35 
 36 struct _EMailConfigNotebookPrivate {
 37 	EMailSession *session;
 38 	ESource *account_source;
 39 	ESource *identity_source;
 40 	ESource *transport_source;
 41 	ESource *collection_source;
 42 };
 43 
 44 struct _AsyncContext {
 45 	ESourceRegistry *registry;
 46 	GCancellable *cancellable;
 47 	GQueue *page_queue;
 48 	GQueue *source_queue;
 49 };
 50 
 51 enum {
 52 	PROP_0,
 53 	PROP_ACCOUNT_SOURCE,
 54 	PROP_COLLECTION_SOURCE,
 55 	PROP_COMPLETE,
 56 	PROP_IDENTITY_SOURCE,
 57 	PROP_SESSION,
 58 	PROP_TRANSPORT_SOURCE
 59 };
 60 
 61 G_DEFINE_TYPE_WITH_CODE (
 62 	EMailConfigNotebook,
 63 	e_mail_config_notebook,
 64 	GTK_TYPE_NOTEBOOK,
 65 	G_IMPLEMENT_INTERFACE (
 66 		E_TYPE_EXTENSIBLE, NULL))
 67 
 68 static void
 69 async_context_free (AsyncContext *async_context)
 70 {
 71 	if (async_context->registry != NULL)
 72 		g_object_unref (async_context->registry);
 73 
 74 	if (async_context->cancellable != NULL)
 75 		g_object_unref (async_context->cancellable);
 76 
 77 	g_queue_free_full (
 78 		async_context->page_queue,
 79 		(GDestroyNotify) g_object_unref);
 80 
 81 	g_queue_free_full (
 82 		async_context->source_queue,
 83 		(GDestroyNotify) g_object_unref);
 84 
 85 	g_slice_free (AsyncContext, async_context);
 86 }
 87 
 88 static void
 89 mail_config_notebook_sort_pages (EMailConfigNotebook *notebook)
 90 {
 91 	GList *list, *link;
 92 	gint ii = 0;
 93 
 94 	list = g_list_sort (
 95 		gtk_container_get_children (GTK_CONTAINER (notebook)),
 96 		(GCompareFunc) e_mail_config_page_compare);
 97 
 98 	for (link = list; link != NULL; link = g_list_next (link))
 99 		gtk_notebook_reorder_child (
100 			GTK_NOTEBOOK (notebook),
101 			GTK_WIDGET (link->data), ii++);
102 
103 	g_list_free (list);
104 }
105 
106 static void
107 mail_config_notebook_page_changed (EMailConfigPage *page,
108                                    EMailConfigNotebook *notebook)
109 {
110 	g_object_notify (G_OBJECT (notebook), "complete");
111 }
112 
113 static void
114 mail_config_notebook_set_account_source (EMailConfigNotebook *notebook,
115                                          ESource *account_source)
116 {
117 	g_return_if_fail (E_IS_SOURCE (account_source));
118 	g_return_if_fail (notebook->priv->account_source == NULL);
119 
120 	notebook->priv->account_source = g_object_ref (account_source);
121 }
122 
123 static void
124 mail_config_notebook_set_collection_source (EMailConfigNotebook *notebook,
125                                             ESource *collection_source)
126 {
127 	g_return_if_fail (notebook->priv->collection_source == NULL);
128 
129 	if (collection_source != NULL) {
130 		g_return_if_fail (E_IS_SOURCE (collection_source));
131 		g_object_ref (collection_source);
132 	}
133 
134 	notebook->priv->collection_source = collection_source;
135 }
136 
137 static void
138 mail_config_notebook_set_identity_source (EMailConfigNotebook *notebook,
139                                           ESource *identity_source)
140 {
141 	g_return_if_fail (E_IS_SOURCE (identity_source));
142 	g_return_if_fail (notebook->priv->identity_source == NULL);
143 
144 	notebook->priv->identity_source = g_object_ref (identity_source);
145 }
146 
147 static void
148 mail_config_notebook_set_session (EMailConfigNotebook *notebook,
149                                   EMailSession *session)
150 {
151 	g_return_if_fail (E_IS_MAIL_SESSION (session));
152 	g_return_if_fail (notebook->priv->session == NULL);
153 
154 	notebook->priv->session = g_object_ref (session);
155 }
156 
157 static void
158 mail_config_notebook_set_transport_source (EMailConfigNotebook *notebook,
159                                            ESource *transport_source)
160 {
161 	g_return_if_fail (E_IS_SOURCE (transport_source));
162 	g_return_if_fail (notebook->priv->transport_source == NULL);
163 
164 	notebook->priv->transport_source = g_object_ref (transport_source);
165 }
166 
167 static void
168 mail_config_notebook_set_property (GObject *object,
169                                    guint property_id,
170                                    const GValue *value,
171                                    GParamSpec *pspec)
172 {
173 	switch (property_id) {
174 		case PROP_ACCOUNT_SOURCE:
175 			mail_config_notebook_set_account_source (
176 				E_MAIL_CONFIG_NOTEBOOK (object),
177 				g_value_get_object (value));
178 			return;
179 
180 		case PROP_COLLECTION_SOURCE:
181 			mail_config_notebook_set_collection_source (
182 				E_MAIL_CONFIG_NOTEBOOK (object),
183 				g_value_get_object (value));
184 			return;
185 
186 		case PROP_IDENTITY_SOURCE:
187 			mail_config_notebook_set_identity_source (
188 				E_MAIL_CONFIG_NOTEBOOK (object),
189 				g_value_get_object (value));
190 			return;
191 
192 		case PROP_SESSION:
193 			mail_config_notebook_set_session (
194 				E_MAIL_CONFIG_NOTEBOOK (object),
195 				g_value_get_object (value));
196 			return;
197 
198 		case PROP_TRANSPORT_SOURCE:
199 			mail_config_notebook_set_transport_source (
200 				E_MAIL_CONFIG_NOTEBOOK (object),
201 				g_value_get_object (value));
202 			return;
203 	}
204 
205 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
206 }
207 
208 static void
209 mail_config_notebook_get_property (GObject *object,
210                                    guint property_id,
211                                    GValue *value,
212                                    GParamSpec *pspec)
213 {
214 	switch (property_id) {
215 		case PROP_ACCOUNT_SOURCE:
216 			g_value_set_object (
217 				value,
218 				e_mail_config_notebook_get_account_source (
219 				E_MAIL_CONFIG_NOTEBOOK (object)));
220 			return;
221 
222 		case PROP_COLLECTION_SOURCE:
223 			g_value_set_object (
224 				value,
225 				e_mail_config_notebook_get_collection_source (
226 				E_MAIL_CONFIG_NOTEBOOK (object)));
227 			return;
228 
229 		case PROP_COMPLETE:
230 			g_value_set_boolean (
231 				value,
232 				e_mail_config_notebook_check_complete (
233 				E_MAIL_CONFIG_NOTEBOOK (object)));
234 			return;
235 
236 		case PROP_IDENTITY_SOURCE:
237 			g_value_set_object (
238 				value,
239 				e_mail_config_notebook_get_identity_source (
240 				E_MAIL_CONFIG_NOTEBOOK (object)));
241 			return;
242 
243 		case PROP_SESSION:
244 			g_value_set_object (
245 				value,
246 				e_mail_config_notebook_get_session (
247 				E_MAIL_CONFIG_NOTEBOOK (object)));
248 			return;
249 
250 		case PROP_TRANSPORT_SOURCE:
251 			g_value_set_object (
252 				value,
253 				e_mail_config_notebook_get_transport_source (
254 				E_MAIL_CONFIG_NOTEBOOK (object)));
255 			return;
256 	}
257 
258 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
259 }
260 
261 static void
262 mail_config_notebook_dispose (GObject *object)
263 {
264 	EMailConfigNotebookPrivate *priv;
265 
266 	priv = E_MAIL_CONFIG_NOTEBOOK_GET_PRIVATE (object);
267 
268 	if (priv->session != NULL) {
269 		g_object_ref (priv->session);
270 		priv->session = NULL;
271 	}
272 
273 	if (priv->account_source != NULL) {
274 		g_object_ref (priv->account_source);
275 		priv->account_source = NULL;
276 	}
277 
278 	if (priv->identity_source != NULL) {
279 		g_object_ref (priv->identity_source);
280 		priv->identity_source = NULL;
281 	}
282 
283 	if (priv->transport_source != NULL) {
284 		g_object_ref (priv->transport_source);
285 		priv->transport_source = NULL;
286 	}
287 
288 	if (priv->collection_source != NULL) {
289 		g_object_ref (priv->collection_source);
290 		priv->collection_source = NULL;
291 	}
292 
293 	/* Chain up to parent's dispose() method. */
294 	G_OBJECT_CLASS (e_mail_config_notebook_parent_class)->
295 		dispose (object);
296 }
297 
298 static void
299 mail_config_notebook_constructed (GObject *object)
300 {
301 	EMailConfigNotebook *notebook;
302 	ESource *source;
303 	ESourceRegistry *registry;
304 	ESourceExtension *extension;
305 	ESourceMailIdentity *mail_identity_extension;
306 	EMailConfigServiceBackend *backend;
307 	CamelProvider *provider = NULL;
308 	EMailSession *session;
309 	EMailConfigPage *page;
310 	const gchar *extension_name;
311 	gboolean add_receiving_page = TRUE;
312 	gboolean add_sending_page = TRUE;
313 	gboolean add_transport_source;
314 	gboolean gnome_online_account = FALSE;
315 
316 	notebook = E_MAIL_CONFIG_NOTEBOOK (object);
317 
318 	/* Chain up to parent's constructed() method. */
319 	G_OBJECT_CLASS (e_mail_config_notebook_parent_class)->
320 		constructed (object);
321 
322 	session = e_mail_config_notebook_get_session (notebook);
323 	registry = e_mail_session_get_registry (session);
324 
325 	source = notebook->priv->identity_source;
326 	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
327 	extension = e_source_get_extension (source, extension_name);
328 	mail_identity_extension = E_SOURCE_MAIL_IDENTITY (extension);
329 
330 	/* If we have a collection source and the collection source
331 	 * has a [GNOME Online Accounts] extension, skip the Receiving
332 	 * and Sending pages since GOA dictates those settings. */
333 	source = notebook->priv->collection_source;
334 	if (source != NULL) {
335 		extension_name = E_SOURCE_EXTENSION_GOA;
336 		if (e_source_has_extension (source, extension_name)) {
337 			gnome_online_account = TRUE;
338 			add_receiving_page = FALSE;
339 			add_sending_page = FALSE;
340 		}
341 	}
342 
343 	/* Keep all the display name properties synchronized.
344 	 * We consider the identity source's display name to
345 	 * be authoritative since technically that's the one
346 	 * shown on the Identity page. */
347 
348 	g_object_bind_property (
349 		notebook->priv->identity_source, "display-name",
350 		notebook->priv->account_source, "display-name",
351 		G_BINDING_SYNC_CREATE);
352 
353 	g_object_bind_property (
354 		notebook->priv->identity_source, "display-name",
355 		notebook->priv->transport_source, "display-name",
356 		G_BINDING_SYNC_CREATE);
357 
358 	if (notebook->priv->collection_source != NULL)
359 		g_object_bind_property (
360 			notebook->priv->identity_source, "display-name",
361 			notebook->priv->collection_source, "display-name",
362 			G_BINDING_SYNC_CREATE);
363 
364 	/*** Identity Page ***/
365 
366 	page = e_mail_config_identity_page_new (
367 		registry, notebook->priv->identity_source);
368 	e_mail_config_identity_page_set_show_instructions (
369 		E_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE);
370 	if (gnome_online_account) {
371 		e_mail_config_identity_page_set_show_account_info (
372 			E_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE);
373 		e_mail_config_identity_page_set_show_email_address (
374 			E_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE);
375 	}
376 	e_mail_config_notebook_add_page (notebook, page);
377 
378 	/*** Receiving Page ***/
379 
380 	page = e_mail_config_receiving_page_new (registry);
381 	backend = e_mail_config_service_page_add_scratch_source (
382 		E_MAIL_CONFIG_SERVICE_PAGE (page),
383 		notebook->priv->account_source,
384 		notebook->priv->collection_source);
385 	if (add_receiving_page) {
386 		e_mail_config_notebook_add_page (notebook, page);
387 
388 		g_object_bind_property (
389 			mail_identity_extension, "address",
390 			page, "email-address",
391 			G_BINDING_SYNC_CREATE);
392 	}
393 
394 	if (backend != NULL)
395 		provider = e_mail_config_service_backend_get_provider (backend);
396 
397 	/*** Receiving Options (conditional) ***/
398 
399 	/* Note: We exclude this page if it has no options,
400 	 *       but we don't know that until we create it. */
401 	page = backend ? e_mail_config_provider_page_new (backend) : NULL;
402 	if (page && e_mail_config_provider_page_is_empty (
403 			E_MAIL_CONFIG_PROVIDER_PAGE (page))) {
404 		g_object_unref (g_object_ref_sink (page));
405 	} else if (page) {
406 		e_mail_config_notebook_add_page (notebook, page);
407 	}
408 
409 	/*** Sending Page (conditional) ***/
410 
411 	add_transport_source =
412 		(provider != NULL) &&
413 		(!CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider));
414 
415 	if (add_transport_source) {
416 		page = e_mail_config_sending_page_new (registry);
417 		e_mail_config_service_page_add_scratch_source (
418 			E_MAIL_CONFIG_SERVICE_PAGE (page),
419 			notebook->priv->transport_source,
420 			notebook->priv->collection_source);
421 		if (add_sending_page) {
422 			e_mail_config_notebook_add_page (notebook, page);
423 
424 			g_object_bind_property (
425 				mail_identity_extension, "address",
426 				page, "email-address",
427 				G_BINDING_SYNC_CREATE);
428 		}
429 	}
430 
431 	/*** Defaults Page ***/
432 
433 	page = e_mail_config_defaults_page_new (
434 		session,
435 		notebook->priv->account_source,
436 		notebook->priv->identity_source);
437 	e_mail_config_notebook_add_page (notebook, page);
438 
439 	/*** Security Page ***/
440 
441 	page = e_mail_config_security_page_new (
442 		notebook->priv->identity_source);
443 	e_mail_config_notebook_add_page (notebook, page);
444 
445 	e_extensible_load_extensions (E_EXTENSIBLE (notebook));
446 }
447 
448 static void
449 mail_config_notebook_page_removed (GtkNotebook *notebook,
450                                    GtkWidget *child,
451                                    guint page_num)
452 {
453 	/* Do not chain up.  GtkNotebook does not implement this method. */
454 
455 	if (E_IS_MAIL_CONFIG_PAGE (child))
456 		g_signal_handlers_disconnect_by_func (
457 			child, mail_config_notebook_page_changed,
458 			E_MAIL_CONFIG_NOTEBOOK (notebook));
459 }
460 
461 static void
462 mail_config_notebook_page_added (GtkNotebook *notebook,
463                                  GtkWidget *child,
464                                  guint page_num)
465 {
466 	/* Do not chain up.  GtkNotebook does not implement this method. */
467 
468 	if (E_IS_MAIL_CONFIG_PAGE (child))
469 		g_signal_connect (
470 			child, "changed",
471 			G_CALLBACK (mail_config_notebook_page_changed),
472 			E_MAIL_CONFIG_NOTEBOOK (notebook));
473 }
474 
475 static void
476 e_mail_config_notebook_class_init (EMailConfigNotebookClass *class)
477 {
478 	GObjectClass *object_class;
479 	GtkNotebookClass *notebook_class;
480 
481 	g_type_class_add_private (class, sizeof (EMailConfigNotebookPrivate));
482 
483 	object_class = G_OBJECT_CLASS (class);
484 	object_class->set_property = mail_config_notebook_set_property;
485 	object_class->get_property = mail_config_notebook_get_property;
486 	object_class->dispose = mail_config_notebook_dispose;
487 	object_class->constructed = mail_config_notebook_constructed;
488 
489 	notebook_class = GTK_NOTEBOOK_CLASS (class);
490 	notebook_class->page_removed = mail_config_notebook_page_removed;
491 	notebook_class->page_added = mail_config_notebook_page_added;
492 
493 	g_object_class_install_property (
494 		object_class,
495 		PROP_ACCOUNT_SOURCE,
496 		g_param_spec_object (
497 			"account-source",
498 			"Account Source",
499 			"Mail account source being edited",
500 			E_TYPE_SOURCE,
501 			G_PARAM_READWRITE |
502 			G_PARAM_CONSTRUCT_ONLY |
503 			G_PARAM_STATIC_STRINGS));
504 
505 	g_object_class_install_property (
506 		object_class,
507 		PROP_COLLECTION_SOURCE,
508 		g_param_spec_object (
509 			"collection-source",
510 			"Collection Source",
511 			"Optional collection source being edited",
512 			E_TYPE_SOURCE,
513 			G_PARAM_READWRITE |
514 			G_PARAM_CONSTRUCT_ONLY |
515 			G_PARAM_STATIC_STRINGS));
516 
517 	g_object_class_install_property (
518 		object_class,
519 		PROP_COMPLETE,
520 		g_param_spec_boolean (
521 			"complete",
522 			"Complete",
523 			"Whether all required fields are complete",
524 			FALSE,  /* default is not used */
525 			G_PARAM_READABLE |
526 			G_PARAM_STATIC_STRINGS));
527 
528 	g_object_class_install_property (
529 		object_class,
530 		PROP_IDENTITY_SOURCE,
531 		g_param_spec_object (
532 			"identity-source",
533 			"Identity Source",
534 			"Mail identity source being edited",
535 			E_TYPE_SOURCE,
536 			G_PARAM_READWRITE |
537 			G_PARAM_CONSTRUCT_ONLY |
538 			G_PARAM_STATIC_STRINGS));
539 
540 	g_object_class_install_property (
541 		object_class,
542 		PROP_SESSION,
543 		g_param_spec_object (
544 			"session",
545 			"Session",
546 			"Mail session",
547 			E_TYPE_MAIL_SESSION,
548 			G_PARAM_READWRITE |
549 			G_PARAM_CONSTRUCT_ONLY |
550 			G_PARAM_STATIC_STRINGS));
551 
552 	g_object_class_install_property (
553 		object_class,
554 		PROP_TRANSPORT_SOURCE,
555 		g_param_spec_object (
556 			"transport-source",
557 			"Transport Source",
558 			"Mail transport source being edited",
559 			E_TYPE_SOURCE,
560 			G_PARAM_READWRITE |
561 			G_PARAM_CONSTRUCT_ONLY |
562 			G_PARAM_STATIC_STRINGS));
563 }
564 
565 static void
566 e_mail_config_notebook_init (EMailConfigNotebook *notebook)
567 {
568 	notebook->priv = E_MAIL_CONFIG_NOTEBOOK_GET_PRIVATE (notebook);
569 }
570 
571 GtkWidget *
572 e_mail_config_notebook_new (EMailSession *session,
573                             ESource *account_source,
574                             ESource *identity_source,
575                             ESource *transport_source,
576                             ESource *collection_source)
577 {
578 	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
579 	g_return_val_if_fail (E_IS_SOURCE (account_source), NULL);
580 	g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL);
581 	g_return_val_if_fail (E_IS_SOURCE (transport_source), NULL);
582 
583 	/* A collection source is optional. */
584 	if (collection_source != NULL)
585 		g_return_val_if_fail (E_IS_SOURCE (collection_source), NULL);
586 
587 	return g_object_new (
588 		E_TYPE_MAIL_CONFIG_NOTEBOOK,
589 		"session", session,
590 		"account-source", account_source,
591 		"identity-source", identity_source,
592 		"transport-source", transport_source,
593 		"collection-source", collection_source,
594 		NULL);
595 }
596 
597 EMailSession *
598 e_mail_config_notebook_get_session (EMailConfigNotebook *notebook)
599 {
600 	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
601 
602 	return notebook->priv->session;
603 }
604 
605 ESource *
606 e_mail_config_notebook_get_account_source (EMailConfigNotebook *notebook)
607 {
608 	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
609 
610 	return notebook->priv->account_source;
611 }
612 
613 ESource *
614 e_mail_config_notebook_get_identity_source (EMailConfigNotebook *notebook)
615 {
616 	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
617 
618 	return notebook->priv->identity_source;
619 }
620 
621 ESource *
622 e_mail_config_notebook_get_transport_source (EMailConfigNotebook *notebook)
623 {
624 	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
625 
626 	return notebook->priv->transport_source;
627 }
628 
629 ESource *
630 e_mail_config_notebook_get_collection_source (EMailConfigNotebook *notebook)
631 {
632 	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
633 
634 	return notebook->priv->collection_source;
635 }
636 
637 void
638 e_mail_config_notebook_add_page (EMailConfigNotebook *notebook,
639                                  EMailConfigPage *page)
640 {
641 	EMailConfigPageInterface *page_interface;
642 	GtkWidget *tab_label;
643 
644 	g_return_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook));
645 	g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page));
646 
647 	page_interface = E_MAIL_CONFIG_PAGE_GET_INTERFACE (page);
648 	tab_label = gtk_label_new (page_interface->title);
649 
650 	gtk_widget_show (GTK_WIDGET (page));
651 
652 	gtk_notebook_append_page (
653 		GTK_NOTEBOOK (notebook),
654 		GTK_WIDGET (page), tab_label);
655 
656 	mail_config_notebook_sort_pages (notebook);
657 }
658 
659 gboolean
660 e_mail_config_notebook_check_complete (EMailConfigNotebook *notebook)
661 {
662 	GList *list, *link;
663 	gboolean complete = TRUE;
664 
665 	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), FALSE);
666 
667 	list = gtk_container_get_children (GTK_CONTAINER (notebook));
668 
669 	for (link = list; link != NULL; link = g_list_next (link)) {
670 		if (E_IS_MAIL_CONFIG_PAGE (link->data)) {
671 			EMailConfigPage *page;
672 			page = E_MAIL_CONFIG_PAGE (link->data);
673 			complete = e_mail_config_page_check_complete (page);
674 
675 			if (!complete)
676 				break;
677 		}
678 	}
679 
680 	g_list_free (list);
681 
682 	return complete;
683 }
684 
685 /********************** e_mail_config_notebook_commit() **********************/
686 
687 static void
688 mail_config_notebook_page_submit_cb (GObject *source_object,
689                                      GAsyncResult *result,
690                                      gpointer user_data)
691 {
692 	GSimpleAsyncResult *simple;
693 	AsyncContext *async_context;
694 	EMailConfigPage *next_page;
695 	GError *error = NULL;
696 
697 	simple = G_SIMPLE_ASYNC_RESULT (user_data);
698 	async_context = g_simple_async_result_get_op_res_gpointer (simple);
699 
700 	e_mail_config_page_submit_finish (
701 		E_MAIL_CONFIG_PAGE (source_object), result, &error);
702 
703 	if (error != NULL) {
704 		g_simple_async_result_take_error (simple, error);
705 		g_simple_async_result_complete (simple);
706 		g_object_unref (simple);
707 		return;
708 	}
709 
710 	next_page = g_queue_pop_head (async_context->page_queue);
711 
712 	/* Submit the next EMailConfigPage. */
713 	if (next_page != NULL) {
714 		e_mail_config_page_submit (
715 			next_page, async_context->cancellable,
716 			mail_config_notebook_page_submit_cb, simple);
717 
718 		g_object_unref (next_page);
719 
720 	/* All done! */
721 	} else {
722 		g_simple_async_result_complete (simple);
723 		g_object_unref (simple);
724 	}
725 }
726 
727 static void
728 mail_config_notebook_source_commit_cb (GObject *source_object,
729                                        GAsyncResult *result,
730                                        gpointer user_data)
731 {
732 	GSimpleAsyncResult *simple;
733 	AsyncContext *async_context;
734 	ESource *next_source;
735 	GError *error = NULL;
736 
737 	simple = G_SIMPLE_ASYNC_RESULT (user_data);
738 	async_context = g_simple_async_result_get_op_res_gpointer (simple);
739 
740 	e_source_registry_commit_source_finish (
741 		E_SOURCE_REGISTRY (source_object), result, &error);
742 
743 	if (error != NULL) {
744 		g_simple_async_result_take_error (simple, error);
745 		g_simple_async_result_complete (simple);
746 		g_object_unref (simple);
747 		return;
748 	}
749 
750 	next_source = g_queue_pop_head (async_context->source_queue);
751 
752 	/* Commit the next ESources. */
753 	if (next_source != NULL) {
754 		e_source_registry_commit_source (
755 			async_context->registry, next_source,
756 			async_context->cancellable,
757 			mail_config_notebook_source_commit_cb, simple);
758 
759 		g_object_unref (next_source);
760 
761 	/* ESources done, start on the EMailConfigPages. */
762 	} else {
763 		EMailConfigPage *page;
764 
765 		/* There should be at least one page,
766 		 * so we can skip the NULL check here. */
767 		page = g_queue_pop_head (async_context->page_queue);
768 
769 		e_mail_config_page_submit (
770 			page, async_context->cancellable,
771 			mail_config_notebook_page_submit_cb, simple);
772 
773 		g_object_unref (page);
774 	}
775 }
776 
777 void
778 e_mail_config_notebook_commit (EMailConfigNotebook *notebook,
779                                GCancellable *cancellable,
780                                GAsyncReadyCallback callback,
781                                gpointer user_data)
782 {
783 	GSimpleAsyncResult *simple;
784 	AsyncContext *async_context;
785 	ESourceRegistry *registry;
786 	EMailSession *session;
787 	ESource *source;
788 	GList *list, *link;
789 	GQueue *page_queue;
790 	GQueue *source_queue;
791 
792 	g_return_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook));
793 
794 	session = e_mail_config_notebook_get_session (notebook);
795 	registry = e_mail_session_get_registry (session);
796 
797 	page_queue = g_queue_new ();
798 	source_queue = g_queue_new ();
799 
800 	/* Queue the collection data source if one is defined. */
801 	source = e_mail_config_notebook_get_collection_source (notebook);
802 	if (source != NULL)
803 		g_queue_push_tail (source_queue, g_object_ref (source));
804 
805 	/* Queue the mail-related data sources for the account. */
806 	source = e_mail_config_notebook_get_account_source (notebook);
807 	if (source != NULL)
808 		g_queue_push_tail (source_queue, g_object_ref (source));
809 	source = e_mail_config_notebook_get_identity_source (notebook);
810 	if (source != NULL)
811 		g_queue_push_tail (source_queue, g_object_ref (source));
812 	source = e_mail_config_notebook_get_transport_source (notebook);
813 	if (source != NULL)
814 		g_queue_push_tail (source_queue, g_object_ref (source));
815 
816 	list = gtk_container_get_children (GTK_CONTAINER (notebook));
817 
818 	/* Tell all EMailConfigPages to commit their UI state to their
819 	 * scratch ESources and push any additional data sources on to
820 	 * the given source queue, such as calendars or address books
821 	 * to be bundled with the mail account. */
822 	for (link = list; link != NULL; link = g_list_next (link)) {
823 		if (E_IS_MAIL_CONFIG_PAGE (link->data)) {
824 			EMailConfigPage *page;
825 			page = E_MAIL_CONFIG_PAGE (link->data);
826 			g_queue_push_tail (page_queue, g_object_ref (page));
827 			e_mail_config_page_commit_changes (page, source_queue);
828 		}
829 	}
830 
831 	g_list_free (list);
832 
833 	async_context = g_slice_new0 (AsyncContext);
834 	async_context->registry = g_object_ref (registry);
835 	async_context->page_queue = page_queue;      /* takes ownership */
836 	async_context->source_queue = source_queue;  /* takes ownership */
837 
838 	if (G_IS_CANCELLABLE (cancellable))
839 		async_context->cancellable = g_object_ref (cancellable);
840 
841 	simple = g_simple_async_result_new (
842 		G_OBJECT (notebook), callback, user_data,
843 		e_mail_config_notebook_commit);
844 
845 	g_simple_async_result_set_op_res_gpointer (
846 		simple, async_context, (GDestroyNotify) async_context_free);
847 
848 	source = g_queue_pop_head (async_context->source_queue);
849 	g_return_if_fail (E_IS_SOURCE (source));
850 
851 	e_source_registry_commit_source (
852 		async_context->registry, source,
853 		async_context->cancellable,
854 		mail_config_notebook_source_commit_cb, simple);
855 
856 	g_object_unref (source);
857 }
858 
859 gboolean
860 e_mail_config_notebook_commit_finish (EMailConfigNotebook *notebook,
861                                       GAsyncResult *result,
862                                       GError **error)
863 {
864 	GSimpleAsyncResult *simple;
865 
866 	g_return_val_if_fail (
867 		g_simple_async_result_is_valid (
868 		result, G_OBJECT (notebook),
869 		e_mail_config_notebook_commit), FALSE);
870 
871 	simple = G_SIMPLE_ASYNC_RESULT (result);
872 
873 	/* Assume success unless a GError is set. */
874 	return !g_simple_async_result_propagate_error (simple, error);
875 }