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.
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.
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/>
20 * SECTION: e-source-registry
21 * @include: libedataserver/libedataserver.h
22 * @short_description: A central repository for data sources
24 * The #ESourceRegistry is a global singleton store for all #ESource
25 * instances. It uses file monitors to react to key file creation and
26 * deletion events, either constructing an #ESource instance from the
27 * newly created key file, or removing from the logical #ESource
28 * hierarchy the instance corresponding to the deleted key file.
30 * The #ESourceRegistry can be queried for individual #ESource instances
31 * by their unique identifier string or key file path, for collections of
32 * #ESource instances having a particular extension, or for all available
35 * The #ESourceRegistry API also provides a front-end for the
36 * "org.gnome.Evolution.DefaultSources" #GSettings schema which tracks
37 * which #ESource instances are designated to be the user's default address
38 * book, calendar, memo list and task list for desktop integration.
41 #include "e-source-registry.h"
44 #include <glib/gstdio.h>
45 #include <glib/gi18n-lib.h>
47 /* XXX Yeah, yeah... */
48 #define GCR_API_SUBJECT_TO_CHANGE
50 #include <gcr/gcr-base.h>
52 /* Private D-Bus classes. */
53 #include <e-dbus-source.h>
54 #include <e-dbus-source-manager.h>
56 #include <libedataserver/e-marshal.h>
57 #include <libedataserver/e-data-server-util.h>
58 #include <libedataserver/e-source-collection.h>
60 /* Needed for the defaults API. */
61 #include <libedataserver/e-source-address-book.h>
62 #include <libedataserver/e-source-calendar.h>
63 #include <libedataserver/e-source-mail-account.h>
64 #include <libedataserver/e-source-mail-identity.h>
66 #include "e-dbus-authenticator.h"
68 #define E_SOURCE_REGISTRY_GET_PRIVATE(obj) \
69 (G_TYPE_INSTANCE_GET_PRIVATE \
70 ((obj), E_TYPE_SOURCE_REGISTRY, ESourceRegistryPrivate))
72 #define DBUS_OBJECT_PATH "/org/gnome/evolution/dataserver/SourceManager"
73 #define GSETTINGS_SCHEMA "org.gnome.Evolution.DefaultSources"
75 /* Built-in data source UIDs. */
76 #define E_SOURCE_BUILTIN_ADDRESS_BOOK_UID "system-address-book"
77 #define E_SOURCE_BUILTIN_CALENDAR_UID "system-calendar"
78 #define E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID "local"
79 #define E_SOURCE_BUILTIN_MEMO_LIST_UID "system-memo-list"
80 #define E_SOURCE_BUILTIN_TASK_LIST_UID "system-task-list"
82 /* GSettings keys for default data sources. */
83 #define E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY "default-address-book"
84 #define E_SETTINGS_DEFAULT_CALENDAR_KEY "default-calendar"
85 #define E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY "default-mail-account"
86 #define E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY "default-mail-identity"
87 #define E_SETTINGS_DEFAULT_MEMO_LIST_KEY "default-memo-list"
88 #define E_SETTINGS_DEFAULT_TASK_LIST_KEY "default-task-list"
90 /* This forces the GType to be registered in a way that
91 * avoids a "statement with no effect" compiler warning.
92 * FIXME Use g_type_ensure() once we require GLib 2.34. */
93 #define REGISTER_TYPE(type) \
94 (g_type_class_unref (g_type_class_ref (type)))
96 typedef struct _AsyncContext AsyncContext;
97 typedef struct _AuthContext AuthContext;
98 typedef struct _CreateContext CreateContext;
99 typedef struct _SourceClosure SourceClosure;
100 typedef struct _ThreadClosure ThreadClosure;
102 struct _ESourceRegistryPrivate {
103 GMainContext *main_context;
105 GThread *manager_thread;
106 ThreadClosure *thread_closure;
108 GDBusObjectManager *dbus_object_manager;
109 EDBusSourceManager *dbus_source_manager;
111 GHashTable *object_path_table;
112 GMutex object_path_table_lock;
120 struct _AsyncContext {
122 GList *list_of_sources;
123 ESourceAuthenticator *auth;
126 /* Used in e_source_registry_authenticate_sync() */
127 struct _AuthContext {
128 ESourceAuthenticator *auth;
129 EDBusAuthenticator *dbus_auth;
130 GCancellable *cancellable;
131 GMainLoop *main_loop;
132 ESourceAuthenticationResult auth_result;
133 GcrSecretExchange *secret_exchange;
134 gboolean authenticating;
139 /* Used in e_source_registry_create_sources_sync() */
140 struct _CreateContext {
141 GHashTable *pending_uids;
142 GMainContext *main_context;
143 GMainLoop *main_loop;
146 struct _SourceClosure {
147 ESourceRegistry *registry;
151 struct _ThreadClosure {
152 ESourceRegistry *registry;
153 GMainContext *main_context;
154 GMainLoop *main_loop;
155 GCond main_loop_cond;
156 GMutex main_loop_mutex;
162 PROP_DEFAULT_ADDRESS_BOOK,
163 PROP_DEFAULT_CALENDAR,
164 PROP_DEFAULT_MAIL_ACCOUNT,
165 PROP_DEFAULT_MAIL_IDENTITY,
166 PROP_DEFAULT_MEMO_LIST,
167 PROP_DEFAULT_TASK_LIST
179 /* Forward Declarations */
180 static void source_registry_add_source (ESourceRegistry *registry,
182 static void e_source_registry_initable_init (GInitableIface *interface);
184 static guint signals[LAST_SIGNAL];
186 /* By default, the GAsyncInitable interface calls GInitable.init()
187 * from a separate thread, so we only have to override GInitable. */
188 G_DEFINE_TYPE_WITH_CODE (
192 G_IMPLEMENT_INTERFACE (
193 G_TYPE_INITABLE, e_source_registry_initable_init)
194 G_IMPLEMENT_INTERFACE (
195 G_TYPE_ASYNC_INITABLE, NULL))
198 async_context_free (AsyncContext *async_context)
200 if (async_context->source != NULL)
201 g_object_unref (async_context->source);
204 async_context->list_of_sources,
205 (GDestroyNotify) g_object_unref);
207 if (async_context->auth != NULL)
208 g_object_unref (async_context->auth);
210 g_slice_free (AsyncContext, async_context);
214 auth_context_free (AuthContext *auth_context)
216 if (auth_context->auth != NULL)
217 g_object_unref (auth_context->auth);
219 if (auth_context->dbus_auth != NULL)
220 g_object_unref (auth_context->dbus_auth);
222 if (auth_context->cancellable != NULL)
223 g_object_unref (auth_context->cancellable);
225 if (auth_context->main_loop != NULL)
226 g_main_loop_unref (auth_context->main_loop);
228 if (auth_context->secret_exchange != NULL)
229 g_object_unref (auth_context->secret_exchange);
231 g_slice_free (AuthContext, auth_context);
234 static CreateContext *
235 create_context_new (void)
237 CreateContext *create_context;
239 create_context = g_slice_new0 (CreateContext);
241 create_context->pending_uids = g_hash_table_new_full (
242 (GHashFunc) g_str_hash,
243 (GEqualFunc) g_str_equal,
244 (GDestroyNotify) g_free,
245 (GDestroyNotify) NULL);
247 create_context->main_context = g_main_context_new ();
249 create_context->main_loop = g_main_loop_new (
250 create_context->main_context, FALSE);
252 return create_context;
256 create_context_free (CreateContext *create_context)
258 g_main_loop_unref (create_context->main_loop);
259 g_main_context_unref (create_context->main_context);
260 g_hash_table_unref (create_context->pending_uids);
262 g_slice_free (CreateContext, create_context);
266 source_closure_free (SourceClosure *closure)
268 g_object_unref (closure->registry);
269 g_object_unref (closure->source);
271 g_slice_free (SourceClosure, closure);
275 thread_closure_free (ThreadClosure *closure)
277 /* The registry member is not referenced. */
279 g_main_context_unref (closure->main_context);
280 g_main_loop_unref (closure->main_loop);
281 g_cond_clear (&closure->main_loop_cond);
282 g_mutex_clear (&closure->main_loop_mutex);
284 /* The GError should be NULL at this point,
285 * regardless of whether an error occurred. */
286 g_warn_if_fail (closure->error == NULL);
288 g_slice_free (ThreadClosure, closure);
292 source_registry_object_path_table_insert (ESourceRegistry *registry,
293 const gchar *object_path,
296 g_return_if_fail (object_path != NULL);
297 g_return_if_fail (E_IS_SOURCE (source));
299 g_mutex_lock (®istry->priv->object_path_table_lock);
301 g_hash_table_insert (
302 registry->priv->object_path_table,
303 g_strdup (object_path),
304 g_object_ref (source));
306 g_mutex_unlock (®istry->priv->object_path_table_lock);
310 source_registry_object_path_table_lookup (ESourceRegistry *registry,
311 const gchar *object_path)
315 g_return_val_if_fail (object_path != NULL, NULL);
317 g_mutex_lock (®istry->priv->object_path_table_lock);
319 source = g_hash_table_lookup (
320 registry->priv->object_path_table, object_path);
322 g_object_ref (source);
324 g_mutex_unlock (®istry->priv->object_path_table_lock);
330 source_registry_object_path_table_remove (ESourceRegistry *registry,
331 const gchar *object_path)
335 g_return_val_if_fail (object_path != NULL, FALSE);
337 g_mutex_lock (®istry->priv->object_path_table_lock);
339 removed = g_hash_table_remove (
340 registry->priv->object_path_table, object_path);
342 g_mutex_unlock (®istry->priv->object_path_table_lock);
348 source_registry_sources_insert (ESourceRegistry *registry,
353 uid = e_source_get_uid (source);
354 g_return_if_fail (uid != NULL);
356 g_mutex_lock (®istry->priv->sources_lock);
358 g_hash_table_insert (
359 registry->priv->sources,
360 g_strdup (uid), g_object_ref (source));
362 g_mutex_unlock (®istry->priv->sources_lock);
366 source_registry_sources_remove (ESourceRegistry *registry,
372 uid = e_source_get_uid (source);
373 g_return_val_if_fail (uid != NULL, FALSE);
375 g_mutex_lock (®istry->priv->sources_lock);
377 removed = g_hash_table_remove (registry->priv->sources, uid);
379 g_mutex_unlock (®istry->priv->sources_lock);
385 source_registry_sources_lookup (ESourceRegistry *registry,
390 g_return_val_if_fail (uid != NULL, NULL);
392 g_mutex_lock (®istry->priv->sources_lock);
394 source = g_hash_table_lookup (registry->priv->sources, uid);
397 g_object_ref (source);
399 g_mutex_unlock (®istry->priv->sources_lock);
405 source_registry_sources_get_values (ESourceRegistry *registry)
409 g_mutex_lock (®istry->priv->sources_lock);
411 values = g_hash_table_get_values (registry->priv->sources);
413 g_list_foreach (values, (GFunc) g_object_ref, NULL);
415 g_mutex_unlock (®istry->priv->sources_lock);
421 source_registry_sources_build_tree (ESourceRegistry *registry)
428 g_mutex_lock (®istry->priv->sources_lock);
430 root = g_node_new (NULL);
431 index = g_hash_table_new (g_str_hash, g_str_equal);
433 /* Add a GNode for each ESource to the index. */
434 g_hash_table_iter_init (&iter, registry->priv->sources);
435 while (g_hash_table_iter_next (&iter, &key, &value)) {
436 ESource *source = g_object_ref (value);
437 g_hash_table_insert (index, key, g_node_new (source));
440 /* Traverse the index and link the nodes together. */
441 g_hash_table_iter_init (&iter, index);
442 while (g_hash_table_iter_next (&iter, NULL, &value)) {
446 const gchar *parent_uid;
448 source_node = (GNode *) value;
449 source = E_SOURCE (source_node->data);
450 parent_uid = e_source_get_parent (source);
452 if (parent_uid == NULL || *parent_uid == '\0') {
455 parent_node = g_hash_table_lookup (index, parent_uid);
456 g_warn_if_fail (parent_node != NULL);
459 /* Should never be NULL, but just to be safe. */
460 if (parent_node != NULL)
461 g_node_append (parent_node, source_node);
464 g_hash_table_destroy (index);
466 g_mutex_unlock (®istry->priv->sources_lock);
472 source_registry_settings_changed_cb (GSettings *settings,
474 ESourceRegistry *registry)
476 /* We define a property name that matches every key in
477 * the "org.gnome.Evolution.DefaultSources" schema. */
478 g_object_notify (G_OBJECT (registry), key);
482 source_registry_source_changed_idle_cb (gpointer user_data)
484 SourceClosure *closure = user_data;
488 signals[SOURCE_CHANGED], 0,
495 source_registry_source_notify_enabled_idle_cb (gpointer user_data)
497 SourceClosure *closure = user_data;
499 if (e_source_get_enabled (closure->source))
502 signals[SOURCE_ENABLED], 0,
507 signals[SOURCE_DISABLED], 0,
514 source_registry_source_changed_cb (ESource *source,
515 ESourceRegistry *registry)
517 GSource *idle_source;
518 SourceClosure *closure;
520 closure = g_slice_new0 (SourceClosure);
521 closure->registry = g_object_ref (registry);
522 closure->source = g_object_ref (source);
524 idle_source = g_idle_source_new ();
525 g_source_set_callback (
527 source_registry_source_changed_idle_cb,
528 closure, (GDestroyNotify) source_closure_free);
529 g_source_attach (idle_source, registry->priv->main_context);
530 g_source_unref (idle_source);
534 source_registry_source_notify_enabled_cb (ESource *source,
536 ESourceRegistry *registry)
538 GSource *idle_source;
539 SourceClosure *closure;
541 closure = g_slice_new0 (SourceClosure);
542 closure->registry = g_object_ref (registry);
543 closure->source = g_object_ref (source);
545 idle_source = g_idle_source_new ();
546 g_source_set_callback (
548 source_registry_source_notify_enabled_idle_cb,
549 closure, (GDestroyNotify) source_closure_free);
550 g_source_attach (idle_source, registry->priv->main_context);
551 g_source_unref (idle_source);
555 source_registry_new_source (ESourceRegistry *registry,
556 GDBusObject *dbus_object)
558 GMainContext *main_context;
560 const gchar *object_path;
561 GError *error = NULL;
563 /* We don't want the ESource emitting "changed" signals from
564 * the manager thread, so we pass it the same main context the
565 * registry uses for scheduling signal emissions. */
566 main_context = registry->priv->main_context;
567 source = e_source_new (dbus_object, main_context, &error);
568 object_path = g_dbus_object_get_object_path (dbus_object);
570 /* The likelihood of an error here is slim, so it's
571 * sufficient to just print a warning if one occurs. */
573 g_warn_if_fail (source == NULL);
575 "ESourceRegistry: Failed to create a "
576 "data source object for path '%s': %s",
577 object_path, error->message);
578 g_error_free (error);
582 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
584 /* Add the ESource to the object path table immediately. */
585 source_registry_object_path_table_insert (
586 registry, object_path, source);
592 source_registry_unref_source (ESource *source)
594 g_signal_handlers_disconnect_matched (
595 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
596 source_registry_source_changed_cb, NULL);
598 g_signal_handlers_disconnect_matched (
599 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
600 source_registry_source_notify_enabled_cb, NULL);
602 g_object_unref (source);
606 source_registry_add_source (ESourceRegistry *registry,
611 /* This is called in the manager thread during initialization
612 * and in response to "object-added" signals from the manager. */
614 uid = e_source_get_uid (source);
615 g_return_if_fail (uid != NULL);
617 g_mutex_lock (®istry->priv->sources_lock);
619 /* Check if we already have this source in the registry. */
620 if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
621 g_mutex_unlock (®istry->priv->sources_lock);
627 G_CALLBACK (source_registry_source_changed_cb),
631 source, "notify::enabled",
632 G_CALLBACK (source_registry_source_notify_enabled_cb),
635 g_mutex_unlock (®istry->priv->sources_lock);
637 source_registry_sources_insert (registry, source);
641 source_registry_object_added_idle_cb (gpointer user_data)
643 SourceClosure *closure = user_data;
644 ESourceRegistry *registry = closure->registry;
645 ESource *source = closure->source;
647 g_signal_emit (registry, signals[SOURCE_ADDED], 0, source);
653 source_registry_object_added_cb (GDBusObjectManager *object_manager,
654 GDBusObject *dbus_object,
655 ESourceRegistry *registry)
657 SourceClosure *closure;
658 GSource *idle_source;
661 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
663 source = source_registry_new_source (registry, dbus_object);
664 g_return_if_fail (source != NULL);
666 /* Add the new ESource to our internal hash table so it can be
667 * obtained through e_source_registry_ref_source() immediately. */
668 source_registry_add_source (registry, source);
670 /* Schedule a callback on the ESourceRegistry's GMainContext. */
672 closure = g_slice_new0 (SourceClosure);
673 closure->registry = g_object_ref (registry);
674 closure->source = g_object_ref (source);
676 idle_source = g_idle_source_new ();
677 g_source_set_callback (
679 source_registry_object_added_idle_cb,
680 closure, (GDestroyNotify) source_closure_free);
681 g_source_attach (idle_source, registry->priv->main_context);
682 g_source_unref (idle_source);
684 g_object_unref (source);
688 source_registry_object_removed_idle_cb (gpointer user_data)
690 SourceClosure *closure = user_data;
691 ESourceRegistry *registry = closure->registry;
692 ESource *source = closure->source;
694 /* Removing the ESource won't finalize it because the
695 * SourceClosure itself still holds a reference on it. */
696 if (source_registry_sources_remove (registry, source))
697 g_signal_emit (registry, signals[SOURCE_REMOVED], 0, source);
703 source_registry_object_removed_cb (GDBusObjectManager *manager,
704 GDBusObject *dbus_object,
705 ESourceRegistry *registry)
707 SourceClosure *closure;
708 GSource *idle_source;
710 const gchar *object_path;
712 /* Find the corresponding ESource in the object path table.
713 * Note that the lookup returns a new ESource reference. */
714 object_path = g_dbus_object_get_object_path (dbus_object);
715 source = source_registry_object_path_table_lookup (
716 registry, object_path);
717 g_return_if_fail (E_IS_SOURCE (source));
719 /* Remove the ESource from the object path table immediately. */
720 source_registry_object_path_table_remove (registry, object_path);
722 /* Schedule a callback on the ESourceRegistry's GMainContext. */
724 closure = g_slice_new0 (SourceClosure);
725 closure->registry = g_object_ref (registry);
726 closure->source = g_object_ref (source);
728 idle_source = g_idle_source_new ();
729 g_source_set_callback (
731 source_registry_object_removed_idle_cb,
732 closure, (GDestroyNotify) source_closure_free);
733 g_source_attach (idle_source, registry->priv->main_context);
734 g_source_unref (idle_source);
736 g_object_unref (source);
740 source_registry_object_manager_running (gpointer data)
742 ThreadClosure *closure = data;
744 g_mutex_lock (&closure->main_loop_mutex);
745 g_cond_broadcast (&closure->main_loop_cond);
746 g_mutex_unlock (&closure->main_loop_mutex);
752 source_registry_object_manager_thread (gpointer data)
754 GDBusObjectManager *object_manager;
755 ThreadClosure *closure = data;
756 GSource *idle_source;
758 gulong object_added_id = 0;
759 gulong object_removed_id = 0;
761 /* GDBusObjectManagerClient grabs the thread-default GMainContext
762 * at creation time and only emits signals from that GMainContext.
763 * Running it in a separate thread prevents its signal emissions
764 * from being inhibited by someone overriding the thread-default
767 /* This becomes the GMainContext that GDBusObjectManagerClient
768 * will emit signals from. Make it the thread-default context
769 * for this thread before creating the client. */
770 g_main_context_push_thread_default (closure->main_context);
772 object_manager = e_dbus_object_manager_client_new_for_bus_sync (
774 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
775 SOURCES_DBUS_SERVICE_NAME,
777 NULL, &closure->error);
781 ((object_manager != NULL) && (closure->error == NULL)) ||
782 ((object_manager == NULL) && (closure->error != NULL)));
784 /* If we failed to create the GDBusObjectManagerClient, skip
785 * straight to the main loop. The GError will be propagated
786 * back to the caller, the main loop will terminate, and the
787 * partially-initialized ESourceRegistry will be destroyed. */
788 if (object_manager == NULL)
791 /* Give the registry a handle to the object manager. */
792 closure->registry->priv->dbus_object_manager =
793 g_object_ref (object_manager);
795 /* Now populate the registry with an initial set of ESources. */
797 list = g_dbus_object_manager_get_objects (object_manager);
799 for (link = list; link != NULL; link = g_list_next (link)) {
800 GDBusObject *dbus_object;
803 dbus_object = G_DBUS_OBJECT (link->data);
805 source = source_registry_new_source (
806 closure->registry, dbus_object);
808 if (source != NULL) {
809 source_registry_add_source (
810 closure->registry, source);
811 g_object_unref (source);
815 g_list_free_full (list, (GDestroyNotify) g_object_unref);
817 /* Listen for D-Bus object additions and removals. */
819 object_added_id = g_signal_connect (
820 object_manager, "object-added",
821 G_CALLBACK (source_registry_object_added_cb),
824 object_removed_id = g_signal_connect (
825 object_manager, "object-removed",
826 G_CALLBACK (source_registry_object_removed_cb),
830 /* Schedule a one-time idle callback to broadcast through a
831 * condition variable that our main loop is up and running. */
833 idle_source = g_idle_source_new ();
834 g_source_set_callback (
836 source_registry_object_manager_running,
837 closure, (GDestroyNotify) NULL);
838 g_source_attach (idle_source, closure->main_context);
839 g_source_unref (idle_source);
841 /* Now we mostly idle here for the rest of the session. */
843 g_main_loop_run (closure->main_loop);
845 /* Clean up and exit. */
847 if (object_manager != NULL) {
848 g_signal_handler_disconnect (object_manager, object_added_id);
849 g_signal_handler_disconnect (object_manager, object_removed_id);
850 g_object_unref (object_manager);
853 g_main_context_pop_thread_default (closure->main_context);
859 source_registry_set_property (GObject *object,
864 switch (property_id) {
865 case PROP_DEFAULT_ADDRESS_BOOK:
866 e_source_registry_set_default_address_book (
867 E_SOURCE_REGISTRY (object),
868 g_value_get_object (value));
871 case PROP_DEFAULT_CALENDAR:
872 e_source_registry_set_default_calendar (
873 E_SOURCE_REGISTRY (object),
874 g_value_get_object (value));
877 case PROP_DEFAULT_MAIL_ACCOUNT:
878 e_source_registry_set_default_mail_account (
879 E_SOURCE_REGISTRY (object),
880 g_value_get_object (value));
883 case PROP_DEFAULT_MAIL_IDENTITY:
884 e_source_registry_set_default_mail_identity (
885 E_SOURCE_REGISTRY (object),
886 g_value_get_object (value));
889 case PROP_DEFAULT_MEMO_LIST:
890 e_source_registry_set_default_memo_list (
891 E_SOURCE_REGISTRY (object),
892 g_value_get_object (value));
895 case PROP_DEFAULT_TASK_LIST:
896 e_source_registry_set_default_task_list (
897 E_SOURCE_REGISTRY (object),
898 g_value_get_object (value));
902 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
906 source_registry_get_property (GObject *object,
911 switch (property_id) {
912 case PROP_DEFAULT_ADDRESS_BOOK:
913 g_value_take_object (
915 e_source_registry_ref_default_address_book (
916 E_SOURCE_REGISTRY (object)));
919 case PROP_DEFAULT_CALENDAR:
920 g_value_take_object (
922 e_source_registry_ref_default_calendar (
923 E_SOURCE_REGISTRY (object)));
926 case PROP_DEFAULT_MAIL_ACCOUNT:
927 g_value_take_object (
929 e_source_registry_ref_default_mail_account (
930 E_SOURCE_REGISTRY (object)));
933 case PROP_DEFAULT_MAIL_IDENTITY:
934 g_value_take_object (
936 e_source_registry_ref_default_mail_identity (
937 E_SOURCE_REGISTRY (object)));
940 case PROP_DEFAULT_MEMO_LIST:
941 g_value_take_object (
943 e_source_registry_ref_default_memo_list (
944 E_SOURCE_REGISTRY (object)));
947 case PROP_DEFAULT_TASK_LIST:
948 g_value_take_object (
950 e_source_registry_ref_default_task_list (
951 E_SOURCE_REGISTRY (object)));
955 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
959 source_registry_dispose (GObject *object)
961 ESourceRegistryPrivate *priv;
963 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
965 /* Terminate the manager thread first. */
966 if (priv->manager_thread != NULL) {
967 g_main_loop_quit (priv->thread_closure->main_loop);
968 g_thread_join (priv->manager_thread);
969 thread_closure_free (priv->thread_closure);
970 priv->manager_thread = NULL;
971 priv->thread_closure = NULL;
974 if (priv->main_context != NULL) {
975 g_main_context_unref (priv->main_context);
976 priv->main_context = NULL;
979 if (priv->dbus_object_manager != NULL) {
980 g_object_unref (priv->dbus_object_manager);
981 priv->dbus_object_manager = NULL;
984 if (priv->dbus_source_manager != NULL) {
985 g_object_unref (priv->dbus_source_manager);
986 priv->dbus_source_manager = NULL;
989 g_hash_table_remove_all (priv->object_path_table);
991 g_hash_table_remove_all (priv->sources);
993 if (priv->settings != NULL) {
994 g_object_unref (priv->settings);
995 priv->settings = NULL;
998 /* Chain up to parent's finalize() method. */
999 G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
1003 source_registry_finalize (GObject *object)
1005 ESourceRegistryPrivate *priv;
1007 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
1009 g_hash_table_destroy (priv->object_path_table);
1010 g_mutex_clear (&priv->object_path_table_lock);
1012 g_hash_table_destroy (priv->sources);
1013 g_mutex_clear (&priv->sources_lock);
1015 /* Chain up to parent's finalize() method. */
1016 G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
1020 source_registry_initable_init (GInitable *initable,
1021 GCancellable *cancellable,
1024 ESourceRegistry *registry;
1025 ThreadClosure *closure;
1027 registry = E_SOURCE_REGISTRY (initable);
1029 closure = g_slice_new0 (ThreadClosure);
1030 closure->registry = registry; /* do not reference */
1031 closure->main_context = g_main_context_new ();
1032 /* It's important to pass 'is_running=FALSE' here because
1033 * we wait for the main loop to start running as a way of
1034 * synchronizing with the manager thread. */
1035 closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
1036 g_cond_init (&closure->main_loop_cond);
1037 g_mutex_init (&closure->main_loop_mutex);
1039 registry->priv->thread_closure = closure;
1041 registry->priv->manager_thread = g_thread_new (NULL,
1042 source_registry_object_manager_thread,
1045 if (registry->priv->manager_thread == NULL)
1048 /* Wait for notification that the manager
1049 * thread's main loop has been started. */
1050 g_mutex_lock (&closure->main_loop_mutex);
1051 while (!g_main_loop_is_running (closure->main_loop))
1053 &closure->main_loop_cond,
1054 &closure->main_loop_mutex);
1055 g_mutex_unlock (&closure->main_loop_mutex);
1057 /* Check for error in the manager thread. */
1058 if (closure->error != NULL) {
1059 g_propagate_error (error, closure->error);
1060 closure->error = NULL;
1064 /* The registry should now be populated with sources.
1066 * XXX Actually, not necessarily if the registry service was
1067 * just now activated. There may yet be a small window
1068 * while the registry service starts up before it exports
1069 * any sources, even built-in sources. This COULD create
1070 * problems if any logic that depends on those built-in
1071 * sources executes during this time window, but so far
1072 * we haven't seen any cases of that.
1074 * Attempts in the past to stop and wait for sources to
1075 * show up have proven problematic. See for example:
1076 * https://bugzilla.gnome.org/678378
1078 * Leave the runtime check disabled for the moment.
1079 * I have a feeling I'll be revisiting this again.
1081 /*g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);*/
1083 /* The EDBusSourceManagerProxy is just another D-Bus interface
1084 * that resides at the same object path. It's unrelated to the
1085 * GDBusObjectManagerClient and doesn't need its own thread. */
1086 registry->priv->dbus_source_manager =
1087 e_dbus_source_manager_proxy_new_for_bus_sync (
1089 G_DBUS_PROXY_FLAGS_NONE,
1090 SOURCES_DBUS_SERVICE_NAME,
1092 cancellable, error);
1094 if (registry->priv->dbus_source_manager == NULL)
1097 /* Allow authentication prompts for all exported data sources
1098 * when a new EDBusSourceManagerProxy is created. The thought
1099 * being, if you cancel an authentication prompt you will not
1100 * be bothered again until you start (or restart) a new E-D-S
1101 * client app. Failure here is non-fatal, ignore errors. */
1102 e_dbus_source_manager_call_allow_auth_prompt_all_sync (
1103 registry->priv->dbus_source_manager, cancellable, NULL);
1109 e_source_registry_class_init (ESourceRegistryClass *class)
1111 GObjectClass *object_class;
1113 g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
1115 object_class = G_OBJECT_CLASS (class);
1116 object_class->set_property = source_registry_set_property;
1117 object_class->get_property = source_registry_get_property;
1118 object_class->dispose = source_registry_dispose;
1119 object_class->finalize = source_registry_finalize;
1121 /* The property names correspond to the key names in the
1122 * "org.gnome.Evolution.DefaultSources" GSettings schema. */
1125 * ESourceRegistry:default-address-book:
1127 * The default address book #ESource.
1129 g_object_class_install_property (
1131 PROP_DEFAULT_ADDRESS_BOOK,
1132 g_param_spec_object (
1133 "default-address-book",
1134 "Default Address Book",
1135 "The default address book ESource",
1138 G_PARAM_STATIC_STRINGS));
1141 * ESourceRegistry:default-calendar:
1143 * The default calendar #ESource.
1145 g_object_class_install_property (
1147 PROP_DEFAULT_CALENDAR,
1148 g_param_spec_object (
1151 "The default calendar ESource",
1154 G_PARAM_STATIC_STRINGS));
1157 * ESourceRegistry:default-mail-account:
1159 * The default mail account #ESource.
1161 g_object_class_install_property (
1163 PROP_DEFAULT_MAIL_ACCOUNT,
1164 g_param_spec_object (
1165 "default-mail-account",
1166 "Default Mail Account",
1167 "The default mail account ESource",
1170 G_PARAM_STATIC_STRINGS));
1173 * ESourceRegistry:default-mail-identity:
1175 * The default mail identity #ESource.
1177 g_object_class_install_property (
1179 PROP_DEFAULT_MAIL_IDENTITY,
1180 g_param_spec_object (
1181 "default-mail-identity",
1182 "Default Mail Identity",
1183 "The default mail identity ESource",
1186 G_PARAM_STATIC_STRINGS));
1189 * ESourceRegistry:default-memo-list:
1191 * The default memo list #ESource.
1193 g_object_class_install_property (
1195 PROP_DEFAULT_MEMO_LIST,
1196 g_param_spec_object (
1197 "default-memo-list",
1198 "Default Memo List",
1199 "The default memo list ESource",
1202 G_PARAM_STATIC_STRINGS));
1205 * ESourceRegistry:default-task-list:
1207 * The default task list #ESource.
1209 g_object_class_install_property (
1211 PROP_DEFAULT_TASK_LIST,
1212 g_param_spec_object (
1213 "default-task-list",
1214 "Default Task List",
1215 "The default task list ESource",
1218 G_PARAM_STATIC_STRINGS));
1221 * ESourceRegistry::source-added:
1222 * @registry: the #ESourceRegistry which emitted the signal
1223 * @source: the newly-added #ESource
1225 * Emitted when an #ESource is added to @registry.
1227 signals[SOURCE_ADDED] = g_signal_new (
1229 G_OBJECT_CLASS_TYPE (object_class),
1231 G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
1233 g_cclosure_marshal_VOID__OBJECT,
1238 * ESourceRegistry::source-changed:
1239 * @registry: the #ESourceRegistry which emitted the signal
1240 * @source: the #ESource that changed
1242 * Emitted when an #ESource registered with @registry emits
1243 * its #ESource::changed signal.
1245 signals[SOURCE_CHANGED] = g_signal_new (
1247 G_OBJECT_CLASS_TYPE (object_class),
1249 G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
1251 g_cclosure_marshal_VOID__OBJECT,
1256 * ESourceRegistry::source-removed:
1257 * @registry: the #ESourceRegistry which emitted the signal
1258 * @source: the #ESource that got removed
1260 * Emitted when an #ESource is removed from @registry.
1262 signals[SOURCE_REMOVED] = g_signal_new (
1264 G_OBJECT_CLASS_TYPE (object_class),
1266 G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
1268 g_cclosure_marshal_VOID__OBJECT,
1273 * ESourceRegistry::source-enabled:
1274 * @registry: the #ESourceRegistry which emitted the signal
1275 * @source: the #ESource that got enabled
1277 * Emitted when an #ESource #ESource:enabled property becomes %TRUE.
1279 signals[SOURCE_ENABLED] = g_signal_new (
1281 G_OBJECT_CLASS_TYPE (object_class),
1283 G_STRUCT_OFFSET (ESourceRegistryClass, source_enabled),
1285 g_cclosure_marshal_VOID__OBJECT,
1290 * ESourceRegistry::source-disabled:
1291 * @registry: the #ESourceRegistry which emitted the signal
1292 * @source: the #ESource that got disabled
1294 * Emitted when an #ESource #ESource:enabled property becomes %FALSE.
1296 signals[SOURCE_DISABLED] = g_signal_new (
1298 G_OBJECT_CLASS_TYPE (object_class),
1300 G_STRUCT_OFFSET (ESourceRegistryClass, source_disabled),
1302 g_cclosure_marshal_VOID__OBJECT,
1308 e_source_registry_initable_init (GInitableIface *interface)
1310 interface->init = source_registry_initable_init;
1314 e_source_registry_init (ESourceRegistry *registry)
1316 registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
1318 /* This is so the object manager thread can schedule signal
1319 * emissions on the thread-default context for this thread. */
1320 registry->priv->main_context = g_main_context_ref_thread_default ();
1322 /* D-Bus object path -> ESource */
1323 registry->priv->object_path_table =
1324 g_hash_table_new_full (
1325 (GHashFunc) g_str_hash,
1326 (GEqualFunc) g_str_equal,
1327 (GDestroyNotify) g_free,
1328 (GDestroyNotify) g_object_unref);
1330 g_mutex_init (®istry->priv->object_path_table_lock);
1332 /* UID string -> ESource */
1333 registry->priv->sources = g_hash_table_new_full (
1334 (GHashFunc) g_str_hash,
1335 (GEqualFunc) g_str_equal,
1336 (GDestroyNotify) g_free,
1337 (GDestroyNotify) source_registry_unref_source);
1339 g_mutex_init (®istry->priv->sources_lock);
1341 registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
1344 registry->priv->settings, "changed",
1345 G_CALLBACK (source_registry_settings_changed_cb), registry);
1349 * e_source_registry_new_sync:
1350 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1351 * @error: return location for a #GError, or %NULL
1353 * Creates a new #ESourceRegistry front-end for the registry D-Bus service.
1354 * If an error occurs in connecting to the D-Bus service, the function sets
1355 * @error and returns %NULL.
1357 * Returns: a new #ESourceRegistry, or %NULL
1362 e_source_registry_new_sync (GCancellable *cancellable,
1365 /* XXX Work around http://bugzilla.gnome.org/show_bug.cgi?id=683519
1366 * until GObject's type initialization deadlock issue is fixed.
1367 * Apparently only the synchronous instantiation is affected. */
1368 REGISTER_TYPE (G_TYPE_DBUS_CONNECTION);
1370 return g_initable_new (
1371 E_TYPE_SOURCE_REGISTRY,
1372 cancellable, error, NULL);
1376 * e_source_registry_new:
1377 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1378 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1380 * @user_data: (closure): data to pass to the callback function
1382 * Asynchronously creates a new #ESourceRegistry front-end for the registry
1385 * When the operation is finished, @callback will be called. You can then
1386 * call e_source_registry_new_finish() to get the result of the operation.
1391 e_source_registry_new (GCancellable *cancellable,
1392 GAsyncReadyCallback callback,
1395 g_async_initable_new_async (
1396 E_TYPE_SOURCE_REGISTRY,
1397 G_PRIORITY_DEFAULT, cancellable,
1398 callback, user_data, NULL);
1402 * e_source_registry_new_finish:
1403 * @result: a #GAsyncResult
1404 * @error: return location for a #GError, or %NULL
1406 * Finishes the operation started with e_source_registry_new_finish().
1407 * If an error occurs in connecting to the D-Bus service, the function
1408 * sets @error and returns %NULL.
1410 * Returns: a new #ESourceRegistry, or %NULL
1415 e_source_registry_new_finish (GAsyncResult *result,
1418 GObject *source_object;
1421 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1423 source_object = g_async_result_get_source_object (result);
1424 g_return_val_if_fail (source_object != NULL, NULL);
1426 object = g_async_initable_new_finish (
1427 G_ASYNC_INITABLE (source_object), result, error);
1429 g_object_unref (source_object);
1431 return (object != NULL) ? E_SOURCE_REGISTRY (object) : NULL;
1434 /* Helper for e_source_registry_authenticate() */
1436 source_registry_authenticate_thread (GSimpleAsyncResult *simple,
1438 GCancellable *cancellable)
1440 AsyncContext *async_context;
1441 GError *error = NULL;
1443 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1445 e_source_registry_authenticate_sync (
1446 E_SOURCE_REGISTRY (object),
1447 async_context->source,
1448 async_context->auth,
1449 cancellable, &error);
1452 g_simple_async_result_take_error (simple, error);
1455 /* Helper for e_source_registry_authenticate_sync() */
1457 source_registry_authenticate_respond_cb (AuthContext *auth_context)
1459 ESourceAuthenticationResult auth_result;
1460 GError *non_fatal_error = NULL;
1462 g_return_val_if_fail (auth_context->authenticating, FALSE);
1464 auth_result = auth_context->auth_result;
1466 /* Allow the next authentication attempt to proceed. */
1467 auth_context->authenticating = FALSE;
1469 /* Send the server a status update based on the authentication
1470 * result. Note, we don't really care if the D-Bus message gets
1471 * through to the server at this point. If it doesn't, the auth
1472 * session will either time out on its own or the authentication
1473 * dialog will eventually be dismissed by the user. */
1475 /* If we were cancelled from our side, we have a bit of a dilemma.
1476 * We need to tell the server to cancel the authentication session,
1477 * but that involves making a synchronous D-Bus call, which we are
1478 * not supposed to do if we know we've been cancelled. But if we
1479 * don't tell the server, the authentication session will be left
1480 * to timeout on its own (which may take minutes), and meanwhile
1481 * all other authentication requests are blocked. So choose the
1482 * lesser evil and make the synchronous call but without passing
1483 * the already-cancelled GCancellable. */
1484 if (g_cancellable_is_cancelled (auth_context->cancellable)) {
1485 e_dbus_authenticator_call_cancel_sync (
1486 auth_context->dbus_auth,
1487 NULL, &non_fatal_error);
1488 g_main_loop_quit (auth_context->main_loop);
1489 auth_context->success = FALSE;
1491 /* If an error occurred while attempting to authenticate,
1492 * tell the server to cancel the authentication session. */
1493 } else if (auth_result == E_SOURCE_AUTHENTICATION_ERROR) {
1494 e_dbus_authenticator_call_cancel_sync (
1495 auth_context->dbus_auth,
1496 auth_context->cancellable,
1498 g_main_loop_quit (auth_context->main_loop);
1499 auth_context->success = FALSE;
1501 /* If the password was accepted, let the server know so it
1502 * can close any authentication dialogs and save the user
1503 * provided password to the keyring. */
1504 } else if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
1505 e_dbus_authenticator_call_accepted_sync (
1506 auth_context->dbus_auth,
1507 auth_context->cancellable,
1509 g_main_loop_quit (auth_context->main_loop);
1510 auth_context->success = TRUE;
1512 /* If the password was rejected, let the server know so it can
1513 * indicate failure and request a different password, and then
1514 * wait for the next "response" signal. */
1516 e_dbus_authenticator_call_rejected_sync (
1517 auth_context->dbus_auth,
1518 auth_context->cancellable,
1522 /* Leave breadcrumbs if something went wrong,
1523 * but don't fail the whole operation over it. */
1524 if (non_fatal_error != NULL) {
1525 g_warning ("%s: %s", G_STRFUNC, non_fatal_error->message);
1526 g_error_free (non_fatal_error);
1532 /* Helper for e_source_registry_authenticate_sync() */
1534 source_registry_authenticate_authenticate_cb (EDBusAuthenticator *dbus_auth,
1535 const gchar *encrypted_secret,
1536 AuthContext *auth_context)
1538 GSource *idle_source;
1539 GMainContext *main_context;
1541 gboolean valid_secret;
1543 /* We should only get one secret at a time. */
1544 g_return_if_fail (!auth_context->authenticating);
1546 valid_secret = gcr_secret_exchange_receive (
1547 auth_context->secret_exchange, encrypted_secret);
1548 g_return_if_fail (valid_secret);
1550 auth_context->authenticating = TRUE;
1552 /* This avoids revealing the password in a stack trace. */
1553 password = g_string_new (
1554 gcr_secret_exchange_get_secret (
1555 auth_context->secret_exchange, NULL));
1557 /* Try authenticating with the given password. We have to
1558 * call this synchronously because some authenticators use
1559 * mutexes to serialize I/O operations and are not prepared
1560 * to make authentication attempts from a different thread.
1562 * Unfortunately this means we won't notice server-side
1563 * dismissals while the main loop is blocked. We respond
1564 * to the server from a low-priority idle callback so that
1565 * any pending "dismissed" signals get handled first. */
1567 auth_context->auth_result =
1568 e_source_authenticator_try_password_sync (
1569 auth_context->auth, password,
1570 auth_context->cancellable,
1571 auth_context->error);
1573 idle_source = g_idle_source_new ();
1574 main_context = g_main_context_get_thread_default ();
1575 g_source_set_callback (
1576 idle_source, (GSourceFunc)
1577 source_registry_authenticate_respond_cb,
1578 auth_context, NULL);
1579 g_source_attach (idle_source, main_context);
1580 g_source_unref (idle_source);
1582 g_string_free (password, TRUE);
1585 /* Helper for e_source_registry_authenticate_sync() */
1587 source_registry_authenticate_dismissed_cb (EDBusAuthenticator *dbus_auth,
1588 AuthContext *auth_context)
1590 /* Be careful not to overwrite an existing error in case this
1591 * is called after e_source_authenticator_try_password_sync()
1592 * but prior to the idle callback. */
1593 if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
1594 /* XXX Use a separate error code for dismissals? */
1595 g_set_error_literal (
1596 auth_context->error,
1597 G_IO_ERROR, G_IO_ERROR_CANCELLED,
1598 _("The user declined to authenticate"));
1599 auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
1602 g_main_loop_quit (auth_context->main_loop);
1603 auth_context->success = FALSE;
1606 /* Helper for e_source_registry_authenticate_sync() */
1608 source_registry_call_authenticate_for_source (ESourceRegistry *registry,
1609 ESourceAuthenticator *auth,
1611 gchar **out_object_path,
1612 GCancellable *cancellable,
1615 ESource *collection;
1617 gchar *prompt_title = NULL;
1618 gchar *prompt_message = NULL;
1619 gchar *prompt_description = NULL;
1622 /* If the source is a member of a collection, we want to store
1623 * the password under the UID of the "collection" source so it
1624 * will apply to the entire collection.
1626 * XXX This assumes all sources in a collection share a single
1627 * password. If that turns out not to be true in all cases
1628 * we could maybe add a "SharedPassword: true/false" key to
1629 * [Collection] and apply it here.
1631 collection = e_source_registry_find_extension (
1632 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1633 if (collection != NULL)
1634 source = collection;
1636 g_object_ref (source);
1638 uid = e_source_get_uid (source);
1640 e_source_authenticator_get_prompt_strings (
1644 &prompt_description);
1646 success = e_dbus_source_manager_call_authenticate_sync (
1647 registry->priv->dbus_source_manager, uid,
1648 prompt_title, prompt_message, prompt_description,
1649 out_object_path, cancellable, error);
1651 g_free (prompt_title);
1652 g_free (prompt_message);
1653 g_free (prompt_description);
1655 g_object_unref (source);
1661 * e_source_registry_authenticate_sync:
1662 * @registry: an #ESourceRegistry
1663 * @source: an #ESource
1664 * @auth: an #ESourceAuthenticator
1665 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1666 * @error: return location for a #GError, or %NULL
1668 * Authenticates @source, using @auth to handle the authentication
1669 * attempts. The operation loops until authentication is successful or
1670 * the user aborts further authentication attempts. If an error occurs,
1671 * the function will set @error and return %FALSE.
1673 * Note that @source need not have a #GDBusObject, which means this
1674 * function can test authentication on a scratch #ESource.
1676 * Only backend implementations and data source editors should call this
1677 * function. The intent is for basic client applications to not have to
1678 * deal with authentication at all.
1680 * Returns: %TRUE on success, %FALSE on failure
1685 e_source_registry_authenticate_sync (ESourceRegistry *registry,
1687 ESourceAuthenticator *auth,
1688 GCancellable *cancellable,
1691 AuthContext *auth_context;
1692 GMainContext *main_context;
1693 EDBusAuthenticator *dbus_auth;
1694 gchar *encryption_key;
1695 gchar *object_path = NULL;
1698 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1699 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1700 g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth), FALSE);
1702 /* This extracts authentication prompt details for the ESource
1703 * before initiating an authentication session with the server,
1704 * so split it out of the main algorithm for clarity's sake. */
1705 success = source_registry_call_authenticate_for_source (
1706 registry, auth, source, &object_path, cancellable, error);
1709 g_warn_if_fail (object_path == NULL);
1713 g_return_val_if_fail (object_path != NULL, FALSE);
1715 main_context = g_main_context_new ();
1716 g_main_context_push_thread_default (main_context);
1718 dbus_auth = e_dbus_authenticator_proxy_new_for_bus_sync (
1720 G_DBUS_PROXY_FLAGS_NONE,
1721 SOURCES_DBUS_SERVICE_NAME,
1722 object_path, cancellable, error);
1724 g_free (object_path);
1726 if (dbus_auth == NULL) {
1731 auth_context = g_slice_new0 (AuthContext);
1732 auth_context->auth = g_object_ref (auth);
1733 auth_context->dbus_auth = dbus_auth; /* takes ownership */
1734 auth_context->main_loop = g_main_loop_new (main_context, FALSE);
1735 auth_context->error = error;
1737 /* This just needs to be something other than
1738 * E_SOURCE_AUTHENTICATION_ERROR so we don't trip
1739 * up source_registry_authenticate_dismissed_cb(). */
1740 auth_context->auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
1742 if (G_IS_CANCELLABLE (cancellable))
1743 auth_context->cancellable = g_object_ref (cancellable);
1745 auth_context->secret_exchange =
1746 gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1);
1749 dbus_auth, "authenticate",
1750 G_CALLBACK (source_registry_authenticate_authenticate_cb),
1754 dbus_auth, "dismissed",
1755 G_CALLBACK (source_registry_authenticate_dismissed_cb),
1758 encryption_key = gcr_secret_exchange_begin (
1759 auth_context->secret_exchange);
1761 /* Signal the D-Bus server that we're ready to begin the
1762 * authentication session. This must happen AFTER we've
1763 * connected to the response signal since the server may
1764 * already have a response ready and waiting for us. */
1765 success = e_dbus_authenticator_call_ready_sync (
1766 dbus_auth, encryption_key, cancellable, error);
1768 g_free (encryption_key);
1771 g_main_loop_run (auth_context->main_loop);
1772 success = auth_context->success;
1775 auth_context_free (auth_context);
1778 g_main_context_pop_thread_default (main_context);
1779 g_main_context_unref (main_context);
1785 * e_source_registry_authenticate:
1786 * @registry: an #ESourceRegistry
1787 * @source: an #ESource
1788 * @auth: an #ESourceAuthenticator
1789 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1790 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1792 * @user_data: (closure): data to pass to the callback function
1794 * Asynchronously authenticates @source, using @auth to handle the
1795 * authentication attempts. The operation loops until authentication
1796 * is successful or the user aborts further authentication attempts.
1798 * Note that @source need not have a #GDBusObject, which means this
1799 * function can test authentication on a scratch #ESource.
1801 * When the operation is finished, @callback will be called. You can then
1802 * call e_source_registry_authenticate_finish() to get the result of the
1805 * Only backend implementations and data source editors should call this
1806 * function. The intent is for basic client applications to not have to
1807 * deal with authentication at all.
1812 e_source_registry_authenticate (ESourceRegistry *registry,
1814 ESourceAuthenticator *auth,
1815 GCancellable *cancellable,
1816 GAsyncReadyCallback callback,
1819 GSimpleAsyncResult *simple;
1820 AsyncContext *async_context;
1822 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1823 g_return_if_fail (E_IS_SOURCE (source));
1824 g_return_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth));
1826 async_context = g_slice_new0 (AsyncContext);
1827 async_context->source = g_object_ref (source);
1828 async_context->auth = g_object_ref (auth);
1830 simple = g_simple_async_result_new (
1831 G_OBJECT (registry), callback, user_data,
1832 e_source_registry_authenticate);
1834 g_simple_async_result_set_check_cancellable (simple, cancellable);
1836 g_simple_async_result_set_op_res_gpointer (
1837 simple, async_context, (GDestroyNotify) async_context_free);
1839 g_simple_async_result_run_in_thread (
1840 simple, source_registry_authenticate_thread,
1841 G_PRIORITY_DEFAULT, cancellable);
1843 g_object_unref (simple);
1847 * e_source_registry_authenticate_finish:
1848 * @registry: an #ESourceRegistry
1849 * @result: a #GAsyncResult
1850 * @error: return location for a #GError, or %NULL
1852 * Finishes the operation started with e_source_registry_authenticate().
1853 * If an error occurred, the function will set @error and return %FALSE.
1855 * Returns: %TRUE on success, %FALSE on failure
1860 e_source_registry_authenticate_finish (ESourceRegistry *registry,
1861 GAsyncResult *result,
1864 GSimpleAsyncResult *simple;
1866 g_return_val_if_fail (
1867 g_simple_async_result_is_valid (
1868 result, G_OBJECT (registry),
1869 e_source_registry_authenticate), FALSE);
1871 simple = G_SIMPLE_ASYNC_RESULT (result);
1873 /* Assume success unless a GError is set. */
1874 return !g_simple_async_result_propagate_error (simple, error);
1877 /* Helper for e_source_registry_commit_source() */
1879 source_registry_commit_source_thread (GSimpleAsyncResult *simple,
1881 GCancellable *cancellable)
1883 AsyncContext *async_context;
1884 GError *error = NULL;
1886 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1888 e_source_registry_commit_source_sync (
1889 E_SOURCE_REGISTRY (object),
1890 async_context->source,
1891 cancellable, &error);
1894 g_simple_async_result_take_error (simple, error);
1898 * e_source_registry_commit_source_sync:
1899 * @registry: an #ESourceRegistry
1900 * @source: an #ESource with changes to commit
1901 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1902 * @error: return location for #GError, or %NULL
1904 * This is a convenience function intended for use with graphical
1905 * #ESource editors. Call this function when the user is finished
1906 * making changes to @source.
1908 * If @source has a #GDBusObject, its contents are submitted to the D-Bus
1909 * service through e_source_write_sync().
1911 * If @source does NOT have a #GDBusObject (implying it's a scratch
1912 * #ESource), its contents are submitted to the D-Bus service through
1913 * either e_source_remote_create_sync() if @source is to be a collection
1914 * member, or e_source_registry_create_sources_sync() if @source to be an
1915 * independent data source.
1917 * If an error occurs, the function will set @error and return %FALSE.
1919 * Returns: %TRUE on success, %FALSE on failure
1924 e_source_registry_commit_source_sync (ESourceRegistry *registry,
1926 GCancellable *cancellable,
1929 GDBusObject *dbus_object;
1930 ESource *collection_source;
1931 gboolean collection_member;
1934 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1935 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1937 dbus_object = e_source_ref_dbus_object (source);
1939 collection_source = e_source_registry_find_extension (
1940 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1943 (collection_source != NULL) &&
1944 (collection_source != source);
1946 if (dbus_object != NULL) {
1947 success = e_source_write_sync (source, cancellable, error);
1948 g_object_unref (dbus_object);
1950 } else if (collection_member) {
1951 success = e_source_remote_create_sync (
1952 collection_source, source, cancellable, error);
1955 GList *list = g_list_prepend (NULL, source);
1956 success = e_source_registry_create_sources_sync (
1957 registry, list, cancellable, error);
1961 if (collection_source != NULL)
1962 g_object_unref (collection_source);
1968 * e_source_registry_commit_source:
1969 * @registry: an #ESourceRegistry
1970 * @source: an #ESource with changes to commit
1971 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1972 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1974 * @user_data: (closure): data to pass to the callback function
1976 * See e_source_registry_commit_source_sync() for details.
1978 * When the operation is finished, @callback will be called. You can then
1979 * call e_source_registry_commit_source_finish() to get the result of the
1985 e_source_registry_commit_source (ESourceRegistry *registry,
1987 GCancellable *cancellable,
1988 GAsyncReadyCallback callback,
1991 GSimpleAsyncResult *simple;
1992 AsyncContext *async_context;
1994 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1995 g_return_if_fail (E_IS_SOURCE (source));
1997 async_context = g_slice_new0 (AsyncContext);
1998 async_context->source = g_object_ref (source);
2000 simple = g_simple_async_result_new (
2001 G_OBJECT (registry), callback, user_data,
2002 e_source_registry_commit_source);
2004 g_simple_async_result_set_check_cancellable (simple, cancellable);
2006 g_simple_async_result_set_op_res_gpointer (
2007 simple, async_context, (GDestroyNotify) async_context_free);
2009 g_simple_async_result_run_in_thread (
2010 simple, source_registry_commit_source_thread,
2011 G_PRIORITY_DEFAULT, cancellable);
2013 g_object_unref (simple);
2017 * e_source_registry_commit_source_finish:
2018 * @registry: an #ESourceRegistry
2019 * @result: a #GAsyncResult
2020 * @error: return location for a #GError, or %NULL
2022 * Finishes the operation started with e_source_registry_commit_source().
2024 * If an error occurred, the function will set @error and return %FALSE.
2026 * Returns: %TRUE on success, %FALSE on failure
2031 e_source_registry_commit_source_finish (ESourceRegistry *registry,
2032 GAsyncResult *result,
2035 GSimpleAsyncResult *simple;
2037 g_return_val_if_fail (
2038 g_simple_async_result_is_valid (
2039 result, G_OBJECT (registry),
2040 e_source_registry_commit_source), FALSE);
2042 simple = G_SIMPLE_ASYNC_RESULT (result);
2044 /* Assume success unless a GError is set. */
2045 return !g_simple_async_result_propagate_error (simple, error);
2048 /* Helper for e_source_registry_create_sources() */
2050 source_registry_create_sources_thread (GSimpleAsyncResult *simple,
2052 GCancellable *cancellable)
2054 AsyncContext *async_context;
2055 GError *error = NULL;
2057 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2059 e_source_registry_create_sources_sync (
2060 E_SOURCE_REGISTRY (object),
2061 async_context->list_of_sources,
2062 cancellable, &error);
2065 g_simple_async_result_take_error (simple, error);
2068 /* Helper for e_source_registry_create_sources_sync() */
2070 source_registry_create_sources_main_loop_quit_cb (gpointer user_data)
2072 GMainLoop *main_loop = user_data;
2074 g_main_loop_quit (main_loop);
2079 /* Helper for e_source_registry_create_sources_sync() */
2081 source_registry_create_sources_object_added_cb (GDBusObjectManager *object_manager,
2082 GDBusObject *dbus_object,
2083 CreateContext *create_context)
2085 EDBusObject *e_dbus_object;
2086 EDBusSource *e_dbus_source;
2089 e_dbus_object = E_DBUS_OBJECT (dbus_object);
2090 e_dbus_source = e_dbus_object_get_source (e_dbus_object);
2091 uid = e_dbus_source_get_uid (e_dbus_source);
2093 g_hash_table_remove (create_context->pending_uids, uid);
2095 /* The hash table will be empty when all of the expected
2096 * GDBusObjects have been added to the GDBusObjectManager. */
2097 if (g_hash_table_size (create_context->pending_uids) == 0) {
2098 GSource *idle_source;
2100 idle_source = g_idle_source_new ();
2101 g_source_set_callback (
2103 source_registry_create_sources_main_loop_quit_cb,
2104 g_main_loop_ref (create_context->main_loop),
2105 (GDestroyNotify) g_main_loop_unref);
2106 g_source_attach (idle_source, create_context->main_context);
2107 g_source_unref (idle_source);
2112 * e_source_registry_create_sources_sync:
2113 * @registry: an #ESourceRegistry
2114 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2116 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2117 * @error: return location for a #GError, or %NULL
2119 * Requests the D-Bus service create new key files for each #ESource in
2120 * @list_of_sources. Each list element must be a scratch #ESource with
2123 * If an error occurs, the function will set @error and return %FALSE.
2125 * Returns: %TRUE on success, %FALSE on failure
2130 e_source_registry_create_sources_sync (ESourceRegistry *registry,
2131 GList *list_of_sources,
2132 GCancellable *cancellable,
2135 CreateContext *create_context;
2136 GVariantBuilder builder;
2139 gulong object_added_id;
2142 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2144 /* Verify the list elements are all ESources. */
2145 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2146 g_return_val_if_fail (E_IS_SOURCE (link->data), FALSE);
2148 create_context = create_context_new ();
2149 g_main_context_push_thread_default (create_context->main_context);
2151 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
2153 for (link = list_of_sources; link != NULL; link = g_list_next (link)) {
2158 source = E_SOURCE (link->data);
2159 uid = e_source_dup_uid (source);
2161 /* Takes ownership of the UID string. */
2162 g_hash_table_add (create_context->pending_uids, uid);
2164 source_data = e_source_to_string (source, NULL);
2165 g_variant_builder_add (&builder, "{ss}", uid, source_data);
2166 g_free (source_data);
2169 variant = g_variant_builder_end (&builder);
2171 /* Use G_CONNECT_AFTER so source_registry_object_added_cb()
2172 * runs first and actually adds the ESource to the internal
2173 * hash table before we go quitting our main loop. */
2174 object_added_id = g_signal_connect_after (
2175 registry->priv->dbus_object_manager, "object-added",
2176 G_CALLBACK (source_registry_create_sources_object_added_cb),
2179 /* This function sinks the floating GVariant reference. */
2180 success = e_dbus_source_manager_call_create_sources_sync (
2181 registry->priv->dbus_source_manager,
2182 variant, cancellable, error);
2184 g_variant_builder_clear (&builder);
2186 /* Wait for an "object-added" signal for each created ESource.
2187 * But also set a short timeout to avoid getting stuck here in
2188 * case the registry service adds sources to its orphan table,
2189 * which prevents them from being exported over D-Bus. */
2191 GSource *timeout_source;
2193 timeout_source = g_timeout_source_new_seconds (2);
2194 g_source_set_callback (
2196 source_registry_create_sources_main_loop_quit_cb,
2197 g_main_loop_ref (create_context->main_loop),
2198 (GDestroyNotify) g_main_loop_unref);
2199 g_source_attach (timeout_source, create_context->main_context);
2200 g_source_unref (timeout_source);
2202 g_main_loop_run (create_context->main_loop);
2205 g_signal_handler_disconnect (
2206 registry->priv->dbus_object_manager, object_added_id);
2208 g_main_context_pop_thread_default (create_context->main_context);
2209 create_context_free (create_context);
2215 * e_source_registry_create_sources:
2216 * @registry: an #ESourceRegistry
2217 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2219 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2220 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2222 * @user_data: (closure): data to pass to the callback function
2224 * Asynchronously requests the D-Bus service create new key files for each
2225 * #ESource in @list_of_sources. Each list element must be a scratch
2226 * #ESource with no #GDBusObject.
2228 * When the operation is finished, @callback will be called. You can then
2229 * call e_source_registry_create_sources_finish() to get the result of the
2235 e_source_registry_create_sources (ESourceRegistry *registry,
2236 GList *list_of_sources,
2237 GCancellable *cancellable,
2238 GAsyncReadyCallback callback,
2241 GSimpleAsyncResult *simple;
2242 AsyncContext *async_context;
2245 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2247 /* Verify the list elements are all ESources. */
2248 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2249 g_return_if_fail (E_IS_SOURCE (link->data));
2251 async_context = g_slice_new0 (AsyncContext);
2252 async_context->list_of_sources = g_list_copy (list_of_sources);
2255 async_context->list_of_sources,
2256 (GFunc) g_object_ref, NULL);
2258 simple = g_simple_async_result_new (
2259 G_OBJECT (registry), callback, user_data,
2260 e_source_registry_create_sources);
2262 g_simple_async_result_set_check_cancellable (simple, cancellable);
2264 g_simple_async_result_set_op_res_gpointer (
2265 simple, async_context, (GDestroyNotify) async_context_free);
2267 g_simple_async_result_run_in_thread (
2268 simple, source_registry_create_sources_thread,
2269 G_PRIORITY_DEFAULT, cancellable);
2271 g_object_unref (simple);
2275 * e_source_registry_create_sources_finish:
2276 * @registry: an #ESourceRegistry
2277 * @result: a #GAsyncResult
2278 * @error: return location for a #GError, or %NULL
2280 * Finishes the operation started with e_source_registry_create_sources().
2282 * If an error occurred, the function will set @error and return %FALSE.
2284 * Returns: %TRUE on success, %FALSE on failure
2289 e_source_registry_create_sources_finish (ESourceRegistry *registry,
2290 GAsyncResult *result,
2293 GSimpleAsyncResult *simple;
2295 g_return_val_if_fail (
2296 g_simple_async_result_is_valid (
2297 result, G_OBJECT (registry),
2298 e_source_registry_create_sources), FALSE);
2300 simple = G_SIMPLE_ASYNC_RESULT (result);
2302 /* Assume success unless a GError is set. */
2303 return !g_simple_async_result_propagate_error (simple, error);
2307 * e_source_registry_ref_source:
2308 * @registry: an #ESourceRegistry
2309 * @uid: a unique identifier string
2311 * Looks up an #ESource in @registry by its unique identifier string.
2313 * The returned #ESource is referenced for thread-safety and must be
2314 * unreferenced with g_object_unref() when finished with it.
2316 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2321 e_source_registry_ref_source (ESourceRegistry *registry,
2324 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2325 g_return_val_if_fail (uid != NULL, NULL);
2327 return source_registry_sources_lookup (registry, uid);
2331 * e_source_registry_list_sources:
2332 * @registry: an #ESourceRegistry
2333 * @extension_name: (allow-none): an extension name, or %NULL
2335 * Returns a list of registered sources, sorted by display name. If
2336 * @extension_name is given, restrict the list to sources having that
2339 * The sources returned in the list are referenced for thread-safety.
2340 * They must each be unreferenced with g_object_unref() when finished
2341 * when them. Free the returned list itself with g_list_free().
2343 * An easy way to free the list properly in one step is as follows:
2346 * g_list_free_full (list, g_object_unref);
2349 * Returns: (element-type ESource) (transfer full): a sorted list of sources
2354 e_source_registry_list_sources (ESourceRegistry *registry,
2355 const gchar *extension_name)
2358 GQueue trash = G_QUEUE_INIT;
2360 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2362 list = g_list_sort (
2363 source_registry_sources_get_values (registry),
2364 (GCompareFunc) e_source_compare_by_display_name);
2366 if (extension_name == NULL)
2369 for (link = list; link != NULL; link = g_list_next (link)) {
2370 ESource *source = E_SOURCE (link->data);
2372 if (!e_source_has_extension (source, extension_name)) {
2373 g_queue_push_tail (&trash, link);
2374 g_object_unref (source);
2378 /* We do want pop_head() here, not pop_head_link(). */
2379 while ((link = g_queue_pop_head (&trash)) != NULL)
2380 list = g_list_delete_link (list, link);
2386 * e_source_registry_check_enabled:
2387 * @registry: an #ESourceRegistry
2388 * @source: an #ESource
2390 * Determines whether @source is "effectively" enabled by examining its
2391 * own #ESource:enabled property as well as those of its ancestors in the
2392 * #ESource hierarchy. If all examined #ESource:enabled properties are
2393 * %TRUE, then the function returns %TRUE. If any are %FALSE, then the
2394 * function returns %FALSE.
2396 * Use this function instead of e_source_get_enabled() to determine
2397 * things like whether to display an #ESource in a user interface or
2398 * whether to act on the data set described by the #ESource.
2400 * Returns: whether @source is "effectively" enabled
2405 e_source_registry_check_enabled (ESourceRegistry *registry,
2411 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2412 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2414 enabled = e_source_get_enabled (source);
2415 parent_uid = e_source_dup_parent (source);
2417 while (enabled && parent_uid != NULL) {
2420 parent = e_source_registry_ref_source (registry, parent_uid);
2422 g_free (parent_uid);
2425 if (parent != NULL) {
2426 enabled = e_source_get_enabled (parent);
2427 parent_uid = e_source_dup_parent (parent);
2428 g_object_unref (parent);
2432 g_free (parent_uid);
2438 * e_source_registry_find_extension:
2439 * @registry: an #ESourceRegistry
2440 * @source: an #ESource
2441 * @extension_name: the extension name to find
2443 * Examines @source and its ancestors and returns the "deepest" #ESource
2444 * having an #ESourceExtension with the given @extension_name. If neither
2445 * @source nor any of its ancestors have such an extension, the function
2448 * This function is useful in cases when an #ESourceExtension is meant to
2449 * apply to both the #ESource it belongs to and the #ESource's descendants.
2451 * A common example is the #ESourceCollection extension, where descendants
2452 * of an #ESource having an #ESourceCollection extension are implied to be
2453 * members of that collection. In that example, this function can be used
2454 * to test whether @source is a member of a collection.
2456 * The returned #ESource is referenced for thread-safety and must be
2457 * unreferenced with g_object_unref() when finished with it.
2459 * Note the function returns the #ESource containing the #ESourceExtension
2460 * instead of the #ESourceExtension itself because extension instances are
2461 * not to be referenced directly (see e_source_get_extension()).
2463 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2468 e_source_registry_find_extension (ESourceRegistry *registry,
2470 const gchar *extension_name)
2472 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2473 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2474 g_return_val_if_fail (extension_name != NULL, NULL);
2476 g_object_ref (source);
2478 while (!e_source_has_extension (source, extension_name)) {
2481 uid = e_source_dup_parent (source);
2483 g_object_unref (source);
2487 source = e_source_registry_ref_source (registry, uid);
2498 /* Helper for e_source_registry_build_display_tree() */
2500 source_registry_compare_nodes (GNode *node_a,
2503 ESource *source_a = E_SOURCE (node_a->data);
2504 ESource *source_b = E_SOURCE (node_b->data);
2505 const gchar *uid_a, *uid_b;
2507 uid_a = e_source_get_uid (source_a);
2508 uid_b = e_source_get_uid (source_b);
2510 /* Sanity check, with runtime warnings. */
2511 if (uid_a == NULL) {
2512 g_warn_if_reached ();
2515 if (uid_b == NULL) {
2516 g_warn_if_reached ();
2520 /* The built-in "local-stub" source comes first at depth 1. */
2522 if (g_strcmp0 (uid_a, "local-stub") == 0)
2525 if (g_strcmp0 (uid_b, "local-stub") == 0)
2528 /* The built-in "system-*" sources come first at depth 2. */
2530 if (g_str_has_prefix (uid_a, "system-"))
2533 if (g_str_has_prefix (uid_b, "system-"))
2536 return e_source_compare_by_display_name (source_a, source_b);
2539 /* Helper for e_source_registry_build_display_tree() */
2541 source_registry_prune_nodes (GNode *node,
2542 const gchar *extension_name)
2544 GQueue queue = G_QUEUE_INIT;
2547 /* Unlink all the child nodes and place them in a queue. */
2548 while ((child_node = g_node_first_child (node)) != NULL) {
2549 g_node_unlink (child_node);
2550 g_queue_push_tail (&queue, child_node);
2553 /* Sort the queue by source name. */
2555 &queue, (GCompareDataFunc)
2556 source_registry_compare_nodes, NULL);
2558 /* Pop nodes off the head of the queue until the queue is empty.
2559 * If the node has either its own children or the given extension
2560 * name, put it back under the parent node (preserving the sorted
2561 * order). Otherwise delete the node and its descendants. */
2562 while ((child_node = g_queue_pop_head (&queue)) != NULL) {
2563 ESource *child = E_SOURCE (child_node->data);
2564 gboolean append_child_node = FALSE;
2566 if (extension_name == NULL)
2567 append_child_node = e_source_get_enabled (child);
2569 else if (e_source_has_extension (child, extension_name))
2570 append_child_node = e_source_get_enabled (child);
2572 else if (g_node_first_child (child_node) != NULL)
2573 append_child_node = e_source_get_enabled (child);
2575 if (append_child_node)
2576 g_node_append (node, child_node);
2578 e_source_registry_free_display_tree (child_node);
2585 * e_source_registry_build_display_tree:
2586 * @registry: an #ESourceRegistry
2587 * @extension_name: (allow-none): an extension name, or %NULL
2589 * Returns a single #GNode tree of registered sources that can be used to
2590 * populate a #GtkTreeModel. (The root #GNode is just an empty placeholder.)
2592 * Similar to e_source_registry_list_sources(), an @extension_name can be
2593 * given to restrict the tree to sources having that extension name. Parents
2594 * of matched sources are included in the tree regardless of whether they have
2595 * an extension named @extension_name.
2597 * Disabled leaf nodes are automatically excluded from the #GNode tree.
2599 * The sources returned in the tree are referenced for thread-safety.
2600 * They must each be unreferenced with g_object_unref() when finished
2601 * with them. Free the returned tree itself with g_node_destroy().
2602 * For convenience, e_source_registry_free_display_tree() does all
2605 * Returns: (element-type ESource) (transfer full): a tree of sources,
2606 * arranged for display
2611 e_source_registry_build_display_tree (ESourceRegistry *registry,
2612 const gchar *extension_name)
2616 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2618 /* Assemble all data sources into a tree. */
2619 root = source_registry_sources_build_tree (registry);
2621 /* Prune unwanted nodes from the copied source trees.
2622 * This must be done in "post" order (children first)
2623 * since it reorders and deletes child nodes. */
2625 root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
2626 (GNodeTraverseFunc) source_registry_prune_nodes,
2627 (gpointer) extension_name);
2632 /* Helper for e_source_registry_free_display_tree() */
2634 source_registry_unref_nodes (GNode *node)
2636 while (node != NULL) {
2637 if (node->children != NULL)
2638 source_registry_unref_nodes (node->children);
2639 if (node->data != NULL)
2640 g_object_unref (node->data);
2646 * e_source_registry_free_display_tree:
2647 * @display_tree: a tree of sources, arranged for display
2649 * Convenience function to free a #GNode tree of registered
2650 * sources created by e_source_registry_build_display_tree().
2655 e_source_registry_free_display_tree (GNode *display_tree)
2657 g_return_if_fail (display_tree != NULL);
2659 /* XXX This would be easier if GLib had something like
2660 * g_node_destroy_full() which took a GDestroyNotify.
2661 * Then the tree would not have to be traversed twice. */
2663 source_registry_unref_nodes (display_tree);
2664 g_node_destroy (display_tree);
2667 /* Helper for e_source_registry_debug_dump() */
2669 source_registry_debug_dump_cb (GNode *node)
2673 /* Root node is an empty placeholder. */
2674 if (G_NODE_IS_ROOT (node))
2677 depth = g_node_depth (node);
2678 for (ii = 2; ii < depth; ii++)
2681 if (E_IS_SOURCE (node->data)) {
2682 ESource *source = E_SOURCE (node->data);
2683 g_print ("\"%s\" ", e_source_get_display_name (source));
2684 g_print ("(%s)", e_source_get_uid (source));
2693 * e_source_registry_debug_dump:
2694 * @registry: an #ESourceRegistry
2695 * @extension_name: (allow-none): an extension name, or %NULL
2697 * Handy debugging function that uses e_source_registry_build_display_tree()
2698 * to print a tree of registered sources to standard output.
2703 e_source_registry_debug_dump (ESourceRegistry *registry,
2704 const gchar *extension_name)
2708 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2710 root = e_source_registry_build_display_tree (registry, extension_name);
2713 root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2714 (GNodeTraverseFunc) source_registry_debug_dump_cb, NULL);
2716 e_source_registry_free_display_tree (root);
2720 * e_source_registry_ref_builtin_address_book:
2721 * @registry: an #ESourceRegistry
2723 * Returns the built-in address book #ESource.
2725 * This #ESource is always present and makes for a safe fallback.
2727 * The returned #ESource is referenced for thread-safety and must be
2728 * unreferenced with g_object_unref() when finished with it.
2730 * Returns: (transfer full): the built-in address book #ESource
2735 e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
2740 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2742 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2743 source = e_source_registry_ref_source (registry, uid);
2744 g_return_val_if_fail (source != NULL, NULL);
2750 * e_source_registry_ref_default_address_book:
2751 * @registry: an #ESourceRegistry
2753 * Returns the #ESource most recently passed to
2754 * e_source_registry_set_default_address_book() either in this session
2755 * or a previous session, or else falls back to the built-in address book.
2757 * The returned #ESource is referenced for thread-safety and must be
2758 * unreferenced with g_object_unref() when finished with it.
2760 * Returns: (transfer full): the default address book #ESource
2765 e_source_registry_ref_default_address_book (ESourceRegistry *registry)
2771 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2773 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2774 uid = g_settings_get_string (registry->priv->settings, key);
2775 source = e_source_registry_ref_source (registry, uid);
2778 /* The built-in source is always present. */
2780 source = e_source_registry_ref_builtin_address_book (registry);
2782 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2788 * e_source_registry_set_default_address_book:
2789 * @registry: an #ESourceRegistry
2790 * @default_source: (allow-none): an address book #ESource, or %NULL
2792 * Sets @default_source as the default address book. If @default_source
2793 * is %NULL, the default address book is reset to the built-in address book.
2794 * This setting will persist across sessions until changed.
2799 e_source_registry_set_default_address_book (ESourceRegistry *registry,
2800 ESource *default_source)
2805 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2807 if (default_source != NULL) {
2808 g_return_if_fail (E_IS_SOURCE (default_source));
2809 uid = e_source_get_uid (default_source);
2811 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2814 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2815 g_settings_set_string (registry->priv->settings, key, uid);
2817 /* The GSettings::changed signal will trigger a "notify" signal
2818 * from the registry, so no need to call g_object_notify() here. */
2822 * e_source_registry_ref_builtin_calendar:
2823 * @registry: an #ESourceRegistry
2825 * Returns the built-in calendar #ESource.
2827 * This #ESource is always present and makes for a safe fallback.
2829 * The returned #ESource is referenced for thread-safety and must be
2830 * unreferenced with g_object_unref() when finished with it.
2832 * Returns: (transfer full): the built-in calendar #ESource
2837 e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
2842 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2844 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2845 source = e_source_registry_ref_source (registry, uid);
2846 g_return_val_if_fail (source != NULL, NULL);
2852 * e_source_registry_ref_default_calendar:
2853 * @registry: an #ESourceRegistry
2855 * Returns the #ESource most recently passed to
2856 * e_source_registry_set_default_calendar() either in this session
2857 * or a previous session, or else falls back to the built-in calendar.
2859 * The returned #ESource is referenced for thread-safety and must be
2860 * unreferenced with g_object_unref() when finished with it.
2862 * Returns: (transfer full): the default calendar #ESource
2867 e_source_registry_ref_default_calendar (ESourceRegistry *registry)
2873 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2875 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2876 uid = g_settings_get_string (registry->priv->settings, key);
2877 source = e_source_registry_ref_source (registry, uid);
2880 /* The built-in source is always present. */
2882 source = e_source_registry_ref_builtin_calendar (registry);
2884 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2890 * e_source_registry_set_default_calendar:
2891 * @registry: an #ESourceRegistry
2892 * @default_source: (allow-none): a calendar #ESource, or %NULL
2894 * Sets @default_source as the default calendar. If @default_source
2895 * is %NULL, the default calendar is reset to the built-in calendar.
2896 * This setting will persist across sessions until changed.
2901 e_source_registry_set_default_calendar (ESourceRegistry *registry,
2902 ESource *default_source)
2907 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2909 if (default_source != NULL) {
2910 g_return_if_fail (E_IS_SOURCE (default_source));
2911 uid = e_source_get_uid (default_source);
2913 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2916 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2917 g_settings_set_string (registry->priv->settings, key, uid);
2919 /* The GSettings::changed signal will trigger a "notify" signal
2920 * from the registry, so no need to call g_object_notify() here. */
2924 * e_source_registry_ref_builtin_mail_account:
2925 * @registry: an #ESourceRegistry
2927 * Returns the built-in mail account #ESource.
2929 * This #ESource is always present and makes for a safe fallback.
2931 * The returned #ESource is referenced for thread-safety and must be
2932 * unreferenced with g_object_unref() when finished with it.
2934 * Returns: (transfer full): the built-in mail account #ESource
2939 e_source_registry_ref_builtin_mail_account (ESourceRegistry *registry)
2944 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2946 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2947 source = e_source_registry_ref_source (registry, uid);
2948 g_return_val_if_fail (source != NULL, NULL);
2954 * e_source_registry_ref_default_mail_account:
2955 * @registry: an #ESourceRegistry
2957 * Returns the #ESource most recently passed to
2958 * e_source_registry_set_default_mail_account() either in this session
2959 * or a previous session, or else falls back to the built-in mail account.
2961 * The returned #ESource is referenced for thread-safety and must be
2962 * unreferenced with g_object_unref() when finished with it.
2964 * Returns: (transfer full): the default mail account #ESource
2969 e_source_registry_ref_default_mail_account (ESourceRegistry *registry)
2975 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2977 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2978 uid = g_settings_get_string (registry->priv->settings, key);
2979 source = e_source_registry_ref_source (registry, uid);
2982 /* The built-in source is always present. */
2984 source = e_source_registry_ref_builtin_mail_account (registry);
2986 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2992 * e_source_registry_set_default_mail_account:
2993 * @registry: an #ESourceRegistry
2994 * @default_source: (allow-none): a mail account #ESource, or %NULL
2996 * Sets @default_source as the default mail account. If @default_source
2997 * is %NULL, the default mail account is reset to the built-in mail account.
2998 * This setting will persist across sessions until changed.
3003 e_source_registry_set_default_mail_account (ESourceRegistry *registry,
3004 ESource *default_source)
3009 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3011 if (default_source != NULL) {
3012 g_return_if_fail (E_IS_SOURCE (default_source));
3013 uid = e_source_get_uid (default_source);
3015 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
3018 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
3019 g_settings_set_string (registry->priv->settings, key, uid);
3021 /* The GSettings::changed signal will trigger a "notify" signal
3022 * from the registry, so no need to call g_object_notify() here. */
3025 /* Helper for e_source_registry_ref_default_mail_identity() */
3027 source_registry_ref_any_mail_identity (ESourceRegistry *registry)
3031 const gchar *extension_name;
3034 /* First fallback: Return the mail identity named
3035 * by the default mail account. */
3037 source = e_source_registry_ref_default_mail_account (registry);
3039 /* This should never be NULL, but just to be safe. */
3040 if (source != NULL) {
3041 ESourceMailAccount *extension;
3043 extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
3044 extension = e_source_get_extension (source, extension_name);
3045 uid = e_source_mail_account_dup_identity_uid (extension);
3047 g_object_unref (source);
3052 source = e_source_registry_ref_source (registry, uid);
3059 /* Second fallback: Pick any available mail identity,
3060 * preferring enabled identities. */
3062 extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
3063 list = e_source_registry_list_sources (registry, extension_name);
3065 for (link = list; link != NULL; link = g_list_next (link)) {
3066 ESource *candidate = E_SOURCE (link->data);
3068 if (e_source_registry_check_enabled (registry, candidate)) {
3069 source = g_object_ref (candidate);
3074 if (source == NULL && list != NULL)
3075 source = g_object_ref (list->data);
3077 g_list_free_full (list, (GDestroyNotify) g_object_unref);
3083 * e_source_registry_ref_default_mail_identity:
3084 * @registry: an #ESourceRegistry
3086 * Returns the #ESource most recently passed to
3087 * e_source_registry_set_default_mail_identity() either in this session
3088 * or a previous session, or else falls back to the mail identity named
3089 * by the default mail account. If even that fails it returns any mail
3090 * identity from @registry, or %NULL if there are none.
3092 * The returned #ESource is referenced for thread-safety and must be
3093 * unreferenced with g_object_unref() when finished with it.
3095 * Returns: (transfer full): the default mail identity #ESource, or %NULL
3100 e_source_registry_ref_default_mail_identity (ESourceRegistry *registry)
3106 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3108 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
3109 uid = g_settings_get_string (registry->priv->settings, key);
3110 source = e_source_registry_ref_source (registry, uid);
3114 source = source_registry_ref_any_mail_identity (registry);
3120 * e_source_registry_set_default_mail_identity:
3121 * @registry: an #ESourceRegistry
3122 * @default_source: (allow-none): a mail identity #ESource, or %NULL
3124 * Sets @default_source as the default mail identity. If @default_source
3125 * is %NULL, the next request for the default mail identity will use the
3126 * fallbacks described in e_source_registry_get_default_mail_identity().
3131 e_source_registry_set_default_mail_identity (ESourceRegistry *registry,
3132 ESource *default_source)
3137 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3139 if (default_source != NULL) {
3140 g_return_if_fail (E_IS_SOURCE (default_source));
3141 uid = e_source_get_uid (default_source);
3143 uid = ""; /* no built-in mail identity */
3146 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
3147 g_settings_set_string (registry->priv->settings, key, uid);
3149 /* The GSettings::changed signal will trigger a "notify" signal
3150 * from the registry, so no need to call g_object_notify() here. */
3154 * e_source_registry_ref_builtin_memo_list:
3155 * @registry: an #ESourceRegistry
3157 * Returns the built-in memo list #ESource.
3159 * This #ESource is always present and makes for a safe fallback.
3161 * The returned #ESource is referenced for thread-safety and must be
3162 * unreferenced with g_object_unref() when finished with it.
3164 * Returns: (transfer full): the built-in memo list #ESource
3169 e_source_registry_ref_builtin_memo_list (ESourceRegistry *registry)
3174 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3176 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3177 source = e_source_registry_ref_source (registry, uid);
3178 g_return_val_if_fail (source != NULL, NULL);
3184 * e_source_registry_ref_default_memo_list:
3185 * @registry: an #ESourceRegistry
3187 * Returns the #ESource most recently passed to
3188 * e_source_registry_set_default_memo_list() either in this session
3189 * or a previous session, or else falls back to the built-in memo list.
3191 * The returned #ESource is referenced for thread-safety and must be
3192 * unreferenced with g_object_unref() when finished with it.
3194 * Returns: (transfer full): the default memo list #ESource
3199 e_source_registry_ref_default_memo_list (ESourceRegistry *registry)
3205 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3207 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3208 uid = g_settings_get_string (registry->priv->settings, key);
3209 source = e_source_registry_ref_source (registry, uid);
3212 /* The built-in source is always present. */
3214 source = e_source_registry_ref_builtin_memo_list (registry);
3216 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3222 * e_source_registry_set_default_memo_list:
3223 * @registry: an #ESourceRegistry
3224 * @default_source: (allow-none): a memo list #ESource, or %NULL
3226 * Sets @default_source as the default memo list. If @default_source
3227 * is %NULL, the default memo list is reset to the built-in memo list.
3228 * This setting will persist across sessions until changed.
3233 e_source_registry_set_default_memo_list (ESourceRegistry *registry,
3234 ESource *default_source)
3239 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3241 if (default_source != NULL) {
3242 g_return_if_fail (E_IS_SOURCE (default_source));
3243 uid = e_source_get_uid (default_source);
3245 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3248 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3249 g_settings_set_string (registry->priv->settings, key, uid);
3251 /* The GSettings::changed signal will trigger a "notify" signal
3252 * from the registry, so no need to call g_object_notify() here. */
3256 * e_source_registry_ref_builtin_task_list:
3257 * @registry: an #ESourceRegistry
3259 * Returns the built-in task list #ESource.
3261 * This #ESource is always present and makes for a safe fallback.
3263 * The returned #ESource is referenced for thread-safety and must be
3264 * unreferenced with g_object_unref() when finished with it.
3266 * Returns: (transfer full): the built-in task list #ESource
3271 e_source_registry_ref_builtin_task_list (ESourceRegistry *registry)
3276 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3278 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3279 source = e_source_registry_ref_source (registry, uid);
3280 g_return_val_if_fail (source != NULL, NULL);
3286 * e_source_registry_ref_default_task_list:
3287 * @registry: an #ESourceRegistry
3289 * Returns the #ESource most recently passed to
3290 * e_source_registry_set_default_task_list() either in this session
3291 * or a previous session, or else falls back to the built-in task list.
3293 * The returned #ESource is referenced for thread-safety and must be
3294 * unreferenced with g_object_unref() when finished with it.
3296 * Returns: (transfer full): the default task list #ESource
3301 e_source_registry_ref_default_task_list (ESourceRegistry *registry)
3307 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3309 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3310 uid = g_settings_get_string (registry->priv->settings, key);
3311 source = e_source_registry_ref_source (registry, uid);
3314 /* The built-in source is always present. */
3316 source = e_source_registry_ref_builtin_task_list (registry);
3318 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3324 * e_source_registry_set_default_task_list:
3325 * @registry: an #ESourceRegistry
3326 * @default_source: (allow-none): a task list #ESource, or %NULL
3328 * Sets @default_source as the default task list. If @default_source
3329 * is %NULL, the default task list is reset to the built-in task list.
3330 * This setting will persist across sessions until changed.
3335 e_source_registry_set_default_task_list (ESourceRegistry *registry,
3336 ESource *default_source)
3341 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3343 if (default_source != NULL) {
3344 g_return_if_fail (E_IS_SOURCE (default_source));
3345 uid = e_source_get_uid (default_source);
3347 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3350 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3351 g_settings_set_string (registry->priv->settings, key, uid);
3353 /* The GSettings::changed signal will trigger a "notify" signal
3354 * from the registry, so no need to call g_object_notify() here. */
3358 * e_source_registry_ref_default_for_extension_name:
3359 * @registry: an #ESourceRegistry
3360 * @extension_name: an extension_name
3362 * This is a convenience function to return a default #ESource based on
3363 * @extension_name. This only works with a subset of extension names.
3365 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3366 * returns the current default address book, or else falls back to the
3367 * built-in address book.
3369 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function returns
3370 * the current default calendar, or else falls back to the built-in calendar.
3372 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3373 * returns the current default mail account, or else falls back to the
3374 * built-in mail account.
3376 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3377 * returns the current default mail identity, or else falls back to the
3378 * mail identity named by the current default mail account.
3380 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function returns
3381 * the current default memo list, or else falls back to the built-in memo list.
3383 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function returns
3384 * the current default task list, or else falls back to the built-in task list.
3386 * For all other values of @extension_name, the function returns %NULL.
3388 * The returned #ESource is referenced for thread-safety and must be
3389 * unreferenced with g_object_unref() when finished with it.
3391 * Returns: (transfer full): the default #ESource based on @extension_name
3396 e_source_registry_ref_default_for_extension_name (ESourceRegistry *registry,
3397 const gchar *extension_name)
3399 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3400 g_return_val_if_fail (extension_name != NULL, NULL);
3402 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3403 return e_source_registry_ref_default_address_book (registry);
3405 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3406 return e_source_registry_ref_default_calendar (registry);
3408 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3409 return e_source_registry_ref_default_mail_account (registry);
3411 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3412 return e_source_registry_ref_default_mail_identity (registry);
3414 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3415 return e_source_registry_ref_default_memo_list (registry);
3417 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3418 return e_source_registry_ref_default_task_list (registry);
3424 * e_source_registry_set_default_for_extension_name:
3425 * @registry: an #ESourceRegistry
3426 * @extension_name: an extension name
3427 * @default_source: (allow-none): an #ESource, or %NULL
3429 * This is a convenience function to set a default #ESource based on
3430 * @extension_name. This only works with a subset of extension names.
3432 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3433 * sets @default_source as the default address book. If @default_source
3434 * is %NULL, the default address book is reset to the built-in address book.
3436 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function sets
3437 * @default_source as the default calendar. If @default_source is %NULL,
3438 * the default calendar is reset to the built-in calendar.
3440 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3441 * sets @default_source as the default mail account. If @default_source
3442 * is %NULL, the default mail account is reset to the built-in mail account.
3444 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3445 * sets @default_source as the default mail identity. If @default_source
3446 * is %NULL, the next request for the default mail identity will return
3447 * the mail identity named by the default mail account.
3449 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function sets
3450 * @default_source as the default memo list. If @default_source is %NULL,
3451 * the default memo list is reset to the built-in memo list.
3453 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function sets
3454 * @default_source as the default task list. If @default_source is %NULL,
3455 * the default task list is reset to the built-in task list.
3457 * For all other values of @extension_name, the function does nothing.
3462 e_source_registry_set_default_for_extension_name (ESourceRegistry *registry,
3463 const gchar *extension_name,
3464 ESource *default_source)
3466 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3467 g_return_if_fail (extension_name != NULL);
3469 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3470 e_source_registry_set_default_address_book (
3471 registry, default_source);
3473 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3474 e_source_registry_set_default_calendar (
3475 registry, default_source);
3477 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3478 e_source_registry_set_default_mail_account (
3479 registry, default_source);
3481 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3482 e_source_registry_set_default_mail_identity (
3483 registry, default_source);
3485 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3486 e_source_registry_set_default_memo_list (
3487 registry, default_source);
3489 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3490 e_source_registry_set_default_task_list (
3491 registry, default_source);