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 _SourceClosure SourceClosure;
99 typedef struct _ThreadClosure ThreadClosure;
101 struct _ESourceRegistryPrivate {
102 GMainContext *main_context;
104 GThread *manager_thread;
105 ThreadClosure *thread_closure;
107 GDBusObjectManager *dbus_object_manager;
108 EDBusSourceManager *dbus_source_manager;
110 GHashTable *object_path_table;
111 GMutex *object_path_table_lock;
114 GMutex *sources_lock;
119 struct _AsyncContext {
121 GList *list_of_sources;
122 ESourceAuthenticator *auth;
125 /* Used in e_source_registry_authenticate_sync() */
126 struct _AuthContext {
127 ESourceAuthenticator *auth;
128 EDBusAuthenticator *dbus_auth;
129 GCancellable *cancellable;
130 GMainLoop *main_loop;
131 ESourceAuthenticationResult auth_result;
132 GcrSecretExchange *secret_exchange;
133 gboolean authenticating;
138 struct _SourceClosure {
139 ESourceRegistry *registry;
143 struct _ThreadClosure {
144 ESourceRegistry *registry;
145 GMainContext *main_context;
146 GMainLoop *main_loop;
147 GCond *main_loop_cond;
148 GMutex *main_loop_mutex;
153 PROP_DEFAULT_ADDRESS_BOOK,
154 PROP_DEFAULT_CALENDAR,
155 PROP_DEFAULT_MAIL_ACCOUNT,
156 PROP_DEFAULT_MAIL_IDENTITY,
157 PROP_DEFAULT_MEMO_LIST,
158 PROP_DEFAULT_TASK_LIST
170 /* Forward Declarations */
171 static void source_registry_add_source (ESourceRegistry *registry,
173 static void e_source_registry_initable_init (GInitableIface *interface);
175 static guint signals[LAST_SIGNAL];
177 /* By default, the GAsyncInitable interface calls GInitable.init()
178 * from a separate thread, so we only have to override GInitable. */
179 G_DEFINE_TYPE_WITH_CODE (
183 G_IMPLEMENT_INTERFACE (
184 G_TYPE_INITABLE, e_source_registry_initable_init)
185 G_IMPLEMENT_INTERFACE (
186 G_TYPE_ASYNC_INITABLE, NULL))
189 async_context_free (AsyncContext *async_context)
191 if (async_context->source != NULL)
192 g_object_unref (async_context->source);
195 async_context->list_of_sources,
196 (GDestroyNotify) g_object_unref);
198 if (async_context->auth != NULL)
199 g_object_unref (async_context->auth);
201 g_slice_free (AsyncContext, async_context);
205 auth_context_free (AuthContext *auth_context)
207 if (auth_context->auth != NULL)
208 g_object_unref (auth_context->auth);
210 if (auth_context->dbus_auth != NULL)
211 g_object_unref (auth_context->dbus_auth);
213 if (auth_context->cancellable != NULL)
214 g_object_unref (auth_context->cancellable);
216 if (auth_context->main_loop != NULL)
217 g_main_loop_unref (auth_context->main_loop);
219 if (auth_context->secret_exchange != NULL)
220 g_object_unref (auth_context->secret_exchange);
222 g_slice_free (AuthContext, auth_context);
226 source_closure_free (SourceClosure *closure)
228 g_object_unref (closure->registry);
229 g_object_unref (closure->source);
231 g_slice_free (SourceClosure, closure);
235 thread_closure_free (ThreadClosure *closure)
237 /* The registry member is not referenced. */
239 g_main_context_unref (closure->main_context);
240 g_main_loop_unref (closure->main_loop);
241 g_cond_free (closure->main_loop_cond);
242 g_mutex_free (closure->main_loop_mutex);
244 g_slice_free (ThreadClosure, closure);
248 source_registry_object_path_table_insert (ESourceRegistry *registry,
249 const gchar *object_path,
252 g_return_if_fail (object_path != NULL);
253 g_return_if_fail (E_IS_SOURCE (source));
255 g_mutex_lock (registry->priv->object_path_table_lock);
257 g_hash_table_insert (
258 registry->priv->object_path_table,
259 g_strdup (object_path),
260 g_object_ref (source));
262 g_mutex_unlock (registry->priv->object_path_table_lock);
266 source_registry_object_path_table_lookup (ESourceRegistry *registry,
267 const gchar *object_path)
271 g_return_val_if_fail (object_path != NULL, NULL);
273 g_mutex_lock (registry->priv->object_path_table_lock);
275 source = g_hash_table_lookup (
276 registry->priv->object_path_table, object_path);
278 g_object_ref (source);
280 g_mutex_unlock (registry->priv->object_path_table_lock);
286 source_registry_object_path_table_remove (ESourceRegistry *registry,
287 const gchar *object_path)
291 g_return_val_if_fail (object_path != NULL, FALSE);
293 g_mutex_lock (registry->priv->object_path_table_lock);
295 removed = g_hash_table_remove (
296 registry->priv->object_path_table, object_path);
298 g_mutex_unlock (registry->priv->object_path_table_lock);
304 source_registry_sources_insert (ESourceRegistry *registry,
309 uid = e_source_get_uid (source);
310 g_return_if_fail (uid != NULL);
312 g_mutex_lock (registry->priv->sources_lock);
314 g_hash_table_insert (
315 registry->priv->sources,
316 g_strdup (uid), g_object_ref (source));
318 g_mutex_unlock (registry->priv->sources_lock);
322 source_registry_sources_remove (ESourceRegistry *registry,
328 uid = e_source_get_uid (source);
329 g_return_val_if_fail (uid != NULL, FALSE);
331 g_mutex_lock (registry->priv->sources_lock);
333 removed = g_hash_table_remove (registry->priv->sources, uid);
335 g_mutex_unlock (registry->priv->sources_lock);
341 source_registry_sources_lookup (ESourceRegistry *registry,
346 g_return_val_if_fail (uid != NULL, NULL);
348 g_mutex_lock (registry->priv->sources_lock);
350 source = g_hash_table_lookup (registry->priv->sources, uid);
353 g_object_ref (source);
355 g_mutex_unlock (registry->priv->sources_lock);
361 source_registry_sources_get_values (ESourceRegistry *registry)
365 g_mutex_lock (registry->priv->sources_lock);
367 values = g_hash_table_get_values (registry->priv->sources);
369 g_list_foreach (values, (GFunc) g_object_ref, NULL);
371 g_mutex_unlock (registry->priv->sources_lock);
377 source_registry_sources_build_tree (ESourceRegistry *registry)
384 g_mutex_lock (registry->priv->sources_lock);
386 root = g_node_new (NULL);
387 index = g_hash_table_new (g_str_hash, g_str_equal);
389 /* Add a GNode for each ESource to the index. */
390 g_hash_table_iter_init (&iter, registry->priv->sources);
391 while (g_hash_table_iter_next (&iter, &key, &value)) {
392 ESource *source = g_object_ref (value);
393 g_hash_table_insert (index, key, g_node_new (source));
396 /* Traverse the index and link the nodes together. */
397 g_hash_table_iter_init (&iter, index);
398 while (g_hash_table_iter_next (&iter, NULL, &value)) {
402 const gchar *parent_uid;
404 source_node = (GNode *) value;
405 source = E_SOURCE (source_node->data);
406 parent_uid = e_source_get_parent (source);
408 if (parent_uid == NULL || *parent_uid == '\0') {
411 parent_node = g_hash_table_lookup (index, parent_uid);
412 g_warn_if_fail (parent_node != NULL);
415 /* Should never be NULL, but just to be safe. */
416 if (parent_node != NULL)
417 g_node_append (parent_node, source_node);
420 g_hash_table_destroy (index);
422 g_mutex_unlock (registry->priv->sources_lock);
428 source_registry_settings_changed_cb (GSettings *settings,
430 ESourceRegistry *registry)
432 /* We define a property name that matches every key in
433 * the "org.gnome.Evolution.DefaultSources" schema. */
434 g_object_notify (G_OBJECT (registry), key);
438 source_registry_source_changed_idle_cb (gpointer user_data)
440 SourceClosure *closure = user_data;
444 signals[SOURCE_CHANGED], 0,
451 source_registry_source_notify_enabled_idle_cb (gpointer user_data)
453 SourceClosure *closure = user_data;
455 if (e_source_get_enabled (closure->source))
458 signals[SOURCE_ENABLED], 0,
463 signals[SOURCE_DISABLED], 0,
470 source_registry_source_changed_cb (ESource *source,
471 ESourceRegistry *registry)
473 GSource *idle_source;
474 SourceClosure *closure;
476 closure = g_slice_new0 (SourceClosure);
477 closure->registry = g_object_ref (registry);
478 closure->source = g_object_ref (source);
480 idle_source = g_idle_source_new ();
481 g_source_set_callback (
483 source_registry_source_changed_idle_cb,
484 closure, (GDestroyNotify) source_closure_free);
485 g_source_attach (idle_source, registry->priv->main_context);
486 g_source_unref (idle_source);
490 source_registry_source_notify_enabled_cb (ESource *source,
492 ESourceRegistry *registry)
494 GSource *idle_source;
495 SourceClosure *closure;
497 closure = g_slice_new0 (SourceClosure);
498 closure->registry = g_object_ref (registry);
499 closure->source = g_object_ref (source);
501 idle_source = g_idle_source_new ();
502 g_source_set_callback (
504 source_registry_source_notify_enabled_idle_cb,
505 closure, (GDestroyNotify) source_closure_free);
506 g_source_attach (idle_source, registry->priv->main_context);
507 g_source_unref (idle_source);
511 source_registry_new_source (ESourceRegistry *registry,
512 GDBusObject *dbus_object)
514 GMainContext *main_context;
516 const gchar *object_path;
517 GError *error = NULL;
519 /* We don't want the ESource emitting "changed" signals from
520 * the manager thread, so we pass it the same main context the
521 * registry uses for scheduling signal emissions. */
522 main_context = registry->priv->main_context;
523 source = e_source_new (dbus_object, main_context, &error);
524 object_path = g_dbus_object_get_object_path (dbus_object);
526 /* The likelihood of an error here is slim, so it's
527 * sufficient to just print a warning if one occurs. */
529 g_warn_if_fail (source == NULL);
531 "ESourceRegistry: Failed to create a "
532 "data source object for path '%s': %s",
533 object_path, error->message);
534 g_error_free (error);
538 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
540 /* Add the ESource to the object path table immediately. */
541 source_registry_object_path_table_insert (
542 registry, object_path, source);
548 source_registry_unref_source (ESource *source)
550 g_signal_handlers_disconnect_matched (
551 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
552 source_registry_source_changed_cb, NULL);
554 g_signal_handlers_disconnect_matched (
555 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
556 source_registry_source_notify_enabled_cb, NULL);
558 g_object_unref (source);
562 source_registry_add_source (ESourceRegistry *registry,
567 uid = e_source_get_uid (source);
568 g_return_if_fail (uid != NULL);
570 g_mutex_lock (registry->priv->sources_lock);
572 /* Check if we already have this source in the registry. */
573 if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
574 g_mutex_unlock (registry->priv->sources_lock);
580 G_CALLBACK (source_registry_source_changed_cb),
584 source, "notify::enabled",
585 G_CALLBACK (source_registry_source_notify_enabled_cb),
588 g_mutex_unlock (registry->priv->sources_lock);
590 source_registry_sources_insert (registry, source);
592 g_signal_emit (registry, signals[SOURCE_ADDED], 0, source);
596 source_registry_remove_source (ESourceRegistry *registry,
599 g_object_ref (source);
601 if (source_registry_sources_remove (registry, source))
602 g_signal_emit (registry, signals[SOURCE_REMOVED], 0, source);
604 g_object_unref (source);
608 source_registry_object_added_idle_cb (gpointer user_data)
610 SourceClosure *closure = user_data;
612 source_registry_add_source (closure->registry, closure->source);
618 source_registry_object_added_cb (GDBusObjectManager *object_manager,
619 GDBusObject *dbus_object,
620 ESourceRegistry *registry)
622 SourceClosure *closure;
623 GSource *idle_source;
626 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
628 source = source_registry_new_source (registry, dbus_object);
629 g_return_if_fail (source != NULL);
631 /* Schedule a callback on the ESourceRegistry's GMainContext. */
633 closure = g_slice_new0 (SourceClosure);
634 closure->registry = g_object_ref (registry);
635 closure->source = g_object_ref (source);
637 idle_source = g_idle_source_new ();
638 g_source_set_callback (
640 source_registry_object_added_idle_cb,
641 closure, (GDestroyNotify) source_closure_free);
642 g_source_attach (idle_source, registry->priv->main_context);
643 g_source_unref (idle_source);
645 g_object_unref (source);
649 source_registry_object_removed_idle_cb (gpointer user_data)
651 SourceClosure *closure = user_data;
653 source_registry_remove_source (closure->registry, closure->source);
659 source_registry_object_removed_cb (GDBusObjectManager *manager,
660 GDBusObject *dbus_object,
661 ESourceRegistry *registry)
663 SourceClosure *closure;
664 GSource *idle_source;
666 const gchar *object_path;
668 /* Find the corresponding ESource in the object path table.
669 * Note that the lookup returns a new ESource reference. */
670 object_path = g_dbus_object_get_object_path (dbus_object);
671 source = source_registry_object_path_table_lookup (
672 registry, object_path);
673 g_return_if_fail (E_IS_SOURCE (source));
675 /* Remove the ESource from the object path table immediately. */
676 source_registry_object_path_table_remove (registry, object_path);
678 /* Schedule a callback on the ESourceRegistry's GMainContext. */
680 closure = g_slice_new0 (SourceClosure);
681 closure->registry = g_object_ref (registry);
682 closure->source = g_object_ref (source);
684 idle_source = g_idle_source_new ();
685 g_source_set_callback (
687 source_registry_object_removed_idle_cb,
688 closure, (GDestroyNotify) source_closure_free);
689 g_source_attach (idle_source, registry->priv->main_context);
690 g_source_unref (idle_source);
692 g_object_unref (source);
696 source_registry_object_manager_running (gpointer data)
698 ThreadClosure *closure = data;
700 g_mutex_lock (closure->main_loop_mutex);
701 g_cond_broadcast (closure->main_loop_cond);
702 g_mutex_unlock (closure->main_loop_mutex);
708 source_registry_object_manager_thread (gpointer data)
710 GDBusObjectManager *object_manager;
711 ThreadClosure *closure = data;
712 GSource *idle_source;
714 gulong object_added_id;
715 gulong object_removed_id;
716 GError *error = NULL;
718 /* GDBusObjectManagerClient grabs the thread-default GMainContext
719 * at creation time and only emits signals from that GMainContext.
720 * Running it in a separate thread prevents its signal emissions
721 * from being inhibited by someone overriding the thread-default
724 /* This becomes the GMainContext that GDBusObjectManagerClient
725 * will emit signals from. Make it the thread-default context
726 * for this thread before creating the client. */
727 g_main_context_push_thread_default (closure->main_context);
729 object_manager = e_dbus_object_manager_client_new_for_bus_sync (
731 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
732 SOURCES_DBUS_SERVICE_NAME,
736 /* If this fails there's really no point in continuing
737 * since we rely on the object manager to populate the
738 * registry. Abort the process with a fatal error. */
740 g_error ("%s", error->message);
741 g_assert_not_reached ();
744 /* Give the registry a handle to the object manager. */
745 closure->registry->priv->dbus_object_manager =
746 g_object_ref (object_manager);
748 /* Now populate the registry with an initial set of ESources. */
750 list = g_dbus_object_manager_get_objects (object_manager);
752 for (link = list; link != NULL; link = g_list_next (link)) {
753 GDBusObject *dbus_object;
756 dbus_object = G_DBUS_OBJECT (link->data);
758 source = source_registry_new_source (
759 closure->registry, dbus_object);
761 if (source != NULL) {
762 source_registry_add_source (
763 closure->registry, source);
764 g_object_unref (source);
768 g_list_free_full (list, (GDestroyNotify) g_object_unref);
770 /* Schedule a one-time idle callback to broadcast through a
771 * condition variable that our main loop is up and running. */
773 idle_source = g_idle_source_new ();
774 g_source_set_callback (
776 source_registry_object_manager_running,
777 closure, (GDestroyNotify) NULL);
778 g_source_attach (idle_source, closure->main_context);
779 g_source_unref (idle_source);
781 /* Listen for D-Bus object additions and removals. */
783 object_added_id = g_signal_connect (
784 object_manager, "object-added",
785 G_CALLBACK (source_registry_object_added_cb),
788 object_removed_id = g_signal_connect (
789 object_manager, "object-removed",
790 G_CALLBACK (source_registry_object_removed_cb),
793 /* Now we mostly idle here for the rest of the session. */
795 g_main_loop_run (closure->main_loop);
797 /* Clean up and exit. */
799 g_signal_handler_disconnect (object_manager, object_added_id);
800 g_signal_handler_disconnect (object_manager, object_removed_id);
802 g_object_unref (object_manager);
804 g_main_context_pop_thread_default (closure->main_context);
810 source_registry_set_property (GObject *object,
815 switch (property_id) {
816 case PROP_DEFAULT_ADDRESS_BOOK:
817 e_source_registry_set_default_address_book (
818 E_SOURCE_REGISTRY (object),
819 g_value_get_object (value));
822 case PROP_DEFAULT_CALENDAR:
823 e_source_registry_set_default_calendar (
824 E_SOURCE_REGISTRY (object),
825 g_value_get_object (value));
828 case PROP_DEFAULT_MAIL_ACCOUNT:
829 e_source_registry_set_default_mail_account (
830 E_SOURCE_REGISTRY (object),
831 g_value_get_object (value));
834 case PROP_DEFAULT_MAIL_IDENTITY:
835 e_source_registry_set_default_mail_identity (
836 E_SOURCE_REGISTRY (object),
837 g_value_get_object (value));
840 case PROP_DEFAULT_MEMO_LIST:
841 e_source_registry_set_default_memo_list (
842 E_SOURCE_REGISTRY (object),
843 g_value_get_object (value));
846 case PROP_DEFAULT_TASK_LIST:
847 e_source_registry_set_default_task_list (
848 E_SOURCE_REGISTRY (object),
849 g_value_get_object (value));
853 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
857 source_registry_get_property (GObject *object,
862 switch (property_id) {
863 case PROP_DEFAULT_ADDRESS_BOOK:
864 g_value_take_object (
866 e_source_registry_ref_default_address_book (
867 E_SOURCE_REGISTRY (object)));
870 case PROP_DEFAULT_CALENDAR:
871 g_value_take_object (
873 e_source_registry_ref_default_calendar (
874 E_SOURCE_REGISTRY (object)));
877 case PROP_DEFAULT_MAIL_ACCOUNT:
878 g_value_take_object (
880 e_source_registry_ref_default_mail_account (
881 E_SOURCE_REGISTRY (object)));
884 case PROP_DEFAULT_MAIL_IDENTITY:
885 g_value_take_object (
887 e_source_registry_ref_default_mail_identity (
888 E_SOURCE_REGISTRY (object)));
891 case PROP_DEFAULT_MEMO_LIST:
892 g_value_take_object (
894 e_source_registry_ref_default_memo_list (
895 E_SOURCE_REGISTRY (object)));
898 case PROP_DEFAULT_TASK_LIST:
899 g_value_take_object (
901 e_source_registry_ref_default_task_list (
902 E_SOURCE_REGISTRY (object)));
906 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
910 source_registry_dispose (GObject *object)
912 ESourceRegistryPrivate *priv;
914 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
916 /* Terminate the manager thread first. */
917 if (priv->manager_thread != NULL) {
918 g_main_loop_quit (priv->thread_closure->main_loop);
919 g_thread_join (priv->manager_thread);
920 thread_closure_free (priv->thread_closure);
921 priv->manager_thread = NULL;
922 priv->thread_closure = NULL;
925 if (priv->main_context != NULL) {
926 g_main_context_unref (priv->main_context);
927 priv->main_context = NULL;
930 if (priv->dbus_object_manager != NULL) {
931 g_object_unref (priv->dbus_object_manager);
932 priv->dbus_object_manager = NULL;
935 if (priv->dbus_source_manager != NULL) {
936 g_object_unref (priv->dbus_source_manager);
937 priv->dbus_source_manager = NULL;
940 g_hash_table_remove_all (priv->object_path_table);
942 g_hash_table_remove_all (priv->sources);
944 if (priv->settings != NULL) {
945 g_object_unref (priv->settings);
946 priv->settings = NULL;
949 /* Chain up to parent's finalize() method. */
950 G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
954 source_registry_finalize (GObject *object)
956 ESourceRegistryPrivate *priv;
958 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
960 g_hash_table_destroy (priv->object_path_table);
961 g_mutex_free (priv->object_path_table_lock);
963 g_hash_table_destroy (priv->sources);
964 g_mutex_free (priv->sources_lock);
966 /* Chain up to parent's finalize() method. */
967 G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
971 source_registry_initable_init (GInitable *initable,
972 GCancellable *cancellable,
975 ESourceRegistry *registry;
976 ThreadClosure *closure;
978 registry = E_SOURCE_REGISTRY (initable);
980 closure = g_slice_new0 (ThreadClosure);
981 closure->registry = registry; /* do not reference */
982 closure->main_context = g_main_context_new ();
983 /* It's important to pass 'is_running=FALSE' here because
984 * we wait for the main loop to start running as a way of
985 * synchronizing with the manager thread. */
986 closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
987 closure->main_loop_cond = g_cond_new ();
988 closure->main_loop_mutex = g_mutex_new ();
990 registry->priv->thread_closure = closure;
992 registry->priv->manager_thread = g_thread_create (
993 source_registry_object_manager_thread,
994 closure, TRUE /* joinable */, error);
996 if (registry->priv->manager_thread == NULL)
999 /* Wait for notification that the manager
1000 * thread's main loop has been started. */
1001 g_mutex_lock (closure->main_loop_mutex);
1002 while (!g_main_loop_is_running (closure->main_loop))
1004 closure->main_loop_cond,
1005 closure->main_loop_mutex);
1006 g_mutex_unlock (closure->main_loop_mutex);
1008 /* We should now have a GDBusObjectManagerClient available. */
1009 g_return_val_if_fail (
1010 G_IS_DBUS_OBJECT_MANAGER_CLIENT (
1011 registry->priv->dbus_object_manager), FALSE);
1013 /* The registry should now be populated with sources. */
1014 g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);
1016 /* The EDBusSourceManagerProxy is just another D-Bus interface
1017 * that resides at the same object path. It's unrelated to the
1018 * GDBusObjectManagerClient and doesn't need its own thread. */
1019 registry->priv->dbus_source_manager =
1020 e_dbus_source_manager_proxy_new_for_bus_sync (
1022 G_DBUS_PROXY_FLAGS_NONE,
1023 SOURCES_DBUS_SERVICE_NAME,
1025 cancellable, error);
1027 if (registry->priv->dbus_source_manager == NULL)
1034 e_source_registry_class_init (ESourceRegistryClass *class)
1036 GObjectClass *object_class;
1038 g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
1040 object_class = G_OBJECT_CLASS (class);
1041 object_class->set_property = source_registry_set_property;
1042 object_class->get_property = source_registry_get_property;
1043 object_class->dispose = source_registry_dispose;
1044 object_class->finalize = source_registry_finalize;
1046 /* The property names correspond to the key names in the
1047 * "org.gnome.Evolution.DefaultSources" GSettings schema. */
1050 * ESourceRegistry:default-address-book:
1052 * The default address book #ESource.
1054 g_object_class_install_property (
1056 PROP_DEFAULT_ADDRESS_BOOK,
1057 g_param_spec_object (
1058 "default-address-book",
1059 "Default Address Book",
1060 "The default address book ESource",
1063 G_PARAM_STATIC_STRINGS));
1066 * ESourceRegistry:default-calendar:
1068 * The default calendar #ESource.
1070 g_object_class_install_property (
1072 PROP_DEFAULT_CALENDAR,
1073 g_param_spec_object (
1076 "The default calendar ESource",
1079 G_PARAM_STATIC_STRINGS));
1082 * ESourceRegistry:default-mail-account:
1084 * The default mail account #ESource.
1086 g_object_class_install_property (
1088 PROP_DEFAULT_MAIL_ACCOUNT,
1089 g_param_spec_object (
1090 "default-mail-account",
1091 "Default Mail Account",
1092 "The default mail account ESource",
1095 G_PARAM_STATIC_STRINGS));
1098 * ESourceRegistry:default-mail-identity:
1100 * The default mail identity #ESource.
1102 g_object_class_install_property (
1104 PROP_DEFAULT_MAIL_IDENTITY,
1105 g_param_spec_object (
1106 "default-mail-identity",
1107 "Default Mail Identity",
1108 "The default mail identity ESource",
1111 G_PARAM_STATIC_STRINGS));
1114 * ESourceRegistry:default-memo-list:
1116 * The default memo list #ESource.
1118 g_object_class_install_property (
1120 PROP_DEFAULT_MEMO_LIST,
1121 g_param_spec_object (
1122 "default-memo-list",
1123 "Default Memo List",
1124 "The default memo list ESource",
1127 G_PARAM_STATIC_STRINGS));
1130 * ESourceRegistry:default-task-list:
1132 * The default task list #ESource.
1134 g_object_class_install_property (
1136 PROP_DEFAULT_TASK_LIST,
1137 g_param_spec_object (
1138 "default-task-list",
1139 "Default Task List",
1140 "The default task list ESource",
1143 G_PARAM_STATIC_STRINGS));
1146 * ESourceRegistry::source-added:
1147 * @registry: the #ESourceRegistry which emitted the signal
1148 * @source: the newly-added #ESource
1150 * Emitted when an #ESource is added to @registry.
1152 signals[SOURCE_ADDED] = g_signal_new (
1154 G_OBJECT_CLASS_TYPE (object_class),
1156 G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
1158 g_cclosure_marshal_VOID__OBJECT,
1163 * ESourceRegistry::source-changed:
1164 * @registry: the #ESourceRegistry which emitted the signal
1165 * @source: the #ESource that changed
1167 * Emitted when an #ESource registered with @registry emits
1168 * its #ESource::changed signal.
1170 signals[SOURCE_CHANGED] = g_signal_new (
1172 G_OBJECT_CLASS_TYPE (object_class),
1174 G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
1176 g_cclosure_marshal_VOID__OBJECT,
1181 * ESourceRegistry::source-removed:
1182 * @registry: the #ESourceRegistry which emitted the signal
1183 * @source: the #ESource that got removed
1185 * Emitted when an #ESource is removed from @registry.
1187 signals[SOURCE_REMOVED] = g_signal_new (
1189 G_OBJECT_CLASS_TYPE (object_class),
1191 G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
1193 g_cclosure_marshal_VOID__OBJECT,
1198 * ESourceRegistry::source-enabled:
1199 * @registry: the #ESourceRegistry which emitted the signal
1200 * @source: the #ESource that got enabled
1202 * Emitted when an #ESource #ESource:enabled property becomes %TRUE.
1204 signals[SOURCE_ENABLED] = g_signal_new (
1206 G_OBJECT_CLASS_TYPE (object_class),
1208 G_STRUCT_OFFSET (ESourceRegistryClass, source_enabled),
1210 g_cclosure_marshal_VOID__OBJECT,
1215 * ESourceRegistry::source-disabled:
1216 * @registry: the #ESourceRegistry which emitted the signal
1217 * @source: the #ESource that got disabled
1219 * Emitted when an #ESource #ESource:enabled property becomes %FALSE.
1221 signals[SOURCE_DISABLED] = g_signal_new (
1223 G_OBJECT_CLASS_TYPE (object_class),
1225 G_STRUCT_OFFSET (ESourceRegistryClass, source_disabled),
1227 g_cclosure_marshal_VOID__OBJECT,
1233 e_source_registry_initable_init (GInitableIface *interface)
1235 interface->init = source_registry_initable_init;
1239 e_source_registry_init (ESourceRegistry *registry)
1241 registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
1243 /* This is so the object manager thread can schedule signal
1244 * emissions on the thread-default context for this thread. */
1245 registry->priv->main_context = g_main_context_ref_thread_default ();
1247 /* D-Bus object path -> ESource */
1248 registry->priv->object_path_table =
1249 g_hash_table_new_full (
1250 (GHashFunc) g_str_hash,
1251 (GEqualFunc) g_str_equal,
1252 (GDestroyNotify) g_free,
1253 (GDestroyNotify) g_object_unref);
1255 registry->priv->object_path_table_lock = g_mutex_new ();
1257 /* UID string -> ESource */
1258 registry->priv->sources = g_hash_table_new_full (
1259 (GHashFunc) g_str_hash,
1260 (GEqualFunc) g_str_equal,
1261 (GDestroyNotify) g_free,
1262 (GDestroyNotify) source_registry_unref_source);
1264 registry->priv->sources_lock = g_mutex_new ();
1266 registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
1269 registry->priv->settings, "changed",
1270 G_CALLBACK (source_registry_settings_changed_cb), registry);
1274 * e_source_registry_new_sync:
1275 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1276 * @error: return location for a #GError, or %NULL
1278 * Creates a new #ESourceRegistry front-end for the registry D-Bus service.
1279 * If an error occurs in connecting to the D-Bus service, the function sets
1280 * @error and returns %NULL.
1282 * Returns: a new #ESourceRegistry, or %NULL
1287 e_source_registry_new_sync (GCancellable *cancellable,
1290 /* XXX Work around http://bugzilla.gnome.org/show_bug.cgi?id=683519
1291 * until GObject's type initialization deadlock issue is fixed.
1292 * Apparently only the synchronous instantiation is affected. */
1293 REGISTER_TYPE (G_TYPE_DBUS_CONNECTION);
1295 return g_initable_new (
1296 E_TYPE_SOURCE_REGISTRY,
1297 cancellable, error, NULL);
1301 * e_source_registry_new:
1302 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1303 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1305 * @user_data: (closure): data to pass to the callback function
1307 * Asynchronously creates a new #ESourceRegistry front-end for the registry
1310 * When the operation is finished, @callback will be called. You can then
1311 * call e_source_registry_new_finish() to get the result of the operation.
1316 e_source_registry_new (GCancellable *cancellable,
1317 GAsyncReadyCallback callback,
1320 g_async_initable_new_async (
1321 E_TYPE_SOURCE_REGISTRY,
1322 G_PRIORITY_DEFAULT, cancellable,
1323 callback, user_data, NULL);
1327 * e_source_registry_new_finish:
1328 * @result: a #GAsyncResult
1329 * @error: return location for a #GError, or %NULL
1331 * Finishes the operation started with e_source_registry_new_finish().
1332 * If an error occurs in connecting to the D-Bus service, the function
1333 * sets @error and returns %NULL.
1335 * Returns: a new #ESourceRegistry, or %NULL
1340 e_source_registry_new_finish (GAsyncResult *result,
1343 GObject *source_object;
1346 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1348 source_object = g_async_result_get_source_object (result);
1349 g_return_val_if_fail (source_object != NULL, NULL);
1351 object = g_async_initable_new_finish (
1352 G_ASYNC_INITABLE (source_object), result, error);
1354 g_object_unref (source_object);
1356 return (object != NULL) ? E_SOURCE_REGISTRY (object) : NULL;
1359 /* Helper for e_source_registry_authenticate() */
1361 source_registry_authenticate_thread (GSimpleAsyncResult *simple,
1363 GCancellable *cancellable)
1365 AsyncContext *async_context;
1366 GError *error = NULL;
1368 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1370 e_source_registry_authenticate_sync (
1371 E_SOURCE_REGISTRY (object),
1372 async_context->source,
1373 async_context->auth,
1374 cancellable, &error);
1377 g_simple_async_result_take_error (simple, error);
1380 /* Helper for e_source_registry_authenticate_sync() */
1382 source_registry_authenticate_respond_cb (AuthContext *auth_context)
1384 ESourceAuthenticationResult auth_result;
1385 GError *non_fatal_error = NULL;
1387 g_return_val_if_fail (auth_context->authenticating, FALSE);
1389 auth_result = auth_context->auth_result;
1391 /* Allow the next authentication attempt to proceed. */
1392 auth_context->authenticating = FALSE;
1394 /* Send the server a status update based on the authentication
1395 * result. Note, we don't really care if the D-Bus message gets
1396 * through to the server at this point. If it doesn't, the auth
1397 * session will either time out on its own or the authentication
1398 * dialog will eventually be dismissed by the user. */
1400 /* If we were cancelled from our side, we have a bit of a dilemma.
1401 * We need to tell the server to cancel the authentication session,
1402 * but that involves making a synchronous D-Bus call, which we are
1403 * not supposed to do if we know we've been cancelled. But if we
1404 * don't tell the server, the authentication session will be left
1405 * to timeout on its own (which may take minutes), and meanwhile
1406 * all other authentication requests are blocked. So choose the
1407 * lesser evil and make the synchronous call but without passing
1408 * the already-cancelled GCancellable. */
1409 if (g_cancellable_is_cancelled (auth_context->cancellable)) {
1410 e_dbus_authenticator_call_cancel_sync (
1411 auth_context->dbus_auth,
1412 NULL, &non_fatal_error);
1413 g_main_loop_quit (auth_context->main_loop);
1414 auth_context->success = FALSE;
1416 /* If an error occurred while attempting to authenticate,
1417 * tell the server to cancel the authentication session. */
1418 } else if (auth_result == E_SOURCE_AUTHENTICATION_ERROR) {
1419 e_dbus_authenticator_call_cancel_sync (
1420 auth_context->dbus_auth,
1421 auth_context->cancellable,
1423 g_main_loop_quit (auth_context->main_loop);
1424 auth_context->success = FALSE;
1426 /* If the password was accepted, let the server know so it
1427 * can close any authentication dialogs and save the user
1428 * provided password to the keyring. */
1429 } else if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
1430 e_dbus_authenticator_call_accepted_sync (
1431 auth_context->dbus_auth,
1432 auth_context->cancellable,
1434 g_main_loop_quit (auth_context->main_loop);
1435 auth_context->success = TRUE;
1437 /* If the password was rejected, let the server know so it can
1438 * indicate failure and request a different password, and then
1439 * wait for the next "response" signal. */
1441 e_dbus_authenticator_call_rejected_sync (
1442 auth_context->dbus_auth,
1443 auth_context->cancellable,
1447 /* Leave breadcrumbs if something went wrong,
1448 * but don't fail the whole operation over it. */
1449 if (non_fatal_error != NULL) {
1450 g_warning ("%s: %s", G_STRFUNC, non_fatal_error->message);
1451 g_error_free (non_fatal_error);
1457 /* Helper for e_source_registry_authenticate_sync() */
1459 source_registry_authenticate_authenticate_cb (EDBusAuthenticator *dbus_auth,
1460 const gchar *encrypted_secret,
1461 AuthContext *auth_context)
1463 GSource *idle_source;
1464 GMainContext *main_context;
1466 gboolean valid_secret;
1468 /* We should only get one secret at a time. */
1469 g_return_if_fail (!auth_context->authenticating);
1471 valid_secret = gcr_secret_exchange_receive (
1472 auth_context->secret_exchange, encrypted_secret);
1473 g_return_if_fail (valid_secret);
1475 auth_context->authenticating = TRUE;
1477 /* This avoids revealing the password in a stack trace. */
1478 password = g_string_new (
1479 gcr_secret_exchange_get_secret (
1480 auth_context->secret_exchange, NULL));
1482 /* Try authenticating with the given password. We have to
1483 * call this synchronously because some authenticators use
1484 * mutexes to serialize I/O operations and are not prepared
1485 * to make authentication attempts from a different thread.
1487 * Unfortunately this means we won't notice server-side
1488 * dismissals while the main loop is blocked. We respond
1489 * to the server from a low-priority idle callback so that
1490 * any pending "dismissed" signals get handled first. */
1492 auth_context->auth_result =
1493 e_source_authenticator_try_password_sync (
1494 auth_context->auth, password,
1495 auth_context->cancellable,
1496 auth_context->error);
1498 idle_source = g_idle_source_new ();
1499 main_context = g_main_context_get_thread_default ();
1500 g_source_set_callback (
1501 idle_source, (GSourceFunc)
1502 source_registry_authenticate_respond_cb,
1503 auth_context, NULL);
1504 g_source_attach (idle_source, main_context);
1505 g_source_unref (idle_source);
1507 g_string_free (password, TRUE);
1510 /* Helper for e_source_registry_authenticate_sync() */
1512 source_registry_authenticate_dismissed_cb (EDBusAuthenticator *dbus_auth,
1513 AuthContext *auth_context)
1515 /* Be careful not to overwrite an existing error in case this
1516 * is called after e_source_authenticator_try_password_sync()
1517 * but prior to the idle callback. */
1518 if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
1519 /* XXX Use a separate error code for dismissals? */
1520 g_set_error_literal (
1521 auth_context->error,
1522 G_IO_ERROR, G_IO_ERROR_CANCELLED,
1523 _("The user declined to authenticate"));
1524 auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
1527 g_main_loop_quit (auth_context->main_loop);
1528 auth_context->success = FALSE;
1531 /* Helper for e_source_registry_authenticate_sync() */
1533 source_registry_call_authenticate_for_source (ESourceRegistry *registry,
1534 ESourceAuthenticator *auth,
1536 gchar **out_object_path,
1537 GCancellable *cancellable,
1540 ESource *collection;
1542 gchar *prompt_title = NULL;
1543 gchar *prompt_message = NULL;
1544 gchar *prompt_description = NULL;
1547 /* If the source is a member of a collection, we want to store
1548 * the password under the UID of the "collection" source so it
1549 * will apply to the entire collection.
1551 * XXX This assumes all sources in a collection share a single
1552 * password. If that turns out not to be true in all cases
1553 * we could maybe add a "SharedPassword: true/false" key to
1554 * [Collection] and apply it here.
1556 collection = e_source_registry_find_extension (
1557 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1558 if (collection != NULL)
1559 source = collection;
1561 g_object_ref (source);
1563 uid = e_source_get_uid (source);
1565 e_source_authenticator_get_prompt_strings (
1569 &prompt_description);
1571 success = e_dbus_source_manager_call_authenticate_sync (
1572 registry->priv->dbus_source_manager, uid,
1573 prompt_title, prompt_message, prompt_description,
1574 out_object_path, cancellable, error);
1576 g_free (prompt_title);
1577 g_free (prompt_message);
1578 g_free (prompt_description);
1580 g_object_unref (source);
1586 * e_source_registry_authenticate_sync:
1587 * @registry: an #ESourceRegistry
1588 * @source: an #ESource
1589 * @auth: an #ESourceAuthenticator
1590 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1591 * @error: return location for a #GError, or %NULL
1593 * Authenticates @source, using @auth to handle the authentication
1594 * attempts. The operation loops until authentication is successful or
1595 * the user aborts further authentication attempts. If an error occurs,
1596 * the function will set @error and return %FALSE.
1598 * Note that @source need not have a #GDBusObject, which means this
1599 * function can test authentication on a scratch #ESource.
1601 * Only backend implementations and data source editors should call this
1602 * function. The intent is for basic client applications to not have to
1603 * deal with authentication at all.
1605 * Returns: %TRUE on success, %FALSE on failure
1610 e_source_registry_authenticate_sync (ESourceRegistry *registry,
1612 ESourceAuthenticator *auth,
1613 GCancellable *cancellable,
1616 AuthContext *auth_context;
1617 GMainContext *main_context;
1618 EDBusAuthenticator *dbus_auth;
1619 gchar *encryption_key;
1620 gchar *object_path = NULL;
1623 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1624 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1625 g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth), FALSE);
1627 /* This extracts authentication prompt details for the ESource
1628 * before initiating an authentication session with the server,
1629 * so split it out of the main algorithm for clarity's sake. */
1630 success = source_registry_call_authenticate_for_source (
1631 registry, auth, source, &object_path, cancellable, error);
1634 g_warn_if_fail (object_path == NULL);
1638 g_return_val_if_fail (object_path != NULL, FALSE);
1640 main_context = g_main_context_new ();
1641 g_main_context_push_thread_default (main_context);
1643 dbus_auth = e_dbus_authenticator_proxy_new_for_bus_sync (
1645 G_DBUS_PROXY_FLAGS_NONE,
1646 SOURCES_DBUS_SERVICE_NAME,
1647 object_path, cancellable, error);
1649 g_free (object_path);
1651 if (dbus_auth == NULL) {
1656 auth_context = g_slice_new0 (AuthContext);
1657 auth_context->auth = g_object_ref (auth);
1658 auth_context->dbus_auth = dbus_auth; /* takes ownership */
1659 auth_context->main_loop = g_main_loop_new (main_context, FALSE);
1660 auth_context->error = error;
1662 /* This just needs to be something other than
1663 * E_SOURCE_AUTHENTICATION_ERROR so we don't trip
1664 * up source_registry_authenticate_dismissed_cb(). */
1665 auth_context->auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
1667 if (G_IS_CANCELLABLE (cancellable))
1668 auth_context->cancellable = g_object_ref (cancellable);
1670 auth_context->secret_exchange =
1671 gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1);
1674 dbus_auth, "authenticate",
1675 G_CALLBACK (source_registry_authenticate_authenticate_cb),
1679 dbus_auth, "dismissed",
1680 G_CALLBACK (source_registry_authenticate_dismissed_cb),
1683 encryption_key = gcr_secret_exchange_begin (
1684 auth_context->secret_exchange);
1686 /* Signal the D-Bus server that we're ready to begin the
1687 * authentication session. This must happen AFTER we've
1688 * connected to the response signal since the server may
1689 * already have a response ready and waiting for us. */
1690 success = e_dbus_authenticator_call_ready_sync (
1691 dbus_auth, encryption_key, cancellable, error);
1693 g_free (encryption_key);
1696 g_main_loop_run (auth_context->main_loop);
1697 success = auth_context->success;
1700 auth_context_free (auth_context);
1703 g_main_context_pop_thread_default (main_context);
1704 g_main_context_unref (main_context);
1710 * e_source_registry_authenticate:
1711 * @registry: an #ESourceRegistry
1712 * @source: an #ESource
1713 * @auth: an #ESourceAuthenticator
1714 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1715 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1717 * @user_data: (closure): data to pass to the callback function
1719 * Asynchronously authenticates @source, using @auth to handle the
1720 * authentication attempts. The operation loops until authentication
1721 * is successful or the user aborts further authentication attempts.
1723 * Note that @source need not have a #GDBusObject, which means this
1724 * function can test authentication on a scratch #ESource.
1726 * When the operation is finished, @callback will be called. You can then
1727 * call e_source_registry_authenticate_finish() to get the result of the
1730 * Only backend implementations and data source editors should call this
1731 * function. The intent is for basic client applications to not have to
1732 * deal with authentication at all.
1737 e_source_registry_authenticate (ESourceRegistry *registry,
1739 ESourceAuthenticator *auth,
1740 GCancellable *cancellable,
1741 GAsyncReadyCallback callback,
1744 GSimpleAsyncResult *simple;
1745 AsyncContext *async_context;
1747 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1748 g_return_if_fail (E_IS_SOURCE (source));
1749 g_return_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth));
1751 async_context = g_slice_new0 (AsyncContext);
1752 async_context->source = g_object_ref (source);
1753 async_context->auth = g_object_ref (auth);
1755 simple = g_simple_async_result_new (
1756 G_OBJECT (registry), callback, user_data,
1757 e_source_registry_authenticate);
1759 g_simple_async_result_set_check_cancellable (simple, cancellable);
1761 g_simple_async_result_set_op_res_gpointer (
1762 simple, async_context, (GDestroyNotify) async_context_free);
1764 g_simple_async_result_run_in_thread (
1765 simple, source_registry_authenticate_thread,
1766 G_PRIORITY_DEFAULT, cancellable);
1768 g_object_unref (simple);
1772 * e_source_registry_authenticate_finish:
1773 * @registry: an #ESourceRegistry
1774 * @result: a #GAsyncResult
1775 * @error: return location for a #GError, or %NULL
1777 * Finishes the operation started with e_source_registry_authenticate().
1778 * If an error occurred, the function will set @error and return %FALSE.
1780 * Returns: %TRUE on success, %FALSE on failure
1785 e_source_registry_authenticate_finish (ESourceRegistry *registry,
1786 GAsyncResult *result,
1789 GSimpleAsyncResult *simple;
1791 g_return_val_if_fail (
1792 g_simple_async_result_is_valid (
1793 result, G_OBJECT (registry),
1794 e_source_registry_authenticate), FALSE);
1796 simple = G_SIMPLE_ASYNC_RESULT (result);
1798 /* Assume success unless a GError is set. */
1799 return !g_simple_async_result_propagate_error (simple, error);
1802 /* Helper for e_source_registry_commit_source() */
1804 source_registry_commit_source_thread (GSimpleAsyncResult *simple,
1806 GCancellable *cancellable)
1808 AsyncContext *async_context;
1809 GError *error = NULL;
1811 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1813 e_source_registry_commit_source_sync (
1814 E_SOURCE_REGISTRY (object),
1815 async_context->source,
1816 cancellable, &error);
1819 g_simple_async_result_take_error (simple, error);
1823 * e_source_registry_commit_source_sync:
1824 * @registry: an #ESourceRegistry
1825 * @source: an #ESource with changes to commit
1826 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1827 * @error: return location for #GError, or %NULL
1829 * This is a convenience function intended for use with graphical
1830 * #ESource editors. Call this function when the user is finished
1831 * making changes to @source.
1833 * If @source has a #GDBusObject, its contents are submitted to the D-Bus
1834 * service through e_source_write_sync().
1836 * If @source does NOT have a #GDBusObject (implying it's a scratch
1837 * #ESource), its contents are submitted to the D-Bus service through
1838 * either e_source_remote_create_sync() if @source is to be a collection
1839 * member, or e_source_registry_create_sources_sync() if @source to be an
1840 * independent data source.
1842 * If an error occurs, the function will set @error and return %FALSE.
1844 * Returns: %TRUE on success, %FALSE on failure
1849 e_source_registry_commit_source_sync (ESourceRegistry *registry,
1851 GCancellable *cancellable,
1854 GDBusObject *dbus_object;
1855 ESource *collection_source;
1856 gboolean collection_member;
1859 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1860 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1862 dbus_object = e_source_ref_dbus_object (source);
1864 collection_source = e_source_registry_find_extension (
1865 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1868 (collection_source != NULL) &&
1869 (collection_source != source);
1871 if (dbus_object != NULL) {
1872 success = e_source_write_sync (source, cancellable, error);
1873 g_object_unref (dbus_object);
1875 } else if (collection_member) {
1876 success = e_source_remote_create_sync (
1877 collection_source, source, cancellable, error);
1880 GList *list = g_list_prepend (NULL, source);
1881 success = e_source_registry_create_sources_sync (
1882 registry, list, cancellable, error);
1886 if (collection_source != NULL)
1887 g_object_unref (collection_source);
1893 * e_source_registry_commit_source:
1894 * @registry: an #ESourceRegistry
1895 * @source: an #ESource with changes to commit
1896 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1897 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1899 * @user_data: (closure): data to pass to the callback function
1901 * See e_source_registry_commit_source_sync() for details.
1903 * When the operation is finished, @callback will be called. You can then
1904 * call e_source_registry_commit_source_finish() to get the result of the
1910 e_source_registry_commit_source (ESourceRegistry *registry,
1912 GCancellable *cancellable,
1913 GAsyncReadyCallback callback,
1916 GSimpleAsyncResult *simple;
1917 AsyncContext *async_context;
1919 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1920 g_return_if_fail (E_IS_SOURCE (source));
1922 async_context = g_slice_new0 (AsyncContext);
1923 async_context->source = g_object_ref (source);
1925 simple = g_simple_async_result_new (
1926 G_OBJECT (registry), callback, user_data,
1927 e_source_registry_commit_source);
1929 g_simple_async_result_set_check_cancellable (simple, cancellable);
1931 g_simple_async_result_set_op_res_gpointer (
1932 simple, async_context, (GDestroyNotify) async_context_free);
1934 g_simple_async_result_run_in_thread (
1935 simple, source_registry_commit_source_thread,
1936 G_PRIORITY_DEFAULT, cancellable);
1938 g_object_unref (simple);
1942 * e_source_registry_commit_source_finish:
1943 * @registry: an #ESourceRegistry
1944 * @result: a #GAsyncResult
1945 * @error: return location for a #GError, or %NULL
1947 * Finishes the operation started with e_source_registry_commit_source().
1949 * If an error occurred, the function will set @error and return %FALSE.
1951 * Returns: %TRUE on success, %FALSE on failure
1956 e_source_registry_commit_source_finish (ESourceRegistry *registry,
1957 GAsyncResult *result,
1960 GSimpleAsyncResult *simple;
1962 g_return_val_if_fail (
1963 g_simple_async_result_is_valid (
1964 result, G_OBJECT (registry),
1965 e_source_registry_commit_source), FALSE);
1967 simple = G_SIMPLE_ASYNC_RESULT (result);
1969 /* Assume success unless a GError is set. */
1970 return !g_simple_async_result_propagate_error (simple, error);
1973 /* Helper for e_source_registry_create_sources() */
1975 source_registry_create_sources_thread (GSimpleAsyncResult *simple,
1977 GCancellable *cancellable)
1979 AsyncContext *async_context;
1980 GError *error = NULL;
1982 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1984 e_source_registry_create_sources_sync (
1985 E_SOURCE_REGISTRY (object),
1986 async_context->list_of_sources,
1987 cancellable, &error);
1990 g_simple_async_result_take_error (simple, error);
1994 * e_source_registry_create_sources_sync:
1995 * @registry: an #ESourceRegistry
1996 * @list_of_sources: (element-type ESource): a list of #ESource instances with
1998 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1999 * @error: return location for a #GError, or %NULL
2001 * Requests the D-Bus service create new key files for each #ESource in
2002 * @list_of_sources. Each list element must be a scratch #ESource with
2005 * If an error occurs, the function will set @error and return %FALSE.
2007 * Returns: %TRUE on success, %FALSE on failure
2012 e_source_registry_create_sources_sync (ESourceRegistry *registry,
2013 GList *list_of_sources,
2014 GCancellable *cancellable,
2017 GVariantBuilder builder;
2022 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2024 /* Verify the list elements are all ESources. */
2025 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2026 g_return_val_if_fail (E_IS_SOURCE (link->data), FALSE);
2028 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
2030 for (link = list_of_sources; link != NULL; link = g_list_next (link)) {
2035 source = E_SOURCE (link->data);
2036 uid = e_source_get_uid (source);
2038 source_data = e_source_to_string (source, NULL);
2039 g_variant_builder_add (&builder, "{ss}", uid, source_data);
2040 g_free (source_data);
2043 variant = g_variant_builder_end (&builder);
2045 /* This function sinks the floating GVariant reference. */
2046 success = e_dbus_source_manager_call_create_sources_sync (
2047 registry->priv->dbus_source_manager,
2048 variant, cancellable, error);
2050 g_variant_builder_clear (&builder);
2056 * e_source_registry_create_sources:
2057 * @registry: an #ESourceRegistry
2058 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2060 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2061 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2063 * @user_data: (closure): data to pass to the callback function
2065 * Asynchronously requests the D-Bus service create new key files for each
2066 * #ESource in @list_of_sources. Each list element must be a scratch
2067 * #ESource with no #GDBusObject.
2069 * When the operation is finished, @callback will be called. You can then
2070 * call e_source_registry_create_sources_finish() to get the result of the
2076 e_source_registry_create_sources (ESourceRegistry *registry,
2077 GList *list_of_sources,
2078 GCancellable *cancellable,
2079 GAsyncReadyCallback callback,
2082 GSimpleAsyncResult *simple;
2083 AsyncContext *async_context;
2086 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2088 /* Verify the list elements are all ESources. */
2089 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2090 g_return_if_fail (E_IS_SOURCE (link->data));
2092 async_context = g_slice_new0 (AsyncContext);
2093 async_context->list_of_sources = g_list_copy (list_of_sources);
2096 async_context->list_of_sources,
2097 (GFunc) g_object_ref, NULL);
2099 simple = g_simple_async_result_new (
2100 G_OBJECT (registry), callback, user_data,
2101 e_source_registry_create_sources);
2103 g_simple_async_result_set_check_cancellable (simple, cancellable);
2105 g_simple_async_result_set_op_res_gpointer (
2106 simple, async_context, (GDestroyNotify) async_context_free);
2108 g_simple_async_result_run_in_thread (
2109 simple, source_registry_create_sources_thread,
2110 G_PRIORITY_DEFAULT, cancellable);
2112 g_object_unref (simple);
2116 * e_source_registry_create_sources_finish:
2117 * @registry: an #ESourceRegistry
2118 * @result: a #GAsyncResult
2119 * @error: return location for a #GError, or %NULL
2121 * Finishes the operation started with e_source_registry_create_sources().
2123 * If an error occurred, the function will set @error and return %FALSE.
2125 * Returns: %TRUE on success, %FALSE on failure
2130 e_source_registry_create_sources_finish (ESourceRegistry *registry,
2131 GAsyncResult *result,
2134 GSimpleAsyncResult *simple;
2136 g_return_val_if_fail (
2137 g_simple_async_result_is_valid (
2138 result, G_OBJECT (registry),
2139 e_source_registry_create_sources), FALSE);
2141 simple = G_SIMPLE_ASYNC_RESULT (result);
2143 /* Assume success unless a GError is set. */
2144 return !g_simple_async_result_propagate_error (simple, error);
2148 * e_source_registry_ref_source:
2149 * @registry: an #ESourceRegistry
2150 * @uid: a unique identifier string
2152 * Looks up an #ESource in @registry by its unique identifier string.
2154 * The returned #ESource is referenced for thread-safety and must be
2155 * unreferenced with g_object_unref() when finished with it.
2157 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2162 e_source_registry_ref_source (ESourceRegistry *registry,
2165 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2166 g_return_val_if_fail (uid != NULL, NULL);
2168 return source_registry_sources_lookup (registry, uid);
2172 * e_source_registry_list_sources:
2173 * @registry: an #ESourceRegistry
2174 * @extension_name: (allow-none): an extension name, or %NULL
2176 * Returns a list of registered sources, sorted by display name. If
2177 * @extension_name is given, restrict the list to sources having that
2180 * The sources returned in the list are referenced for thread-safety.
2181 * They must each be unreferenced with g_object_unref() when finished
2182 * when them. Free the returned list itself with g_list_free().
2184 * An easy way to free the list properly in one step is as follows:
2187 * g_list_free_full (list, g_object_unref);
2190 * Returns: (element-type ESource) (transfer full): a sorted list of sources
2195 e_source_registry_list_sources (ESourceRegistry *registry,
2196 const gchar *extension_name)
2199 GQueue trash = G_QUEUE_INIT;
2201 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2203 list = g_list_sort (
2204 source_registry_sources_get_values (registry),
2205 (GCompareFunc) e_source_compare_by_display_name);
2207 if (extension_name == NULL)
2210 for (link = list; link != NULL; link = g_list_next (link)) {
2211 ESource *source = E_SOURCE (link->data);
2213 if (!e_source_has_extension (source, extension_name)) {
2214 g_queue_push_tail (&trash, link);
2215 g_object_unref (source);
2219 /* We do want pop_head() here, not pop_head_link(). */
2220 while ((link = g_queue_pop_head (&trash)) != NULL)
2221 list = g_list_delete_link (list, link);
2227 * e_source_registry_find_extension:
2228 * @registry: an #ESourceRegistry
2229 * @source: an #ESource
2230 * @extension_name: the extension name to find
2232 * Examines @source and its ancestors and returns the "deepest" #ESource
2233 * having an #ESourceExtension with the given @extension_name. If neither
2234 * @source nor any of its ancestors have such an extension, the function
2237 * This function is useful in cases when an #ESourceExtension is meant to
2238 * apply to both the #ESource it belongs to and the #ESource's descendants.
2240 * A common example is the #ESourceCollection extension, where descendants
2241 * of an #ESource having an #ESourceCollection extension are implied to be
2242 * members of that collection. In that example, this function can be used
2243 * to test whether @source is a member of a collection.
2245 * The returned #ESource is referenced for thread-safety and must be
2246 * unreferenced with g_object_unref() when finished with it.
2248 * Note the function returns the #ESource containing the #ESourceExtension
2249 * instead of the #ESourceExtension itself because extension instances are
2250 * not to be referenced directly (see e_source_get_extension()).
2252 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2257 e_source_registry_find_extension (ESourceRegistry *registry,
2259 const gchar *extension_name)
2261 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2262 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2263 g_return_val_if_fail (extension_name != NULL, NULL);
2265 g_object_ref (source);
2267 while (!e_source_has_extension (source, extension_name)) {
2270 uid = e_source_dup_parent (source);
2272 g_object_unref (source);
2276 source = e_source_registry_ref_source (registry, uid);
2287 /* Helper for e_source_registry_build_display_tree() */
2289 source_registry_compare_nodes (GNode *node_a,
2292 ESource *source_a = E_SOURCE (node_a->data);
2293 ESource *source_b = E_SOURCE (node_b->data);
2294 const gchar *uid_a, *uid_b;
2296 uid_a = e_source_get_uid (source_a);
2297 uid_b = e_source_get_uid (source_b);
2299 /* Sanity check, with runtime warnings. */
2300 if (uid_a == NULL) {
2301 g_warn_if_reached ();
2304 if (uid_b == NULL) {
2305 g_warn_if_reached ();
2309 /* The built-in "local-stub" source comes first at depth 1. */
2311 if (g_strcmp0 (uid_a, "local-stub") == 0)
2314 if (g_strcmp0 (uid_b, "local-stub") == 0)
2317 /* The built-in "system-*" sources come first at depth 2. */
2319 if (g_str_has_prefix (uid_a, "system-"))
2322 if (g_str_has_prefix (uid_b, "system-"))
2325 return e_source_compare_by_display_name (source_a, source_b);
2328 /* Helper for e_source_registry_build_display_tree() */
2330 source_registry_prune_nodes (GNode *node,
2331 const gchar *extension_name)
2333 GQueue queue = G_QUEUE_INIT;
2336 /* Unlink all the child nodes and place them in a queue. */
2337 while ((child_node = g_node_first_child (node)) != NULL) {
2338 g_node_unlink (child_node);
2339 g_queue_push_tail (&queue, child_node);
2342 /* Sort the queue by source name. */
2344 &queue, (GCompareDataFunc)
2345 source_registry_compare_nodes, NULL);
2347 /* Pop nodes off the head of the queue until the queue is empty.
2348 * If the node has either its own children or the given extension
2349 * name, put it back under the parent node (preserving the sorted
2350 * order). Otherwise delete the node and its descendants. */
2351 while ((child_node = g_queue_pop_head (&queue)) != NULL) {
2352 ESource *child = E_SOURCE (child_node->data);
2353 gboolean append_child_node = FALSE;
2355 if (extension_name == NULL)
2356 append_child_node = e_source_get_enabled (child);
2358 else if (e_source_has_extension (child, extension_name))
2359 append_child_node = e_source_get_enabled (child);
2361 else if (g_node_first_child (child_node) != NULL)
2362 append_child_node = e_source_get_enabled (child);
2364 if (append_child_node)
2365 g_node_append (node, child_node);
2367 e_source_registry_free_display_tree (child_node);
2374 * e_source_registry_build_display_tree:
2375 * @registry: an #ESourceRegistry
2376 * @extension_name: (allow-none): an extension name, or %NULL
2378 * Returns a single #GNode tree of registered sources that can be used to
2379 * populate a #GtkTreeModel. (The root #GNode is just an empty placeholder.)
2381 * Similar to e_source_registry_list_sources(), an @extension_name can be
2382 * given to restrict the tree to sources having that extension name. Parents
2383 * of matched sources are included in the tree regardless of whether they have
2384 * an extension named @extension_name.
2386 * Disabled leaf nodes are automatically excluded from the #GNode tree.
2388 * The sources returned in the tree are referenced for thread-safety.
2389 * They must each be unreferenced with g_object_unref() when finished
2390 * with them. Free the returned tree itself with g_node_destroy().
2391 * For convenience, e_source_registry_free_display_tree() does all
2394 * Returns: (element-type ESource) (transfer full): a tree of sources,
2395 * arranged for display
2400 e_source_registry_build_display_tree (ESourceRegistry *registry,
2401 const gchar *extension_name)
2405 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2407 /* Assemble all data sources into a tree. */
2408 root = source_registry_sources_build_tree (registry);
2410 /* Prune unwanted nodes from the copied source trees.
2411 * This must be done in "post" order (children first)
2412 * since it reorders and deletes child nodes. */
2414 root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
2415 (GNodeTraverseFunc) source_registry_prune_nodes,
2416 (gpointer) extension_name);
2421 /* Helper for e_source_registry_free_display_tree() */
2423 source_registry_unref_nodes (GNode *node)
2425 while (node != NULL) {
2426 if (node->children != NULL)
2427 source_registry_unref_nodes (node->children);
2428 if (node->data != NULL)
2429 g_object_unref (node->data);
2435 * e_source_registry_free_display_tree:
2436 * @display_tree: a tree of sources, arranged for display
2438 * Convenience function to free a #GNode tree of registered
2439 * sources created by e_source_registry_build_display_tree().
2444 e_source_registry_free_display_tree (GNode *display_tree)
2446 g_return_if_fail (display_tree != NULL);
2448 /* XXX This would be easier if GLib had something like
2449 * g_node_destroy_full() which took a GDestroyNotify.
2450 * Then the tree would not have to be traversed twice. */
2452 source_registry_unref_nodes (display_tree);
2453 g_node_destroy (display_tree);
2456 /* Helper for e_source_registry_debug_dump() */
2458 source_registry_debug_dump_cb (GNode *node)
2462 /* Root node is an empty placeholder. */
2463 if (G_NODE_IS_ROOT (node))
2466 depth = g_node_depth (node);
2467 for (ii = 2; ii < depth; ii++)
2470 if (E_IS_SOURCE (node->data)) {
2471 ESource *source = E_SOURCE (node->data);
2472 g_print ("\"%s\" ", e_source_get_display_name (source));
2473 g_print ("(%s)", e_source_get_uid (source));
2482 * e_source_registry_debug_dump:
2483 * @registry: an #ESourceRegistry
2484 * @extension_name: (allow-none): an extension name, or %NULL
2486 * Handy debugging function that uses e_source_registry_build_display_tree()
2487 * to print a tree of registered sources to standard output.
2492 e_source_registry_debug_dump (ESourceRegistry *registry,
2493 const gchar *extension_name)
2497 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2499 root = e_source_registry_build_display_tree (registry, extension_name);
2502 root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2503 (GNodeTraverseFunc) source_registry_debug_dump_cb, NULL);
2505 e_source_registry_free_display_tree (root);
2509 * e_source_registry_ref_builtin_address_book:
2510 * @registry: an #ESourceRegistry
2512 * Returns the built-in address book #ESource.
2514 * This #ESource is always present and makes for a safe fallback.
2516 * The returned #ESource is referenced for thread-safety and must be
2517 * unreferenced with g_object_unref() when finished with it.
2519 * Returns: (transfer full): the built-in address book #ESource
2524 e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
2529 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2531 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2532 source = e_source_registry_ref_source (registry, uid);
2533 g_return_val_if_fail (source != NULL, NULL);
2539 * e_source_registry_ref_default_address_book:
2540 * @registry: an #ESourceRegistry
2542 * Returns the #ESource most recently passed to
2543 * e_source_registry_set_default_address_book() either in this session
2544 * or a previous session, or else falls back to the built-in address book.
2546 * The returned #ESource is referenced for thread-safety and must be
2547 * unreferenced with g_object_unref() when finished with it.
2549 * Returns: (transfer full): the default address book #ESource
2554 e_source_registry_ref_default_address_book (ESourceRegistry *registry)
2560 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2562 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2563 uid = g_settings_get_string (registry->priv->settings, key);
2564 source = e_source_registry_ref_source (registry, uid);
2567 /* The built-in source is always present. */
2569 source = e_source_registry_ref_builtin_address_book (registry);
2571 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2577 * e_source_registry_set_default_address_book:
2578 * @registry: an #ESourceRegistry
2579 * @default_source: (allow-none): an address book #ESource, or %NULL
2581 * Sets @default_source as the default address book. If @default_source
2582 * is %NULL, the default address book is reset to the built-in address book.
2583 * This setting will persist across sessions until changed.
2588 e_source_registry_set_default_address_book (ESourceRegistry *registry,
2589 ESource *default_source)
2594 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2596 if (default_source != NULL) {
2597 g_return_if_fail (E_IS_SOURCE (default_source));
2598 uid = e_source_get_uid (default_source);
2600 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2603 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2604 g_settings_set_string (registry->priv->settings, key, uid);
2606 /* The GSettings::changed signal will trigger a "notify" signal
2607 * from the registry, so no need to call g_object_notify() here. */
2611 * e_source_registry_ref_builtin_calendar:
2612 * @registry: an #ESourceRegistry
2614 * Returns the built-in calendar #ESource.
2616 * This #ESource is always present and makes for a safe fallback.
2618 * The returned #ESource is referenced for thread-safety and must be
2619 * unreferenced with g_object_unref() when finished with it.
2621 * Returns: (transfer full): the built-in calendar #ESource
2626 e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
2631 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2633 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2634 source = e_source_registry_ref_source (registry, uid);
2635 g_return_val_if_fail (source != NULL, NULL);
2641 * e_source_registry_ref_default_calendar:
2642 * @registry: an #ESourceRegistry
2644 * Returns the #ESource most recently passed to
2645 * e_source_registry_set_default_calendar() either in this session
2646 * or a previous session, or else falls back to the built-in calendar.
2648 * The returned #ESource is referenced for thread-safety and must be
2649 * unreferenced with g_object_unref() when finished with it.
2651 * Returns: (transfer full): the default calendar #ESource
2656 e_source_registry_ref_default_calendar (ESourceRegistry *registry)
2662 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2664 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2665 uid = g_settings_get_string (registry->priv->settings, key);
2666 source = e_source_registry_ref_source (registry, uid);
2669 /* The built-in source is always present. */
2671 source = e_source_registry_ref_builtin_calendar (registry);
2673 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2679 * e_source_registry_set_default_calendar:
2680 * @registry: an #ESourceRegistry
2681 * @default_source: (allow-none): a calendar #ESource, or %NULL
2683 * Sets @default_source as the default calendar. If @default_source
2684 * is %NULL, the default calendar is reset to the built-in calendar.
2685 * This setting will persist across sessions until changed.
2690 e_source_registry_set_default_calendar (ESourceRegistry *registry,
2691 ESource *default_source)
2696 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2698 if (default_source != NULL) {
2699 g_return_if_fail (E_IS_SOURCE (default_source));
2700 uid = e_source_get_uid (default_source);
2702 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2705 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2706 g_settings_set_string (registry->priv->settings, key, uid);
2708 /* The GSettings::changed signal will trigger a "notify" signal
2709 * from the registry, so no need to call g_object_notify() here. */
2713 * e_source_registry_ref_builtin_mail_account:
2714 * @registry: an #ESourceRegistry
2716 * Returns the built-in mail account #ESource.
2718 * This #ESource is always present and makes for a safe fallback.
2720 * The returned #ESource is referenced for thread-safety and must be
2721 * unreferenced with g_object_unref() when finished with it.
2723 * Returns: (transfer full): the built-in mail account #ESource
2728 e_source_registry_ref_builtin_mail_account (ESourceRegistry *registry)
2733 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2735 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2736 source = e_source_registry_ref_source (registry, uid);
2737 g_return_val_if_fail (source != NULL, NULL);
2743 * e_source_registry_ref_default_mail_account:
2744 * @registry: an #ESourceRegistry
2746 * Returns the #ESource most recently passed to
2747 * e_source_registry_set_default_mail_account() either in this session
2748 * or a previous session, or else falls back to the built-in mail account.
2750 * The returned #ESource is referenced for thread-safety and must be
2751 * unreferenced with g_object_unref() when finished with it.
2753 * Returns: (transfer full): the default mail account #ESource
2758 e_source_registry_ref_default_mail_account (ESourceRegistry *registry)
2764 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2766 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2767 uid = g_settings_get_string (registry->priv->settings, key);
2768 source = e_source_registry_ref_source (registry, uid);
2771 /* The built-in source is always present. */
2773 source = e_source_registry_ref_builtin_mail_account (registry);
2775 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2781 * e_source_registry_set_default_mail_account:
2782 * @registry: an #ESourceRegistry
2783 * @default_source: (allow-none): a mail account #ESource, or %NULL
2785 * Sets @default_source as the default mail account. If @default_source
2786 * is %NULL, the default mail account is reset to the built-in mail account.
2787 * This setting will persist across sessions until changed.
2792 e_source_registry_set_default_mail_account (ESourceRegistry *registry,
2793 ESource *default_source)
2798 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2800 if (default_source != NULL) {
2801 g_return_if_fail (E_IS_SOURCE (default_source));
2802 uid = e_source_get_uid (default_source);
2804 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2807 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2808 g_settings_set_string (registry->priv->settings, key, uid);
2810 /* The GSettings::changed signal will trigger a "notify" signal
2811 * from the registry, so no need to call g_object_notify() here. */
2814 /* Helper for e_source_registry_ref_default_mail_identity() */
2816 source_registry_ref_any_mail_identity (ESourceRegistry *registry)
2820 const gchar *extension_name;
2823 /* First fallback: Return the mail identity named
2824 * by the default mail account. */
2826 source = e_source_registry_ref_default_mail_account (registry);
2828 /* This should never be NULL, but just to be safe. */
2829 if (source != NULL) {
2830 ESourceMailAccount *extension;
2832 extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
2833 extension = e_source_get_extension (source, extension_name);
2834 uid = e_source_mail_account_dup_identity_uid (extension);
2836 g_object_unref (source);
2841 source = e_source_registry_ref_source (registry, uid);
2848 /* Second fallback: Pick any available mail identity,
2849 * preferring enabled identities. */
2851 extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
2852 list = e_source_registry_list_sources (registry, extension_name);
2854 for (link = list; link != NULL; link = g_list_next (link)) {
2855 ESource *candidate = E_SOURCE (link->data);
2857 if (e_source_get_enabled (candidate)) {
2858 source = g_object_ref (candidate);
2863 if (source == NULL && list != NULL)
2864 source = g_object_ref (list->data);
2866 g_list_free_full (list, (GDestroyNotify) g_object_unref);
2872 * e_source_registry_ref_default_mail_identity:
2873 * @registry: an #ESourceRegistry
2875 * Returns the #ESource most recently passed to
2876 * e_source_registry_set_default_mail_identity() either in this session
2877 * or a previous session, or else falls back to the mail identity named
2878 * by the default mail account. If even that fails it returns any mail
2879 * identity from @registry, or %NULL if there are none.
2881 * The returned #ESource is referenced for thread-safety and must be
2882 * unreferenced with g_object_unref() when finished with it.
2884 * Returns: (transfer full): the default mail identity #ESource, or %NULL
2889 e_source_registry_ref_default_mail_identity (ESourceRegistry *registry)
2895 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2897 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
2898 uid = g_settings_get_string (registry->priv->settings, key);
2899 source = e_source_registry_ref_source (registry, uid);
2903 source = source_registry_ref_any_mail_identity (registry);
2909 * e_source_registry_set_default_mail_identity:
2910 * @registry: an #ESourceRegistry
2911 * @default_source: (allow-none): a mail identity #ESource, or %NULL
2913 * Sets @default_source as the default mail identity. If @default_source
2914 * is %NULL, the next request for the default mail identity will use the
2915 * fallbacks described in e_source_registry_get_default_mail_identity().
2920 e_source_registry_set_default_mail_identity (ESourceRegistry *registry,
2921 ESource *default_source)
2926 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2928 if (default_source != NULL) {
2929 g_return_if_fail (E_IS_SOURCE (default_source));
2930 uid = e_source_get_uid (default_source);
2932 uid = ""; /* no built-in mail identity */
2935 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
2936 g_settings_set_string (registry->priv->settings, key, uid);
2938 /* The GSettings::changed signal will trigger a "notify" signal
2939 * from the registry, so no need to call g_object_notify() here. */
2943 * e_source_registry_ref_builtin_memo_list:
2944 * @registry: an #ESourceRegistry
2946 * Returns the built-in memo list #ESource.
2948 * This #ESource is always present and makes for a safe fallback.
2950 * The returned #ESource is referenced for thread-safety and must be
2951 * unreferenced with g_object_unref() when finished with it.
2953 * Returns: (transfer full): the built-in memo list #ESource
2958 e_source_registry_ref_builtin_memo_list (ESourceRegistry *registry)
2963 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2965 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
2966 source = e_source_registry_ref_source (registry, uid);
2967 g_return_val_if_fail (source != NULL, NULL);
2973 * e_source_registry_ref_default_memo_list:
2974 * @registry: an #ESourceRegistry
2976 * Returns the #ESource most recently passed to
2977 * e_source_registry_set_default_memo_list() either in this session
2978 * or a previous session, or else falls back to the built-in memo list.
2980 * The returned #ESource is referenced for thread-safety and must be
2981 * unreferenced with g_object_unref() when finished with it.
2983 * Returns: (transfer full): the default memo list #ESource
2988 e_source_registry_ref_default_memo_list (ESourceRegistry *registry)
2994 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2996 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
2997 uid = g_settings_get_string (registry->priv->settings, key);
2998 source = e_source_registry_ref_source (registry, uid);
3001 /* The built-in source is always present. */
3003 source = e_source_registry_ref_builtin_memo_list (registry);
3005 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3011 * e_source_registry_set_default_memo_list:
3012 * @registry: an #ESourceRegistry
3013 * @default_source: (allow-none): a memo list #ESource, or %NULL
3015 * Sets @default_source as the default memo list. If @default_source
3016 * is %NULL, the default memo list is reset to the built-in memo list.
3017 * This setting will persist across sessions until changed.
3022 e_source_registry_set_default_memo_list (ESourceRegistry *registry,
3023 ESource *default_source)
3028 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3030 if (default_source != NULL) {
3031 g_return_if_fail (E_IS_SOURCE (default_source));
3032 uid = e_source_get_uid (default_source);
3034 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3037 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3038 g_settings_set_string (registry->priv->settings, key, uid);
3040 /* The GSettings::changed signal will trigger a "notify" signal
3041 * from the registry, so no need to call g_object_notify() here. */
3045 * e_source_registry_ref_builtin_task_list:
3046 * @registry: an #ESourceRegistry
3048 * Returns the built-in task list #ESource.
3050 * This #ESource is always present and makes for a safe fallback.
3052 * The returned #ESource is referenced for thread-safety and must be
3053 * unreferenced with g_object_unref() when finished with it.
3055 * Returns: (transfer full): the built-in task list #ESource
3060 e_source_registry_ref_builtin_task_list (ESourceRegistry *registry)
3065 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3067 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3068 source = e_source_registry_ref_source (registry, uid);
3069 g_return_val_if_fail (source != NULL, NULL);
3075 * e_source_registry_ref_default_task_list:
3076 * @registry: an #ESourceRegistry
3078 * Returns the #ESource most recently passed to
3079 * e_source_registry_set_default_task_list() either in this session
3080 * or a previous session, or else falls back to the built-in task list.
3082 * The returned #ESource is referenced for thread-safety and must be
3083 * unreferenced with g_object_unref() when finished with it.
3085 * Returns: (transfer full): the default task list #ESource
3090 e_source_registry_ref_default_task_list (ESourceRegistry *registry)
3096 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3098 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3099 uid = g_settings_get_string (registry->priv->settings, key);
3100 source = e_source_registry_ref_source (registry, uid);
3103 /* The built-in source is always present. */
3105 source = e_source_registry_ref_builtin_task_list (registry);
3107 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3113 * e_source_registry_set_default_task_list:
3114 * @registry: an #ESourceRegistry
3115 * @default_source: (allow-none): a task list #ESource, or %NULL
3117 * Sets @default_source as the default task list. If @default_source
3118 * is %NULL, the default task list is reset to the built-in task list.
3119 * This setting will persist across sessions until changed.
3124 e_source_registry_set_default_task_list (ESourceRegistry *registry,
3125 ESource *default_source)
3130 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3132 if (default_source != NULL) {
3133 g_return_if_fail (E_IS_SOURCE (default_source));
3134 uid = e_source_get_uid (default_source);
3136 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3139 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3140 g_settings_set_string (registry->priv->settings, key, uid);
3142 /* The GSettings::changed signal will trigger a "notify" signal
3143 * from the registry, so no need to call g_object_notify() here. */
3147 * e_source_registry_ref_default_for_extension_name:
3148 * @registry: an #ESourceRegistry
3149 * @extension_name: an extension_name
3151 * This is a convenience function to return a default #ESource based on
3152 * @extension_name. This only works with a subset of extension names.
3154 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3155 * returns the current default address book, or else falls back to the
3156 * built-in address book.
3158 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function returns
3159 * the current default calendar, or else falls back to the built-in calendar.
3161 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3162 * returns the current default mail account, or else falls back to the
3163 * built-in mail account.
3165 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3166 * returns the current default mail identity, or else falls back to the
3167 * mail identity named by the current default mail account.
3169 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function returns
3170 * the current default memo list, or else falls back to the built-in memo list.
3172 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function returns
3173 * the current default task list, or else falls back to the built-in task list.
3175 * For all other values of @extension_name, the function returns %NULL.
3177 * The returned #ESource is referenced for thread-safety and must be
3178 * unreferenced with g_object_unref() when finished with it.
3180 * Returns: (transfer full): the default #ESource based on @extension_name
3185 e_source_registry_ref_default_for_extension_name (ESourceRegistry *registry,
3186 const gchar *extension_name)
3188 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3189 g_return_val_if_fail (extension_name != NULL, NULL);
3191 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3192 return e_source_registry_ref_default_address_book (registry);
3194 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3195 return e_source_registry_ref_default_calendar (registry);
3197 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3198 return e_source_registry_ref_default_mail_account (registry);
3200 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3201 return e_source_registry_ref_default_mail_identity (registry);
3203 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3204 return e_source_registry_ref_default_memo_list (registry);
3206 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3207 return e_source_registry_ref_default_task_list (registry);
3213 * e_source_registry_set_default_for_extension_name:
3214 * @registry: an #ESourceRegistry
3215 * @extension_name: an extension name
3216 * @default_source: (allow-none): an #ESource, or %NULL
3218 * This is a convenience function to set a default #ESource based on
3219 * @extension_name. This only works with a subset of extension names.
3221 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3222 * sets @default_source as the default address book. If @default_source
3223 * is %NULL, the default address book is reset to the built-in address book.
3225 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function sets
3226 * @default_source as the default calendar. If @default_source is %NULL,
3227 * the default calendar is reset to the built-in calendar.
3229 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3230 * sets @default_source as the default mail account. If @default_source
3231 * is %NULL, the default mail account is reset to the built-in mail account.
3233 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3234 * sets @default_source as the default mail identity. If @default_source
3235 * is %NULL, the next request for the default mail identity will return
3236 * the mail identity named by the default mail account.
3238 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function sets
3239 * @default_source as the default memo list. If @default_source is %NULL,
3240 * the default memo list is reset to the built-in memo list.
3242 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function sets
3243 * @default_source as the default task list. If @default_source is %NULL,
3244 * the default task list is reset to the built-in task list.
3246 * For all other values of @extension_name, the function does nothing.
3251 e_source_registry_set_default_for_extension_name (ESourceRegistry *registry,
3252 const gchar *extension_name,
3253 ESource *default_source)
3255 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3256 g_return_if_fail (extension_name != NULL);
3258 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3259 e_source_registry_set_default_address_book (
3260 registry, default_source);
3262 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3263 e_source_registry_set_default_calendar (
3264 registry, default_source);
3266 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3267 e_source_registry_set_default_mail_account (
3268 registry, default_source);
3270 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3271 e_source_registry_set_default_mail_identity (
3272 registry, default_source);
3274 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3275 e_source_registry_set_default_memo_list (
3276 registry, default_source);
3278 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3279 e_source_registry_set_default_task_list (
3280 registry, default_source);