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 _CreateContext CreateContext;
93 typedef struct _SourceClosure SourceClosure;
94 typedef struct _ThreadClosure ThreadClosure;
96 struct _ESourceRegistryPrivate {
97 GMainContext *main_context;
99 GThread *manager_thread;
100 ThreadClosure *thread_closure;
102 GDBusObjectManager *dbus_object_manager;
103 EDBusSourceManager *dbus_source_manager;
105 GHashTable *object_path_table;
106 GMutex object_path_table_lock;
114 struct _AsyncContext {
116 GList *list_of_sources;
117 ESourceAuthenticator *auth;
120 /* Used in e_source_registry_authenticate_sync() */
121 struct _AuthContext {
122 ESourceAuthenticator *auth;
123 EDBusAuthenticator *dbus_auth;
124 GCancellable *cancellable;
125 GMainLoop *main_loop;
126 ESourceAuthenticationResult auth_result;
127 GcrSecretExchange *secret_exchange;
128 gboolean authenticating;
133 /* Used in e_source_registry_create_sources_sync() */
134 struct _CreateContext {
135 GHashTable *pending_uids;
136 GMainContext *main_context;
137 GMainLoop *main_loop;
140 struct _SourceClosure {
141 ESourceRegistry *registry;
145 struct _ThreadClosure {
146 ESourceRegistry *registry;
147 GMainContext *main_context;
148 GMainLoop *main_loop;
149 GCond main_loop_cond;
150 GMutex main_loop_mutex;
156 PROP_DEFAULT_ADDRESS_BOOK,
157 PROP_DEFAULT_CALENDAR,
158 PROP_DEFAULT_MAIL_ACCOUNT,
159 PROP_DEFAULT_MAIL_IDENTITY,
160 PROP_DEFAULT_MEMO_LIST,
161 PROP_DEFAULT_TASK_LIST
173 /* Forward Declarations */
174 static void source_registry_add_source (ESourceRegistry *registry,
176 static void e_source_registry_initable_init (GInitableIface *interface);
178 static guint signals[LAST_SIGNAL];
180 /* By default, the GAsyncInitable interface calls GInitable.init()
181 * from a separate thread, so we only have to override GInitable. */
182 G_DEFINE_TYPE_WITH_CODE (
186 G_IMPLEMENT_INTERFACE (
187 G_TYPE_INITABLE, e_source_registry_initable_init)
188 G_IMPLEMENT_INTERFACE (
189 G_TYPE_ASYNC_INITABLE, NULL))
192 async_context_free (AsyncContext *async_context)
194 if (async_context->source != NULL)
195 g_object_unref (async_context->source);
198 async_context->list_of_sources,
199 (GDestroyNotify) g_object_unref);
201 if (async_context->auth != NULL)
202 g_object_unref (async_context->auth);
204 g_slice_free (AsyncContext, async_context);
208 auth_context_free (AuthContext *auth_context)
210 if (auth_context->auth != NULL)
211 g_object_unref (auth_context->auth);
213 if (auth_context->dbus_auth != NULL)
214 g_object_unref (auth_context->dbus_auth);
216 if (auth_context->cancellable != NULL)
217 g_object_unref (auth_context->cancellable);
219 if (auth_context->main_loop != NULL)
220 g_main_loop_unref (auth_context->main_loop);
222 if (auth_context->secret_exchange != NULL)
223 g_object_unref (auth_context->secret_exchange);
225 g_slice_free (AuthContext, auth_context);
228 static CreateContext *
229 create_context_new (void)
231 CreateContext *create_context;
233 create_context = g_slice_new0 (CreateContext);
235 create_context->pending_uids = g_hash_table_new_full (
236 (GHashFunc) g_str_hash,
237 (GEqualFunc) g_str_equal,
238 (GDestroyNotify) g_free,
239 (GDestroyNotify) NULL);
241 create_context->main_context = g_main_context_new ();
243 create_context->main_loop = g_main_loop_new (
244 create_context->main_context, FALSE);
246 return create_context;
250 create_context_free (CreateContext *create_context)
252 g_main_loop_unref (create_context->main_loop);
253 g_main_context_unref (create_context->main_context);
254 g_hash_table_unref (create_context->pending_uids);
256 g_slice_free (CreateContext, create_context);
260 source_closure_free (SourceClosure *closure)
262 g_object_unref (closure->registry);
263 g_object_unref (closure->source);
265 g_slice_free (SourceClosure, closure);
269 thread_closure_free (ThreadClosure *closure)
271 /* The registry member is not referenced. */
273 g_main_context_unref (closure->main_context);
274 g_main_loop_unref (closure->main_loop);
275 g_cond_clear (&closure->main_loop_cond);
276 g_mutex_clear (&closure->main_loop_mutex);
278 /* The GError should be NULL at this point,
279 * regardless of whether an error occurred. */
280 g_warn_if_fail (closure->error == NULL);
282 g_slice_free (ThreadClosure, closure);
286 source_registry_object_path_table_insert (ESourceRegistry *registry,
287 const gchar *object_path,
290 g_return_if_fail (object_path != NULL);
291 g_return_if_fail (E_IS_SOURCE (source));
293 g_mutex_lock (®istry->priv->object_path_table_lock);
295 g_hash_table_insert (
296 registry->priv->object_path_table,
297 g_strdup (object_path),
298 g_object_ref (source));
300 g_mutex_unlock (®istry->priv->object_path_table_lock);
304 source_registry_object_path_table_lookup (ESourceRegistry *registry,
305 const gchar *object_path)
309 g_return_val_if_fail (object_path != NULL, NULL);
311 g_mutex_lock (®istry->priv->object_path_table_lock);
313 source = g_hash_table_lookup (
314 registry->priv->object_path_table, object_path);
316 g_object_ref (source);
318 g_mutex_unlock (®istry->priv->object_path_table_lock);
324 source_registry_object_path_table_remove (ESourceRegistry *registry,
325 const gchar *object_path)
329 g_return_val_if_fail (object_path != NULL, FALSE);
331 g_mutex_lock (®istry->priv->object_path_table_lock);
333 removed = g_hash_table_remove (
334 registry->priv->object_path_table, object_path);
336 g_mutex_unlock (®istry->priv->object_path_table_lock);
342 source_registry_sources_insert (ESourceRegistry *registry,
347 uid = e_source_get_uid (source);
348 g_return_if_fail (uid != NULL);
350 g_mutex_lock (®istry->priv->sources_lock);
352 g_hash_table_insert (
353 registry->priv->sources,
354 g_strdup (uid), g_object_ref (source));
356 g_mutex_unlock (®istry->priv->sources_lock);
360 source_registry_sources_remove (ESourceRegistry *registry,
366 uid = e_source_get_uid (source);
367 g_return_val_if_fail (uid != NULL, FALSE);
369 g_mutex_lock (®istry->priv->sources_lock);
371 removed = g_hash_table_remove (registry->priv->sources, uid);
373 g_mutex_unlock (®istry->priv->sources_lock);
379 source_registry_sources_lookup (ESourceRegistry *registry,
384 g_return_val_if_fail (uid != NULL, NULL);
386 g_mutex_lock (®istry->priv->sources_lock);
388 source = g_hash_table_lookup (registry->priv->sources, uid);
391 g_object_ref (source);
393 g_mutex_unlock (®istry->priv->sources_lock);
399 source_registry_sources_get_values (ESourceRegistry *registry)
403 g_mutex_lock (®istry->priv->sources_lock);
405 values = g_hash_table_get_values (registry->priv->sources);
407 g_list_foreach (values, (GFunc) g_object_ref, NULL);
409 g_mutex_unlock (®istry->priv->sources_lock);
415 source_registry_sources_build_tree (ESourceRegistry *registry)
422 g_mutex_lock (®istry->priv->sources_lock);
424 root = g_node_new (NULL);
425 index = g_hash_table_new (g_str_hash, g_str_equal);
427 /* Add a GNode for each ESource to the index. */
428 g_hash_table_iter_init (&iter, registry->priv->sources);
429 while (g_hash_table_iter_next (&iter, &key, &value)) {
430 ESource *source = g_object_ref (value);
431 g_hash_table_insert (index, key, g_node_new (source));
434 /* Traverse the index and link the nodes together. */
435 g_hash_table_iter_init (&iter, index);
436 while (g_hash_table_iter_next (&iter, NULL, &value)) {
440 const gchar *parent_uid;
442 source_node = (GNode *) value;
443 source = E_SOURCE (source_node->data);
444 parent_uid = e_source_get_parent (source);
446 if (parent_uid == NULL || *parent_uid == '\0') {
449 parent_node = g_hash_table_lookup (index, parent_uid);
450 g_warn_if_fail (parent_node != NULL);
453 /* Should never be NULL, but just to be safe. */
454 if (parent_node != NULL)
455 g_node_append (parent_node, source_node);
458 g_hash_table_destroy (index);
460 g_mutex_unlock (®istry->priv->sources_lock);
466 source_registry_settings_changed_cb (GSettings *settings,
468 ESourceRegistry *registry)
470 /* We define a property name that matches every key in
471 * the "org.gnome.Evolution.DefaultSources" schema. */
472 g_object_notify (G_OBJECT (registry), key);
476 source_registry_source_changed_idle_cb (gpointer user_data)
478 SourceClosure *closure = user_data;
482 signals[SOURCE_CHANGED], 0,
489 source_registry_source_notify_enabled_idle_cb (gpointer user_data)
491 SourceClosure *closure = user_data;
493 if (e_source_get_enabled (closure->source))
496 signals[SOURCE_ENABLED], 0,
501 signals[SOURCE_DISABLED], 0,
508 source_registry_source_changed_cb (ESource *source,
509 ESourceRegistry *registry)
511 GSource *idle_source;
512 SourceClosure *closure;
514 closure = g_slice_new0 (SourceClosure);
515 closure->registry = g_object_ref (registry);
516 closure->source = g_object_ref (source);
518 idle_source = g_idle_source_new ();
519 g_source_set_callback (
521 source_registry_source_changed_idle_cb,
522 closure, (GDestroyNotify) source_closure_free);
523 g_source_attach (idle_source, registry->priv->main_context);
524 g_source_unref (idle_source);
528 source_registry_source_notify_enabled_cb (ESource *source,
530 ESourceRegistry *registry)
532 GSource *idle_source;
533 SourceClosure *closure;
535 closure = g_slice_new0 (SourceClosure);
536 closure->registry = g_object_ref (registry);
537 closure->source = g_object_ref (source);
539 idle_source = g_idle_source_new ();
540 g_source_set_callback (
542 source_registry_source_notify_enabled_idle_cb,
543 closure, (GDestroyNotify) source_closure_free);
544 g_source_attach (idle_source, registry->priv->main_context);
545 g_source_unref (idle_source);
549 source_registry_new_source (ESourceRegistry *registry,
550 GDBusObject *dbus_object)
552 GMainContext *main_context;
554 const gchar *object_path;
555 GError *error = NULL;
557 /* We don't want the ESource emitting "changed" signals from
558 * the manager thread, so we pass it the same main context the
559 * registry uses for scheduling signal emissions. */
560 main_context = registry->priv->main_context;
561 source = e_source_new (dbus_object, main_context, &error);
562 object_path = g_dbus_object_get_object_path (dbus_object);
564 /* The likelihood of an error here is slim, so it's
565 * sufficient to just print a warning if one occurs. */
567 g_warn_if_fail (source == NULL);
569 "ESourceRegistry: Failed to create a "
570 "data source object for path '%s': %s",
571 object_path, error->message);
572 g_error_free (error);
576 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
578 /* Add the ESource to the object path table immediately. */
579 source_registry_object_path_table_insert (
580 registry, object_path, source);
586 source_registry_unref_source (ESource *source)
588 g_signal_handlers_disconnect_matched (
589 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
590 source_registry_source_changed_cb, NULL);
592 g_signal_handlers_disconnect_matched (
593 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
594 source_registry_source_notify_enabled_cb, NULL);
596 g_object_unref (source);
600 source_registry_add_source (ESourceRegistry *registry,
605 /* This is called in the manager thread during initialization
606 * and in response to "object-added" signals from the manager. */
608 uid = e_source_get_uid (source);
609 g_return_if_fail (uid != NULL);
611 g_mutex_lock (®istry->priv->sources_lock);
613 /* Check if we already have this source in the registry. */
614 if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
615 g_mutex_unlock (®istry->priv->sources_lock);
621 G_CALLBACK (source_registry_source_changed_cb),
625 source, "notify::enabled",
626 G_CALLBACK (source_registry_source_notify_enabled_cb),
629 g_mutex_unlock (®istry->priv->sources_lock);
631 source_registry_sources_insert (registry, source);
635 source_registry_object_added_idle_cb (gpointer user_data)
637 SourceClosure *closure = user_data;
638 ESourceRegistry *registry = closure->registry;
639 ESource *source = closure->source;
641 g_signal_emit (registry, signals[SOURCE_ADDED], 0, source);
647 source_registry_object_added_cb (GDBusObjectManager *object_manager,
648 GDBusObject *dbus_object,
649 ESourceRegistry *registry)
651 SourceClosure *closure;
652 GSource *idle_source;
655 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
657 source = source_registry_new_source (registry, dbus_object);
658 g_return_if_fail (source != NULL);
660 /* Add the new ESource to our internal hash table so it can be
661 * obtained through e_source_registry_ref_source() immediately. */
662 source_registry_add_source (registry, source);
664 /* Schedule a callback on the ESourceRegistry's GMainContext. */
666 closure = g_slice_new0 (SourceClosure);
667 closure->registry = g_object_ref (registry);
668 closure->source = g_object_ref (source);
670 idle_source = g_idle_source_new ();
671 g_source_set_callback (
673 source_registry_object_added_idle_cb,
674 closure, (GDestroyNotify) source_closure_free);
675 g_source_attach (idle_source, registry->priv->main_context);
676 g_source_unref (idle_source);
678 g_object_unref (source);
682 source_registry_object_removed_idle_cb (gpointer user_data)
684 SourceClosure *closure = user_data;
685 ESourceRegistry *registry = closure->registry;
686 ESource *source = closure->source;
688 /* Removing the ESource won't finalize it because the
689 * SourceClosure itself still holds a reference on it. */
690 if (source_registry_sources_remove (registry, source))
691 g_signal_emit (registry, signals[SOURCE_REMOVED], 0, source);
697 source_registry_object_removed_cb (GDBusObjectManager *manager,
698 GDBusObject *dbus_object,
699 ESourceRegistry *registry)
701 SourceClosure *closure;
702 GSource *idle_source;
704 const gchar *object_path;
706 /* Find the corresponding ESource in the object path table.
707 * Note that the lookup returns a new ESource reference. */
708 object_path = g_dbus_object_get_object_path (dbus_object);
709 source = source_registry_object_path_table_lookup (
710 registry, object_path);
711 g_return_if_fail (E_IS_SOURCE (source));
713 /* Remove the ESource from the object path table immediately. */
714 source_registry_object_path_table_remove (registry, object_path);
716 /* Schedule a callback on the ESourceRegistry's GMainContext. */
718 closure = g_slice_new0 (SourceClosure);
719 closure->registry = g_object_ref (registry);
720 closure->source = g_object_ref (source);
722 idle_source = g_idle_source_new ();
723 g_source_set_callback (
725 source_registry_object_removed_idle_cb,
726 closure, (GDestroyNotify) source_closure_free);
727 g_source_attach (idle_source, registry->priv->main_context);
728 g_source_unref (idle_source);
730 g_object_unref (source);
734 source_registry_object_manager_running (gpointer data)
736 ThreadClosure *closure = data;
738 g_mutex_lock (&closure->main_loop_mutex);
739 g_cond_broadcast (&closure->main_loop_cond);
740 g_mutex_unlock (&closure->main_loop_mutex);
746 source_registry_object_manager_thread (gpointer data)
748 GDBusObjectManager *object_manager;
749 ThreadClosure *closure = data;
750 GSource *idle_source;
752 gulong object_added_id = 0;
753 gulong object_removed_id = 0;
755 /* GDBusObjectManagerClient grabs the thread-default GMainContext
756 * at creation time and only emits signals from that GMainContext.
757 * Running it in a separate thread prevents its signal emissions
758 * from being inhibited by someone overriding the thread-default
761 /* This becomes the GMainContext that GDBusObjectManagerClient
762 * will emit signals from. Make it the thread-default context
763 * for this thread before creating the client. */
764 g_main_context_push_thread_default (closure->main_context);
766 object_manager = e_dbus_object_manager_client_new_for_bus_sync (
768 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
769 SOURCES_DBUS_SERVICE_NAME,
771 NULL, &closure->error);
775 ((object_manager != NULL) && (closure->error == NULL)) ||
776 ((object_manager == NULL) && (closure->error != NULL)));
778 /* If we failed to create the GDBusObjectManagerClient, skip
779 * straight to the main loop. The GError will be propagated
780 * back to the caller, the main loop will terminate, and the
781 * partially-initialized ESourceRegistry will be destroyed. */
782 if (object_manager == NULL)
785 /* Give the registry a handle to the object manager. */
786 closure->registry->priv->dbus_object_manager =
787 g_object_ref (object_manager);
789 /* Now populate the registry with an initial set of ESources. */
791 list = g_dbus_object_manager_get_objects (object_manager);
793 for (link = list; link != NULL; link = g_list_next (link)) {
794 GDBusObject *dbus_object;
797 dbus_object = G_DBUS_OBJECT (link->data);
799 source = source_registry_new_source (
800 closure->registry, dbus_object);
802 if (source != NULL) {
803 source_registry_add_source (
804 closure->registry, source);
805 g_object_unref (source);
809 g_list_free_full (list, (GDestroyNotify) g_object_unref);
811 /* Listen for D-Bus object additions and removals. */
813 object_added_id = g_signal_connect (
814 object_manager, "object-added",
815 G_CALLBACK (source_registry_object_added_cb),
818 object_removed_id = g_signal_connect (
819 object_manager, "object-removed",
820 G_CALLBACK (source_registry_object_removed_cb),
824 /* Schedule a one-time idle callback to broadcast through a
825 * condition variable that our main loop is up and running. */
827 idle_source = g_idle_source_new ();
828 g_source_set_callback (
830 source_registry_object_manager_running,
831 closure, (GDestroyNotify) NULL);
832 g_source_attach (idle_source, closure->main_context);
833 g_source_unref (idle_source);
835 /* Now we mostly idle here for the rest of the session. */
837 g_main_loop_run (closure->main_loop);
839 /* Clean up and exit. */
841 if (object_manager != NULL) {
842 g_signal_handler_disconnect (object_manager, object_added_id);
843 g_signal_handler_disconnect (object_manager, object_removed_id);
844 g_object_unref (object_manager);
847 g_main_context_pop_thread_default (closure->main_context);
853 source_registry_set_property (GObject *object,
858 switch (property_id) {
859 case PROP_DEFAULT_ADDRESS_BOOK:
860 e_source_registry_set_default_address_book (
861 E_SOURCE_REGISTRY (object),
862 g_value_get_object (value));
865 case PROP_DEFAULT_CALENDAR:
866 e_source_registry_set_default_calendar (
867 E_SOURCE_REGISTRY (object),
868 g_value_get_object (value));
871 case PROP_DEFAULT_MAIL_ACCOUNT:
872 e_source_registry_set_default_mail_account (
873 E_SOURCE_REGISTRY (object),
874 g_value_get_object (value));
877 case PROP_DEFAULT_MAIL_IDENTITY:
878 e_source_registry_set_default_mail_identity (
879 E_SOURCE_REGISTRY (object),
880 g_value_get_object (value));
883 case PROP_DEFAULT_MEMO_LIST:
884 e_source_registry_set_default_memo_list (
885 E_SOURCE_REGISTRY (object),
886 g_value_get_object (value));
889 case PROP_DEFAULT_TASK_LIST:
890 e_source_registry_set_default_task_list (
891 E_SOURCE_REGISTRY (object),
892 g_value_get_object (value));
896 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
900 source_registry_get_property (GObject *object,
905 switch (property_id) {
906 case PROP_DEFAULT_ADDRESS_BOOK:
907 g_value_take_object (
909 e_source_registry_ref_default_address_book (
910 E_SOURCE_REGISTRY (object)));
913 case PROP_DEFAULT_CALENDAR:
914 g_value_take_object (
916 e_source_registry_ref_default_calendar (
917 E_SOURCE_REGISTRY (object)));
920 case PROP_DEFAULT_MAIL_ACCOUNT:
921 g_value_take_object (
923 e_source_registry_ref_default_mail_account (
924 E_SOURCE_REGISTRY (object)));
927 case PROP_DEFAULT_MAIL_IDENTITY:
928 g_value_take_object (
930 e_source_registry_ref_default_mail_identity (
931 E_SOURCE_REGISTRY (object)));
934 case PROP_DEFAULT_MEMO_LIST:
935 g_value_take_object (
937 e_source_registry_ref_default_memo_list (
938 E_SOURCE_REGISTRY (object)));
941 case PROP_DEFAULT_TASK_LIST:
942 g_value_take_object (
944 e_source_registry_ref_default_task_list (
945 E_SOURCE_REGISTRY (object)));
949 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
953 source_registry_dispose (GObject *object)
955 ESourceRegistryPrivate *priv;
957 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
959 /* Terminate the manager thread first. */
960 if (priv->manager_thread != NULL) {
961 g_main_loop_quit (priv->thread_closure->main_loop);
962 g_thread_join (priv->manager_thread);
963 thread_closure_free (priv->thread_closure);
964 priv->manager_thread = NULL;
965 priv->thread_closure = NULL;
968 if (priv->main_context != NULL) {
969 g_main_context_unref (priv->main_context);
970 priv->main_context = NULL;
973 if (priv->dbus_object_manager != NULL) {
974 g_object_unref (priv->dbus_object_manager);
975 priv->dbus_object_manager = NULL;
978 if (priv->dbus_source_manager != NULL) {
979 g_object_unref (priv->dbus_source_manager);
980 priv->dbus_source_manager = NULL;
983 g_hash_table_remove_all (priv->object_path_table);
985 g_hash_table_remove_all (priv->sources);
987 if (priv->settings != NULL) {
988 g_signal_handlers_disconnect_by_data (priv->settings, object);
989 g_object_unref (priv->settings);
990 priv->settings = NULL;
993 /* Chain up to parent's finalize() method. */
994 G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
998 source_registry_finalize (GObject *object)
1000 ESourceRegistryPrivate *priv;
1002 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
1004 g_hash_table_destroy (priv->object_path_table);
1005 g_mutex_clear (&priv->object_path_table_lock);
1007 g_hash_table_destroy (priv->sources);
1008 g_mutex_clear (&priv->sources_lock);
1010 /* Chain up to parent's finalize() method. */
1011 G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
1015 source_registry_initable_init (GInitable *initable,
1016 GCancellable *cancellable,
1019 ESourceRegistry *registry;
1020 ThreadClosure *closure;
1022 registry = E_SOURCE_REGISTRY (initable);
1024 closure = g_slice_new0 (ThreadClosure);
1025 closure->registry = registry; /* do not reference */
1026 closure->main_context = g_main_context_new ();
1027 /* It's important to pass 'is_running=FALSE' here because
1028 * we wait for the main loop to start running as a way of
1029 * synchronizing with the manager thread. */
1030 closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
1031 g_cond_init (&closure->main_loop_cond);
1032 g_mutex_init (&closure->main_loop_mutex);
1034 registry->priv->thread_closure = closure;
1036 registry->priv->manager_thread = g_thread_new (
1038 source_registry_object_manager_thread,
1041 if (registry->priv->manager_thread == NULL)
1044 /* Wait for notification that the manager
1045 * thread's main loop has been started. */
1046 g_mutex_lock (&closure->main_loop_mutex);
1047 while (!g_main_loop_is_running (closure->main_loop))
1049 &closure->main_loop_cond,
1050 &closure->main_loop_mutex);
1051 g_mutex_unlock (&closure->main_loop_mutex);
1053 /* Check for error in the manager thread. */
1054 if (closure->error != NULL) {
1055 g_propagate_error (error, closure->error);
1056 closure->error = NULL;
1060 /* The registry should now be populated with sources.
1062 * XXX Actually, not necessarily if the registry service was
1063 * just now activated. There may yet be a small window
1064 * while the registry service starts up before it exports
1065 * any sources, even built-in sources. This COULD create
1066 * problems if any logic that depends on those built-in
1067 * sources executes during this time window, but so far
1068 * we haven't seen any cases of that.
1070 * Attempts in the past to stop and wait for sources to
1071 * show up have proven problematic. See for example:
1072 * https://bugzilla.gnome.org/678378
1074 * Leave the runtime check disabled for the moment.
1075 * I have a feeling I'll be revisiting this again.
1077 /*g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);*/
1079 /* The EDBusSourceManagerProxy is just another D-Bus interface
1080 * that resides at the same object path. It's unrelated to the
1081 * GDBusObjectManagerClient and doesn't need its own thread. */
1082 registry->priv->dbus_source_manager =
1083 e_dbus_source_manager_proxy_new_for_bus_sync (
1085 G_DBUS_PROXY_FLAGS_NONE,
1086 SOURCES_DBUS_SERVICE_NAME,
1088 cancellable, error);
1090 if (registry->priv->dbus_source_manager == NULL)
1093 /* Allow authentication prompts for all exported data sources
1094 * when a new EDBusSourceManagerProxy is created. The thought
1095 * being, if you cancel an authentication prompt you will not
1096 * be bothered again until you start (or restart) a new E-D-S
1097 * client app. Failure here is non-fatal, ignore errors. */
1098 e_dbus_source_manager_call_allow_auth_prompt_all_sync (
1099 registry->priv->dbus_source_manager, cancellable, NULL);
1105 e_source_registry_class_init (ESourceRegistryClass *class)
1107 GObjectClass *object_class;
1109 g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
1111 object_class = G_OBJECT_CLASS (class);
1112 object_class->set_property = source_registry_set_property;
1113 object_class->get_property = source_registry_get_property;
1114 object_class->dispose = source_registry_dispose;
1115 object_class->finalize = source_registry_finalize;
1117 /* The property names correspond to the key names in the
1118 * "org.gnome.Evolution.DefaultSources" GSettings schema. */
1121 * ESourceRegistry:default-address-book:
1123 * The default address book #ESource.
1125 g_object_class_install_property (
1127 PROP_DEFAULT_ADDRESS_BOOK,
1128 g_param_spec_object (
1129 "default-address-book",
1130 "Default Address Book",
1131 "The default address book ESource",
1134 G_PARAM_STATIC_STRINGS));
1137 * ESourceRegistry:default-calendar:
1139 * The default calendar #ESource.
1141 g_object_class_install_property (
1143 PROP_DEFAULT_CALENDAR,
1144 g_param_spec_object (
1147 "The default calendar ESource",
1150 G_PARAM_STATIC_STRINGS));
1153 * ESourceRegistry:default-mail-account:
1155 * The default mail account #ESource.
1157 g_object_class_install_property (
1159 PROP_DEFAULT_MAIL_ACCOUNT,
1160 g_param_spec_object (
1161 "default-mail-account",
1162 "Default Mail Account",
1163 "The default mail account ESource",
1166 G_PARAM_STATIC_STRINGS));
1169 * ESourceRegistry:default-mail-identity:
1171 * The default mail identity #ESource.
1173 g_object_class_install_property (
1175 PROP_DEFAULT_MAIL_IDENTITY,
1176 g_param_spec_object (
1177 "default-mail-identity",
1178 "Default Mail Identity",
1179 "The default mail identity ESource",
1182 G_PARAM_STATIC_STRINGS));
1185 * ESourceRegistry:default-memo-list:
1187 * The default memo list #ESource.
1189 g_object_class_install_property (
1191 PROP_DEFAULT_MEMO_LIST,
1192 g_param_spec_object (
1193 "default-memo-list",
1194 "Default Memo List",
1195 "The default memo list ESource",
1198 G_PARAM_STATIC_STRINGS));
1201 * ESourceRegistry:default-task-list:
1203 * The default task list #ESource.
1205 g_object_class_install_property (
1207 PROP_DEFAULT_TASK_LIST,
1208 g_param_spec_object (
1209 "default-task-list",
1210 "Default Task List",
1211 "The default task list ESource",
1214 G_PARAM_STATIC_STRINGS));
1217 * ESourceRegistry::source-added:
1218 * @registry: the #ESourceRegistry which emitted the signal
1219 * @source: the newly-added #ESource
1221 * Emitted when an #ESource is added to @registry.
1223 signals[SOURCE_ADDED] = g_signal_new (
1225 G_OBJECT_CLASS_TYPE (object_class),
1227 G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
1229 g_cclosure_marshal_VOID__OBJECT,
1234 * ESourceRegistry::source-changed:
1235 * @registry: the #ESourceRegistry which emitted the signal
1236 * @source: the #ESource that changed
1238 * Emitted when an #ESource registered with @registry emits
1239 * its #ESource::changed signal.
1241 signals[SOURCE_CHANGED] = g_signal_new (
1243 G_OBJECT_CLASS_TYPE (object_class),
1245 G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
1247 g_cclosure_marshal_VOID__OBJECT,
1252 * ESourceRegistry::source-removed:
1253 * @registry: the #ESourceRegistry which emitted the signal
1254 * @source: the #ESource that got removed
1256 * Emitted when an #ESource is removed from @registry.
1258 signals[SOURCE_REMOVED] = g_signal_new (
1260 G_OBJECT_CLASS_TYPE (object_class),
1262 G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
1264 g_cclosure_marshal_VOID__OBJECT,
1269 * ESourceRegistry::source-enabled:
1270 * @registry: the #ESourceRegistry which emitted the signal
1271 * @source: the #ESource that got enabled
1273 * Emitted when an #ESource #ESource:enabled property becomes %TRUE.
1275 signals[SOURCE_ENABLED] = g_signal_new (
1277 G_OBJECT_CLASS_TYPE (object_class),
1279 G_STRUCT_OFFSET (ESourceRegistryClass, source_enabled),
1281 g_cclosure_marshal_VOID__OBJECT,
1286 * ESourceRegistry::source-disabled:
1287 * @registry: the #ESourceRegistry which emitted the signal
1288 * @source: the #ESource that got disabled
1290 * Emitted when an #ESource #ESource:enabled property becomes %FALSE.
1292 signals[SOURCE_DISABLED] = g_signal_new (
1294 G_OBJECT_CLASS_TYPE (object_class),
1296 G_STRUCT_OFFSET (ESourceRegistryClass, source_disabled),
1298 g_cclosure_marshal_VOID__OBJECT,
1304 e_source_registry_initable_init (GInitableIface *interface)
1306 interface->init = source_registry_initable_init;
1310 e_source_registry_init (ESourceRegistry *registry)
1312 registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
1314 /* This is so the object manager thread can schedule signal
1315 * emissions on the thread-default context for this thread. */
1316 registry->priv->main_context = g_main_context_ref_thread_default ();
1318 /* D-Bus object path -> ESource */
1319 registry->priv->object_path_table =
1320 g_hash_table_new_full (
1321 (GHashFunc) g_str_hash,
1322 (GEqualFunc) g_str_equal,
1323 (GDestroyNotify) g_free,
1324 (GDestroyNotify) g_object_unref);
1326 g_mutex_init (®istry->priv->object_path_table_lock);
1328 /* UID string -> ESource */
1329 registry->priv->sources = g_hash_table_new_full (
1330 (GHashFunc) g_str_hash,
1331 (GEqualFunc) g_str_equal,
1332 (GDestroyNotify) g_free,
1333 (GDestroyNotify) source_registry_unref_source);
1335 g_mutex_init (®istry->priv->sources_lock);
1337 registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
1340 registry->priv->settings, "changed",
1341 G_CALLBACK (source_registry_settings_changed_cb), registry);
1345 * e_source_registry_new_sync:
1346 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1347 * @error: return location for a #GError, or %NULL
1349 * Creates a new #ESourceRegistry front-end for the registry D-Bus service.
1350 * If an error occurs in connecting to the D-Bus service, the function sets
1351 * @error and returns %NULL.
1353 * Returns: a new #ESourceRegistry, or %NULL
1358 e_source_registry_new_sync (GCancellable *cancellable,
1361 /* XXX Work around http://bugzilla.gnome.org/show_bug.cgi?id=683519
1362 * until GObject's type initialization deadlock issue is fixed.
1363 * Apparently only the synchronous instantiation is affected. */
1364 g_type_ensure (G_TYPE_DBUS_CONNECTION);
1366 return g_initable_new (
1367 E_TYPE_SOURCE_REGISTRY,
1368 cancellable, error, NULL);
1372 * e_source_registry_new:
1373 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1374 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1376 * @user_data: (closure): data to pass to the callback function
1378 * Asynchronously creates a new #ESourceRegistry front-end for the registry
1381 * When the operation is finished, @callback will be called. You can then
1382 * call e_source_registry_new_finish() to get the result of the operation.
1387 e_source_registry_new (GCancellable *cancellable,
1388 GAsyncReadyCallback callback,
1391 g_async_initable_new_async (
1392 E_TYPE_SOURCE_REGISTRY,
1393 G_PRIORITY_DEFAULT, cancellable,
1394 callback, user_data, NULL);
1398 * e_source_registry_new_finish:
1399 * @result: a #GAsyncResult
1400 * @error: return location for a #GError, or %NULL
1402 * Finishes the operation started with e_source_registry_new_finish().
1403 * If an error occurs in connecting to the D-Bus service, the function
1404 * sets @error and returns %NULL.
1406 * Returns: a new #ESourceRegistry, or %NULL
1411 e_source_registry_new_finish (GAsyncResult *result,
1414 GObject *source_object;
1417 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1419 source_object = g_async_result_get_source_object (result);
1420 g_return_val_if_fail (source_object != NULL, NULL);
1422 object = g_async_initable_new_finish (
1423 G_ASYNC_INITABLE (source_object), result, error);
1425 g_object_unref (source_object);
1427 return (object != NULL) ? E_SOURCE_REGISTRY (object) : NULL;
1430 /* Helper for e_source_registry_authenticate() */
1432 source_registry_authenticate_thread (GSimpleAsyncResult *simple,
1434 GCancellable *cancellable)
1436 AsyncContext *async_context;
1437 GError *error = NULL;
1439 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1441 e_source_registry_authenticate_sync (
1442 E_SOURCE_REGISTRY (object),
1443 async_context->source,
1444 async_context->auth,
1445 cancellable, &error);
1448 g_simple_async_result_take_error (simple, error);
1451 /* Helper for e_source_registry_authenticate_sync() */
1453 source_registry_authenticate_respond_cb (AuthContext *auth_context)
1455 ESourceAuthenticationResult auth_result;
1456 GError *non_fatal_error = NULL;
1458 g_return_val_if_fail (auth_context->authenticating, FALSE);
1460 auth_result = auth_context->auth_result;
1462 /* Allow the next authentication attempt to proceed. */
1463 auth_context->authenticating = FALSE;
1465 /* Send the server a status update based on the authentication
1466 * result. Note, we don't really care if the D-Bus message gets
1467 * through to the server at this point. If it doesn't, the auth
1468 * session will either time out on its own or the authentication
1469 * dialog will eventually be dismissed by the user. */
1471 /* If we were cancelled from our side, we have a bit of a dilemma.
1472 * We need to tell the server to cancel the authentication session,
1473 * but that involves making a synchronous D-Bus call, which we are
1474 * not supposed to do if we know we've been cancelled. But if we
1475 * don't tell the server, the authentication session will be left
1476 * to timeout on its own (which may take minutes), and meanwhile
1477 * all other authentication requests are blocked. So choose the
1478 * lesser evil and make the synchronous call but without passing
1479 * the already-cancelled GCancellable. */
1480 if (g_cancellable_is_cancelled (auth_context->cancellable)) {
1481 e_dbus_authenticator_call_cancel_sync (
1482 auth_context->dbus_auth,
1483 NULL, &non_fatal_error);
1484 g_main_loop_quit (auth_context->main_loop);
1485 auth_context->success = FALSE;
1487 /* If an error occurred while attempting to authenticate,
1488 * tell the server to cancel the authentication session. */
1489 } else if (auth_result == E_SOURCE_AUTHENTICATION_ERROR) {
1490 e_dbus_authenticator_call_cancel_sync (
1491 auth_context->dbus_auth,
1492 auth_context->cancellable,
1494 g_main_loop_quit (auth_context->main_loop);
1495 auth_context->success = FALSE;
1497 /* If the password was accepted, let the server know so it
1498 * can close any authentication dialogs and save the user
1499 * provided password to the keyring. */
1500 } else if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
1501 e_dbus_authenticator_call_accepted_sync (
1502 auth_context->dbus_auth,
1503 auth_context->cancellable,
1505 g_main_loop_quit (auth_context->main_loop);
1506 auth_context->success = TRUE;
1508 /* If the password was rejected, let the server know so it can
1509 * indicate failure and request a different password, and then
1510 * wait for the next "response" signal. */
1512 e_dbus_authenticator_call_rejected_sync (
1513 auth_context->dbus_auth,
1514 auth_context->cancellable,
1518 /* Leave breadcrumbs if something went wrong,
1519 * but don't fail the whole operation over it. */
1520 if (non_fatal_error != NULL) {
1521 g_warning ("%s: %s", G_STRFUNC, non_fatal_error->message);
1522 g_error_free (non_fatal_error);
1528 /* Helper for e_source_registry_authenticate_sync() */
1530 source_registry_authenticate_authenticate_cb (EDBusAuthenticator *dbus_auth,
1531 const gchar *encrypted_secret,
1532 AuthContext *auth_context)
1534 GSource *idle_source;
1535 GMainContext *main_context;
1537 gboolean valid_secret;
1539 /* We should only get one secret at a time. */
1540 g_return_if_fail (!auth_context->authenticating);
1542 valid_secret = gcr_secret_exchange_receive (
1543 auth_context->secret_exchange, encrypted_secret);
1544 g_return_if_fail (valid_secret);
1546 auth_context->authenticating = TRUE;
1548 /* This avoids revealing the password in a stack trace. */
1549 password = g_string_new (
1550 gcr_secret_exchange_get_secret (
1551 auth_context->secret_exchange, NULL));
1553 /* Try authenticating with the given password. We have to
1554 * call this synchronously because some authenticators use
1555 * mutexes to serialize I/O operations and are not prepared
1556 * to make authentication attempts from a different thread.
1558 * Unfortunately this means we won't notice server-side
1559 * dismissals while the main loop is blocked. We respond
1560 * to the server from a low-priority idle callback so that
1561 * any pending "dismissed" signals get handled first. */
1563 auth_context->auth_result =
1564 e_source_authenticator_try_password_sync (
1565 auth_context->auth, password,
1566 auth_context->cancellable,
1567 auth_context->error);
1569 idle_source = g_idle_source_new ();
1570 main_context = g_main_context_get_thread_default ();
1571 g_source_set_callback (
1572 idle_source, (GSourceFunc)
1573 source_registry_authenticate_respond_cb,
1574 auth_context, NULL);
1575 g_source_attach (idle_source, main_context);
1576 g_source_unref (idle_source);
1578 g_string_free (password, TRUE);
1581 /* Helper for e_source_registry_authenticate_sync() */
1583 source_registry_authenticate_dismissed_cb (EDBusAuthenticator *dbus_auth,
1584 AuthContext *auth_context)
1586 /* Be careful not to overwrite an existing error in case this
1587 * is called after e_source_authenticator_try_password_sync()
1588 * but prior to the idle callback. */
1589 if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
1590 /* XXX Use a separate error code for dismissals? */
1591 g_set_error_literal (
1592 auth_context->error,
1593 G_IO_ERROR, G_IO_ERROR_CANCELLED,
1594 _("The user declined to authenticate"));
1595 auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
1598 g_main_loop_quit (auth_context->main_loop);
1599 auth_context->success = FALSE;
1602 /* Helper for e_source_registry_authenticate_sync() */
1604 source_registry_call_authenticate_for_source (ESourceRegistry *registry,
1605 ESourceAuthenticator *auth,
1607 gchar **out_object_path,
1608 GCancellable *cancellable,
1611 ESource *collection;
1613 gchar *prompt_title = NULL;
1614 gchar *prompt_message = NULL;
1615 gchar *prompt_description = NULL;
1618 g_object_ref (source);
1620 /* If the source is a member of a collection, we want to store
1621 * the password under the UID of the "collection" source so it
1622 * will apply to the entire collection.
1624 * XXX This assumes all sources in a collection share a single
1625 * password. If that turns out not to be true in all cases
1626 * we could maybe add a "SharedPassword: true/false" key to
1627 * [Collection] and apply it here.
1629 * Addendum: Assumption proven wrong. GOA's generic IMAP/SMTP
1630 * provider uses a plain ECollectionBackend (backend
1631 * name "none") with separately stored passwords for
1632 * IMAP vs SMTP. Just handle this case directly for
1633 * now, but don't rule out the "SharedPassword" idea.
1635 collection = e_source_registry_find_extension (
1636 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1637 if (collection != NULL) {
1638 ESourceBackend *extension;
1639 gchar *backend_name;
1641 extension = e_source_get_extension (
1642 collection, E_SOURCE_EXTENSION_COLLECTION);
1643 backend_name = e_source_backend_dup_backend_name (extension);
1645 if (g_strcmp0 (backend_name, "none") != 0) {
1646 g_object_unref (source);
1647 source = g_object_ref (collection);
1650 g_free (backend_name);
1652 g_object_unref (collection);
1655 uid = e_source_get_uid (source);
1657 e_source_authenticator_get_prompt_strings (
1661 &prompt_description);
1663 success = e_dbus_source_manager_call_authenticate_sync (
1664 registry->priv->dbus_source_manager, uid,
1665 prompt_title, prompt_message, prompt_description,
1666 out_object_path, cancellable, error);
1668 g_free (prompt_title);
1669 g_free (prompt_message);
1670 g_free (prompt_description);
1672 g_object_unref (source);
1678 * e_source_registry_authenticate_sync:
1679 * @registry: an #ESourceRegistry
1680 * @source: an #ESource
1681 * @auth: an #ESourceAuthenticator
1682 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1683 * @error: return location for a #GError, or %NULL
1685 * Authenticates @source, using @auth to handle the authentication
1686 * attempts. The operation loops until authentication is successful or
1687 * the user aborts further authentication attempts. If an error occurs,
1688 * the function will set @error and return %FALSE.
1690 * Note that @source need not have a #GDBusObject, which means this
1691 * function can test authentication on a scratch #ESource.
1693 * Only backend implementations and data source editors should call this
1694 * function. The intent is for basic client applications to not have to
1695 * deal with authentication at all.
1697 * Returns: %TRUE on success, %FALSE on failure
1702 e_source_registry_authenticate_sync (ESourceRegistry *registry,
1704 ESourceAuthenticator *auth,
1705 GCancellable *cancellable,
1708 AuthContext *auth_context;
1709 GMainContext *main_context;
1710 EDBusAuthenticator *dbus_auth;
1711 gchar *encryption_key;
1712 gchar *object_path = NULL;
1715 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1716 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1717 g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth), FALSE);
1719 /* This extracts authentication prompt details for the ESource
1720 * before initiating an authentication session with the server,
1721 * so split it out of the main algorithm for clarity's sake. */
1722 success = source_registry_call_authenticate_for_source (
1723 registry, auth, source, &object_path, cancellable, error);
1726 g_warn_if_fail (object_path == NULL);
1730 g_return_val_if_fail (object_path != NULL, FALSE);
1732 main_context = g_main_context_new ();
1733 g_main_context_push_thread_default (main_context);
1735 dbus_auth = e_dbus_authenticator_proxy_new_for_bus_sync (
1737 G_DBUS_PROXY_FLAGS_NONE,
1738 SOURCES_DBUS_SERVICE_NAME,
1739 object_path, cancellable, error);
1741 g_free (object_path);
1743 if (dbus_auth == NULL) {
1748 auth_context = g_slice_new0 (AuthContext);
1749 auth_context->auth = g_object_ref (auth);
1750 auth_context->dbus_auth = dbus_auth; /* takes ownership */
1751 auth_context->main_loop = g_main_loop_new (main_context, FALSE);
1752 auth_context->error = error;
1754 /* This just needs to be something other than
1755 * E_SOURCE_AUTHENTICATION_ERROR so we don't trip
1756 * up source_registry_authenticate_dismissed_cb(). */
1757 auth_context->auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
1759 if (G_IS_CANCELLABLE (cancellable))
1760 auth_context->cancellable = g_object_ref (cancellable);
1762 auth_context->secret_exchange =
1763 gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1);
1766 dbus_auth, "authenticate",
1767 G_CALLBACK (source_registry_authenticate_authenticate_cb),
1771 dbus_auth, "dismissed",
1772 G_CALLBACK (source_registry_authenticate_dismissed_cb),
1775 encryption_key = gcr_secret_exchange_begin (
1776 auth_context->secret_exchange);
1778 /* Signal the D-Bus server that we're ready to begin the
1779 * authentication session. This must happen AFTER we've
1780 * connected to the response signal since the server may
1781 * already have a response ready and waiting for us. */
1782 success = e_dbus_authenticator_call_ready_sync (
1783 dbus_auth, encryption_key, cancellable, error);
1785 g_free (encryption_key);
1788 g_main_loop_run (auth_context->main_loop);
1789 success = auth_context->success;
1792 auth_context_free (auth_context);
1795 g_main_context_pop_thread_default (main_context);
1797 /* Make sure the main_context doesn't have pending operations;
1798 * workarounds https://bugzilla.gnome.org/show_bug.cgi?id=690126 */
1799 while (g_main_context_pending (main_context))
1800 g_main_context_iteration (main_context, FALSE);
1802 g_main_context_unref (main_context);
1808 * e_source_registry_authenticate:
1809 * @registry: an #ESourceRegistry
1810 * @source: an #ESource
1811 * @auth: an #ESourceAuthenticator
1812 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1813 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1815 * @user_data: (closure): data to pass to the callback function
1817 * Asynchronously authenticates @source, using @auth to handle the
1818 * authentication attempts. The operation loops until authentication
1819 * is successful or the user aborts further authentication attempts.
1821 * Note that @source need not have a #GDBusObject, which means this
1822 * function can test authentication on a scratch #ESource.
1824 * When the operation is finished, @callback will be called. You can then
1825 * call e_source_registry_authenticate_finish() to get the result of the
1828 * Only backend implementations and data source editors should call this
1829 * function. The intent is for basic client applications to not have to
1830 * deal with authentication at all.
1835 e_source_registry_authenticate (ESourceRegistry *registry,
1837 ESourceAuthenticator *auth,
1838 GCancellable *cancellable,
1839 GAsyncReadyCallback callback,
1842 GSimpleAsyncResult *simple;
1843 AsyncContext *async_context;
1845 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1846 g_return_if_fail (E_IS_SOURCE (source));
1847 g_return_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth));
1849 async_context = g_slice_new0 (AsyncContext);
1850 async_context->source = g_object_ref (source);
1851 async_context->auth = g_object_ref (auth);
1853 simple = g_simple_async_result_new (
1854 G_OBJECT (registry), callback, user_data,
1855 e_source_registry_authenticate);
1857 g_simple_async_result_set_check_cancellable (simple, cancellable);
1859 g_simple_async_result_set_op_res_gpointer (
1860 simple, async_context, (GDestroyNotify) async_context_free);
1862 g_simple_async_result_run_in_thread (
1863 simple, source_registry_authenticate_thread,
1864 G_PRIORITY_DEFAULT, cancellable);
1866 g_object_unref (simple);
1870 * e_source_registry_authenticate_finish:
1871 * @registry: an #ESourceRegistry
1872 * @result: a #GAsyncResult
1873 * @error: return location for a #GError, or %NULL
1875 * Finishes the operation started with e_source_registry_authenticate().
1876 * If an error occurred, the function will set @error and return %FALSE.
1878 * Returns: %TRUE on success, %FALSE on failure
1883 e_source_registry_authenticate_finish (ESourceRegistry *registry,
1884 GAsyncResult *result,
1887 GSimpleAsyncResult *simple;
1889 g_return_val_if_fail (
1890 g_simple_async_result_is_valid (
1891 result, G_OBJECT (registry),
1892 e_source_registry_authenticate), FALSE);
1894 simple = G_SIMPLE_ASYNC_RESULT (result);
1896 /* Assume success unless a GError is set. */
1897 return !g_simple_async_result_propagate_error (simple, error);
1900 /* Helper for e_source_registry_commit_source() */
1902 source_registry_commit_source_thread (GSimpleAsyncResult *simple,
1904 GCancellable *cancellable)
1906 AsyncContext *async_context;
1907 GError *error = NULL;
1909 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1911 e_source_registry_commit_source_sync (
1912 E_SOURCE_REGISTRY (object),
1913 async_context->source,
1914 cancellable, &error);
1917 g_simple_async_result_take_error (simple, error);
1921 * e_source_registry_commit_source_sync:
1922 * @registry: an #ESourceRegistry
1923 * @source: an #ESource with changes to commit
1924 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1925 * @error: return location for #GError, or %NULL
1927 * This is a convenience function intended for use with graphical
1928 * #ESource editors. Call this function when the user is finished
1929 * making changes to @source.
1931 * If @source has a #GDBusObject, its contents are submitted to the D-Bus
1932 * service through e_source_write_sync().
1934 * If @source does NOT have a #GDBusObject (implying it's a scratch
1935 * #ESource), its contents are submitted to the D-Bus service through
1936 * either e_source_remote_create_sync() if @source is to be a collection
1937 * member, or e_source_registry_create_sources_sync() if @source to be an
1938 * independent data source.
1940 * If an error occurs, the function will set @error and return %FALSE.
1942 * Returns: %TRUE on success, %FALSE on failure
1947 e_source_registry_commit_source_sync (ESourceRegistry *registry,
1949 GCancellable *cancellable,
1952 GDBusObject *dbus_object;
1953 ESource *collection_source;
1954 gboolean collection_member;
1957 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1958 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1960 dbus_object = e_source_ref_dbus_object (source);
1962 collection_source = e_source_registry_find_extension (
1963 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1966 (collection_source != NULL) &&
1967 (collection_source != source);
1969 if (dbus_object != NULL) {
1970 success = e_source_write_sync (source, cancellable, error);
1971 g_object_unref (dbus_object);
1973 } else if (collection_member) {
1974 success = e_source_remote_create_sync (
1975 collection_source, source, cancellable, error);
1978 GList *list = g_list_prepend (NULL, source);
1979 success = e_source_registry_create_sources_sync (
1980 registry, list, cancellable, error);
1984 if (collection_source != NULL)
1985 g_object_unref (collection_source);
1991 * e_source_registry_commit_source:
1992 * @registry: an #ESourceRegistry
1993 * @source: an #ESource with changes to commit
1994 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1995 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1997 * @user_data: (closure): data to pass to the callback function
1999 * See e_source_registry_commit_source_sync() for details.
2001 * When the operation is finished, @callback will be called. You can then
2002 * call e_source_registry_commit_source_finish() to get the result of the
2008 e_source_registry_commit_source (ESourceRegistry *registry,
2010 GCancellable *cancellable,
2011 GAsyncReadyCallback callback,
2014 GSimpleAsyncResult *simple;
2015 AsyncContext *async_context;
2017 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2018 g_return_if_fail (E_IS_SOURCE (source));
2020 async_context = g_slice_new0 (AsyncContext);
2021 async_context->source = g_object_ref (source);
2023 simple = g_simple_async_result_new (
2024 G_OBJECT (registry), callback, user_data,
2025 e_source_registry_commit_source);
2027 g_simple_async_result_set_check_cancellable (simple, cancellable);
2029 g_simple_async_result_set_op_res_gpointer (
2030 simple, async_context, (GDestroyNotify) async_context_free);
2032 g_simple_async_result_run_in_thread (
2033 simple, source_registry_commit_source_thread,
2034 G_PRIORITY_DEFAULT, cancellable);
2036 g_object_unref (simple);
2040 * e_source_registry_commit_source_finish:
2041 * @registry: an #ESourceRegistry
2042 * @result: a #GAsyncResult
2043 * @error: return location for a #GError, or %NULL
2045 * Finishes the operation started with e_source_registry_commit_source().
2047 * If an error occurred, the function will set @error and return %FALSE.
2049 * Returns: %TRUE on success, %FALSE on failure
2054 e_source_registry_commit_source_finish (ESourceRegistry *registry,
2055 GAsyncResult *result,
2058 GSimpleAsyncResult *simple;
2060 g_return_val_if_fail (
2061 g_simple_async_result_is_valid (
2062 result, G_OBJECT (registry),
2063 e_source_registry_commit_source), FALSE);
2065 simple = G_SIMPLE_ASYNC_RESULT (result);
2067 /* Assume success unless a GError is set. */
2068 return !g_simple_async_result_propagate_error (simple, error);
2071 /* Helper for e_source_registry_create_sources() */
2073 source_registry_create_sources_thread (GSimpleAsyncResult *simple,
2075 GCancellable *cancellable)
2077 AsyncContext *async_context;
2078 GError *error = NULL;
2080 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2082 e_source_registry_create_sources_sync (
2083 E_SOURCE_REGISTRY (object),
2084 async_context->list_of_sources,
2085 cancellable, &error);
2088 g_simple_async_result_take_error (simple, error);
2091 /* Helper for e_source_registry_create_sources_sync() */
2093 source_registry_create_sources_main_loop_quit_cb (gpointer user_data)
2095 GMainLoop *main_loop = user_data;
2097 g_main_loop_quit (main_loop);
2102 /* Helper for e_source_registry_create_sources_sync() */
2104 source_registry_create_sources_object_added_cb (GDBusObjectManager *object_manager,
2105 GDBusObject *dbus_object,
2106 CreateContext *create_context)
2108 EDBusObject *e_dbus_object;
2109 EDBusSource *e_dbus_source;
2112 e_dbus_object = E_DBUS_OBJECT (dbus_object);
2113 e_dbus_source = e_dbus_object_get_source (e_dbus_object);
2114 uid = e_dbus_source_get_uid (e_dbus_source);
2116 g_hash_table_remove (create_context->pending_uids, uid);
2118 /* The hash table will be empty when all of the expected
2119 * GDBusObjects have been added to the GDBusObjectManager. */
2120 if (g_hash_table_size (create_context->pending_uids) == 0) {
2121 GSource *idle_source;
2123 idle_source = g_idle_source_new ();
2124 g_source_set_callback (
2126 source_registry_create_sources_main_loop_quit_cb,
2127 g_main_loop_ref (create_context->main_loop),
2128 (GDestroyNotify) g_main_loop_unref);
2129 g_source_attach (idle_source, create_context->main_context);
2130 g_source_unref (idle_source);
2135 * e_source_registry_create_sources_sync:
2136 * @registry: an #ESourceRegistry
2137 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2139 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2140 * @error: return location for a #GError, or %NULL
2142 * Requests the D-Bus service create new key files for each #ESource in
2143 * @list_of_sources. Each list element must be a scratch #ESource with
2146 * If an error occurs, the function will set @error and return %FALSE.
2148 * Returns: %TRUE on success, %FALSE on failure
2153 e_source_registry_create_sources_sync (ESourceRegistry *registry,
2154 GList *list_of_sources,
2155 GCancellable *cancellable,
2158 CreateContext *create_context;
2159 GVariantBuilder builder;
2162 gulong object_added_id;
2165 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2167 /* Verify the list elements are all ESources. */
2168 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2169 g_return_val_if_fail (E_IS_SOURCE (link->data), FALSE);
2171 create_context = create_context_new ();
2172 g_main_context_push_thread_default (create_context->main_context);
2174 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
2176 for (link = list_of_sources; link != NULL; link = g_list_next (link)) {
2181 source = E_SOURCE (link->data);
2182 uid = e_source_dup_uid (source);
2184 /* Takes ownership of the UID string. */
2185 g_hash_table_add (create_context->pending_uids, uid);
2187 source_data = e_source_to_string (source, NULL);
2188 g_variant_builder_add (&builder, "{ss}", uid, source_data);
2189 g_free (source_data);
2192 variant = g_variant_builder_end (&builder);
2194 /* Use G_CONNECT_AFTER so source_registry_object_added_cb()
2195 * runs first and actually adds the ESource to the internal
2196 * hash table before we go quitting our main loop. */
2197 object_added_id = g_signal_connect_after (
2198 registry->priv->dbus_object_manager, "object-added",
2199 G_CALLBACK (source_registry_create_sources_object_added_cb),
2202 /* This function sinks the floating GVariant reference. */
2203 success = e_dbus_source_manager_call_create_sources_sync (
2204 registry->priv->dbus_source_manager,
2205 variant, cancellable, error);
2207 g_variant_builder_clear (&builder);
2209 /* Wait for an "object-added" signal for each created ESource.
2210 * But also set a short timeout to avoid getting stuck here in
2211 * case the registry service adds sources to its orphan table,
2212 * which prevents them from being exported over D-Bus. */
2214 GSource *timeout_source;
2216 timeout_source = g_timeout_source_new_seconds (2);
2217 g_source_set_callback (
2219 source_registry_create_sources_main_loop_quit_cb,
2220 g_main_loop_ref (create_context->main_loop),
2221 (GDestroyNotify) g_main_loop_unref);
2222 g_source_attach (timeout_source, create_context->main_context);
2223 g_source_unref (timeout_source);
2225 g_main_loop_run (create_context->main_loop);
2228 g_signal_handler_disconnect (
2229 registry->priv->dbus_object_manager, object_added_id);
2231 g_main_context_pop_thread_default (create_context->main_context);
2232 create_context_free (create_context);
2238 * e_source_registry_create_sources:
2239 * @registry: an #ESourceRegistry
2240 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2242 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2243 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2245 * @user_data: (closure): data to pass to the callback function
2247 * Asynchronously requests the D-Bus service create new key files for each
2248 * #ESource in @list_of_sources. Each list element must be a scratch
2249 * #ESource with no #GDBusObject.
2251 * When the operation is finished, @callback will be called. You can then
2252 * call e_source_registry_create_sources_finish() to get the result of the
2258 e_source_registry_create_sources (ESourceRegistry *registry,
2259 GList *list_of_sources,
2260 GCancellable *cancellable,
2261 GAsyncReadyCallback callback,
2264 GSimpleAsyncResult *simple;
2265 AsyncContext *async_context;
2268 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2270 /* Verify the list elements are all ESources. */
2271 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2272 g_return_if_fail (E_IS_SOURCE (link->data));
2274 async_context = g_slice_new0 (AsyncContext);
2275 async_context->list_of_sources = g_list_copy (list_of_sources);
2278 async_context->list_of_sources,
2279 (GFunc) g_object_ref, NULL);
2281 simple = g_simple_async_result_new (
2282 G_OBJECT (registry), callback, user_data,
2283 e_source_registry_create_sources);
2285 g_simple_async_result_set_check_cancellable (simple, cancellable);
2287 g_simple_async_result_set_op_res_gpointer (
2288 simple, async_context, (GDestroyNotify) async_context_free);
2290 g_simple_async_result_run_in_thread (
2291 simple, source_registry_create_sources_thread,
2292 G_PRIORITY_DEFAULT, cancellable);
2294 g_object_unref (simple);
2298 * e_source_registry_create_sources_finish:
2299 * @registry: an #ESourceRegistry
2300 * @result: a #GAsyncResult
2301 * @error: return location for a #GError, or %NULL
2303 * Finishes the operation started with e_source_registry_create_sources().
2305 * If an error occurred, the function will set @error and return %FALSE.
2307 * Returns: %TRUE on success, %FALSE on failure
2312 e_source_registry_create_sources_finish (ESourceRegistry *registry,
2313 GAsyncResult *result,
2316 GSimpleAsyncResult *simple;
2318 g_return_val_if_fail (
2319 g_simple_async_result_is_valid (
2320 result, G_OBJECT (registry),
2321 e_source_registry_create_sources), FALSE);
2323 simple = G_SIMPLE_ASYNC_RESULT (result);
2325 /* Assume success unless a GError is set. */
2326 return !g_simple_async_result_propagate_error (simple, error);
2330 * e_source_registry_ref_source:
2331 * @registry: an #ESourceRegistry
2332 * @uid: a unique identifier string
2334 * Looks up an #ESource in @registry by its unique identifier string.
2336 * The returned #ESource is referenced for thread-safety and must be
2337 * unreferenced with g_object_unref() when finished with it.
2339 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2344 e_source_registry_ref_source (ESourceRegistry *registry,
2347 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2348 g_return_val_if_fail (uid != NULL, NULL);
2350 return source_registry_sources_lookup (registry, uid);
2354 * e_source_registry_list_sources:
2355 * @registry: an #ESourceRegistry
2356 * @extension_name: (allow-none): an extension name, or %NULL
2358 * Returns a list of registered sources, sorted by display name. If
2359 * @extension_name is given, restrict the list to sources having that
2362 * The sources returned in the list are referenced for thread-safety.
2363 * They must each be unreferenced with g_object_unref() when finished
2364 * when them. Free the returned list itself with g_list_free().
2366 * An easy way to free the list properly in one step is as follows:
2369 * g_list_free_full (list, g_object_unref);
2372 * Returns: (element-type ESource) (transfer full): a sorted list of sources
2377 e_source_registry_list_sources (ESourceRegistry *registry,
2378 const gchar *extension_name)
2381 GQueue trash = G_QUEUE_INIT;
2383 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2385 list = g_list_sort (
2386 source_registry_sources_get_values (registry),
2387 (GCompareFunc) e_source_compare_by_display_name);
2389 if (extension_name == NULL)
2392 for (link = list; link != NULL; link = g_list_next (link)) {
2393 ESource *source = E_SOURCE (link->data);
2395 if (!e_source_has_extension (source, extension_name)) {
2396 g_queue_push_tail (&trash, link);
2397 g_object_unref (source);
2401 /* We do want pop_head() here, not pop_head_link(). */
2402 while ((link = g_queue_pop_head (&trash)) != NULL)
2403 list = g_list_delete_link (list, link);
2409 * e_source_registry_find_extension:
2410 * @registry: an #ESourceRegistry
2411 * @source: an #ESource
2412 * @extension_name: the extension name to find
2414 * Examines @source and its ancestors and returns the "deepest" #ESource
2415 * having an #ESourceExtension with the given @extension_name. If neither
2416 * @source nor any of its ancestors have such an extension, the function
2419 * This function is useful in cases when an #ESourceExtension is meant to
2420 * apply to both the #ESource it belongs to and the #ESource's descendants.
2422 * A common example is the #ESourceCollection extension, where descendants
2423 * of an #ESource having an #ESourceCollection extension are implied to be
2424 * members of that collection. In that example, this function can be used
2425 * to test whether @source is a member of a collection.
2427 * The returned #ESource is referenced for thread-safety and must be
2428 * unreferenced with g_object_unref() when finished with it.
2430 * Note the function returns the #ESource containing the #ESourceExtension
2431 * instead of the #ESourceExtension itself because extension instances are
2432 * not to be referenced directly (see e_source_get_extension()).
2434 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2439 e_source_registry_find_extension (ESourceRegistry *registry,
2441 const gchar *extension_name)
2443 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2444 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2445 g_return_val_if_fail (extension_name != NULL, NULL);
2447 g_object_ref (source);
2449 while (!e_source_has_extension (source, extension_name)) {
2452 uid = e_source_dup_parent (source);
2454 g_object_unref (source);
2458 source = e_source_registry_ref_source (registry, uid);
2470 * e_source_registry_check_enabled:
2471 * @registry: an #ESourceRegistry
2472 * @source: an #ESource
2474 * Determines whether @source is "effectively" enabled by examining its
2475 * own #ESource:enabled property as well as those of its ancestors in the
2476 * #ESource hierarchy. If all examined #ESource:enabled properties are
2477 * %TRUE, then the function returns %TRUE. If any are %FALSE, then the
2478 * function returns %FALSE.
2480 * Use this function instead of e_source_get_enabled() to determine
2481 * things like whether to display an #ESource in a user interface or
2482 * whether to act on the data set described by the #ESource.
2484 * Returns: whether @source is "effectively" enabled
2489 e_source_registry_check_enabled (ESourceRegistry *registry,
2495 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2496 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2498 enabled = e_source_get_enabled (source);
2499 parent_uid = e_source_dup_parent (source);
2501 while (enabled && parent_uid != NULL) {
2504 parent = e_source_registry_ref_source (registry, parent_uid);
2506 g_free (parent_uid);
2509 if (parent != NULL) {
2510 enabled = e_source_get_enabled (parent);
2511 parent_uid = e_source_dup_parent (parent);
2512 g_object_unref (parent);
2516 g_free (parent_uid);
2521 /* Helper for e_source_registry_build_display_tree() */
2523 source_registry_compare_nodes (GNode *node_a,
2526 ESource *source_a = E_SOURCE (node_a->data);
2527 ESource *source_b = E_SOURCE (node_b->data);
2528 const gchar *uid_a, *uid_b;
2530 uid_a = e_source_get_uid (source_a);
2531 uid_b = e_source_get_uid (source_b);
2533 /* Sanity check, with runtime warnings. */
2534 if (uid_a == NULL) {
2535 g_warn_if_reached ();
2538 if (uid_b == NULL) {
2539 g_warn_if_reached ();
2543 /* The built-in "local-stub" source comes first at depth 1. */
2545 if (g_strcmp0 (uid_a, "local-stub") == 0)
2548 if (g_strcmp0 (uid_b, "local-stub") == 0)
2551 /* The built-in "system-*" sources come first at depth 2. */
2553 if (g_str_has_prefix (uid_a, "system-"))
2556 if (g_str_has_prefix (uid_b, "system-"))
2559 return e_source_compare_by_display_name (source_a, source_b);
2562 /* Helper for e_source_registry_build_display_tree() */
2564 source_registry_prune_nodes (GNode *node,
2565 const gchar *extension_name)
2567 GQueue queue = G_QUEUE_INIT;
2570 /* Unlink all the child nodes and place them in a queue. */
2571 while ((child_node = g_node_first_child (node)) != NULL) {
2572 g_node_unlink (child_node);
2573 g_queue_push_tail (&queue, child_node);
2576 /* Sort the queue by source name. */
2578 &queue, (GCompareDataFunc)
2579 source_registry_compare_nodes, NULL);
2581 /* Pop nodes off the head of the queue until the queue is empty.
2582 * If the node has either its own children or the given extension
2583 * name, put it back under the parent node (preserving the sorted
2584 * order). Otherwise delete the node and its descendants. */
2585 while ((child_node = g_queue_pop_head (&queue)) != NULL) {
2586 ESource *child = E_SOURCE (child_node->data);
2587 gboolean append_child_node = FALSE;
2589 if (extension_name == NULL)
2590 append_child_node = e_source_get_enabled (child);
2592 else if (e_source_has_extension (child, extension_name))
2593 append_child_node = e_source_get_enabled (child);
2595 else if (g_node_first_child (child_node) != NULL)
2596 append_child_node = e_source_get_enabled (child);
2598 if (append_child_node)
2599 g_node_append (node, child_node);
2601 e_source_registry_free_display_tree (child_node);
2608 * e_source_registry_build_display_tree:
2609 * @registry: an #ESourceRegistry
2610 * @extension_name: (allow-none): an extension name, or %NULL
2612 * Returns a single #GNode tree of registered sources that can be used to
2613 * populate a #GtkTreeModel. (The root #GNode is just an empty placeholder.)
2615 * Similar to e_source_registry_list_sources(), an @extension_name can be
2616 * given to restrict the tree to sources having that extension name. Parents
2617 * of matched sources are included in the tree regardless of whether they have
2618 * an extension named @extension_name.
2620 * Disabled leaf nodes are automatically excluded from the #GNode tree.
2622 * The sources returned in the tree are referenced for thread-safety.
2623 * They must each be unreferenced with g_object_unref() when finished
2624 * with them. Free the returned tree itself with g_node_destroy().
2625 * For convenience, e_source_registry_free_display_tree() does all
2628 * Returns: (element-type ESource) (transfer full): a tree of sources,
2629 * arranged for display
2634 e_source_registry_build_display_tree (ESourceRegistry *registry,
2635 const gchar *extension_name)
2639 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2641 /* Assemble all data sources into a tree. */
2642 root = source_registry_sources_build_tree (registry);
2644 /* Prune unwanted nodes from the copied source trees.
2645 * This must be done in "post" order (children first)
2646 * since it reorders and deletes child nodes. */
2648 root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
2649 (GNodeTraverseFunc) source_registry_prune_nodes,
2650 (gpointer) extension_name);
2655 /* Helper for e_source_registry_free_display_tree() */
2657 source_registry_unref_nodes (GNode *node)
2659 while (node != NULL) {
2660 if (node->children != NULL)
2661 source_registry_unref_nodes (node->children);
2662 if (node->data != NULL)
2663 g_object_unref (node->data);
2669 * e_source_registry_free_display_tree:
2670 * @display_tree: a tree of sources, arranged for display
2672 * Convenience function to free a #GNode tree of registered
2673 * sources created by e_source_registry_build_display_tree().
2678 e_source_registry_free_display_tree (GNode *display_tree)
2680 g_return_if_fail (display_tree != NULL);
2682 /* XXX This would be easier if GLib had something like
2683 * g_node_destroy_full() which took a GDestroyNotify.
2684 * Then the tree would not have to be traversed twice. */
2686 source_registry_unref_nodes (display_tree);
2687 g_node_destroy (display_tree);
2691 * e_source_registry_dup_unique_display_name:
2692 * @registry: an #ESourceRegistry
2693 * @source: an #ESource
2694 * @extension_name: (allow-none): an extension name, or %NULL
2696 * Compares @source's #ESource:display-name against other sources having
2697 * an #ESourceExtension named @extension_name, if given, or else against
2698 * all other sources in the @registry.
2700 * If @sources's #ESource:display-name is unique among these other sources,
2701 * the function will return the #ESource:display-name verbatim. Otherwise
2702 * the function will construct a string that includes the @sources's own
2703 * #ESource:display-name as well as those of its ancestors.
2705 * The function's return value is intended to be used in messages shown to
2706 * the user to help clarify which source is being referred to. It assumes
2707 * @source's #ESource:display-name is at least unique among its siblings.
2709 * Free the returned string with g_free() when finished with it.
2711 * Returns: a unique display name for @source
2716 e_source_registry_dup_unique_display_name (ESourceRegistry *registry,
2718 const gchar *extension_name)
2722 gchar *display_name;
2723 gboolean need_clarification = FALSE;
2725 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2726 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2728 list = e_source_registry_list_sources (registry, extension_name);
2730 /* Remove the input source from the list, if present. */
2731 link = g_list_find (list, source);
2733 g_object_unref (link->data);
2734 list = g_list_remove_link (list, link);
2737 /* Now find another source with a matching display name. */
2738 link = g_list_find_custom (
2739 list, source, (GCompareFunc)
2740 e_source_compare_by_display_name);
2742 need_clarification = (link != NULL);
2744 g_list_free_full (list, (GDestroyNotify) g_object_unref);
2747 display_name = e_source_dup_display_name (source);
2748 buffer = g_string_new (display_name);
2749 g_free (display_name);
2751 if (need_clarification) {
2752 /* Build a list of ancestor sources. */
2754 g_object_ref (source);
2756 while (source != NULL) {
2759 parent_uid = e_source_dup_parent (source);
2761 g_object_unref (source);
2764 if (parent_uid != NULL) {
2765 source = e_source_registry_ref_source (
2766 registry, parent_uid);
2767 g_free (parent_uid);
2770 if (source != NULL) {
2771 g_object_ref (source);
2772 list = g_list_prepend (list, source);
2776 /* Display the ancestor names from the most distant
2777 * ancestor to the input source's immediate parent. */
2780 g_string_append (buffer, " (");
2782 for (link = list; link != NULL; link = g_list_next (link)) {
2784 g_string_append (buffer, " / ");
2786 source = E_SOURCE (link->data);
2787 display_name = e_source_dup_display_name (source);
2788 g_string_append (buffer, display_name);
2789 g_free (display_name);
2793 g_string_append (buffer, ")");
2795 g_list_free_full (list, (GDestroyNotify) g_object_unref);
2798 return g_string_free (buffer, FALSE);
2801 /* Helper for e_source_registry_debug_dump() */
2803 source_registry_debug_dump_cb (GNode *node)
2807 /* Root node is an empty placeholder. */
2808 if (G_NODE_IS_ROOT (node))
2811 depth = g_node_depth (node);
2812 for (ii = 2; ii < depth; ii++)
2815 if (E_IS_SOURCE (node->data)) {
2816 ESource *source = E_SOURCE (node->data);
2817 g_print ("\"%s\" ", e_source_get_display_name (source));
2818 g_print ("(%s)", e_source_get_uid (source));
2827 * e_source_registry_debug_dump:
2828 * @registry: an #ESourceRegistry
2829 * @extension_name: (allow-none): an extension name, or %NULL
2831 * Handy debugging function that uses e_source_registry_build_display_tree()
2832 * to print a tree of registered sources to standard output.
2837 e_source_registry_debug_dump (ESourceRegistry *registry,
2838 const gchar *extension_name)
2842 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2844 root = e_source_registry_build_display_tree (registry, extension_name);
2847 root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2848 (GNodeTraverseFunc) source_registry_debug_dump_cb, NULL);
2850 e_source_registry_free_display_tree (root);
2854 * e_source_registry_ref_builtin_address_book:
2855 * @registry: an #ESourceRegistry
2857 * Returns the built-in address book #ESource.
2859 * This #ESource is always present and makes for a safe fallback.
2861 * The returned #ESource is referenced for thread-safety and must be
2862 * unreferenced with g_object_unref() when finished with it.
2864 * Returns: (transfer full): the built-in address book #ESource
2869 e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
2874 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2876 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2877 source = e_source_registry_ref_source (registry, uid);
2878 g_return_val_if_fail (source != NULL, NULL);
2884 * e_source_registry_ref_default_address_book:
2885 * @registry: an #ESourceRegistry
2887 * Returns the #ESource most recently passed to
2888 * e_source_registry_set_default_address_book() either in this session
2889 * or a previous session, or else falls back to the built-in address book.
2891 * The returned #ESource is referenced for thread-safety and must be
2892 * unreferenced with g_object_unref() when finished with it.
2894 * Returns: (transfer full): the default address book #ESource
2899 e_source_registry_ref_default_address_book (ESourceRegistry *registry)
2905 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2907 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2908 uid = g_settings_get_string (registry->priv->settings, key);
2909 source = e_source_registry_ref_source (registry, uid);
2912 /* The built-in source is always present. */
2914 source = e_source_registry_ref_builtin_address_book (registry);
2916 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2922 * e_source_registry_set_default_address_book:
2923 * @registry: an #ESourceRegistry
2924 * @default_source: (allow-none): an address book #ESource, or %NULL
2926 * Sets @default_source as the default address book. If @default_source
2927 * is %NULL, the default address book is reset to the built-in address book.
2928 * This setting will persist across sessions until changed.
2933 e_source_registry_set_default_address_book (ESourceRegistry *registry,
2934 ESource *default_source)
2939 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2941 if (default_source != NULL) {
2942 g_return_if_fail (E_IS_SOURCE (default_source));
2943 uid = e_source_get_uid (default_source);
2945 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2948 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2949 g_settings_set_string (registry->priv->settings, key, uid);
2951 /* The GSettings::changed signal will trigger a "notify" signal
2952 * from the registry, so no need to call g_object_notify() here. */
2956 * e_source_registry_ref_builtin_calendar:
2957 * @registry: an #ESourceRegistry
2959 * Returns the built-in calendar #ESource.
2961 * This #ESource is always present and makes for a safe fallback.
2963 * The returned #ESource is referenced for thread-safety and must be
2964 * unreferenced with g_object_unref() when finished with it.
2966 * Returns: (transfer full): the built-in calendar #ESource
2971 e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
2976 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2978 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2979 source = e_source_registry_ref_source (registry, uid);
2980 g_return_val_if_fail (source != NULL, NULL);
2986 * e_source_registry_ref_default_calendar:
2987 * @registry: an #ESourceRegistry
2989 * Returns the #ESource most recently passed to
2990 * e_source_registry_set_default_calendar() either in this session
2991 * or a previous session, or else falls back to the built-in calendar.
2993 * The returned #ESource is referenced for thread-safety and must be
2994 * unreferenced with g_object_unref() when finished with it.
2996 * Returns: (transfer full): the default calendar #ESource
3001 e_source_registry_ref_default_calendar (ESourceRegistry *registry)
3007 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3009 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
3010 uid = g_settings_get_string (registry->priv->settings, key);
3011 source = e_source_registry_ref_source (registry, uid);
3014 /* The built-in source is always present. */
3016 source = e_source_registry_ref_builtin_calendar (registry);
3018 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3024 * e_source_registry_set_default_calendar:
3025 * @registry: an #ESourceRegistry
3026 * @default_source: (allow-none): a calendar #ESource, or %NULL
3028 * Sets @default_source as the default calendar. If @default_source
3029 * is %NULL, the default calendar is reset to the built-in calendar.
3030 * This setting will persist across sessions until changed.
3035 e_source_registry_set_default_calendar (ESourceRegistry *registry,
3036 ESource *default_source)
3041 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3043 if (default_source != NULL) {
3044 g_return_if_fail (E_IS_SOURCE (default_source));
3045 uid = e_source_get_uid (default_source);
3047 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
3050 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
3051 g_settings_set_string (registry->priv->settings, key, uid);
3053 /* The GSettings::changed signal will trigger a "notify" signal
3054 * from the registry, so no need to call g_object_notify() here. */
3058 * e_source_registry_ref_builtin_mail_account:
3059 * @registry: an #ESourceRegistry
3061 * Returns the built-in mail account #ESource.
3063 * This #ESource is always present and makes for a safe fallback.
3065 * The returned #ESource is referenced for thread-safety and must be
3066 * unreferenced with g_object_unref() when finished with it.
3068 * Returns: (transfer full): the built-in mail account #ESource
3073 e_source_registry_ref_builtin_mail_account (ESourceRegistry *registry)
3078 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3080 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
3081 source = e_source_registry_ref_source (registry, uid);
3082 g_return_val_if_fail (source != NULL, NULL);
3088 * e_source_registry_ref_default_mail_account:
3089 * @registry: an #ESourceRegistry
3091 * Returns the #ESource most recently passed to
3092 * e_source_registry_set_default_mail_account() either in this session
3093 * or a previous session, or else falls back to the built-in mail account.
3095 * The returned #ESource is referenced for thread-safety and must be
3096 * unreferenced with g_object_unref() when finished with it.
3098 * Returns: (transfer full): the default mail account #ESource
3103 e_source_registry_ref_default_mail_account (ESourceRegistry *registry)
3109 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3111 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
3112 uid = g_settings_get_string (registry->priv->settings, key);
3113 source = e_source_registry_ref_source (registry, uid);
3116 /* The built-in source is always present. */
3118 source = e_source_registry_ref_builtin_mail_account (registry);
3120 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3126 * e_source_registry_set_default_mail_account:
3127 * @registry: an #ESourceRegistry
3128 * @default_source: (allow-none): a mail account #ESource, or %NULL
3130 * Sets @default_source as the default mail account. If @default_source
3131 * is %NULL, the default mail account is reset to the built-in mail account.
3132 * This setting will persist across sessions until changed.
3137 e_source_registry_set_default_mail_account (ESourceRegistry *registry,
3138 ESource *default_source)
3143 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3145 if (default_source != NULL) {
3146 g_return_if_fail (E_IS_SOURCE (default_source));
3147 uid = e_source_get_uid (default_source);
3149 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
3152 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
3153 g_settings_set_string (registry->priv->settings, key, uid);
3155 /* The GSettings::changed signal will trigger a "notify" signal
3156 * from the registry, so no need to call g_object_notify() here. */
3159 /* Helper for e_source_registry_ref_default_mail_identity() */
3161 source_registry_ref_any_mail_identity (ESourceRegistry *registry)
3165 const gchar *extension_name;
3168 /* First fallback: Return the mail identity named
3169 * by the default mail account. */
3171 source = e_source_registry_ref_default_mail_account (registry);
3173 /* This should never be NULL, but just to be safe. */
3174 if (source != NULL) {
3175 ESourceMailAccount *extension;
3177 extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
3178 extension = e_source_get_extension (source, extension_name);
3179 uid = e_source_mail_account_dup_identity_uid (extension);
3181 g_object_unref (source);
3186 source = e_source_registry_ref_source (registry, uid);
3193 /* Second fallback: Pick any available mail identity,
3194 * preferring enabled identities. */
3196 extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
3197 list = e_source_registry_list_sources (registry, extension_name);
3199 for (link = list; link != NULL; link = g_list_next (link)) {
3200 ESource *candidate = E_SOURCE (link->data);
3202 if (e_source_registry_check_enabled (registry, candidate)) {
3203 source = g_object_ref (candidate);
3208 if (source == NULL && list != NULL)
3209 source = g_object_ref (list->data);
3211 g_list_free_full (list, (GDestroyNotify) g_object_unref);
3217 * e_source_registry_ref_default_mail_identity:
3218 * @registry: an #ESourceRegistry
3220 * Returns the #ESource most recently passed to
3221 * e_source_registry_set_default_mail_identity() either in this session
3222 * or a previous session, or else falls back to the mail identity named
3223 * by the default mail account. If even that fails it returns any mail
3224 * identity from @registry, or %NULL if there are none.
3226 * The returned #ESource is referenced for thread-safety and must be
3227 * unreferenced with g_object_unref() when finished with it.
3229 * Returns: (transfer full): the default mail identity #ESource, or %NULL
3234 e_source_registry_ref_default_mail_identity (ESourceRegistry *registry)
3240 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3242 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
3243 uid = g_settings_get_string (registry->priv->settings, key);
3244 source = e_source_registry_ref_source (registry, uid);
3248 source = source_registry_ref_any_mail_identity (registry);
3254 * e_source_registry_set_default_mail_identity:
3255 * @registry: an #ESourceRegistry
3256 * @default_source: (allow-none): a mail identity #ESource, or %NULL
3258 * Sets @default_source as the default mail identity. If @default_source
3259 * is %NULL, the next request for the default mail identity will use the
3260 * fallbacks described in e_source_registry_get_default_mail_identity().
3265 e_source_registry_set_default_mail_identity (ESourceRegistry *registry,
3266 ESource *default_source)
3271 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3273 if (default_source != NULL) {
3274 g_return_if_fail (E_IS_SOURCE (default_source));
3275 uid = e_source_get_uid (default_source);
3277 uid = ""; /* no built-in mail identity */
3280 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
3281 g_settings_set_string (registry->priv->settings, key, uid);
3283 /* The GSettings::changed signal will trigger a "notify" signal
3284 * from the registry, so no need to call g_object_notify() here. */
3288 * e_source_registry_ref_builtin_memo_list:
3289 * @registry: an #ESourceRegistry
3291 * Returns the built-in memo list #ESource.
3293 * This #ESource is always present and makes for a safe fallback.
3295 * The returned #ESource is referenced for thread-safety and must be
3296 * unreferenced with g_object_unref() when finished with it.
3298 * Returns: (transfer full): the built-in memo list #ESource
3303 e_source_registry_ref_builtin_memo_list (ESourceRegistry *registry)
3308 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3310 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3311 source = e_source_registry_ref_source (registry, uid);
3312 g_return_val_if_fail (source != NULL, NULL);
3318 * e_source_registry_ref_default_memo_list:
3319 * @registry: an #ESourceRegistry
3321 * Returns the #ESource most recently passed to
3322 * e_source_registry_set_default_memo_list() either in this session
3323 * or a previous session, or else falls back to the built-in memo list.
3325 * The returned #ESource is referenced for thread-safety and must be
3326 * unreferenced with g_object_unref() when finished with it.
3328 * Returns: (transfer full): the default memo list #ESource
3333 e_source_registry_ref_default_memo_list (ESourceRegistry *registry)
3339 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3341 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3342 uid = g_settings_get_string (registry->priv->settings, key);
3343 source = e_source_registry_ref_source (registry, uid);
3346 /* The built-in source is always present. */
3348 source = e_source_registry_ref_builtin_memo_list (registry);
3350 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3356 * e_source_registry_set_default_memo_list:
3357 * @registry: an #ESourceRegistry
3358 * @default_source: (allow-none): a memo list #ESource, or %NULL
3360 * Sets @default_source as the default memo list. If @default_source
3361 * is %NULL, the default memo list is reset to the built-in memo list.
3362 * This setting will persist across sessions until changed.
3367 e_source_registry_set_default_memo_list (ESourceRegistry *registry,
3368 ESource *default_source)
3373 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3375 if (default_source != NULL) {
3376 g_return_if_fail (E_IS_SOURCE (default_source));
3377 uid = e_source_get_uid (default_source);
3379 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3382 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3383 g_settings_set_string (registry->priv->settings, key, uid);
3385 /* The GSettings::changed signal will trigger a "notify" signal
3386 * from the registry, so no need to call g_object_notify() here. */
3390 * e_source_registry_ref_builtin_task_list:
3391 * @registry: an #ESourceRegistry
3393 * Returns the built-in task list #ESource.
3395 * This #ESource is always present and makes for a safe fallback.
3397 * The returned #ESource is referenced for thread-safety and must be
3398 * unreferenced with g_object_unref() when finished with it.
3400 * Returns: (transfer full): the built-in task list #ESource
3405 e_source_registry_ref_builtin_task_list (ESourceRegistry *registry)
3410 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3412 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3413 source = e_source_registry_ref_source (registry, uid);
3414 g_return_val_if_fail (source != NULL, NULL);
3420 * e_source_registry_ref_default_task_list:
3421 * @registry: an #ESourceRegistry
3423 * Returns the #ESource most recently passed to
3424 * e_source_registry_set_default_task_list() either in this session
3425 * or a previous session, or else falls back to the built-in task list.
3427 * The returned #ESource is referenced for thread-safety and must be
3428 * unreferenced with g_object_unref() when finished with it.
3430 * Returns: (transfer full): the default task list #ESource
3435 e_source_registry_ref_default_task_list (ESourceRegistry *registry)
3441 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3443 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3444 uid = g_settings_get_string (registry->priv->settings, key);
3445 source = e_source_registry_ref_source (registry, uid);
3448 /* The built-in source is always present. */
3450 source = e_source_registry_ref_builtin_task_list (registry);
3452 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3458 * e_source_registry_set_default_task_list:
3459 * @registry: an #ESourceRegistry
3460 * @default_source: (allow-none): a task list #ESource, or %NULL
3462 * Sets @default_source as the default task list. If @default_source
3463 * is %NULL, the default task list is reset to the built-in task list.
3464 * This setting will persist across sessions until changed.
3469 e_source_registry_set_default_task_list (ESourceRegistry *registry,
3470 ESource *default_source)
3475 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3477 if (default_source != NULL) {
3478 g_return_if_fail (E_IS_SOURCE (default_source));
3479 uid = e_source_get_uid (default_source);
3481 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3484 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3485 g_settings_set_string (registry->priv->settings, key, uid);
3487 /* The GSettings::changed signal will trigger a "notify" signal
3488 * from the registry, so no need to call g_object_notify() here. */
3492 * e_source_registry_ref_default_for_extension_name:
3493 * @registry: an #ESourceRegistry
3494 * @extension_name: an extension_name
3496 * This is a convenience function to return a default #ESource based on
3497 * @extension_name. This only works with a subset of extension names.
3499 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3500 * returns the current default address book, or else falls back to the
3501 * built-in address book.
3503 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function returns
3504 * the current default calendar, or else falls back to the built-in calendar.
3506 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3507 * returns the current default mail account, or else falls back to the
3508 * built-in mail account.
3510 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3511 * returns the current default mail identity, or else falls back to the
3512 * mail identity named by the current default mail account.
3514 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function returns
3515 * the current default memo list, or else falls back to the built-in memo list.
3517 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function returns
3518 * the current default task list, or else falls back to the built-in task list.
3520 * For all other values of @extension_name, the function returns %NULL.
3522 * The returned #ESource is referenced for thread-safety and must be
3523 * unreferenced with g_object_unref() when finished with it.
3525 * Returns: (transfer full): the default #ESource based on @extension_name
3530 e_source_registry_ref_default_for_extension_name (ESourceRegistry *registry,
3531 const gchar *extension_name)
3533 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3534 g_return_val_if_fail (extension_name != NULL, NULL);
3536 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3537 return e_source_registry_ref_default_address_book (registry);
3539 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3540 return e_source_registry_ref_default_calendar (registry);
3542 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3543 return e_source_registry_ref_default_mail_account (registry);
3545 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3546 return e_source_registry_ref_default_mail_identity (registry);
3548 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3549 return e_source_registry_ref_default_memo_list (registry);
3551 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3552 return e_source_registry_ref_default_task_list (registry);
3558 * e_source_registry_set_default_for_extension_name:
3559 * @registry: an #ESourceRegistry
3560 * @extension_name: an extension name
3561 * @default_source: (allow-none): an #ESource, or %NULL
3563 * This is a convenience function to set a default #ESource based on
3564 * @extension_name. This only works with a subset of extension names.
3566 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3567 * sets @default_source as the default address book. If @default_source
3568 * is %NULL, the default address book is reset to the built-in address book.
3570 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function sets
3571 * @default_source as the default calendar. If @default_source is %NULL,
3572 * the default calendar is reset to the built-in calendar.
3574 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3575 * sets @default_source as the default mail account. If @default_source
3576 * is %NULL, the default mail account is reset to the built-in mail account.
3578 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3579 * sets @default_source as the default mail identity. If @default_source
3580 * is %NULL, the next request for the default mail identity will return
3581 * the mail identity named by the default mail account.
3583 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function sets
3584 * @default_source as the default memo list. If @default_source is %NULL,
3585 * the default memo list is reset to the built-in memo list.
3587 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function sets
3588 * @default_source as the default task list. If @default_source is %NULL,
3589 * the default task list is reset to the built-in task list.
3591 * For all other values of @extension_name, the function does nothing.
3596 e_source_registry_set_default_for_extension_name (ESourceRegistry *registry,
3597 const gchar *extension_name,
3598 ESource *default_source)
3600 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3601 g_return_if_fail (extension_name != NULL);
3603 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3604 e_source_registry_set_default_address_book (
3605 registry, default_source);
3607 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3608 e_source_registry_set_default_calendar (
3609 registry, default_source);
3611 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3612 e_source_registry_set_default_mail_account (
3613 registry, default_source);
3615 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3616 e_source_registry_set_default_mail_identity (
3617 registry, default_source);
3619 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3620 e_source_registry_set_default_memo_list (
3621 registry, default_source);
3623 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3624 e_source_registry_set_default_task_list (
3625 registry, default_source);