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 typedef struct _AsyncContext AsyncContext;
91 typedef struct _AuthContext AuthContext;
92 typedef struct _SourceClosure SourceClosure;
93 typedef struct _ThreadClosure ThreadClosure;
95 struct _ESourceRegistryPrivate {
96 GMainContext *main_context;
98 GThread *manager_thread;
99 ThreadClosure *thread_closure;
101 GDBusObjectManager *dbus_object_manager;
102 EDBusSourceManager *dbus_source_manager;
104 GHashTable *object_path_table;
105 GMutex *object_path_table_lock;
108 GMutex *sources_lock;
113 struct _AsyncContext {
115 GList *list_of_sources;
116 ESourceAuthenticator *auth;
119 /* Used in e_source_registry_authenticate_sync() */
120 struct _AuthContext {
121 ESourceAuthenticator *auth;
122 EDBusAuthenticator *dbus_auth;
123 GCancellable *cancellable;
124 GMainLoop *main_loop;
125 ESourceAuthenticationResult auth_result;
126 GcrSecretExchange *secret_exchange;
127 gboolean authenticating;
132 struct _SourceClosure {
133 ESourceRegistry *registry;
137 struct _ThreadClosure {
138 ESourceRegistry *registry;
139 GMainContext *main_context;
140 GMainLoop *main_loop;
141 GCond *main_loop_cond;
142 GMutex *main_loop_mutex;
147 PROP_DEFAULT_ADDRESS_BOOK,
148 PROP_DEFAULT_CALENDAR,
149 PROP_DEFAULT_MAIL_ACCOUNT,
150 PROP_DEFAULT_MAIL_IDENTITY,
151 PROP_DEFAULT_MEMO_LIST,
152 PROP_DEFAULT_TASK_LIST
164 /* Forward Declarations */
165 static void source_registry_add_source (ESourceRegistry *registry,
167 static void e_source_registry_initable_init (GInitableIface *interface);
169 static guint signals[LAST_SIGNAL];
171 /* By default, the GAsyncInitable interface calls GInitable.init()
172 * from a separate thread, so we only have to override GInitable. */
173 G_DEFINE_TYPE_WITH_CODE (
177 G_IMPLEMENT_INTERFACE (
178 G_TYPE_INITABLE, e_source_registry_initable_init)
179 G_IMPLEMENT_INTERFACE (
180 G_TYPE_ASYNC_INITABLE, NULL))
183 async_context_free (AsyncContext *async_context)
185 if (async_context->source != NULL)
186 g_object_unref (async_context->source);
189 async_context->list_of_sources,
190 (GDestroyNotify) g_object_unref);
192 if (async_context->auth != NULL)
193 g_object_unref (async_context->auth);
195 g_slice_free (AsyncContext, async_context);
199 auth_context_free (AuthContext *auth_context)
201 if (auth_context->auth != NULL)
202 g_object_unref (auth_context->auth);
204 if (auth_context->dbus_auth != NULL)
205 g_object_unref (auth_context->dbus_auth);
207 if (auth_context->cancellable != NULL)
208 g_object_unref (auth_context->cancellable);
210 if (auth_context->main_loop != NULL)
211 g_main_loop_unref (auth_context->main_loop);
213 if (auth_context->secret_exchange != NULL)
214 g_object_unref (auth_context->secret_exchange);
216 g_slice_free (AuthContext, auth_context);
220 source_closure_free (SourceClosure *closure)
222 g_object_unref (closure->registry);
223 g_object_unref (closure->source);
225 g_slice_free (SourceClosure, closure);
229 thread_closure_free (ThreadClosure *closure)
231 /* The registry member is not referenced. */
233 g_main_context_unref (closure->main_context);
234 g_main_loop_unref (closure->main_loop);
235 g_cond_free (closure->main_loop_cond);
236 g_mutex_free (closure->main_loop_mutex);
238 g_slice_free (ThreadClosure, closure);
242 source_registry_object_path_table_insert (ESourceRegistry *registry,
243 const gchar *object_path,
246 g_return_if_fail (object_path != NULL);
247 g_return_if_fail (E_IS_SOURCE (source));
249 g_mutex_lock (registry->priv->object_path_table_lock);
251 g_hash_table_insert (
252 registry->priv->object_path_table,
253 g_strdup (object_path),
254 g_object_ref (source));
256 g_mutex_unlock (registry->priv->object_path_table_lock);
260 source_registry_object_path_table_lookup (ESourceRegistry *registry,
261 const gchar *object_path)
265 g_return_val_if_fail (object_path != NULL, NULL);
267 g_mutex_lock (registry->priv->object_path_table_lock);
269 source = g_hash_table_lookup (
270 registry->priv->object_path_table, object_path);
272 g_object_ref (source);
274 g_mutex_unlock (registry->priv->object_path_table_lock);
280 source_registry_object_path_table_remove (ESourceRegistry *registry,
281 const gchar *object_path)
285 g_return_val_if_fail (object_path != NULL, FALSE);
287 g_mutex_lock (registry->priv->object_path_table_lock);
289 removed = g_hash_table_remove (
290 registry->priv->object_path_table, object_path);
292 g_mutex_unlock (registry->priv->object_path_table_lock);
298 source_registry_sources_insert (ESourceRegistry *registry,
303 uid = e_source_get_uid (source);
304 g_return_if_fail (uid != NULL);
306 g_mutex_lock (registry->priv->sources_lock);
308 g_hash_table_insert (
309 registry->priv->sources,
310 g_strdup (uid), g_object_ref (source));
312 g_mutex_unlock (registry->priv->sources_lock);
316 source_registry_sources_remove (ESourceRegistry *registry,
322 uid = e_source_get_uid (source);
323 g_return_val_if_fail (uid != NULL, FALSE);
325 g_mutex_lock (registry->priv->sources_lock);
327 removed = g_hash_table_remove (registry->priv->sources, uid);
329 g_mutex_unlock (registry->priv->sources_lock);
335 source_registry_sources_lookup (ESourceRegistry *registry,
340 g_return_val_if_fail (uid != NULL, NULL);
342 g_mutex_lock (registry->priv->sources_lock);
344 source = g_hash_table_lookup (registry->priv->sources, uid);
347 g_object_ref (source);
349 g_mutex_unlock (registry->priv->sources_lock);
355 source_registry_sources_get_values (ESourceRegistry *registry)
359 g_mutex_lock (registry->priv->sources_lock);
361 values = g_hash_table_get_values (registry->priv->sources);
363 g_list_foreach (values, (GFunc) g_object_ref, NULL);
365 g_mutex_unlock (registry->priv->sources_lock);
371 source_registry_sources_build_tree (ESourceRegistry *registry)
378 g_mutex_lock (registry->priv->sources_lock);
380 root = g_node_new (NULL);
381 index = g_hash_table_new (g_str_hash, g_str_equal);
383 /* Add a GNode for each ESource to the index. */
384 g_hash_table_iter_init (&iter, registry->priv->sources);
385 while (g_hash_table_iter_next (&iter, &key, &value)) {
386 ESource *source = g_object_ref (value);
387 g_hash_table_insert (index, key, g_node_new (source));
390 /* Traverse the index and link the nodes together. */
391 g_hash_table_iter_init (&iter, index);
392 while (g_hash_table_iter_next (&iter, NULL, &value)) {
396 const gchar *parent_uid;
398 source_node = (GNode *) value;
399 source = E_SOURCE (source_node->data);
400 parent_uid = e_source_get_parent (source);
402 if (parent_uid == NULL || *parent_uid == '\0') {
405 parent_node = g_hash_table_lookup (index, parent_uid);
406 g_warn_if_fail (parent_node != NULL);
409 /* Should never be NULL, but just to be safe. */
410 if (parent_node != NULL)
411 g_node_append (parent_node, source_node);
414 g_hash_table_destroy (index);
416 g_mutex_unlock (registry->priv->sources_lock);
422 source_registry_settings_changed_cb (GSettings *settings,
424 ESourceRegistry *registry)
426 /* We define a property name that matches every key in
427 * the "org.gnome.Evolution.DefaultSources" schema. */
428 g_object_notify (G_OBJECT (registry), key);
432 source_registry_source_changed_idle_cb (gpointer user_data)
434 SourceClosure *closure = user_data;
438 signals[SOURCE_CHANGED], 0,
445 source_registry_source_notify_enabled_idle_cb (gpointer user_data)
447 SourceClosure *closure = user_data;
449 if (e_source_get_enabled (closure->source))
452 signals[SOURCE_ENABLED], 0,
457 signals[SOURCE_DISABLED], 0,
464 source_registry_source_changed_cb (ESource *source,
465 ESourceRegistry *registry)
467 GSource *idle_source;
468 SourceClosure *closure;
470 closure = g_slice_new0 (SourceClosure);
471 closure->registry = g_object_ref (registry);
472 closure->source = g_object_ref (source);
474 idle_source = g_idle_source_new ();
475 g_source_set_callback (
477 source_registry_source_changed_idle_cb,
478 closure, (GDestroyNotify) source_closure_free);
479 g_source_attach (idle_source, registry->priv->main_context);
480 g_source_unref (idle_source);
484 source_registry_source_notify_enabled_cb (ESource *source,
486 ESourceRegistry *registry)
488 GSource *idle_source;
489 SourceClosure *closure;
491 closure = g_slice_new0 (SourceClosure);
492 closure->registry = g_object_ref (registry);
493 closure->source = g_object_ref (source);
495 idle_source = g_idle_source_new ();
496 g_source_set_callback (
498 source_registry_source_notify_enabled_idle_cb,
499 closure, (GDestroyNotify) source_closure_free);
500 g_source_attach (idle_source, registry->priv->main_context);
501 g_source_unref (idle_source);
505 source_registry_unref_source (ESource *source)
507 g_signal_handlers_disconnect_matched (
508 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
509 source_registry_source_changed_cb, NULL);
511 g_signal_handlers_disconnect_matched (
512 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
513 source_registry_source_notify_enabled_cb, NULL);
515 g_object_unref (source);
519 source_registry_add_source (ESourceRegistry *registry,
524 uid = e_source_get_uid (source);
525 g_return_if_fail (uid != NULL);
527 g_mutex_lock (registry->priv->sources_lock);
529 /* Check if we already have this source in the registry. */
530 if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
531 g_mutex_unlock (registry->priv->sources_lock);
537 G_CALLBACK (source_registry_source_changed_cb),
541 source, "notify::enabled",
542 G_CALLBACK (source_registry_source_notify_enabled_cb),
545 g_mutex_unlock (registry->priv->sources_lock);
547 source_registry_sources_insert (registry, source);
549 g_signal_emit (registry, signals[SOURCE_ADDED], 0, source);
553 source_registry_remove_source (ESourceRegistry *registry,
556 g_object_ref (source);
558 if (source_registry_sources_remove (registry, source))
559 g_signal_emit (registry, signals[SOURCE_REMOVED], 0, source);
561 g_object_unref (source);
565 source_registry_object_added_idle_cb (gpointer user_data)
567 SourceClosure *closure = user_data;
569 source_registry_add_source (closure->registry, closure->source);
575 source_registry_object_added_cb (GDBusObjectManager *object_manager,
576 GDBusObject *dbus_object,
577 ESourceRegistry *registry)
579 SourceClosure *closure;
580 GMainContext *main_context;
581 GSource *idle_source;
583 const gchar *object_path;
584 GError *error = NULL;
586 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
588 /* We don't want the ESource emitting "changed" signals from
589 * the manager thread, so we pass it the same main context the
590 * registry uses for scheduling signal emissions. */
591 main_context = registry->priv->main_context;
592 source = e_source_new (dbus_object, main_context, &error);
593 object_path = g_dbus_object_get_object_path (dbus_object);
595 /* The likelihood of an error here is slim, so it's
596 * sufficient to just print a warning if one occurs. */
598 g_warn_if_fail (source == NULL);
600 "ESourceRegistry: Failed to create a "
601 "data source object for path '%s': %s",
602 object_path, error->message);
603 g_error_free (error);
607 g_return_if_fail (E_IS_SOURCE (source));
609 /* Add the ESource to the object path table immediately. */
610 source_registry_object_path_table_insert (
611 registry, object_path, source);
613 /* Schedule a callback on the ESourceRegistry's GMainContext. */
615 closure = g_slice_new0 (SourceClosure);
616 closure->registry = g_object_ref (registry);
617 closure->source = g_object_ref (source);
619 idle_source = g_idle_source_new ();
620 g_source_set_callback (
622 source_registry_object_added_idle_cb,
623 closure, (GDestroyNotify) source_closure_free);
624 g_source_attach (idle_source, registry->priv->main_context);
625 g_source_unref (idle_source);
627 g_object_unref (source);
631 source_registry_object_removed_idle_cb (gpointer user_data)
633 SourceClosure *closure = user_data;
635 source_registry_remove_source (closure->registry, closure->source);
641 source_registry_object_removed_cb (GDBusObjectManager *manager,
642 GDBusObject *dbus_object,
643 ESourceRegistry *registry)
645 SourceClosure *closure;
646 GSource *idle_source;
648 const gchar *object_path;
650 /* Find the corresponding ESource in the object path table.
651 * Note that the lookup returns a new ESource reference. */
652 object_path = g_dbus_object_get_object_path (dbus_object);
653 source = source_registry_object_path_table_lookup (
654 registry, object_path);
655 g_return_if_fail (E_IS_SOURCE (source));
657 /* Remove the ESource from the object path table immediately. */
658 source_registry_object_path_table_remove (registry, object_path);
660 /* Schedule a callback on the ESourceRegistry's GMainContext. */
662 closure = g_slice_new0 (SourceClosure);
663 closure->registry = g_object_ref (registry);
664 closure->source = g_object_ref (source);
666 idle_source = g_idle_source_new ();
667 g_source_set_callback (
669 source_registry_object_removed_idle_cb,
670 closure, (GDestroyNotify) source_closure_free);
671 g_source_attach (idle_source, registry->priv->main_context);
672 g_source_unref (idle_source);
674 g_object_unref (source);
678 source_registry_object_manager_running (gpointer data)
680 ThreadClosure *closure = data;
682 g_mutex_lock (closure->main_loop_mutex);
683 g_cond_broadcast (closure->main_loop_cond);
684 g_mutex_unlock (closure->main_loop_mutex);
690 source_registry_object_manager_thread (gpointer data)
692 GDBusObjectManager *object_manager;
693 ThreadClosure *closure = data;
694 GSource *idle_source;
696 gulong object_added_id;
697 gulong object_removed_id;
698 GError *error = NULL;
700 /* GDBusObjectManagerClient grabs the thread-default GMainContext
701 * at creation time and only emits signals from that GMainContext.
702 * Running it in a separate thread prevents its signal emissions
703 * from being inhibited by someone overriding the thread-default
706 /* This becomes the GMainContext that GDBusObjectManagerClient
707 * will emit signals from. Make it the thread-default context
708 * for this thread before creating the client. */
709 g_main_context_push_thread_default (closure->main_context);
711 object_manager = e_dbus_object_manager_client_new_for_bus_sync (
713 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
714 SOURCES_DBUS_SERVICE_NAME,
718 /* If this fails there's really no point in continuing
719 * since we rely on the object manager to populate the
720 * registry. Abort the process with a fatal error. */
722 g_error ("%s", error->message);
723 g_assert_not_reached ();
726 /* Give the registry a handle to the object manager. */
727 closure->registry->priv->dbus_object_manager =
728 g_object_ref (object_manager);
730 /* Now populate the registry with an initial set of ESources. */
732 list = g_dbus_object_manager_get_objects (object_manager);
734 for (link = list; link != NULL; link = g_list_next (link))
735 source_registry_object_added_cb (
737 G_DBUS_OBJECT (link->data),
740 g_list_free_full (list, (GDestroyNotify) g_object_unref);
742 /* Schedule a one-time idle callback to broadcast through a
743 * condition variable that our main loop is up and running. */
745 idle_source = g_idle_source_new ();
746 g_source_set_callback (
748 source_registry_object_manager_running,
749 closure, (GDestroyNotify) NULL);
750 g_source_attach (idle_source, closure->main_context);
751 g_source_unref (idle_source);
753 /* Listen for D-Bus object additions and removals. */
755 object_added_id = g_signal_connect (
756 object_manager, "object-added",
757 G_CALLBACK (source_registry_object_added_cb),
760 object_removed_id = g_signal_connect (
761 object_manager, "object-removed",
762 G_CALLBACK (source_registry_object_removed_cb),
765 /* Now we mostly idle here for the rest of the session. */
767 g_main_loop_run (closure->main_loop);
769 /* Clean up and exit. */
771 g_signal_handler_disconnect (object_manager, object_added_id);
772 g_signal_handler_disconnect (object_manager, object_removed_id);
774 g_object_unref (object_manager);
776 g_main_context_pop_thread_default (closure->main_context);
782 source_registry_set_property (GObject *object,
787 switch (property_id) {
788 case PROP_DEFAULT_ADDRESS_BOOK:
789 e_source_registry_set_default_address_book (
790 E_SOURCE_REGISTRY (object),
791 g_value_get_object (value));
794 case PROP_DEFAULT_CALENDAR:
795 e_source_registry_set_default_calendar (
796 E_SOURCE_REGISTRY (object),
797 g_value_get_object (value));
800 case PROP_DEFAULT_MAIL_ACCOUNT:
801 e_source_registry_set_default_mail_account (
802 E_SOURCE_REGISTRY (object),
803 g_value_get_object (value));
806 case PROP_DEFAULT_MAIL_IDENTITY:
807 e_source_registry_set_default_mail_identity (
808 E_SOURCE_REGISTRY (object),
809 g_value_get_object (value));
812 case PROP_DEFAULT_MEMO_LIST:
813 e_source_registry_set_default_memo_list (
814 E_SOURCE_REGISTRY (object),
815 g_value_get_object (value));
818 case PROP_DEFAULT_TASK_LIST:
819 e_source_registry_set_default_task_list (
820 E_SOURCE_REGISTRY (object),
821 g_value_get_object (value));
825 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
829 source_registry_get_property (GObject *object,
834 switch (property_id) {
835 case PROP_DEFAULT_ADDRESS_BOOK:
836 g_value_take_object (
838 e_source_registry_ref_default_address_book (
839 E_SOURCE_REGISTRY (object)));
842 case PROP_DEFAULT_CALENDAR:
843 g_value_take_object (
845 e_source_registry_ref_default_calendar (
846 E_SOURCE_REGISTRY (object)));
849 case PROP_DEFAULT_MAIL_ACCOUNT:
850 g_value_take_object (
852 e_source_registry_ref_default_mail_account (
853 E_SOURCE_REGISTRY (object)));
856 case PROP_DEFAULT_MAIL_IDENTITY:
857 g_value_take_object (
859 e_source_registry_ref_default_mail_identity (
860 E_SOURCE_REGISTRY (object)));
863 case PROP_DEFAULT_MEMO_LIST:
864 g_value_take_object (
866 e_source_registry_ref_default_memo_list (
867 E_SOURCE_REGISTRY (object)));
870 case PROP_DEFAULT_TASK_LIST:
871 g_value_take_object (
873 e_source_registry_ref_default_task_list (
874 E_SOURCE_REGISTRY (object)));
878 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
882 source_registry_dispose (GObject *object)
884 ESourceRegistryPrivate *priv;
886 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
888 /* Terminate the manager thread first. */
889 if (priv->manager_thread != NULL) {
890 g_main_loop_quit (priv->thread_closure->main_loop);
891 g_thread_join (priv->manager_thread);
892 thread_closure_free (priv->thread_closure);
893 priv->manager_thread = NULL;
894 priv->thread_closure = NULL;
897 if (priv->main_context != NULL) {
898 g_main_context_unref (priv->main_context);
899 priv->main_context = NULL;
902 if (priv->dbus_object_manager != NULL) {
903 g_object_unref (priv->dbus_object_manager);
904 priv->dbus_object_manager = NULL;
907 if (priv->dbus_source_manager != NULL) {
908 g_object_unref (priv->dbus_source_manager);
909 priv->dbus_source_manager = NULL;
912 g_hash_table_remove_all (priv->object_path_table);
914 g_hash_table_remove_all (priv->sources);
916 if (priv->settings != NULL) {
917 g_object_unref (priv->settings);
918 priv->settings = NULL;
921 /* Chain up to parent's finalize() method. */
922 G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
926 source_registry_finalize (GObject *object)
928 ESourceRegistryPrivate *priv;
930 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
932 g_hash_table_destroy (priv->object_path_table);
933 g_mutex_free (priv->object_path_table_lock);
935 g_hash_table_destroy (priv->sources);
936 g_mutex_free (priv->sources_lock);
938 /* Chain up to parent's finalize() method. */
939 G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
943 source_registry_initable_init (GInitable *initable,
944 GCancellable *cancellable,
947 ESourceRegistry *registry;
948 ThreadClosure *closure;
950 registry = E_SOURCE_REGISTRY (initable);
952 closure = g_slice_new0 (ThreadClosure);
953 closure->registry = registry; /* do not reference */
954 closure->main_context = g_main_context_new ();
955 /* It's important to pass 'is_running=FALSE' here because
956 * we wait for the main loop to start running as a way of
957 * synchronizing with the manager thread. */
958 closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
959 closure->main_loop_cond = g_cond_new ();
960 closure->main_loop_mutex = g_mutex_new ();
962 registry->priv->thread_closure = closure;
964 registry->priv->manager_thread = g_thread_create (
965 source_registry_object_manager_thread,
966 closure, TRUE /* joinable */, error);
968 if (registry->priv->manager_thread == NULL)
971 /* Wait for notification that the manager
972 * thread's main loop has been started. */
973 g_mutex_lock (closure->main_loop_mutex);
974 while (!g_main_loop_is_running (closure->main_loop))
976 closure->main_loop_cond,
977 closure->main_loop_mutex);
978 g_mutex_unlock (closure->main_loop_mutex);
980 /* We should now have a GDBusObjectManagerClient available. */
981 g_return_val_if_fail (
982 G_IS_DBUS_OBJECT_MANAGER_CLIENT (
983 registry->priv->dbus_object_manager), FALSE);
985 /* The manager thread will have queued up a bunch of idle
986 * sources on our GMainContext to populate the registry.
987 * Iterate our GMainContext until they get dispatched. */
988 while (g_hash_table_size (registry->priv->sources) == 0)
989 g_main_context_iteration (registry->priv->main_context, TRUE);
991 /* The EDBusSourceManagerProxy is just another D-Bus interface
992 * that resides at the same object path. It's unrelated to the
993 * GDBusObjectManagerClient and doesn't need its own thread. */
994 registry->priv->dbus_source_manager =
995 e_dbus_source_manager_proxy_new_for_bus_sync (
997 G_DBUS_PROXY_FLAGS_NONE,
998 SOURCES_DBUS_SERVICE_NAME,
1000 cancellable, error);
1002 if (registry->priv->dbus_source_manager == NULL)
1009 e_source_registry_class_init (ESourceRegistryClass *class)
1011 GObjectClass *object_class;
1013 g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
1015 object_class = G_OBJECT_CLASS (class);
1016 object_class->set_property = source_registry_set_property;
1017 object_class->get_property = source_registry_get_property;
1018 object_class->dispose = source_registry_dispose;
1019 object_class->finalize = source_registry_finalize;
1021 /* The property names correspond to the key names in the
1022 * "org.gnome.Evolution.DefaultSources" GSettings schema. */
1025 * ESourceRegistry:default-address-book
1027 * The default address book #ESource.
1029 g_object_class_install_property (
1031 PROP_DEFAULT_ADDRESS_BOOK,
1032 g_param_spec_object (
1033 "default-address-book",
1034 "Default Address Book",
1035 "The default address book ESource",
1038 G_PARAM_STATIC_STRINGS));
1041 * ESourceRegistry:default-calendar
1043 * The default calendar #ESource.
1045 g_object_class_install_property (
1047 PROP_DEFAULT_CALENDAR,
1048 g_param_spec_object (
1051 "The default calendar ESource",
1054 G_PARAM_STATIC_STRINGS));
1057 * ESourceRegistry:default-mail-account
1059 * The default mail account #ESource.
1061 g_object_class_install_property (
1063 PROP_DEFAULT_MAIL_ACCOUNT,
1064 g_param_spec_object (
1065 "default-mail-account",
1066 "Default Mail Account",
1067 "The default mail account ESource",
1070 G_PARAM_STATIC_STRINGS));
1073 * ESourceRegistry:default-mail-identity
1075 * The default mail identity #ESource.
1077 g_object_class_install_property (
1079 PROP_DEFAULT_MAIL_IDENTITY,
1080 g_param_spec_object (
1081 "default-mail-identity",
1082 "Default Mail Identity",
1083 "The default mail identity ESource",
1086 G_PARAM_STATIC_STRINGS));
1089 * ESourceRegistry:default-memo-list
1091 * The default memo list #ESource.
1093 g_object_class_install_property (
1095 PROP_DEFAULT_MEMO_LIST,
1096 g_param_spec_object (
1097 "default-memo-list",
1098 "Default Memo List",
1099 "The default memo list ESource",
1102 G_PARAM_STATIC_STRINGS));
1105 * ESourceRegistry:default-task-list
1107 * The default task list #ESource.
1109 g_object_class_install_property (
1111 PROP_DEFAULT_TASK_LIST,
1112 g_param_spec_object (
1113 "default-task-list",
1114 "Default Task List",
1115 "The default task list ESource",
1118 G_PARAM_STATIC_STRINGS));
1121 * ESourceRegistry::source-added:
1122 * @registry: the #ESourceRegistry which emitted the signal
1123 * @source: the newly-added #ESource
1125 * Emitted when an #ESource is added to @registry.
1127 signals[SOURCE_ADDED] = g_signal_new (
1129 G_OBJECT_CLASS_TYPE (object_class),
1131 G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
1133 g_cclosure_marshal_VOID__OBJECT,
1138 * ESourceRegistry::source-changed
1139 * @registry: the #ESourceRegistry which emitted the signal
1140 * @source: the #ESource that changed
1142 * Emitted when an #ESource registered with @registry emits
1143 * its #ESource::changed signal.
1145 signals[SOURCE_CHANGED] = g_signal_new (
1147 G_OBJECT_CLASS_TYPE (object_class),
1149 G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
1151 g_cclosure_marshal_VOID__OBJECT,
1156 * ESourceRegistry::source-removed:
1157 * @registry: the #ESourceRegistry which emitted the signal
1158 * @source: the #ESource that got removed
1160 * Emitted when an #ESource is removed from @registry.
1162 signals[SOURCE_REMOVED] = g_signal_new (
1164 G_OBJECT_CLASS_TYPE (object_class),
1166 G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
1168 g_cclosure_marshal_VOID__OBJECT,
1173 * ESourceRegistry::source-enabled:
1174 * @registry: the #ESourceRegistry which emitted the signal
1175 * @source: the #ESource that got enabled
1177 * Emitted when an #ESource #ESource:enabled property becomes %TRUE.
1179 signals[SOURCE_ENABLED] = g_signal_new (
1181 G_OBJECT_CLASS_TYPE (object_class),
1183 G_STRUCT_OFFSET (ESourceRegistryClass, source_enabled),
1185 g_cclosure_marshal_VOID__OBJECT,
1190 * ESourceRegistry::source-disabled:
1191 * @registry: the #ESourceRegistry which emitted the signal
1192 * @source: the #ESource that got disabled
1194 * Emitted when an #ESource #ESource:enabled property becomes %FALSE.
1196 signals[SOURCE_DISABLED] = g_signal_new (
1198 G_OBJECT_CLASS_TYPE (object_class),
1200 G_STRUCT_OFFSET (ESourceRegistryClass, source_disabled),
1202 g_cclosure_marshal_VOID__OBJECT,
1208 e_source_registry_initable_init (GInitableIface *interface)
1210 interface->init = source_registry_initable_init;
1214 e_source_registry_init (ESourceRegistry *registry)
1216 registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
1218 /* This is so the object manager thread can schedule signal
1219 * emissions on the thread-default context for this thread. */
1220 registry->priv->main_context = g_main_context_get_thread_default ();
1221 if (registry->priv->main_context != NULL)
1222 g_main_context_ref (registry->priv->main_context);
1224 /* D-Bus object path -> ESource */
1225 registry->priv->object_path_table =
1226 g_hash_table_new_full (
1227 (GHashFunc) g_str_hash,
1228 (GEqualFunc) g_str_equal,
1229 (GDestroyNotify) g_free,
1230 (GDestroyNotify) g_object_unref);
1232 registry->priv->object_path_table_lock = g_mutex_new ();
1234 /* UID string -> ESource */
1235 registry->priv->sources = g_hash_table_new_full (
1236 (GHashFunc) g_str_hash,
1237 (GEqualFunc) g_str_equal,
1238 (GDestroyNotify) g_free,
1239 (GDestroyNotify) source_registry_unref_source);
1241 registry->priv->sources_lock = g_mutex_new ();
1243 registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
1246 registry->priv->settings, "changed",
1247 G_CALLBACK (source_registry_settings_changed_cb), registry);
1251 * e_source_registry_new_sync:
1252 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1253 * @error: return location for a #GError, or %NULL
1255 * Creates a new #ESourceRegistry front-end for the registry D-Bus service.
1256 * If an error occurs in connecting to the D-Bus service, the function sets
1257 * @error and returns %NULL.
1259 * Returns: a new #ESourceRegistry, or %NULL
1264 e_source_registry_new_sync (GCancellable *cancellable,
1267 return g_initable_new (
1268 E_TYPE_SOURCE_REGISTRY,
1269 cancellable, error, NULL);
1273 * e_source_registry_new:
1274 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1275 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1277 * @user_data: (closure): data to pass to the callback function
1279 * Asynchronously creates a new #ESourceRegistry front-end for the registry
1282 * When the operation is finished, @callback will be called. You can then
1283 * call e_source_registry_new_finish() to get the result of the operation.
1288 e_source_registry_new (GCancellable *cancellable,
1289 GAsyncReadyCallback callback,
1292 g_async_initable_new_async (
1293 E_TYPE_SOURCE_REGISTRY,
1294 G_PRIORITY_DEFAULT, cancellable,
1295 callback, user_data, NULL);
1299 * e_source_registry_new_finish:
1300 * @result: a #GAsyncResult
1301 * @error: return location for a #GError, or %NULL
1303 * Finishes the operation started with e_source_registry_new_finish().
1304 * If an error occurs in connecting to the D-Bus service, the function
1305 * sets @error and returns %NULL.
1307 * Returns: a new #ESourceRegistry, or %NULL
1312 e_source_registry_new_finish (GAsyncResult *result,
1315 GObject *source_object;
1318 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1320 source_object = g_async_result_get_source_object (result);
1321 g_return_val_if_fail (source_object != NULL, NULL);
1323 object = g_async_initable_new_finish (
1324 G_ASYNC_INITABLE (source_object), result, error);
1326 g_object_unref (source_object);
1328 return (object != NULL) ? E_SOURCE_REGISTRY (object) : NULL;
1331 /* Helper for e_source_registry_authenticate() */
1333 source_registry_authenticate_thread (GSimpleAsyncResult *simple,
1335 GCancellable *cancellable)
1337 AsyncContext *async_context;
1338 GError *error = NULL;
1340 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1342 e_source_registry_authenticate_sync (
1343 E_SOURCE_REGISTRY (object),
1344 async_context->source,
1345 async_context->auth,
1346 cancellable, &error);
1349 g_simple_async_result_take_error (simple, error);
1352 /* Helper for e_source_registry_authenticate_sync() */
1354 source_registry_authenticate_respond_cb (AuthContext *auth_context)
1356 ESourceAuthenticationResult auth_result;
1357 GError *non_fatal_error = NULL;
1359 g_return_val_if_fail (auth_context->authenticating, FALSE);
1361 auth_result = auth_context->auth_result;
1363 /* Allow the next authentication attempt to proceed. */
1364 auth_context->authenticating = FALSE;
1366 /* Send the server a status update based on the authentication
1367 * result. Note, we don't really care if the D-Bus message gets
1368 * through to the server at this point. If it doesn't, the auth
1369 * session will either time out on its own or the authentication
1370 * dialog will eventually be dismissed by the user. */
1372 /* If an error occurred while attempting to authenticate,
1373 * tell the server to cancel the authentication session. */
1374 if (auth_result == E_SOURCE_AUTHENTICATION_ERROR) {
1375 e_dbus_authenticator_call_cancel_sync (
1376 auth_context->dbus_auth,
1377 auth_context->cancellable,
1379 g_main_loop_quit (auth_context->main_loop);
1380 auth_context->success = FALSE;
1382 /* If the password was accepted, let the server know so it
1383 * can close any authentication dialogs and save the user
1384 * provided password to the keyring. */
1385 } else if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
1386 e_dbus_authenticator_call_accepted_sync (
1387 auth_context->dbus_auth,
1388 auth_context->cancellable,
1390 g_main_loop_quit (auth_context->main_loop);
1391 auth_context->success = TRUE;
1393 /* If the password was rejected, let the server know so it can
1394 * indicate failure and request a different password, and then
1395 * wait for the next "response" signal. */
1397 e_dbus_authenticator_call_rejected_sync (
1398 auth_context->dbus_auth,
1399 auth_context->cancellable,
1403 /* Leave breadcrumbs if something went wrong,
1404 * but don't fail the whole operation over it. */
1405 if (non_fatal_error != NULL) {
1406 g_warning ("%s: %s", G_STRFUNC, non_fatal_error->message);
1407 g_error_free (non_fatal_error);
1413 /* Helper for e_source_registry_authenticate_sync() */
1415 source_registry_authenticate_authenticate_cb (EDBusAuthenticator *dbus_auth,
1416 const gchar *encrypted_secret,
1417 AuthContext *auth_context)
1419 GSource *idle_source;
1420 GMainContext *main_context;
1422 gboolean valid_secret;
1424 /* We should only get one secret at a time. */
1425 g_return_if_fail (!auth_context->authenticating);
1427 valid_secret = gcr_secret_exchange_receive (
1428 auth_context->secret_exchange, encrypted_secret);
1429 g_return_if_fail (valid_secret);
1431 auth_context->authenticating = TRUE;
1433 /* This avoids revealing the password in a stack trace. */
1434 password = g_string_new (
1435 gcr_secret_exchange_get_secret (
1436 auth_context->secret_exchange, NULL));
1438 /* Try authenticating with the given password. We have to
1439 * call this synchronously because some authenticators use
1440 * mutexes to serialize I/O operations and are not prepared
1441 * to make authentication attempts from a different thread.
1443 * Unfortunately this means we won't notice server-side
1444 * dismissals while the main loop is blocked. We respond
1445 * to the server from a low-priority idle callback so that
1446 * any pending "dismissed" signals get handled first. */
1448 auth_context->auth_result =
1449 e_source_authenticator_try_password_sync (
1450 auth_context->auth, password,
1451 auth_context->cancellable,
1452 auth_context->error);
1454 idle_source = g_idle_source_new ();
1455 main_context = g_main_context_get_thread_default ();
1456 g_source_set_callback (
1457 idle_source, (GSourceFunc)
1458 source_registry_authenticate_respond_cb,
1459 auth_context, NULL);
1460 g_source_attach (idle_source, main_context);
1461 g_source_unref (idle_source);
1463 g_string_free (password, TRUE);
1466 /* Helper for e_source_registry_authenticate_sync() */
1468 source_registry_authenticate_dismissed_cb (EDBusAuthenticator *dbus_auth,
1469 AuthContext *auth_context)
1471 /* Be careful not to overwrite an existing error in case this
1472 * is called after e_source_authenticator_try_password_sync()
1473 * but prior to the idle callback. */
1474 if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
1475 /* XXX Use a separate error code for dismissals? */
1476 g_set_error_literal (
1477 auth_context->error,
1478 G_IO_ERROR, G_IO_ERROR_CANCELLED,
1479 _("The user declined to authenticate"));
1480 auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
1483 g_main_loop_quit (auth_context->main_loop);
1484 auth_context->success = FALSE;
1487 /* Helper for e_source_registry_authenticate_sync() */
1489 source_registry_call_authenticate_for_source (ESourceRegistry *registry,
1490 ESourceAuthenticator *auth,
1492 gchar **out_object_path,
1493 GCancellable *cancellable,
1496 ESource *collection;
1498 gchar *prompt_title = NULL;
1499 gchar *prompt_message = NULL;
1500 gchar *prompt_description = NULL;
1503 /* If the source is a member of a collection, we want to store
1504 * the password under the UID of the "collection" source so it
1505 * will apply to the entire collection.
1507 * XXX This assumes all sources in a collection share a single
1508 * password. If that turns out not to be true in all cases
1509 * we could maybe add a "SharedPassword: true/false" key to
1510 * [Collection] and apply it here.
1512 collection = e_source_registry_find_extension (
1513 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1514 if (collection != NULL)
1515 source = collection;
1517 g_object_ref (source);
1519 uid = e_source_get_uid (source);
1521 e_source_authenticator_get_prompt_strings (
1525 &prompt_description);
1527 success = e_dbus_source_manager_call_authenticate_sync (
1528 registry->priv->dbus_source_manager, uid,
1529 prompt_title, prompt_message, prompt_description,
1530 out_object_path, cancellable, error);
1532 g_free (prompt_title);
1533 g_free (prompt_message);
1534 g_free (prompt_description);
1536 g_object_unref (source);
1542 * e_source_registry_authenticate_sync:
1543 * @registry: an #ESourceRegistry
1544 * @source: an #ESource
1545 * @auth: an #ESourceAuthenticator
1546 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1547 * @error: return location for a #GError, or %NULL
1549 * Authenticates @source, using @auth to handle the authentication
1550 * attempts. The operation loops until authentication is successful or
1551 * the user aborts further authentication attempts. If an error occurs,
1552 * the function will set @error and return %FALSE.
1554 * Note that @source need not have a #GDBusObject, which means this
1555 * function can test authentication on a scratch #ESource.
1557 * Only backend implementations and data source editors should call this
1558 * function. The intent is for basic client applications to not have to
1559 * deal with authentication at all.
1561 * Returns: %TRUE on success, %FALSE on failure
1566 e_source_registry_authenticate_sync (ESourceRegistry *registry,
1568 ESourceAuthenticator *auth,
1569 GCancellable *cancellable,
1572 AuthContext *auth_context;
1573 GMainContext *main_context;
1574 EDBusAuthenticator *dbus_auth;
1575 gchar *encryption_key;
1576 gchar *object_path = NULL;
1579 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1580 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1581 g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth), FALSE);
1583 /* This extracts authentication prompt details for the ESource
1584 * before initiating an authentication session with the server,
1585 * so split it out of the main algorithm for clarity's sake. */
1586 success = source_registry_call_authenticate_for_source (
1587 registry, auth, source, &object_path, cancellable, error);
1590 g_warn_if_fail (object_path == NULL);
1594 g_return_val_if_fail (object_path != NULL, FALSE);
1596 main_context = g_main_context_new ();
1597 g_main_context_push_thread_default (main_context);
1599 dbus_auth = e_dbus_authenticator_proxy_new_for_bus_sync (
1601 G_DBUS_PROXY_FLAGS_NONE,
1602 SOURCES_DBUS_SERVICE_NAME,
1603 object_path, cancellable, error);
1605 g_free (object_path);
1607 if (dbus_auth == NULL) {
1612 auth_context = g_slice_new0 (AuthContext);
1613 auth_context->auth = g_object_ref (auth);
1614 auth_context->dbus_auth = dbus_auth; /* takes ownership */
1615 auth_context->main_loop = g_main_loop_new (main_context, FALSE);
1616 auth_context->error = error;
1618 /* This just needs to be something other than
1619 * E_SOURCE_AUTHENTICATION_ERROR so we don't trip
1620 * up source_registry_authenticate_dismissed_cb(). */
1621 auth_context->auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
1623 if (G_IS_CANCELLABLE (cancellable))
1624 auth_context->cancellable = g_object_ref (cancellable);
1626 auth_context->secret_exchange =
1627 gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1);
1630 dbus_auth, "authenticate",
1631 G_CALLBACK (source_registry_authenticate_authenticate_cb),
1635 dbus_auth, "dismissed",
1636 G_CALLBACK (source_registry_authenticate_dismissed_cb),
1639 encryption_key = gcr_secret_exchange_begin (
1640 auth_context->secret_exchange);
1642 /* Signal the D-Bus server that we're ready to begin the
1643 * authentication session. This must happen AFTER we've
1644 * connected to the response signal since the server may
1645 * already have a response ready and waiting for us. */
1646 success = e_dbus_authenticator_call_ready_sync (
1647 dbus_auth, encryption_key, cancellable, error);
1649 g_free (encryption_key);
1652 g_main_loop_run (auth_context->main_loop);
1653 success = auth_context->success;
1656 auth_context_free (auth_context);
1659 g_main_context_pop_thread_default (main_context);
1660 g_main_context_unref (main_context);
1666 * e_source_registry_authenticate:
1667 * @registry: an #ESourceRegistry
1668 * @source: an #ESource
1669 * @auth: an #ESourceAuthenticator
1670 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1671 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1673 * @user_data: (closure): data to pass to the callback function
1675 * Asynchronously authenticates @source, using @auth to handle the
1676 * authentication attempts. The operation loops until authentication
1677 * is successful or the user aborts further authentication attempts.
1679 * Note that @source need not have a #GDBusObject, which means this
1680 * function can test authentication on a scratch #ESource.
1682 * When the operation is finished, @callback will be called. You can then
1683 * call e_source_registry_authenticate_finish() to get the result of the
1686 * Only backend implementations and data source editors should call this
1687 * function. The intent is for basic client applications to not have to
1688 * deal with authentication at all.
1693 e_source_registry_authenticate (ESourceRegistry *registry,
1695 ESourceAuthenticator *auth,
1696 GCancellable *cancellable,
1697 GAsyncReadyCallback callback,
1700 GSimpleAsyncResult *simple;
1701 AsyncContext *async_context;
1703 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1704 g_return_if_fail (E_IS_SOURCE (source));
1705 g_return_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth));
1707 async_context = g_slice_new0 (AsyncContext);
1708 async_context->source = g_object_ref (source);
1709 async_context->auth = g_object_ref (auth);
1711 simple = g_simple_async_result_new (
1712 G_OBJECT (registry), callback, user_data,
1713 e_source_registry_authenticate);
1715 g_simple_async_result_set_check_cancellable (simple, cancellable);
1717 g_simple_async_result_set_op_res_gpointer (
1718 simple, async_context, (GDestroyNotify) async_context_free);
1720 g_simple_async_result_run_in_thread (
1721 simple, source_registry_authenticate_thread,
1722 G_PRIORITY_DEFAULT, cancellable);
1724 g_object_unref (simple);
1728 * e_source_registry_authenticate_finish:
1729 * @registry: an #ESourceRegistry
1730 * @result: a #GAsyncResult
1731 * @error: return location for a #GError, or %NULL
1733 * Finishes the operation started with e_source_registry_authenticate().
1734 * If an error occurred, the function will set @error and return %FALSE.
1736 * Returns: %TRUE on success, %FALSE on failure
1741 e_source_registry_authenticate_finish (ESourceRegistry *registry,
1742 GAsyncResult *result,
1745 GSimpleAsyncResult *simple;
1747 g_return_val_if_fail (
1748 g_simple_async_result_is_valid (
1749 result, G_OBJECT (registry),
1750 e_source_registry_authenticate), FALSE);
1752 simple = G_SIMPLE_ASYNC_RESULT (result);
1754 /* Assume success unless a GError is set. */
1755 return !g_simple_async_result_propagate_error (simple, error);
1758 /* Helper for e_source_registry_commit_source() */
1760 source_registry_commit_source_thread (GSimpleAsyncResult *simple,
1762 GCancellable *cancellable)
1764 AsyncContext *async_context;
1765 GError *error = NULL;
1767 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1769 e_source_registry_commit_source_sync (
1770 E_SOURCE_REGISTRY (object),
1771 async_context->source,
1772 cancellable, &error);
1775 g_simple_async_result_take_error (simple, error);
1779 * e_source_registry_commit_source_sync:
1780 * @registry: an #ESourceRegistry
1781 * @source: an #ESource with changes to commit
1782 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1783 * @error: return location for #GError, or %NULL
1785 * This is a convenience function intended for use with graphical
1786 * #ESource editors. Call this function when the user is finished
1787 * making changes to @source.
1789 * If @source has a #GDBusObject, its contents are submitted to the D-Bus
1790 * service through e_source_write_sync().
1792 * If @source does NOT have a #GDBusObject (implying it's a scratch
1793 * #ESource), its contents are submitted to the D-Bus service through
1794 * e_source_registry_create_sources_sync().
1796 * If an error occurs, the function will set @error and return %FALSE.
1798 * Returns: %TRUE on success, %FALSE on failure
1803 e_source_registry_commit_source_sync (ESourceRegistry *registry,
1805 GCancellable *cancellable,
1808 GDBusObject *dbus_object;
1811 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1812 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1814 dbus_object = e_source_ref_dbus_object (source);
1816 if (dbus_object != NULL) {
1817 success = e_source_write_sync (source, cancellable, error);
1818 g_object_unref (dbus_object);
1820 GList *list = g_list_prepend (NULL, source);
1821 success = e_source_registry_create_sources_sync (
1822 registry, list, cancellable, error);
1830 * e_source_registry_commit_source:
1831 * @registry: an #ESourceRegistry
1832 * @source: an #ESource with changes to commit
1833 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1834 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1836 * @user_data: (closure): data to pass to the callback function
1838 * See e_source_registry_commit_source_sync() for details.
1840 * When the operation is finished, @callback will be called. You can then
1841 * call e_source_registry_commit_source_finish() to get the result of the
1847 e_source_registry_commit_source (ESourceRegistry *registry,
1849 GCancellable *cancellable,
1850 GAsyncReadyCallback callback,
1853 GSimpleAsyncResult *simple;
1854 AsyncContext *async_context;
1856 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1857 g_return_if_fail (E_IS_SOURCE (source));
1859 async_context = g_slice_new0 (AsyncContext);
1860 async_context->source = g_object_ref (source);
1862 simple = g_simple_async_result_new (
1863 G_OBJECT (registry), callback, user_data,
1864 e_source_registry_commit_source);
1866 g_simple_async_result_set_check_cancellable (simple, cancellable);
1868 g_simple_async_result_set_op_res_gpointer (
1869 simple, async_context, (GDestroyNotify) async_context_free);
1871 g_simple_async_result_run_in_thread (
1872 simple, source_registry_commit_source_thread,
1873 G_PRIORITY_DEFAULT, cancellable);
1875 g_object_unref (simple);
1879 * e_source_registry_commit_source_finish:
1880 * @registry: an #ESourceRegistry
1881 * @result: a #GAsyncResult
1882 * @error: return location for a #GError, or %NULL
1884 * Finishes the operation started with e_source_registry_commit_source().
1886 * If an error occurred, the function will set @error and return %FALSE.
1888 * Returns: %TRUE on success, %FALSE on failure
1893 e_source_registry_commit_source_finish (ESourceRegistry *registry,
1894 GAsyncResult *result,
1897 GSimpleAsyncResult *simple;
1899 g_return_val_if_fail (
1900 g_simple_async_result_is_valid (
1901 result, G_OBJECT (registry),
1902 e_source_registry_commit_source), FALSE);
1904 simple = G_SIMPLE_ASYNC_RESULT (result);
1906 /* Assume success unless a GError is set. */
1907 return !g_simple_async_result_propagate_error (simple, error);
1910 /* Helper for e_source_registry_create_sources() */
1912 source_registry_create_sources_thread (GSimpleAsyncResult *simple,
1914 GCancellable *cancellable)
1916 AsyncContext *async_context;
1917 GError *error = NULL;
1919 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1921 e_source_registry_create_sources_sync (
1922 E_SOURCE_REGISTRY (object),
1923 async_context->list_of_sources,
1924 cancellable, &error);
1927 g_simple_async_result_take_error (simple, error);
1931 * e_source_registry_create_sources_sync:
1932 * @registry: an #ESourceRegistry
1933 * @list_of_sources: a list of #ESource instances with no #GDBusObject
1934 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1935 * @error: return location for a #GError, or %NULL
1937 * Requests the D-Bus service create new key files for each #ESource in
1938 * @list_of_sources. Each list element must be a scratch #ESource with
1941 * If an error occurs, the function will set @error and return %FALSE.
1943 * Returns: %TRUE on success, %FALSE on failure
1948 e_source_registry_create_sources_sync (ESourceRegistry *registry,
1949 GList *list_of_sources,
1950 GCancellable *cancellable,
1953 GVariantBuilder builder;
1958 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1960 /* Verify the list elements are all ESources. */
1961 for (link = list_of_sources; link != NULL; link = g_list_next (link))
1962 g_return_val_if_fail (E_IS_SOURCE (link->data), FALSE);
1964 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
1966 for (link = list_of_sources; link != NULL; link = g_list_next (link)) {
1971 source = E_SOURCE (link->data);
1972 uid = e_source_get_uid (source);
1974 source_data = e_source_to_string (source, NULL);
1975 g_variant_builder_add (&builder, "{ss}", uid, source_data);
1976 g_free (source_data);
1979 variant = g_variant_builder_end (&builder);
1981 /* This function sinks the floating GVariant reference. */
1982 success = e_dbus_source_manager_call_create_sources_sync (
1983 registry->priv->dbus_source_manager,
1984 variant, cancellable, error);
1986 g_variant_builder_clear (&builder);
1992 * e_source_registry_create_sources:
1993 * @registry: an #ESourceRegistry
1994 * @list_of_sources: a list of #ESource instances with no #GDBusObject
1995 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1996 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1998 * @user_data: (closure): data to pass to the callback function
2000 * Asynchronously requests the D-Bus service create new key files for each
2001 * #ESource in @list_of_sources. Each list element must be a scratch
2002 * #ESource with no #GDBusObject.
2004 * When the operation is finished, @callback will be called. You can then
2005 * call e_source_registry_create_sources_finish() to get the result of the
2011 e_source_registry_create_sources (ESourceRegistry *registry,
2012 GList *list_of_sources,
2013 GCancellable *cancellable,
2014 GAsyncReadyCallback callback,
2017 GSimpleAsyncResult *simple;
2018 AsyncContext *async_context;
2021 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2023 /* Verify the list elements are all ESources. */
2024 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2025 g_return_if_fail (E_IS_SOURCE (link->data));
2027 async_context = g_slice_new0 (AsyncContext);
2028 async_context->list_of_sources = g_list_copy (list_of_sources);
2031 async_context->list_of_sources,
2032 (GFunc) g_object_ref, NULL);
2034 simple = g_simple_async_result_new (
2035 G_OBJECT (registry), callback, user_data,
2036 e_source_registry_create_sources);
2038 g_simple_async_result_set_check_cancellable (simple, cancellable);
2040 g_simple_async_result_set_op_res_gpointer (
2041 simple, async_context, (GDestroyNotify) async_context_free);
2043 g_simple_async_result_run_in_thread (
2044 simple, source_registry_create_sources_thread,
2045 G_PRIORITY_DEFAULT, cancellable);
2047 g_object_unref (simple);
2051 * e_source_registry_create_sources_finish:
2052 * @registry: an #ESourceRegistry
2053 * @result: a #GAsyncResult
2054 * @error: return location for a #GError, or %NULL
2056 * Finishes the operation started with e_source_registry_create_sources().
2058 * If an error occurred, the function will set @error and return %FALSE.
2060 * Returns: %TRUE on success, %FALSE on failure
2065 e_source_registry_create_sources_finish (ESourceRegistry *registry,
2066 GAsyncResult *result,
2069 GSimpleAsyncResult *simple;
2071 g_return_val_if_fail (
2072 g_simple_async_result_is_valid (
2073 result, G_OBJECT (registry),
2074 e_source_registry_create_sources), FALSE);
2076 simple = G_SIMPLE_ASYNC_RESULT (result);
2078 /* Assume success unless a GError is set. */
2079 return !g_simple_async_result_propagate_error (simple, error);
2083 * e_source_registry_ref_source:
2084 * @registry: an #ESourceRegistry
2085 * @uid: a unique identifier string
2087 * Looks up an #ESource in @registry by its unique identifier string.
2089 * The returned #ESource is referenced for thread-safety and must be
2090 * unreferenced with g_object_unref() when finished with it.
2092 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2097 e_source_registry_ref_source (ESourceRegistry *registry,
2100 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2101 g_return_val_if_fail (uid != NULL, NULL);
2103 return source_registry_sources_lookup (registry, uid);
2107 * e_source_registry_list_sources:
2108 * @registry: an #ESourceRegistry
2109 * @extension_name: (allow-none): an extension name, or %NULL
2111 * Returns a list of registered sources, sorted by display name. If
2112 * @extension_name is given, restrict the list to sources having that
2115 * The sources returned in the list are referenced for thread-safety.
2116 * They must each be unreferenced with g_object_unref() when finished
2117 * when them. Free the returned list itself with g_list_free().
2119 * An easy way to free the list properly in one step is as follows:
2122 * g_list_free_full (list, g_object_unref);
2125 * Returns: (transfer full): a sorted list of sources
2130 e_source_registry_list_sources (ESourceRegistry *registry,
2131 const gchar *extension_name)
2134 GQueue trash = G_QUEUE_INIT;
2136 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2138 list = g_list_sort (
2139 source_registry_sources_get_values (registry),
2140 (GCompareFunc) e_source_compare_by_display_name);
2142 if (extension_name == NULL)
2145 for (link = list; link != NULL; link = g_list_next (link)) {
2146 ESource *source = E_SOURCE (link->data);
2148 if (!e_source_has_extension (source, extension_name)) {
2149 g_queue_push_tail (&trash, link);
2150 g_object_unref (source);
2154 /* We do want pop_head() here, not pop_head_link(). */
2155 while ((link = g_queue_pop_head (&trash)) != NULL)
2156 list = g_list_delete_link (list, link);
2162 * e_source_registry_find_extension:
2163 * @registry: an #ESourceRegistry
2164 * @source: an #ESource
2165 * @extension_name: the extension name to find
2167 * Examines @source and its ancestors and returns the "deepest" #ESource
2168 * having an #ESourceExtension with the given @extension_name. If neither
2169 * @source nor any of its ancestors have such an extension, the function
2172 * This function is useful in cases when an #ESourceExtension is meant to
2173 * apply to both the #ESource it belongs to and the #ESource's descendants.
2175 * A common example is the #ESourceCollection extension, where descendants
2176 * of an #ESource having an #ESourceCollection extension are implied to be
2177 * members of that collection. In that example, this function can be used
2178 * to test whether @source is a member of a collection.
2180 * The returned #ESource is referenced for thread-safety and must be
2181 * unreferenced with g_object_unref() when finished with it.
2183 * Note the function returns the #ESource containing the #ESourceExtension
2184 * instead of the #ESourceExtension itself because extension instances are
2185 * not to be referenced directly (see e_source_get_extension()).
2187 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2192 e_source_registry_find_extension (ESourceRegistry *registry,
2194 const gchar *extension_name)
2196 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2197 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2198 g_return_val_if_fail (extension_name != NULL, NULL);
2200 g_object_ref (source);
2202 while (!e_source_has_extension (source, extension_name)) {
2205 uid = e_source_dup_parent (source);
2207 g_object_unref (source);
2211 source = e_source_registry_ref_source (registry, uid);
2222 /* Helper for e_source_registry_build_display_tree() */
2224 source_registry_compare_nodes (GNode *node_a,
2227 ESource *source_a = E_SOURCE (node_a->data);
2228 ESource *source_b = E_SOURCE (node_b->data);
2229 const gchar *uid_a, *uid_b;
2231 uid_a = e_source_get_uid (source_a);
2232 uid_b = e_source_get_uid (source_b);
2234 /* Sanity check, with runtime warnings. */
2235 if (uid_a == NULL) {
2236 g_warn_if_reached ();
2239 if (uid_b == NULL) {
2240 g_warn_if_reached ();
2244 /* The built-in "local-stub" source comes first at depth 1. */
2246 if (g_strcmp0 (uid_a, "local-stub") == 0)
2249 if (g_strcmp0 (uid_b, "local-stub") == 0)
2252 /* The built-in "system-*" sources come first at depth 2. */
2254 if (g_str_has_prefix (uid_a, "system-"))
2257 if (g_str_has_prefix (uid_b, "system-"))
2260 return e_source_compare_by_display_name (source_a, source_b);
2263 /* Helper for e_source_registry_build_display_tree() */
2265 source_registry_prune_nodes (GNode *node,
2266 const gchar *extension_name)
2268 GQueue queue = G_QUEUE_INIT;
2271 /* Unlink all the child nodes and place them in a queue. */
2272 while ((child_node = g_node_first_child (node)) != NULL) {
2273 g_node_unlink (child_node);
2274 g_queue_push_tail (&queue, child_node);
2277 /* Sort the queue by source name. */
2279 &queue, (GCompareDataFunc)
2280 source_registry_compare_nodes, NULL);
2282 /* Pop nodes off the head of the queue until the queue is empty.
2283 * If the node has either its own children or the given extension
2284 * name, put it back under the parent node (preserving the sorted
2285 * order). Otherwise delete the node and its descendants. */
2286 while ((child_node = g_queue_pop_head (&queue)) != NULL) {
2287 ESource *child = E_SOURCE (child_node->data);
2288 gboolean append_child_node = FALSE;
2290 if (extension_name == NULL)
2291 append_child_node = e_source_get_enabled (child);
2293 else if (e_source_has_extension (child, extension_name))
2294 append_child_node = e_source_get_enabled (child);
2296 else if (g_node_first_child (child_node) != NULL)
2297 append_child_node = e_source_get_enabled (child);
2299 if (append_child_node)
2300 g_node_append (node, child_node);
2302 e_source_registry_free_display_tree (child_node);
2309 * e_source_registry_build_display_tree:
2310 * @registry: an #ESourceRegistry
2311 * @extension_name: (allow-none): an extension name, or %NULL
2313 * Returns a single #GNode tree of registered sources that can be used to
2314 * populate a #GtkTreeModel. (The root #GNode is just an empty placeholder.)
2316 * Similar to e_source_registry_list_sources(), an @extension_name can be
2317 * given to restrict the tree to sources having that extension name. Parents
2318 * of matched sources are included in the tree regardless of whether they have
2319 * an extension named @extension_name.
2321 * Disabled leaf nodes are automatically excluded from the #GNode tree.
2323 * The sources returned in the tree are referenced for thread-safety.
2324 * They must each be unreferenced with g_object_unref() when finished
2325 * with them. Free the returned tree itself with g_node_destroy().
2326 * For convenience, e_source_registry_free_display_tree() does all
2329 * Returns: (transfer full): a tree of sources, arranged for display
2334 e_source_registry_build_display_tree (ESourceRegistry *registry,
2335 const gchar *extension_name)
2339 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2341 /* Assemble all data sources into a tree. */
2342 root = source_registry_sources_build_tree (registry);
2344 /* Prune unwanted nodes from the copied source trees.
2345 * This must be done in "post" order (children first)
2346 * since it reorders and deletes child nodes. */
2348 root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
2349 (GNodeTraverseFunc) source_registry_prune_nodes,
2350 (gpointer) extension_name);
2355 /* Helper for e_source_registry_free_display_tree() */
2357 source_registry_unref_nodes (GNode *node)
2359 while (node != NULL) {
2360 if (node->children != NULL)
2361 source_registry_unref_nodes (node->children);
2362 if (node->data != NULL)
2363 g_object_unref (node->data);
2369 * e_source_registry_free_display_tree:
2370 * @display_tree: a tree of sources, arranged for display
2372 * Convenience function to free a #GNode tree of registered
2373 * sources created by e_source_registry_build_display_tree().
2378 e_source_registry_free_display_tree (GNode *display_tree)
2380 g_return_if_fail (display_tree != NULL);
2382 /* XXX This would be easier if GLib had something like
2383 * g_node_destroy_full() which took a GDestroyNotify.
2384 * Then the tree would not have to be traversed twice. */
2386 source_registry_unref_nodes (display_tree);
2387 g_node_destroy (display_tree);
2390 /* Helper for e_source_registry_debug_dump() */
2392 source_registry_debug_dump_cb (GNode *node)
2396 /* Root node is an empty placeholder. */
2397 if (G_NODE_IS_ROOT (node))
2400 depth = g_node_depth (node);
2401 for (ii = 2; ii < depth; ii++)
2404 if (E_IS_SOURCE (node->data)) {
2405 ESource *source = E_SOURCE (node->data);
2406 g_print ("\"%s\" ", e_source_get_display_name (source));
2407 g_print ("(%s)", e_source_get_uid (source));
2416 * e_source_registry_debug_dump:
2417 * @registry: an #ESourceRegistry
2418 * @extension_name: (allow-none): an extension name, or %NULL
2420 * Handy debugging function that uses e_source_registry_build_display_tree()
2421 * to print a tree of registered sources to standard output.
2426 e_source_registry_debug_dump (ESourceRegistry *registry,
2427 const gchar *extension_name)
2431 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2433 root = e_source_registry_build_display_tree (registry, extension_name);
2436 root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2437 (GNodeTraverseFunc) source_registry_debug_dump_cb, NULL);
2439 e_source_registry_free_display_tree (root);
2443 * e_source_registry_ref_builtin_address_book:
2444 * @registry: an #ESourceRegistry
2446 * Returns the built-in address book #ESource.
2448 * This #ESource is always present and makes for a safe fallback.
2450 * The returned #ESource is referenced for thread-safety and must be
2451 * unreferenced with g_object_unref() when finished with it.
2453 * Returns: (transfer full): the built-in address book #ESource
2458 e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
2463 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2465 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2466 source = e_source_registry_ref_source (registry, uid);
2467 g_return_val_if_fail (source != NULL, NULL);
2473 * e_source_registry_ref_default_address_book:
2474 * @registry: an #ESourceRegistry
2476 * Returns the #ESource most recently passed to
2477 * e_source_registry_set_default_address_book() either in this session
2478 * or a previous session, or else falls back to the built-in address book.
2480 * The returned #ESource is referenced for thread-safety and must be
2481 * unreferenced with g_object_unref() when finished with it.
2483 * Returns: (transfer full): the default address book #ESource
2488 e_source_registry_ref_default_address_book (ESourceRegistry *registry)
2494 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2496 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2497 uid = g_settings_get_string (registry->priv->settings, key);
2498 source = e_source_registry_ref_source (registry, uid);
2501 /* The built-in source is always present. */
2503 source = e_source_registry_ref_builtin_address_book (registry);
2505 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2511 * e_source_registry_set_default_address_book:
2512 * @registry: an #ESourceRegistry
2513 * @default_source: (allow-none): an address book #ESource, or %NULL
2515 * Sets @default_source as the default address book. If @default_source
2516 * is %NULL, the default address book is reset to the built-in address book.
2517 * This setting will persist across sessions until changed.
2522 e_source_registry_set_default_address_book (ESourceRegistry *registry,
2523 ESource *default_source)
2528 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2530 if (default_source != NULL) {
2531 g_return_if_fail (E_IS_SOURCE (default_source));
2532 uid = e_source_get_uid (default_source);
2534 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2537 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2538 g_settings_set_string (registry->priv->settings, key, uid);
2540 /* The GSettings::changed signal will trigger a "notify" signal
2541 * from the registry, so no need to call g_object_notify() here. */
2545 * e_source_registry_ref_builtin_calendar:
2546 * @registry: an #ESourceRegistry
2548 * Returns the built-in calendar #ESource.
2550 * This #ESource is always present and makes for a safe fallback.
2552 * The returned #ESource is referenced for thread-safety and must be
2553 * unreferenced with g_object_unref() when finished with it.
2555 * Returns: (transfer full): the built-in calendar #ESource
2560 e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
2565 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2567 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2568 source = e_source_registry_ref_source (registry, uid);
2569 g_return_val_if_fail (source != NULL, NULL);
2575 * e_source_registry_ref_default_calendar:
2576 * @registry: an #ESourceRegistry
2578 * Returns the #ESource most recently passed to
2579 * e_source_registry_set_default_calendar() either in this session
2580 * or a previous session, or else falls back to the built-in calendar.
2582 * The returned #ESource is referenced for thread-safety and must be
2583 * unreferenced with g_object_unref() when finished with it.
2585 * Returns: (transfer full): the default calendar #ESource
2590 e_source_registry_ref_default_calendar (ESourceRegistry *registry)
2596 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2598 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2599 uid = g_settings_get_string (registry->priv->settings, key);
2600 source = e_source_registry_ref_source (registry, uid);
2603 /* The built-in source is always present. */
2605 source = e_source_registry_ref_builtin_calendar (registry);
2607 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2613 * e_source_registry_set_default_calendar:
2614 * @registry: an #ESourceRegistry
2615 * @default_source: (allow-none): a calendar #ESource, or %NULL
2617 * Sets @default_source as the default calendar. If @default_source
2618 * is %NULL, the default calendar is reset to the built-in calendar.
2619 * This setting will persist across sessions until changed.
2624 e_source_registry_set_default_calendar (ESourceRegistry *registry,
2625 ESource *default_source)
2630 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2632 if (default_source != NULL) {
2633 g_return_if_fail (E_IS_SOURCE (default_source));
2634 uid = e_source_get_uid (default_source);
2636 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2639 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2640 g_settings_set_string (registry->priv->settings, key, uid);
2642 /* The GSettings::changed signal will trigger a "notify" signal
2643 * from the registry, so no need to call g_object_notify() here. */
2647 * e_source_registry_ref_builtin_mail_account:
2648 * @registry: an #ESourceRegistry
2650 * Returns the built-in mail account #ESource.
2652 * This #ESource is always present and makes for a safe fallback.
2654 * The returned #ESource is referenced for thread-safety and must be
2655 * unreferenced with g_object_unref() when finished with it.
2657 * Returns: (transfer full): the built-in mail account #ESource
2662 e_source_registry_ref_builtin_mail_account (ESourceRegistry *registry)
2667 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2669 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2670 source = e_source_registry_ref_source (registry, uid);
2671 g_return_val_if_fail (source != NULL, NULL);
2677 * e_source_registry_ref_default_mail_account:
2678 * @registry: an #ESourceRegistry
2680 * Returns the #ESource most recently passed to
2681 * e_source_registry_set_default_mail_account() either in this session
2682 * or a previous session, or else falls back to the built-in mail account.
2684 * The returned #ESource is referenced for thread-safety and must be
2685 * unreferenced with g_object_unref() when finished with it.
2687 * Returns: (transfer full): the default mail account #ESource
2692 e_source_registry_ref_default_mail_account (ESourceRegistry *registry)
2698 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2700 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2701 uid = g_settings_get_string (registry->priv->settings, key);
2702 source = e_source_registry_ref_source (registry, uid);
2705 /* The built-in source is always present. */
2707 source = e_source_registry_ref_builtin_mail_account (registry);
2709 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2715 * e_source_registry_set_default_mail_account:
2716 * @registry: an #ESourceRegistry
2717 * @default_source: (allow-none): a mail account #ESource, or %NULL
2719 * Sets @default_source as the default mail account. If @default_source
2720 * is %NULL, the default mail account is reset to the built-in mail account.
2721 * This setting will persist across sessions until changed.
2726 e_source_registry_set_default_mail_account (ESourceRegistry *registry,
2727 ESource *default_source)
2732 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2734 if (default_source != NULL) {
2735 g_return_if_fail (E_IS_SOURCE (default_source));
2736 uid = e_source_get_uid (default_source);
2738 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2741 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2742 g_settings_set_string (registry->priv->settings, key, uid);
2744 /* The GSettings::changed signal will trigger a "notify" signal
2745 * from the registry, so no need to call g_object_notify() here. */
2748 /* Helper for e_source_registry_ref_default_mail_identity() */
2750 source_registry_ref_any_mail_identity (ESourceRegistry *registry)
2754 const gchar *extension_name;
2757 /* First fallback: Return the mail identity named
2758 * by the default mail account. */
2760 source = e_source_registry_ref_default_mail_account (registry);
2762 /* This should never be NULL, but just to be safe. */
2763 if (source != NULL) {
2764 ESourceMailAccount *extension;
2766 extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
2767 extension = e_source_get_extension (source, extension_name);
2768 uid = e_source_mail_account_dup_identity_uid (extension);
2770 g_object_unref (source);
2775 source = e_source_registry_ref_source (registry, uid);
2782 /* Second fallback: Pick any available mail identity,
2783 * preferring enabled identities. */
2785 extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
2786 list = e_source_registry_list_sources (registry, extension_name);
2788 for (link = list; link != NULL; link = g_list_next (link)) {
2789 ESource *candidate = E_SOURCE (link->data);
2791 if (e_source_get_enabled (candidate)) {
2792 source = g_object_ref (candidate);
2797 if (source == NULL && list != NULL)
2798 source = g_object_ref (link->data);
2800 g_list_free_full (list, (GDestroyNotify) g_object_unref);
2806 * e_source_registry_ref_default_mail_identity:
2807 * @registry: an #ESourceRegistry
2809 * Returns the #ESource most recently passed to
2810 * e_source_registry_set_default_mail_identity() either in this session
2811 * or a previous session, or else falls back to the mail identity named
2812 * by the default mail account. If even that fails it returns any mail
2813 * identity from @registry, or %NULL if there are none.
2815 * The returned #ESource is referenced for thread-safety and must be
2816 * unreferenced with g_object_unref() when finished with it.
2818 * Returns: (transfer full): the default mail identity #ESource, or %NULL
2823 e_source_registry_ref_default_mail_identity (ESourceRegistry *registry)
2829 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2831 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
2832 uid = g_settings_get_string (registry->priv->settings, key);
2833 source = e_source_registry_ref_source (registry, uid);
2837 source = source_registry_ref_any_mail_identity (registry);
2843 * e_source_registry_set_default_mail_identity:
2844 * @registry: an #ESourceRegistry
2845 * @default_source: (allow-none): a mail identity #ESource, or %NULL
2847 * Sets @default_source as the default mail identity. If @default_source
2848 * is %NULL, the next request for the default mail identity will use the
2849 * fallbacks described in e_source_registry_get_default_mail_identity().
2854 e_source_registry_set_default_mail_identity (ESourceRegistry *registry,
2855 ESource *default_source)
2860 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2862 if (default_source != NULL) {
2863 g_return_if_fail (E_IS_SOURCE (default_source));
2864 uid = e_source_get_uid (default_source);
2866 uid = ""; /* no built-in mail identity */
2869 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
2870 g_settings_set_string (registry->priv->settings, key, uid);
2872 /* The GSettings::changed signal will trigger a "notify" signal
2873 * from the registry, so no need to call g_object_notify() here. */
2877 * e_source_registry_ref_builtin_memo_list:
2878 * @registry: an #ESourceRegistry
2880 * Returns the built-in memo list #ESource.
2882 * This #ESource is always present and makes for a safe fallback.
2884 * The returned #ESource is referenced for thread-safety and must be
2885 * unreferenced with g_object_unref() when finished with it.
2887 * Returns: (transfer full): the built-in memo list #ESource
2892 e_source_registry_ref_builtin_memo_list (ESourceRegistry *registry)
2897 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2899 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
2900 source = e_source_registry_ref_source (registry, uid);
2901 g_return_val_if_fail (source != NULL, NULL);
2907 * e_source_registry_ref_default_memo_list:
2908 * @registry: an #ESourceRegistry
2910 * Returns the #ESource most recently passed to
2911 * e_source_registry_set_default_memo_list() either in this session
2912 * or a previous session, or else falls back to the built-in memo list.
2914 * The returned #ESource is referenced for thread-safety and must be
2915 * unreferenced with g_object_unref() when finished with it.
2917 * Returns: (transfer full): the default memo list #ESource
2922 e_source_registry_ref_default_memo_list (ESourceRegistry *registry)
2928 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2930 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
2931 uid = g_settings_get_string (registry->priv->settings, key);
2932 source = e_source_registry_ref_source (registry, uid);
2935 /* The built-in source is always present. */
2937 source = e_source_registry_ref_builtin_memo_list (registry);
2939 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2945 * e_source_registry_set_default_memo_list:
2946 * @registry: an #ESourceRegistry
2947 * @default_source: (allow-none): a memo list #ESource, or %NULL
2949 * Sets @default_source as the default memo list. If @default_source
2950 * is %NULL, the default memo list is reset to the built-in memo list.
2951 * This setting will persist across sessions until changed.
2956 e_source_registry_set_default_memo_list (ESourceRegistry *registry,
2957 ESource *default_source)
2962 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2964 if (default_source != NULL) {
2965 g_return_if_fail (E_IS_SOURCE (default_source));
2966 uid = e_source_get_uid (default_source);
2968 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
2971 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
2972 g_settings_set_string (registry->priv->settings, key, uid);
2974 /* The GSettings::changed signal will trigger a "notify" signal
2975 * from the registry, so no need to call g_object_notify() here. */
2979 * e_source_registry_ref_builtin_task_list:
2980 * @registry: an #ESourceRegistry
2982 * Returns the built-in task list #ESource.
2984 * This #ESource is always present and makes for a safe fallback.
2986 * The returned #ESource is referenced for thread-safety and must be
2987 * unreferenced with g_object_unref() when finished with it.
2989 * Returns: (transfer full): the built-in task list #ESource
2994 e_source_registry_ref_builtin_task_list (ESourceRegistry *registry)
2999 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3001 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3002 source = e_source_registry_ref_source (registry, uid);
3003 g_return_val_if_fail (source != NULL, NULL);
3009 * e_source_registry_ref_default_task_list:
3010 * @registry: an #ESourceRegistry
3012 * Returns the #ESource most recently passed to
3013 * e_source_registry_set_default_task_list() either in this session
3014 * or a previous session, or else falls back to the built-in task list.
3016 * The returned #ESource is referenced for thread-safety and must be
3017 * unreferenced with g_object_unref() when finished with it.
3019 * Returns: (transfer full): the default task list #ESource
3024 e_source_registry_ref_default_task_list (ESourceRegistry *registry)
3030 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3032 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3033 uid = g_settings_get_string (registry->priv->settings, key);
3034 source = e_source_registry_ref_source (registry, uid);
3037 /* The built-in source is always present. */
3039 source = e_source_registry_ref_builtin_task_list (registry);
3041 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3047 * e_source_registry_set_default_task_list:
3048 * @registry: an #ESourceRegistry
3049 * @default_source: (allow-none): a task list #ESource, or %NULL
3051 * Sets @default_source as the default task list. If @default_source
3052 * is %NULL, the default task list is reset to the built-in task list.
3053 * This setting will persist across sessions until changed.
3058 e_source_registry_set_default_task_list (ESourceRegistry *registry,
3059 ESource *default_source)
3064 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3066 if (default_source != NULL) {
3067 g_return_if_fail (E_IS_SOURCE (default_source));
3068 uid = e_source_get_uid (default_source);
3070 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3073 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3074 g_settings_set_string (registry->priv->settings, key, uid);
3076 /* The GSettings::changed signal will trigger a "notify" signal
3077 * from the registry, so no need to call g_object_notify() here. */
3081 * e_source_registry_ref_default_for_extension_name:
3082 * @registry: an #ESourceRegistry
3083 * @extension_name: an extension_name
3085 * This is a convenience function to return a default #ESource based on
3086 * @extension_name. This only works with a subset of extension names.
3088 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3089 * returns the current default address book, or else falls back to the
3090 * built-in address book.
3092 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function returns
3093 * the current default calendar, or else falls back to the built-in calendar.
3095 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3096 * returns the current default mail account, or else falls back to the
3097 * built-in mail account.
3099 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3100 * returns the current default mail identity, or else falls back to the
3101 * mail identity named by the current default mail account.
3103 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function returns
3104 * the current default memo list, or else falls back to the built-in memo list.
3106 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function returns
3107 * the current default task list, or else falls back to the built-in task list.
3109 * For all other values of @extension_name, the function returns %NULL.
3111 * The returned #ESource is referenced for thread-safety and must be
3112 * unreferenced with g_object_unref() when finished with it.
3114 * Returns: (transfer full): the default #ESource based on @extension_name
3119 e_source_registry_ref_default_for_extension_name (ESourceRegistry *registry,
3120 const gchar *extension_name)
3122 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3123 g_return_val_if_fail (extension_name != NULL, NULL);
3125 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3126 return e_source_registry_ref_default_address_book (registry);
3128 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3129 return e_source_registry_ref_default_calendar (registry);
3131 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3132 return e_source_registry_ref_default_mail_account (registry);
3134 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3135 return e_source_registry_ref_default_mail_identity (registry);
3137 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3138 return e_source_registry_ref_default_memo_list (registry);
3140 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3141 return e_source_registry_ref_default_task_list (registry);
3147 * e_source_registry_set_default_for_extension_name:
3148 * @registry: an #ESourceRegistry
3149 * @extension_name: an extension name
3150 * @default_source: (allow-none): an #ESource, or %NULL
3152 * This is a convenience function to set a default #ESource based on
3153 * @extension_name. This only works with a subset of extension names.
3155 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3156 * sets @default_source as the default address book. If @default_source
3157 * is %NULL, the default address book is reset to the built-in address book.
3159 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function sets
3160 * @default_source as the default calendar. If @default_source is %NULL,
3161 * the default calendar is reset to the built-in calendar.
3163 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3164 * sets @default_source as the default mail account. If @default_source
3165 * is %NULL, the default mail account is reset to the built-in mail account.
3167 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3168 * sets @default_source as the default mail identity. If @default_source
3169 * is %NULL, the next request for the default mail identity will return
3170 * the mail identity named by the default mail account.
3172 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function sets
3173 * @default_source as the default memo list. If @default_source is %NULL,
3174 * the default memo list is reset to the built-in memo list.
3176 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function sets
3177 * @default_source as the default task list. If @default_source is %NULL,
3178 * the default task list is reset to the built-in task list.
3180 * For all other values of @extension_name, the function does nothing.
3185 e_source_registry_set_default_for_extension_name (ESourceRegistry *registry,
3186 const gchar *extension_name,
3187 ESource *default_source)
3189 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3190 g_return_if_fail (extension_name != NULL);
3192 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3193 e_source_registry_set_default_address_book (
3194 registry, default_source);
3196 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3197 e_source_registry_set_default_calendar (
3198 registry, default_source);
3200 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3201 e_source_registry_set_default_mail_account (
3202 registry, default_source);
3204 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3205 e_source_registry_set_default_mail_identity (
3206 registry, default_source);
3208 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3209 e_source_registry_set_default_memo_list (
3210 registry, default_source);
3212 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3213 e_source_registry_set_default_task_list (
3214 registry, default_source);