4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
20 * SECTION: e-source-registry
21 * @include: libedataserver/libedataserver.h
22 * @short_description: A central repository for data sources
24 * The #ESourceRegistry is a global singleton store for all #ESource
25 * instances. It uses file monitors to react to key file creation and
26 * deletion events, either constructing an #ESource instance from the
27 * newly created key file, or removing from the logical #ESource
28 * hierarchy the instance corresponding to the deleted key file.
30 * The #ESourceRegistry can be queried for individual #ESource instances
31 * by their unique identifier string or key file path, for collections of
32 * #ESource instances having a particular extension, or for all available
35 * The #ESourceRegistry API also provides a front-end for the
36 * "org.gnome.Evolution.DefaultSources" #GSettings schema which tracks
37 * which #ESource instances are designated to be the user's default address
38 * book, calendar, memo list and task list for desktop integration.
41 #include "e-source-registry.h"
44 #include <glib/gstdio.h>
45 #include <glib/gi18n-lib.h>
47 /* XXX Yeah, yeah... */
48 #define GCR_API_SUBJECT_TO_CHANGE
50 #include <gcr/gcr-base.h>
52 /* Private D-Bus classes. */
53 #include <e-dbus-source.h>
54 #include <e-dbus-source-manager.h>
56 #include <libedataserver/e-marshal.h>
57 #include <libedataserver/e-data-server-util.h>
58 #include <libedataserver/e-source-collection.h>
60 /* Needed for the defaults API. */
61 #include <libedataserver/e-source-address-book.h>
62 #include <libedataserver/e-source-calendar.h>
63 #include <libedataserver/e-source-mail-account.h>
64 #include <libedataserver/e-source-mail-identity.h>
66 #include "e-dbus-authenticator.h"
68 #define E_SOURCE_REGISTRY_GET_PRIVATE(obj) \
69 (G_TYPE_INSTANCE_GET_PRIVATE \
70 ((obj), E_TYPE_SOURCE_REGISTRY, ESourceRegistryPrivate))
72 #define DBUS_OBJECT_PATH "/org/gnome/evolution/dataserver/SourceManager"
73 #define GSETTINGS_SCHEMA "org.gnome.Evolution.DefaultSources"
75 /* Built-in data source UIDs. */
76 #define E_SOURCE_BUILTIN_ADDRESS_BOOK_UID "system-address-book"
77 #define E_SOURCE_BUILTIN_CALENDAR_UID "system-calendar"
78 #define E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID "local"
79 #define E_SOURCE_BUILTIN_MEMO_LIST_UID "system-memo-list"
80 #define E_SOURCE_BUILTIN_TASK_LIST_UID "system-task-list"
82 /* GSettings keys for default data sources. */
83 #define E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY "default-address-book"
84 #define E_SETTINGS_DEFAULT_CALENDAR_KEY "default-calendar"
85 #define E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY "default-mail-account"
86 #define E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY "default-mail-identity"
87 #define E_SETTINGS_DEFAULT_MEMO_LIST_KEY "default-memo-list"
88 #define E_SETTINGS_DEFAULT_TASK_LIST_KEY "default-task-list"
90 typedef struct _AsyncContext AsyncContext;
91 typedef struct _AuthContext AuthContext;
92 typedef struct _SourceClosure SourceClosure;
93 typedef struct _ThreadClosure ThreadClosure;
95 struct _ESourceRegistryPrivate {
96 GMainContext *main_context;
98 GThread *manager_thread;
99 ThreadClosure *thread_closure;
101 GDBusObjectManager *dbus_object_manager;
102 EDBusSourceManager *dbus_source_manager;
104 GHashTable *object_path_table;
105 GMutex *object_path_table_lock;
108 GMutex *sources_lock;
113 struct _AsyncContext {
115 GList *list_of_sources;
116 ESourceAuthenticator *auth;
119 /* Used in e_source_registry_authenticate_sync() */
120 struct _AuthContext {
121 ESourceAuthenticator *auth;
122 EDBusAuthenticator *dbus_auth;
123 GCancellable *cancellable;
124 GMainLoop *main_loop;
125 ESourceAuthenticationResult auth_result;
126 GcrSecretExchange *secret_exchange;
127 gboolean authenticating;
132 struct _SourceClosure {
133 ESourceRegistry *registry;
137 struct _ThreadClosure {
138 ESourceRegistry *registry;
139 GMainContext *main_context;
140 GMainLoop *main_loop;
141 GCond *main_loop_cond;
142 GMutex *main_loop_mutex;
147 PROP_DEFAULT_ADDRESS_BOOK,
148 PROP_DEFAULT_CALENDAR,
149 PROP_DEFAULT_MAIL_ACCOUNT,
150 PROP_DEFAULT_MAIL_IDENTITY,
151 PROP_DEFAULT_MEMO_LIST,
152 PROP_DEFAULT_TASK_LIST
164 /* Forward Declarations */
165 static void source_registry_add_source (ESourceRegistry *registry,
167 static void e_source_registry_initable_init (GInitableIface *interface);
169 static guint signals[LAST_SIGNAL];
171 /* By default, the GAsyncInitable interface calls GInitable.init()
172 * from a separate thread, so we only have to override GInitable. */
173 G_DEFINE_TYPE_WITH_CODE (
177 G_IMPLEMENT_INTERFACE (
178 G_TYPE_INITABLE, e_source_registry_initable_init)
179 G_IMPLEMENT_INTERFACE (
180 G_TYPE_ASYNC_INITABLE, NULL))
183 async_context_free (AsyncContext *async_context)
185 if (async_context->source != NULL)
186 g_object_unref (async_context->source);
189 async_context->list_of_sources,
190 (GDestroyNotify) g_object_unref);
192 if (async_context->auth != NULL)
193 g_object_unref (async_context->auth);
195 g_slice_free (AsyncContext, async_context);
199 auth_context_free (AuthContext *auth_context)
201 if (auth_context->auth != NULL)
202 g_object_unref (auth_context->auth);
204 if (auth_context->dbus_auth != NULL)
205 g_object_unref (auth_context->dbus_auth);
207 if (auth_context->cancellable != NULL)
208 g_object_unref (auth_context->cancellable);
210 if (auth_context->main_loop != NULL)
211 g_main_loop_unref (auth_context->main_loop);
213 if (auth_context->secret_exchange != NULL)
214 g_object_unref (auth_context->secret_exchange);
216 g_slice_free (AuthContext, auth_context);
220 source_closure_free (SourceClosure *closure)
222 g_object_unref (closure->registry);
223 g_object_unref (closure->source);
225 g_slice_free (SourceClosure, closure);
229 thread_closure_free (ThreadClosure *closure)
231 /* The registry member is not referenced. */
233 g_main_context_unref (closure->main_context);
234 g_main_loop_unref (closure->main_loop);
235 g_cond_free (closure->main_loop_cond);
236 g_mutex_free (closure->main_loop_mutex);
238 g_slice_free (ThreadClosure, closure);
242 source_registry_object_path_table_insert (ESourceRegistry *registry,
243 const gchar *object_path,
246 g_return_if_fail (object_path != NULL);
247 g_return_if_fail (E_IS_SOURCE (source));
249 g_mutex_lock (registry->priv->object_path_table_lock);
251 g_hash_table_insert (
252 registry->priv->object_path_table,
253 g_strdup (object_path),
254 g_object_ref (source));
256 g_mutex_unlock (registry->priv->object_path_table_lock);
260 source_registry_object_path_table_lookup (ESourceRegistry *registry,
261 const gchar *object_path)
265 g_return_val_if_fail (object_path != NULL, NULL);
267 g_mutex_lock (registry->priv->object_path_table_lock);
269 source = g_hash_table_lookup (
270 registry->priv->object_path_table, object_path);
272 g_object_ref (source);
274 g_mutex_unlock (registry->priv->object_path_table_lock);
280 source_registry_object_path_table_remove (ESourceRegistry *registry,
281 const gchar *object_path)
285 g_return_val_if_fail (object_path != NULL, FALSE);
287 g_mutex_lock (registry->priv->object_path_table_lock);
289 removed = g_hash_table_remove (
290 registry->priv->object_path_table, object_path);
292 g_mutex_unlock (registry->priv->object_path_table_lock);
298 source_registry_sources_insert (ESourceRegistry *registry,
303 uid = e_source_get_uid (source);
304 g_return_if_fail (uid != NULL);
306 g_mutex_lock (registry->priv->sources_lock);
308 g_hash_table_insert (
309 registry->priv->sources,
310 g_strdup (uid), g_object_ref (source));
312 g_mutex_unlock (registry->priv->sources_lock);
316 source_registry_sources_remove (ESourceRegistry *registry,
322 uid = e_source_get_uid (source);
323 g_return_val_if_fail (uid != NULL, FALSE);
325 g_mutex_lock (registry->priv->sources_lock);
327 removed = g_hash_table_remove (registry->priv->sources, uid);
329 g_mutex_unlock (registry->priv->sources_lock);
335 source_registry_sources_lookup (ESourceRegistry *registry,
340 g_return_val_if_fail (uid != NULL, NULL);
342 g_mutex_lock (registry->priv->sources_lock);
344 source = g_hash_table_lookup (registry->priv->sources, uid);
347 g_object_ref (source);
349 g_mutex_unlock (registry->priv->sources_lock);
355 source_registry_sources_get_values (ESourceRegistry *registry)
359 g_mutex_lock (registry->priv->sources_lock);
361 values = g_hash_table_get_values (registry->priv->sources);
363 g_list_foreach (values, (GFunc) g_object_ref, NULL);
365 g_mutex_unlock (registry->priv->sources_lock);
371 source_registry_sources_build_tree (ESourceRegistry *registry)
378 g_mutex_lock (registry->priv->sources_lock);
380 root = g_node_new (NULL);
381 index = g_hash_table_new (g_str_hash, g_str_equal);
383 /* Add a GNode for each ESource to the index. */
384 g_hash_table_iter_init (&iter, registry->priv->sources);
385 while (g_hash_table_iter_next (&iter, &key, &value)) {
386 ESource *source = g_object_ref (value);
387 g_hash_table_insert (index, key, g_node_new (source));
390 /* Traverse the index and link the nodes together. */
391 g_hash_table_iter_init (&iter, index);
392 while (g_hash_table_iter_next (&iter, NULL, &value)) {
396 const gchar *parent_uid;
398 source_node = (GNode *) value;
399 source = E_SOURCE (source_node->data);
400 parent_uid = e_source_get_parent (source);
402 if (parent_uid == NULL || *parent_uid == '\0') {
405 parent_node = g_hash_table_lookup (index, parent_uid);
406 g_warn_if_fail (parent_node != NULL);
409 /* Should never be NULL, but just to be safe. */
410 if (parent_node != NULL)
411 g_node_append (parent_node, source_node);
414 g_hash_table_destroy (index);
416 g_mutex_unlock (registry->priv->sources_lock);
422 source_registry_settings_changed_cb (GSettings *settings,
424 ESourceRegistry *registry)
426 /* We define a property name that matches every key in
427 * the "org.gnome.Evolution.DefaultSources" schema. */
428 g_object_notify (G_OBJECT (registry), key);
432 source_registry_source_changed_idle_cb (gpointer user_data)
434 SourceClosure *closure = user_data;
438 signals[SOURCE_CHANGED], 0,
445 source_registry_source_notify_enabled_idle_cb (gpointer user_data)
447 SourceClosure *closure = user_data;
449 if (e_source_get_enabled (closure->source))
452 signals[SOURCE_ENABLED], 0,
457 signals[SOURCE_DISABLED], 0,
464 source_registry_source_changed_cb (ESource *source,
465 ESourceRegistry *registry)
467 GSource *idle_source;
468 SourceClosure *closure;
470 closure = g_slice_new0 (SourceClosure);
471 closure->registry = g_object_ref (registry);
472 closure->source = g_object_ref (source);
474 idle_source = g_idle_source_new ();
475 g_source_set_callback (
477 source_registry_source_changed_idle_cb,
478 closure, (GDestroyNotify) source_closure_free);
479 g_source_attach (idle_source, registry->priv->main_context);
480 g_source_unref (idle_source);
484 source_registry_source_notify_enabled_cb (ESource *source,
486 ESourceRegistry *registry)
488 GSource *idle_source;
489 SourceClosure *closure;
491 closure = g_slice_new0 (SourceClosure);
492 closure->registry = g_object_ref (registry);
493 closure->source = g_object_ref (source);
495 idle_source = g_idle_source_new ();
496 g_source_set_callback (
498 source_registry_source_notify_enabled_idle_cb,
499 closure, (GDestroyNotify) source_closure_free);
500 g_source_attach (idle_source, registry->priv->main_context);
501 g_source_unref (idle_source);
505 source_registry_new_source (ESourceRegistry *registry,
506 GDBusObject *dbus_object)
508 GMainContext *main_context;
510 const gchar *object_path;
511 GError *error = NULL;
513 /* We don't want the ESource emitting "changed" signals from
514 * the manager thread, so we pass it the same main context the
515 * registry uses for scheduling signal emissions. */
516 main_context = registry->priv->main_context;
517 source = e_source_new (dbus_object, main_context, &error);
518 object_path = g_dbus_object_get_object_path (dbus_object);
520 /* The likelihood of an error here is slim, so it's
521 * sufficient to just print a warning if one occurs. */
523 g_warn_if_fail (source == NULL);
525 "ESourceRegistry: Failed to create a "
526 "data source object for path '%s': %s",
527 object_path, error->message);
528 g_error_free (error);
532 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
534 /* Add the ESource to the object path table immediately. */
535 source_registry_object_path_table_insert (
536 registry, object_path, source);
542 source_registry_unref_source (ESource *source)
544 g_signal_handlers_disconnect_matched (
545 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
546 source_registry_source_changed_cb, NULL);
548 g_signal_handlers_disconnect_matched (
549 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
550 source_registry_source_notify_enabled_cb, NULL);
552 g_object_unref (source);
556 source_registry_add_source (ESourceRegistry *registry,
561 uid = e_source_get_uid (source);
562 g_return_if_fail (uid != NULL);
564 g_mutex_lock (registry->priv->sources_lock);
566 /* Check if we already have this source in the registry. */
567 if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
568 g_mutex_unlock (registry->priv->sources_lock);
574 G_CALLBACK (source_registry_source_changed_cb),
578 source, "notify::enabled",
579 G_CALLBACK (source_registry_source_notify_enabled_cb),
582 g_mutex_unlock (registry->priv->sources_lock);
584 source_registry_sources_insert (registry, source);
586 g_signal_emit (registry, signals[SOURCE_ADDED], 0, source);
590 source_registry_remove_source (ESourceRegistry *registry,
593 g_object_ref (source);
595 if (source_registry_sources_remove (registry, source))
596 g_signal_emit (registry, signals[SOURCE_REMOVED], 0, source);
598 g_object_unref (source);
602 source_registry_object_added_idle_cb (gpointer user_data)
604 SourceClosure *closure = user_data;
606 source_registry_add_source (closure->registry, closure->source);
612 source_registry_object_added_cb (GDBusObjectManager *object_manager,
613 GDBusObject *dbus_object,
614 ESourceRegistry *registry)
616 SourceClosure *closure;
617 GSource *idle_source;
620 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
622 source = source_registry_new_source (registry, dbus_object);
623 g_return_if_fail (source != NULL);
625 /* Schedule a callback on the ESourceRegistry's GMainContext. */
627 closure = g_slice_new0 (SourceClosure);
628 closure->registry = g_object_ref (registry);
629 closure->source = g_object_ref (source);
631 idle_source = g_idle_source_new ();
632 g_source_set_callback (
634 source_registry_object_added_idle_cb,
635 closure, (GDestroyNotify) source_closure_free);
636 g_source_attach (idle_source, registry->priv->main_context);
637 g_source_unref (idle_source);
639 g_object_unref (source);
643 source_registry_object_removed_idle_cb (gpointer user_data)
645 SourceClosure *closure = user_data;
647 source_registry_remove_source (closure->registry, closure->source);
653 source_registry_object_removed_cb (GDBusObjectManager *manager,
654 GDBusObject *dbus_object,
655 ESourceRegistry *registry)
657 SourceClosure *closure;
658 GSource *idle_source;
660 const gchar *object_path;
662 /* Find the corresponding ESource in the object path table.
663 * Note that the lookup returns a new ESource reference. */
664 object_path = g_dbus_object_get_object_path (dbus_object);
665 source = source_registry_object_path_table_lookup (
666 registry, object_path);
667 g_return_if_fail (E_IS_SOURCE (source));
669 /* Remove the ESource from the object path table immediately. */
670 source_registry_object_path_table_remove (registry, object_path);
672 /* Schedule a callback on the ESourceRegistry's GMainContext. */
674 closure = g_slice_new0 (SourceClosure);
675 closure->registry = g_object_ref (registry);
676 closure->source = g_object_ref (source);
678 idle_source = g_idle_source_new ();
679 g_source_set_callback (
681 source_registry_object_removed_idle_cb,
682 closure, (GDestroyNotify) source_closure_free);
683 g_source_attach (idle_source, registry->priv->main_context);
684 g_source_unref (idle_source);
686 g_object_unref (source);
690 source_registry_object_manager_running (gpointer data)
692 ThreadClosure *closure = data;
694 g_mutex_lock (closure->main_loop_mutex);
695 g_cond_broadcast (closure->main_loop_cond);
696 g_mutex_unlock (closure->main_loop_mutex);
702 source_registry_object_manager_thread (gpointer data)
704 GDBusObjectManager *object_manager;
705 ThreadClosure *closure = data;
706 GSource *idle_source;
708 gulong object_added_id;
709 gulong object_removed_id;
710 GError *error = NULL;
712 /* GDBusObjectManagerClient grabs the thread-default GMainContext
713 * at creation time and only emits signals from that GMainContext.
714 * Running it in a separate thread prevents its signal emissions
715 * from being inhibited by someone overriding the thread-default
718 /* This becomes the GMainContext that GDBusObjectManagerClient
719 * will emit signals from. Make it the thread-default context
720 * for this thread before creating the client. */
721 g_main_context_push_thread_default (closure->main_context);
723 object_manager = e_dbus_object_manager_client_new_for_bus_sync (
725 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
726 SOURCES_DBUS_SERVICE_NAME,
730 /* If this fails there's really no point in continuing
731 * since we rely on the object manager to populate the
732 * registry. Abort the process with a fatal error. */
734 g_error ("%s", error->message);
735 g_assert_not_reached ();
738 /* Give the registry a handle to the object manager. */
739 closure->registry->priv->dbus_object_manager =
740 g_object_ref (object_manager);
742 /* Now populate the registry with an initial set of ESources. */
744 list = g_dbus_object_manager_get_objects (object_manager);
746 for (link = list; link != NULL; link = g_list_next (link)) {
747 GDBusObject *dbus_object;
750 dbus_object = G_DBUS_OBJECT (link->data);
752 source = source_registry_new_source (
753 closure->registry, dbus_object);
755 if (source != NULL) {
756 source_registry_add_source (
757 closure->registry, source);
758 g_object_unref (source);
762 g_list_free_full (list, (GDestroyNotify) g_object_unref);
764 /* Schedule a one-time idle callback to broadcast through a
765 * condition variable that our main loop is up and running. */
767 idle_source = g_idle_source_new ();
768 g_source_set_callback (
770 source_registry_object_manager_running,
771 closure, (GDestroyNotify) NULL);
772 g_source_attach (idle_source, closure->main_context);
773 g_source_unref (idle_source);
775 /* Listen for D-Bus object additions and removals. */
777 object_added_id = g_signal_connect (
778 object_manager, "object-added",
779 G_CALLBACK (source_registry_object_added_cb),
782 object_removed_id = g_signal_connect (
783 object_manager, "object-removed",
784 G_CALLBACK (source_registry_object_removed_cb),
787 /* Now we mostly idle here for the rest of the session. */
789 g_main_loop_run (closure->main_loop);
791 /* Clean up and exit. */
793 g_signal_handler_disconnect (object_manager, object_added_id);
794 g_signal_handler_disconnect (object_manager, object_removed_id);
796 g_object_unref (object_manager);
798 g_main_context_pop_thread_default (closure->main_context);
804 source_registry_set_property (GObject *object,
809 switch (property_id) {
810 case PROP_DEFAULT_ADDRESS_BOOK:
811 e_source_registry_set_default_address_book (
812 E_SOURCE_REGISTRY (object),
813 g_value_get_object (value));
816 case PROP_DEFAULT_CALENDAR:
817 e_source_registry_set_default_calendar (
818 E_SOURCE_REGISTRY (object),
819 g_value_get_object (value));
822 case PROP_DEFAULT_MAIL_ACCOUNT:
823 e_source_registry_set_default_mail_account (
824 E_SOURCE_REGISTRY (object),
825 g_value_get_object (value));
828 case PROP_DEFAULT_MAIL_IDENTITY:
829 e_source_registry_set_default_mail_identity (
830 E_SOURCE_REGISTRY (object),
831 g_value_get_object (value));
834 case PROP_DEFAULT_MEMO_LIST:
835 e_source_registry_set_default_memo_list (
836 E_SOURCE_REGISTRY (object),
837 g_value_get_object (value));
840 case PROP_DEFAULT_TASK_LIST:
841 e_source_registry_set_default_task_list (
842 E_SOURCE_REGISTRY (object),
843 g_value_get_object (value));
847 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
851 source_registry_get_property (GObject *object,
856 switch (property_id) {
857 case PROP_DEFAULT_ADDRESS_BOOK:
858 g_value_take_object (
860 e_source_registry_ref_default_address_book (
861 E_SOURCE_REGISTRY (object)));
864 case PROP_DEFAULT_CALENDAR:
865 g_value_take_object (
867 e_source_registry_ref_default_calendar (
868 E_SOURCE_REGISTRY (object)));
871 case PROP_DEFAULT_MAIL_ACCOUNT:
872 g_value_take_object (
874 e_source_registry_ref_default_mail_account (
875 E_SOURCE_REGISTRY (object)));
878 case PROP_DEFAULT_MAIL_IDENTITY:
879 g_value_take_object (
881 e_source_registry_ref_default_mail_identity (
882 E_SOURCE_REGISTRY (object)));
885 case PROP_DEFAULT_MEMO_LIST:
886 g_value_take_object (
888 e_source_registry_ref_default_memo_list (
889 E_SOURCE_REGISTRY (object)));
892 case PROP_DEFAULT_TASK_LIST:
893 g_value_take_object (
895 e_source_registry_ref_default_task_list (
896 E_SOURCE_REGISTRY (object)));
900 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
904 source_registry_dispose (GObject *object)
906 ESourceRegistryPrivate *priv;
908 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
910 /* Terminate the manager thread first. */
911 if (priv->manager_thread != NULL) {
912 g_main_loop_quit (priv->thread_closure->main_loop);
913 g_thread_join (priv->manager_thread);
914 thread_closure_free (priv->thread_closure);
915 priv->manager_thread = NULL;
916 priv->thread_closure = NULL;
919 if (priv->main_context != NULL) {
920 g_main_context_unref (priv->main_context);
921 priv->main_context = NULL;
924 if (priv->dbus_object_manager != NULL) {
925 g_object_unref (priv->dbus_object_manager);
926 priv->dbus_object_manager = NULL;
929 if (priv->dbus_source_manager != NULL) {
930 g_object_unref (priv->dbus_source_manager);
931 priv->dbus_source_manager = NULL;
934 g_hash_table_remove_all (priv->object_path_table);
936 g_hash_table_remove_all (priv->sources);
938 if (priv->settings != NULL) {
939 g_object_unref (priv->settings);
940 priv->settings = NULL;
943 /* Chain up to parent's finalize() method. */
944 G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
948 source_registry_finalize (GObject *object)
950 ESourceRegistryPrivate *priv;
952 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
954 g_hash_table_destroy (priv->object_path_table);
955 g_mutex_free (priv->object_path_table_lock);
957 g_hash_table_destroy (priv->sources);
958 g_mutex_free (priv->sources_lock);
960 /* Chain up to parent's finalize() method. */
961 G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
965 source_registry_initable_init (GInitable *initable,
966 GCancellable *cancellable,
969 ESourceRegistry *registry;
970 ThreadClosure *closure;
972 registry = E_SOURCE_REGISTRY (initable);
974 closure = g_slice_new0 (ThreadClosure);
975 closure->registry = registry; /* do not reference */
976 closure->main_context = g_main_context_new ();
977 /* It's important to pass 'is_running=FALSE' here because
978 * we wait for the main loop to start running as a way of
979 * synchronizing with the manager thread. */
980 closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
981 closure->main_loop_cond = g_cond_new ();
982 closure->main_loop_mutex = g_mutex_new ();
984 registry->priv->thread_closure = closure;
986 registry->priv->manager_thread = g_thread_create (
987 source_registry_object_manager_thread,
988 closure, TRUE /* joinable */, error);
990 if (registry->priv->manager_thread == NULL)
993 /* Wait for notification that the manager
994 * thread's main loop has been started. */
995 g_mutex_lock (closure->main_loop_mutex);
996 while (!g_main_loop_is_running (closure->main_loop))
998 closure->main_loop_cond,
999 closure->main_loop_mutex);
1000 g_mutex_unlock (closure->main_loop_mutex);
1002 /* We should now have a GDBusObjectManagerClient available. */
1003 g_return_val_if_fail (
1004 G_IS_DBUS_OBJECT_MANAGER_CLIENT (
1005 registry->priv->dbus_object_manager), FALSE);
1007 /* The registry should now be populated with sources. */
1008 g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);
1010 /* The EDBusSourceManagerProxy is just another D-Bus interface
1011 * that resides at the same object path. It's unrelated to the
1012 * GDBusObjectManagerClient and doesn't need its own thread. */
1013 registry->priv->dbus_source_manager =
1014 e_dbus_source_manager_proxy_new_for_bus_sync (
1016 G_DBUS_PROXY_FLAGS_NONE,
1017 SOURCES_DBUS_SERVICE_NAME,
1019 cancellable, error);
1021 if (registry->priv->dbus_source_manager == NULL)
1028 e_source_registry_class_init (ESourceRegistryClass *class)
1030 GObjectClass *object_class;
1032 g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
1034 object_class = G_OBJECT_CLASS (class);
1035 object_class->set_property = source_registry_set_property;
1036 object_class->get_property = source_registry_get_property;
1037 object_class->dispose = source_registry_dispose;
1038 object_class->finalize = source_registry_finalize;
1040 /* The property names correspond to the key names in the
1041 * "org.gnome.Evolution.DefaultSources" GSettings schema. */
1044 * ESourceRegistry:default-address-book:
1046 * The default address book #ESource.
1048 g_object_class_install_property (
1050 PROP_DEFAULT_ADDRESS_BOOK,
1051 g_param_spec_object (
1052 "default-address-book",
1053 "Default Address Book",
1054 "The default address book ESource",
1057 G_PARAM_STATIC_STRINGS));
1060 * ESourceRegistry:default-calendar:
1062 * The default calendar #ESource.
1064 g_object_class_install_property (
1066 PROP_DEFAULT_CALENDAR,
1067 g_param_spec_object (
1070 "The default calendar ESource",
1073 G_PARAM_STATIC_STRINGS));
1076 * ESourceRegistry:default-mail-account:
1078 * The default mail account #ESource.
1080 g_object_class_install_property (
1082 PROP_DEFAULT_MAIL_ACCOUNT,
1083 g_param_spec_object (
1084 "default-mail-account",
1085 "Default Mail Account",
1086 "The default mail account ESource",
1089 G_PARAM_STATIC_STRINGS));
1092 * ESourceRegistry:default-mail-identity:
1094 * The default mail identity #ESource.
1096 g_object_class_install_property (
1098 PROP_DEFAULT_MAIL_IDENTITY,
1099 g_param_spec_object (
1100 "default-mail-identity",
1101 "Default Mail Identity",
1102 "The default mail identity ESource",
1105 G_PARAM_STATIC_STRINGS));
1108 * ESourceRegistry:default-memo-list:
1110 * The default memo list #ESource.
1112 g_object_class_install_property (
1114 PROP_DEFAULT_MEMO_LIST,
1115 g_param_spec_object (
1116 "default-memo-list",
1117 "Default Memo List",
1118 "The default memo list ESource",
1121 G_PARAM_STATIC_STRINGS));
1124 * ESourceRegistry:default-task-list:
1126 * The default task list #ESource.
1128 g_object_class_install_property (
1130 PROP_DEFAULT_TASK_LIST,
1131 g_param_spec_object (
1132 "default-task-list",
1133 "Default Task List",
1134 "The default task list ESource",
1137 G_PARAM_STATIC_STRINGS));
1140 * ESourceRegistry::source-added:
1141 * @registry: the #ESourceRegistry which emitted the signal
1142 * @source: the newly-added #ESource
1144 * Emitted when an #ESource is added to @registry.
1146 signals[SOURCE_ADDED] = g_signal_new (
1148 G_OBJECT_CLASS_TYPE (object_class),
1150 G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
1152 g_cclosure_marshal_VOID__OBJECT,
1157 * ESourceRegistry::source-changed:
1158 * @registry: the #ESourceRegistry which emitted the signal
1159 * @source: the #ESource that changed
1161 * Emitted when an #ESource registered with @registry emits
1162 * its #ESource::changed signal.
1164 signals[SOURCE_CHANGED] = g_signal_new (
1166 G_OBJECT_CLASS_TYPE (object_class),
1168 G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
1170 g_cclosure_marshal_VOID__OBJECT,
1175 * ESourceRegistry::source-removed:
1176 * @registry: the #ESourceRegistry which emitted the signal
1177 * @source: the #ESource that got removed
1179 * Emitted when an #ESource is removed from @registry.
1181 signals[SOURCE_REMOVED] = g_signal_new (
1183 G_OBJECT_CLASS_TYPE (object_class),
1185 G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
1187 g_cclosure_marshal_VOID__OBJECT,
1192 * ESourceRegistry::source-enabled:
1193 * @registry: the #ESourceRegistry which emitted the signal
1194 * @source: the #ESource that got enabled
1196 * Emitted when an #ESource #ESource:enabled property becomes %TRUE.
1198 signals[SOURCE_ENABLED] = g_signal_new (
1200 G_OBJECT_CLASS_TYPE (object_class),
1202 G_STRUCT_OFFSET (ESourceRegistryClass, source_enabled),
1204 g_cclosure_marshal_VOID__OBJECT,
1209 * ESourceRegistry::source-disabled:
1210 * @registry: the #ESourceRegistry which emitted the signal
1211 * @source: the #ESource that got disabled
1213 * Emitted when an #ESource #ESource:enabled property becomes %FALSE.
1215 signals[SOURCE_DISABLED] = g_signal_new (
1217 G_OBJECT_CLASS_TYPE (object_class),
1219 G_STRUCT_OFFSET (ESourceRegistryClass, source_disabled),
1221 g_cclosure_marshal_VOID__OBJECT,
1227 e_source_registry_initable_init (GInitableIface *interface)
1229 interface->init = source_registry_initable_init;
1233 e_source_registry_init (ESourceRegistry *registry)
1235 registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
1237 /* This is so the object manager thread can schedule signal
1238 * emissions on the thread-default context for this thread. */
1239 registry->priv->main_context = g_main_context_ref_thread_default ();
1241 /* D-Bus object path -> ESource */
1242 registry->priv->object_path_table =
1243 g_hash_table_new_full (
1244 (GHashFunc) g_str_hash,
1245 (GEqualFunc) g_str_equal,
1246 (GDestroyNotify) g_free,
1247 (GDestroyNotify) g_object_unref);
1249 registry->priv->object_path_table_lock = g_mutex_new ();
1251 /* UID string -> ESource */
1252 registry->priv->sources = g_hash_table_new_full (
1253 (GHashFunc) g_str_hash,
1254 (GEqualFunc) g_str_equal,
1255 (GDestroyNotify) g_free,
1256 (GDestroyNotify) source_registry_unref_source);
1258 registry->priv->sources_lock = g_mutex_new ();
1260 registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
1263 registry->priv->settings, "changed",
1264 G_CALLBACK (source_registry_settings_changed_cb), registry);
1268 * e_source_registry_new_sync:
1269 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1270 * @error: return location for a #GError, or %NULL
1272 * Creates a new #ESourceRegistry front-end for the registry D-Bus service.
1273 * If an error occurs in connecting to the D-Bus service, the function sets
1274 * @error and returns %NULL.
1276 * Returns: a new #ESourceRegistry, or %NULL
1281 e_source_registry_new_sync (GCancellable *cancellable,
1284 return g_initable_new (
1285 E_TYPE_SOURCE_REGISTRY,
1286 cancellable, error, NULL);
1290 * e_source_registry_new:
1291 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1292 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1294 * @user_data: (closure): data to pass to the callback function
1296 * Asynchronously creates a new #ESourceRegistry front-end for the registry
1299 * When the operation is finished, @callback will be called. You can then
1300 * call e_source_registry_new_finish() to get the result of the operation.
1305 e_source_registry_new (GCancellable *cancellable,
1306 GAsyncReadyCallback callback,
1309 g_async_initable_new_async (
1310 E_TYPE_SOURCE_REGISTRY,
1311 G_PRIORITY_DEFAULT, cancellable,
1312 callback, user_data, NULL);
1316 * e_source_registry_new_finish:
1317 * @result: a #GAsyncResult
1318 * @error: return location for a #GError, or %NULL
1320 * Finishes the operation started with e_source_registry_new_finish().
1321 * If an error occurs in connecting to the D-Bus service, the function
1322 * sets @error and returns %NULL.
1324 * Returns: a new #ESourceRegistry, or %NULL
1329 e_source_registry_new_finish (GAsyncResult *result,
1332 GObject *source_object;
1335 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1337 source_object = g_async_result_get_source_object (result);
1338 g_return_val_if_fail (source_object != NULL, NULL);
1340 object = g_async_initable_new_finish (
1341 G_ASYNC_INITABLE (source_object), result, error);
1343 g_object_unref (source_object);
1345 return (object != NULL) ? E_SOURCE_REGISTRY (object) : NULL;
1348 /* Helper for e_source_registry_authenticate() */
1350 source_registry_authenticate_thread (GSimpleAsyncResult *simple,
1352 GCancellable *cancellable)
1354 AsyncContext *async_context;
1355 GError *error = NULL;
1357 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1359 e_source_registry_authenticate_sync (
1360 E_SOURCE_REGISTRY (object),
1361 async_context->source,
1362 async_context->auth,
1363 cancellable, &error);
1366 g_simple_async_result_take_error (simple, error);
1369 /* Helper for e_source_registry_authenticate_sync() */
1371 source_registry_authenticate_respond_cb (AuthContext *auth_context)
1373 ESourceAuthenticationResult auth_result;
1374 GError *non_fatal_error = NULL;
1376 g_return_val_if_fail (auth_context->authenticating, FALSE);
1378 auth_result = auth_context->auth_result;
1380 /* Allow the next authentication attempt to proceed. */
1381 auth_context->authenticating = FALSE;
1383 /* Send the server a status update based on the authentication
1384 * result. Note, we don't really care if the D-Bus message gets
1385 * through to the server at this point. If it doesn't, the auth
1386 * session will either time out on its own or the authentication
1387 * dialog will eventually be dismissed by the user. */
1389 /* If we were cancelled from our side, we have a bit of a dilemma.
1390 * We need to tell the server to cancel the authentication session,
1391 * but that involves making a synchronous D-Bus call, which we are
1392 * not supposed to do if we know we've been cancelled. But if we
1393 * don't tell the server, the authentication session will be left
1394 * to timeout on its own (which may take minutes), and meanwhile
1395 * all other authentication requests are blocked. So choose the
1396 * lesser evil and make the synchronous call but without passing
1397 * the already-cancelled GCancellable. */
1398 if (g_cancellable_is_cancelled (auth_context->cancellable)) {
1399 e_dbus_authenticator_call_cancel_sync (
1400 auth_context->dbus_auth,
1401 NULL, &non_fatal_error);
1402 g_main_loop_quit (auth_context->main_loop);
1403 auth_context->success = FALSE;
1405 /* If an error occurred while attempting to authenticate,
1406 * tell the server to cancel the authentication session. */
1407 } else if (auth_result == E_SOURCE_AUTHENTICATION_ERROR) {
1408 e_dbus_authenticator_call_cancel_sync (
1409 auth_context->dbus_auth,
1410 auth_context->cancellable,
1412 g_main_loop_quit (auth_context->main_loop);
1413 auth_context->success = FALSE;
1415 /* If the password was accepted, let the server know so it
1416 * can close any authentication dialogs and save the user
1417 * provided password to the keyring. */
1418 } else if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
1419 e_dbus_authenticator_call_accepted_sync (
1420 auth_context->dbus_auth,
1421 auth_context->cancellable,
1423 g_main_loop_quit (auth_context->main_loop);
1424 auth_context->success = TRUE;
1426 /* If the password was rejected, let the server know so it can
1427 * indicate failure and request a different password, and then
1428 * wait for the next "response" signal. */
1430 e_dbus_authenticator_call_rejected_sync (
1431 auth_context->dbus_auth,
1432 auth_context->cancellable,
1436 /* Leave breadcrumbs if something went wrong,
1437 * but don't fail the whole operation over it. */
1438 if (non_fatal_error != NULL) {
1439 g_warning ("%s: %s", G_STRFUNC, non_fatal_error->message);
1440 g_error_free (non_fatal_error);
1446 /* Helper for e_source_registry_authenticate_sync() */
1448 source_registry_authenticate_authenticate_cb (EDBusAuthenticator *dbus_auth,
1449 const gchar *encrypted_secret,
1450 AuthContext *auth_context)
1452 GSource *idle_source;
1453 GMainContext *main_context;
1455 gboolean valid_secret;
1457 /* We should only get one secret at a time. */
1458 g_return_if_fail (!auth_context->authenticating);
1460 valid_secret = gcr_secret_exchange_receive (
1461 auth_context->secret_exchange, encrypted_secret);
1462 g_return_if_fail (valid_secret);
1464 auth_context->authenticating = TRUE;
1466 /* This avoids revealing the password in a stack trace. */
1467 password = g_string_new (
1468 gcr_secret_exchange_get_secret (
1469 auth_context->secret_exchange, NULL));
1471 /* Try authenticating with the given password. We have to
1472 * call this synchronously because some authenticators use
1473 * mutexes to serialize I/O operations and are not prepared
1474 * to make authentication attempts from a different thread.
1476 * Unfortunately this means we won't notice server-side
1477 * dismissals while the main loop is blocked. We respond
1478 * to the server from a low-priority idle callback so that
1479 * any pending "dismissed" signals get handled first. */
1481 auth_context->auth_result =
1482 e_source_authenticator_try_password_sync (
1483 auth_context->auth, password,
1484 auth_context->cancellable,
1485 auth_context->error);
1487 idle_source = g_idle_source_new ();
1488 main_context = g_main_context_get_thread_default ();
1489 g_source_set_callback (
1490 idle_source, (GSourceFunc)
1491 source_registry_authenticate_respond_cb,
1492 auth_context, NULL);
1493 g_source_attach (idle_source, main_context);
1494 g_source_unref (idle_source);
1496 g_string_free (password, TRUE);
1499 /* Helper for e_source_registry_authenticate_sync() */
1501 source_registry_authenticate_dismissed_cb (EDBusAuthenticator *dbus_auth,
1502 AuthContext *auth_context)
1504 /* Be careful not to overwrite an existing error in case this
1505 * is called after e_source_authenticator_try_password_sync()
1506 * but prior to the idle callback. */
1507 if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
1508 /* XXX Use a separate error code for dismissals? */
1509 g_set_error_literal (
1510 auth_context->error,
1511 G_IO_ERROR, G_IO_ERROR_CANCELLED,
1512 _("The user declined to authenticate"));
1513 auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
1516 g_main_loop_quit (auth_context->main_loop);
1517 auth_context->success = FALSE;
1520 /* Helper for e_source_registry_authenticate_sync() */
1522 source_registry_call_authenticate_for_source (ESourceRegistry *registry,
1523 ESourceAuthenticator *auth,
1525 gchar **out_object_path,
1526 GCancellable *cancellable,
1529 ESource *collection;
1531 gchar *prompt_title = NULL;
1532 gchar *prompt_message = NULL;
1533 gchar *prompt_description = NULL;
1536 /* If the source is a member of a collection, we want to store
1537 * the password under the UID of the "collection" source so it
1538 * will apply to the entire collection.
1540 * XXX This assumes all sources in a collection share a single
1541 * password. If that turns out not to be true in all cases
1542 * we could maybe add a "SharedPassword: true/false" key to
1543 * [Collection] and apply it here.
1545 collection = e_source_registry_find_extension (
1546 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1547 if (collection != NULL)
1548 source = collection;
1550 g_object_ref (source);
1552 uid = e_source_get_uid (source);
1554 e_source_authenticator_get_prompt_strings (
1558 &prompt_description);
1560 success = e_dbus_source_manager_call_authenticate_sync (
1561 registry->priv->dbus_source_manager, uid,
1562 prompt_title, prompt_message, prompt_description,
1563 out_object_path, cancellable, error);
1565 g_free (prompt_title);
1566 g_free (prompt_message);
1567 g_free (prompt_description);
1569 g_object_unref (source);
1575 * e_source_registry_authenticate_sync:
1576 * @registry: an #ESourceRegistry
1577 * @source: an #ESource
1578 * @auth: an #ESourceAuthenticator
1579 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1580 * @error: return location for a #GError, or %NULL
1582 * Authenticates @source, using @auth to handle the authentication
1583 * attempts. The operation loops until authentication is successful or
1584 * the user aborts further authentication attempts. If an error occurs,
1585 * the function will set @error and return %FALSE.
1587 * Note that @source need not have a #GDBusObject, which means this
1588 * function can test authentication on a scratch #ESource.
1590 * Only backend implementations and data source editors should call this
1591 * function. The intent is for basic client applications to not have to
1592 * deal with authentication at all.
1594 * Returns: %TRUE on success, %FALSE on failure
1599 e_source_registry_authenticate_sync (ESourceRegistry *registry,
1601 ESourceAuthenticator *auth,
1602 GCancellable *cancellable,
1605 AuthContext *auth_context;
1606 GMainContext *main_context;
1607 EDBusAuthenticator *dbus_auth;
1608 gchar *encryption_key;
1609 gchar *object_path = NULL;
1612 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1613 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1614 g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth), FALSE);
1616 /* This extracts authentication prompt details for the ESource
1617 * before initiating an authentication session with the server,
1618 * so split it out of the main algorithm for clarity's sake. */
1619 success = source_registry_call_authenticate_for_source (
1620 registry, auth, source, &object_path, cancellable, error);
1623 g_warn_if_fail (object_path == NULL);
1627 g_return_val_if_fail (object_path != NULL, FALSE);
1629 main_context = g_main_context_new ();
1630 g_main_context_push_thread_default (main_context);
1632 dbus_auth = e_dbus_authenticator_proxy_new_for_bus_sync (
1634 G_DBUS_PROXY_FLAGS_NONE,
1635 SOURCES_DBUS_SERVICE_NAME,
1636 object_path, cancellable, error);
1638 g_free (object_path);
1640 if (dbus_auth == NULL) {
1645 auth_context = g_slice_new0 (AuthContext);
1646 auth_context->auth = g_object_ref (auth);
1647 auth_context->dbus_auth = dbus_auth; /* takes ownership */
1648 auth_context->main_loop = g_main_loop_new (main_context, FALSE);
1649 auth_context->error = error;
1651 /* This just needs to be something other than
1652 * E_SOURCE_AUTHENTICATION_ERROR so we don't trip
1653 * up source_registry_authenticate_dismissed_cb(). */
1654 auth_context->auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
1656 if (G_IS_CANCELLABLE (cancellable))
1657 auth_context->cancellable = g_object_ref (cancellable);
1659 auth_context->secret_exchange =
1660 gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1);
1663 dbus_auth, "authenticate",
1664 G_CALLBACK (source_registry_authenticate_authenticate_cb),
1668 dbus_auth, "dismissed",
1669 G_CALLBACK (source_registry_authenticate_dismissed_cb),
1672 encryption_key = gcr_secret_exchange_begin (
1673 auth_context->secret_exchange);
1675 /* Signal the D-Bus server that we're ready to begin the
1676 * authentication session. This must happen AFTER we've
1677 * connected to the response signal since the server may
1678 * already have a response ready and waiting for us. */
1679 success = e_dbus_authenticator_call_ready_sync (
1680 dbus_auth, encryption_key, cancellable, error);
1682 g_free (encryption_key);
1685 g_main_loop_run (auth_context->main_loop);
1686 success = auth_context->success;
1689 auth_context_free (auth_context);
1692 g_main_context_pop_thread_default (main_context);
1693 g_main_context_unref (main_context);
1699 * e_source_registry_authenticate:
1700 * @registry: an #ESourceRegistry
1701 * @source: an #ESource
1702 * @auth: an #ESourceAuthenticator
1703 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1704 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1706 * @user_data: (closure): data to pass to the callback function
1708 * Asynchronously authenticates @source, using @auth to handle the
1709 * authentication attempts. The operation loops until authentication
1710 * is successful or the user aborts further authentication attempts.
1712 * Note that @source need not have a #GDBusObject, which means this
1713 * function can test authentication on a scratch #ESource.
1715 * When the operation is finished, @callback will be called. You can then
1716 * call e_source_registry_authenticate_finish() to get the result of the
1719 * Only backend implementations and data source editors should call this
1720 * function. The intent is for basic client applications to not have to
1721 * deal with authentication at all.
1726 e_source_registry_authenticate (ESourceRegistry *registry,
1728 ESourceAuthenticator *auth,
1729 GCancellable *cancellable,
1730 GAsyncReadyCallback callback,
1733 GSimpleAsyncResult *simple;
1734 AsyncContext *async_context;
1736 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1737 g_return_if_fail (E_IS_SOURCE (source));
1738 g_return_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth));
1740 async_context = g_slice_new0 (AsyncContext);
1741 async_context->source = g_object_ref (source);
1742 async_context->auth = g_object_ref (auth);
1744 simple = g_simple_async_result_new (
1745 G_OBJECT (registry), callback, user_data,
1746 e_source_registry_authenticate);
1748 g_simple_async_result_set_check_cancellable (simple, cancellable);
1750 g_simple_async_result_set_op_res_gpointer (
1751 simple, async_context, (GDestroyNotify) async_context_free);
1753 g_simple_async_result_run_in_thread (
1754 simple, source_registry_authenticate_thread,
1755 G_PRIORITY_DEFAULT, cancellable);
1757 g_object_unref (simple);
1761 * e_source_registry_authenticate_finish:
1762 * @registry: an #ESourceRegistry
1763 * @result: a #GAsyncResult
1764 * @error: return location for a #GError, or %NULL
1766 * Finishes the operation started with e_source_registry_authenticate().
1767 * If an error occurred, the function will set @error and return %FALSE.
1769 * Returns: %TRUE on success, %FALSE on failure
1774 e_source_registry_authenticate_finish (ESourceRegistry *registry,
1775 GAsyncResult *result,
1778 GSimpleAsyncResult *simple;
1780 g_return_val_if_fail (
1781 g_simple_async_result_is_valid (
1782 result, G_OBJECT (registry),
1783 e_source_registry_authenticate), FALSE);
1785 simple = G_SIMPLE_ASYNC_RESULT (result);
1787 /* Assume success unless a GError is set. */
1788 return !g_simple_async_result_propagate_error (simple, error);
1791 /* Helper for e_source_registry_commit_source() */
1793 source_registry_commit_source_thread (GSimpleAsyncResult *simple,
1795 GCancellable *cancellable)
1797 AsyncContext *async_context;
1798 GError *error = NULL;
1800 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1802 e_source_registry_commit_source_sync (
1803 E_SOURCE_REGISTRY (object),
1804 async_context->source,
1805 cancellable, &error);
1808 g_simple_async_result_take_error (simple, error);
1812 * e_source_registry_commit_source_sync:
1813 * @registry: an #ESourceRegistry
1814 * @source: an #ESource with changes to commit
1815 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1816 * @error: return location for #GError, or %NULL
1818 * This is a convenience function intended for use with graphical
1819 * #ESource editors. Call this function when the user is finished
1820 * making changes to @source.
1822 * If @source has a #GDBusObject, its contents are submitted to the D-Bus
1823 * service through e_source_write_sync().
1825 * If @source does NOT have a #GDBusObject (implying it's a scratch
1826 * #ESource), its contents are submitted to the D-Bus service through
1827 * either e_source_remote_create_sync() if @source is to be a collection
1828 * member, or e_source_registry_create_sources_sync() if @source to be an
1829 * independent data source.
1831 * If an error occurs, the function will set @error and return %FALSE.
1833 * Returns: %TRUE on success, %FALSE on failure
1838 e_source_registry_commit_source_sync (ESourceRegistry *registry,
1840 GCancellable *cancellable,
1843 GDBusObject *dbus_object;
1844 ESource *collection_source;
1845 gboolean collection_member;
1848 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1849 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1851 dbus_object = e_source_ref_dbus_object (source);
1853 collection_source = e_source_registry_find_extension (
1854 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1857 (collection_source != NULL) &&
1858 (collection_source != source);
1860 if (dbus_object != NULL) {
1861 success = e_source_write_sync (source, cancellable, error);
1862 g_object_unref (dbus_object);
1864 } else if (collection_member) {
1865 success = e_source_remote_create_sync (
1866 collection_source, source, cancellable, error);
1869 GList *list = g_list_prepend (NULL, source);
1870 success = e_source_registry_create_sources_sync (
1871 registry, list, cancellable, error);
1875 if (collection_source != NULL)
1876 g_object_unref (collection_source);
1882 * e_source_registry_commit_source:
1883 * @registry: an #ESourceRegistry
1884 * @source: an #ESource with changes to commit
1885 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1886 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1888 * @user_data: (closure): data to pass to the callback function
1890 * See e_source_registry_commit_source_sync() for details.
1892 * When the operation is finished, @callback will be called. You can then
1893 * call e_source_registry_commit_source_finish() to get the result of the
1899 e_source_registry_commit_source (ESourceRegistry *registry,
1901 GCancellable *cancellable,
1902 GAsyncReadyCallback callback,
1905 GSimpleAsyncResult *simple;
1906 AsyncContext *async_context;
1908 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1909 g_return_if_fail (E_IS_SOURCE (source));
1911 async_context = g_slice_new0 (AsyncContext);
1912 async_context->source = g_object_ref (source);
1914 simple = g_simple_async_result_new (
1915 G_OBJECT (registry), callback, user_data,
1916 e_source_registry_commit_source);
1918 g_simple_async_result_set_check_cancellable (simple, cancellable);
1920 g_simple_async_result_set_op_res_gpointer (
1921 simple, async_context, (GDestroyNotify) async_context_free);
1923 g_simple_async_result_run_in_thread (
1924 simple, source_registry_commit_source_thread,
1925 G_PRIORITY_DEFAULT, cancellable);
1927 g_object_unref (simple);
1931 * e_source_registry_commit_source_finish:
1932 * @registry: an #ESourceRegistry
1933 * @result: a #GAsyncResult
1934 * @error: return location for a #GError, or %NULL
1936 * Finishes the operation started with e_source_registry_commit_source().
1938 * If an error occurred, the function will set @error and return %FALSE.
1940 * Returns: %TRUE on success, %FALSE on failure
1945 e_source_registry_commit_source_finish (ESourceRegistry *registry,
1946 GAsyncResult *result,
1949 GSimpleAsyncResult *simple;
1951 g_return_val_if_fail (
1952 g_simple_async_result_is_valid (
1953 result, G_OBJECT (registry),
1954 e_source_registry_commit_source), FALSE);
1956 simple = G_SIMPLE_ASYNC_RESULT (result);
1958 /* Assume success unless a GError is set. */
1959 return !g_simple_async_result_propagate_error (simple, error);
1962 /* Helper for e_source_registry_create_sources() */
1964 source_registry_create_sources_thread (GSimpleAsyncResult *simple,
1966 GCancellable *cancellable)
1968 AsyncContext *async_context;
1969 GError *error = NULL;
1971 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1973 e_source_registry_create_sources_sync (
1974 E_SOURCE_REGISTRY (object),
1975 async_context->list_of_sources,
1976 cancellable, &error);
1979 g_simple_async_result_take_error (simple, error);
1983 * e_source_registry_create_sources_sync:
1984 * @registry: an #ESourceRegistry
1985 * @list_of_sources: (element-type ESource): a list of #ESource instances with
1987 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1988 * @error: return location for a #GError, or %NULL
1990 * Requests the D-Bus service create new key files for each #ESource in
1991 * @list_of_sources. Each list element must be a scratch #ESource with
1994 * If an error occurs, the function will set @error and return %FALSE.
1996 * Returns: %TRUE on success, %FALSE on failure
2001 e_source_registry_create_sources_sync (ESourceRegistry *registry,
2002 GList *list_of_sources,
2003 GCancellable *cancellable,
2006 GVariantBuilder builder;
2011 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2013 /* Verify the list elements are all ESources. */
2014 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2015 g_return_val_if_fail (E_IS_SOURCE (link->data), FALSE);
2017 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
2019 for (link = list_of_sources; link != NULL; link = g_list_next (link)) {
2024 source = E_SOURCE (link->data);
2025 uid = e_source_get_uid (source);
2027 source_data = e_source_to_string (source, NULL);
2028 g_variant_builder_add (&builder, "{ss}", uid, source_data);
2029 g_free (source_data);
2032 variant = g_variant_builder_end (&builder);
2034 /* This function sinks the floating GVariant reference. */
2035 success = e_dbus_source_manager_call_create_sources_sync (
2036 registry->priv->dbus_source_manager,
2037 variant, cancellable, error);
2039 g_variant_builder_clear (&builder);
2045 * e_source_registry_create_sources:
2046 * @registry: an #ESourceRegistry
2047 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2049 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2050 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2052 * @user_data: (closure): data to pass to the callback function
2054 * Asynchronously requests the D-Bus service create new key files for each
2055 * #ESource in @list_of_sources. Each list element must be a scratch
2056 * #ESource with no #GDBusObject.
2058 * When the operation is finished, @callback will be called. You can then
2059 * call e_source_registry_create_sources_finish() to get the result of the
2065 e_source_registry_create_sources (ESourceRegistry *registry,
2066 GList *list_of_sources,
2067 GCancellable *cancellable,
2068 GAsyncReadyCallback callback,
2071 GSimpleAsyncResult *simple;
2072 AsyncContext *async_context;
2075 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2077 /* Verify the list elements are all ESources. */
2078 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2079 g_return_if_fail (E_IS_SOURCE (link->data));
2081 async_context = g_slice_new0 (AsyncContext);
2082 async_context->list_of_sources = g_list_copy (list_of_sources);
2085 async_context->list_of_sources,
2086 (GFunc) g_object_ref, NULL);
2088 simple = g_simple_async_result_new (
2089 G_OBJECT (registry), callback, user_data,
2090 e_source_registry_create_sources);
2092 g_simple_async_result_set_check_cancellable (simple, cancellable);
2094 g_simple_async_result_set_op_res_gpointer (
2095 simple, async_context, (GDestroyNotify) async_context_free);
2097 g_simple_async_result_run_in_thread (
2098 simple, source_registry_create_sources_thread,
2099 G_PRIORITY_DEFAULT, cancellable);
2101 g_object_unref (simple);
2105 * e_source_registry_create_sources_finish:
2106 * @registry: an #ESourceRegistry
2107 * @result: a #GAsyncResult
2108 * @error: return location for a #GError, or %NULL
2110 * Finishes the operation started with e_source_registry_create_sources().
2112 * If an error occurred, the function will set @error and return %FALSE.
2114 * Returns: %TRUE on success, %FALSE on failure
2119 e_source_registry_create_sources_finish (ESourceRegistry *registry,
2120 GAsyncResult *result,
2123 GSimpleAsyncResult *simple;
2125 g_return_val_if_fail (
2126 g_simple_async_result_is_valid (
2127 result, G_OBJECT (registry),
2128 e_source_registry_create_sources), FALSE);
2130 simple = G_SIMPLE_ASYNC_RESULT (result);
2132 /* Assume success unless a GError is set. */
2133 return !g_simple_async_result_propagate_error (simple, error);
2137 * e_source_registry_ref_source:
2138 * @registry: an #ESourceRegistry
2139 * @uid: a unique identifier string
2141 * Looks up an #ESource in @registry by its unique identifier string.
2143 * The returned #ESource is referenced for thread-safety and must be
2144 * unreferenced with g_object_unref() when finished with it.
2146 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2151 e_source_registry_ref_source (ESourceRegistry *registry,
2154 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2155 g_return_val_if_fail (uid != NULL, NULL);
2157 return source_registry_sources_lookup (registry, uid);
2161 * e_source_registry_list_sources:
2162 * @registry: an #ESourceRegistry
2163 * @extension_name: (allow-none): an extension name, or %NULL
2165 * Returns a list of registered sources, sorted by display name. If
2166 * @extension_name is given, restrict the list to sources having that
2169 * The sources returned in the list are referenced for thread-safety.
2170 * They must each be unreferenced with g_object_unref() when finished
2171 * when them. Free the returned list itself with g_list_free().
2173 * An easy way to free the list properly in one step is as follows:
2176 * g_list_free_full (list, g_object_unref);
2179 * Returns: (element-type ESource) (transfer full): a sorted list of sources
2184 e_source_registry_list_sources (ESourceRegistry *registry,
2185 const gchar *extension_name)
2188 GQueue trash = G_QUEUE_INIT;
2190 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2192 list = g_list_sort (
2193 source_registry_sources_get_values (registry),
2194 (GCompareFunc) e_source_compare_by_display_name);
2196 if (extension_name == NULL)
2199 for (link = list; link != NULL; link = g_list_next (link)) {
2200 ESource *source = E_SOURCE (link->data);
2202 if (!e_source_has_extension (source, extension_name)) {
2203 g_queue_push_tail (&trash, link);
2204 g_object_unref (source);
2208 /* We do want pop_head() here, not pop_head_link(). */
2209 while ((link = g_queue_pop_head (&trash)) != NULL)
2210 list = g_list_delete_link (list, link);
2216 * e_source_registry_find_extension:
2217 * @registry: an #ESourceRegistry
2218 * @source: an #ESource
2219 * @extension_name: the extension name to find
2221 * Examines @source and its ancestors and returns the "deepest" #ESource
2222 * having an #ESourceExtension with the given @extension_name. If neither
2223 * @source nor any of its ancestors have such an extension, the function
2226 * This function is useful in cases when an #ESourceExtension is meant to
2227 * apply to both the #ESource it belongs to and the #ESource's descendants.
2229 * A common example is the #ESourceCollection extension, where descendants
2230 * of an #ESource having an #ESourceCollection extension are implied to be
2231 * members of that collection. In that example, this function can be used
2232 * to test whether @source is a member of a collection.
2234 * The returned #ESource is referenced for thread-safety and must be
2235 * unreferenced with g_object_unref() when finished with it.
2237 * Note the function returns the #ESource containing the #ESourceExtension
2238 * instead of the #ESourceExtension itself because extension instances are
2239 * not to be referenced directly (see e_source_get_extension()).
2241 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2246 e_source_registry_find_extension (ESourceRegistry *registry,
2248 const gchar *extension_name)
2250 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2251 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2252 g_return_val_if_fail (extension_name != NULL, NULL);
2254 g_object_ref (source);
2256 while (!e_source_has_extension (source, extension_name)) {
2259 uid = e_source_dup_parent (source);
2261 g_object_unref (source);
2265 source = e_source_registry_ref_source (registry, uid);
2276 /* Helper for e_source_registry_build_display_tree() */
2278 source_registry_compare_nodes (GNode *node_a,
2281 ESource *source_a = E_SOURCE (node_a->data);
2282 ESource *source_b = E_SOURCE (node_b->data);
2283 const gchar *uid_a, *uid_b;
2285 uid_a = e_source_get_uid (source_a);
2286 uid_b = e_source_get_uid (source_b);
2288 /* Sanity check, with runtime warnings. */
2289 if (uid_a == NULL) {
2290 g_warn_if_reached ();
2293 if (uid_b == NULL) {
2294 g_warn_if_reached ();
2298 /* The built-in "local-stub" source comes first at depth 1. */
2300 if (g_strcmp0 (uid_a, "local-stub") == 0)
2303 if (g_strcmp0 (uid_b, "local-stub") == 0)
2306 /* The built-in "system-*" sources come first at depth 2. */
2308 if (g_str_has_prefix (uid_a, "system-"))
2311 if (g_str_has_prefix (uid_b, "system-"))
2314 return e_source_compare_by_display_name (source_a, source_b);
2317 /* Helper for e_source_registry_build_display_tree() */
2319 source_registry_prune_nodes (GNode *node,
2320 const gchar *extension_name)
2322 GQueue queue = G_QUEUE_INIT;
2325 /* Unlink all the child nodes and place them in a queue. */
2326 while ((child_node = g_node_first_child (node)) != NULL) {
2327 g_node_unlink (child_node);
2328 g_queue_push_tail (&queue, child_node);
2331 /* Sort the queue by source name. */
2333 &queue, (GCompareDataFunc)
2334 source_registry_compare_nodes, NULL);
2336 /* Pop nodes off the head of the queue until the queue is empty.
2337 * If the node has either its own children or the given extension
2338 * name, put it back under the parent node (preserving the sorted
2339 * order). Otherwise delete the node and its descendants. */
2340 while ((child_node = g_queue_pop_head (&queue)) != NULL) {
2341 ESource *child = E_SOURCE (child_node->data);
2342 gboolean append_child_node = FALSE;
2344 if (extension_name == NULL)
2345 append_child_node = e_source_get_enabled (child);
2347 else if (e_source_has_extension (child, extension_name))
2348 append_child_node = e_source_get_enabled (child);
2350 else if (g_node_first_child (child_node) != NULL)
2351 append_child_node = e_source_get_enabled (child);
2353 if (append_child_node)
2354 g_node_append (node, child_node);
2356 e_source_registry_free_display_tree (child_node);
2363 * e_source_registry_build_display_tree:
2364 * @registry: an #ESourceRegistry
2365 * @extension_name: (allow-none): an extension name, or %NULL
2367 * Returns a single #GNode tree of registered sources that can be used to
2368 * populate a #GtkTreeModel. (The root #GNode is just an empty placeholder.)
2370 * Similar to e_source_registry_list_sources(), an @extension_name can be
2371 * given to restrict the tree to sources having that extension name. Parents
2372 * of matched sources are included in the tree regardless of whether they have
2373 * an extension named @extension_name.
2375 * Disabled leaf nodes are automatically excluded from the #GNode tree.
2377 * The sources returned in the tree are referenced for thread-safety.
2378 * They must each be unreferenced with g_object_unref() when finished
2379 * with them. Free the returned tree itself with g_node_destroy().
2380 * For convenience, e_source_registry_free_display_tree() does all
2383 * Returns: (element-type ESource) (transfer full): a tree of sources,
2384 * arranged for display
2389 e_source_registry_build_display_tree (ESourceRegistry *registry,
2390 const gchar *extension_name)
2394 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2396 /* Assemble all data sources into a tree. */
2397 root = source_registry_sources_build_tree (registry);
2399 /* Prune unwanted nodes from the copied source trees.
2400 * This must be done in "post" order (children first)
2401 * since it reorders and deletes child nodes. */
2403 root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
2404 (GNodeTraverseFunc) source_registry_prune_nodes,
2405 (gpointer) extension_name);
2410 /* Helper for e_source_registry_free_display_tree() */
2412 source_registry_unref_nodes (GNode *node)
2414 while (node != NULL) {
2415 if (node->children != NULL)
2416 source_registry_unref_nodes (node->children);
2417 if (node->data != NULL)
2418 g_object_unref (node->data);
2424 * e_source_registry_free_display_tree:
2425 * @display_tree: a tree of sources, arranged for display
2427 * Convenience function to free a #GNode tree of registered
2428 * sources created by e_source_registry_build_display_tree().
2433 e_source_registry_free_display_tree (GNode *display_tree)
2435 g_return_if_fail (display_tree != NULL);
2437 /* XXX This would be easier if GLib had something like
2438 * g_node_destroy_full() which took a GDestroyNotify.
2439 * Then the tree would not have to be traversed twice. */
2441 source_registry_unref_nodes (display_tree);
2442 g_node_destroy (display_tree);
2445 /* Helper for e_source_registry_debug_dump() */
2447 source_registry_debug_dump_cb (GNode *node)
2451 /* Root node is an empty placeholder. */
2452 if (G_NODE_IS_ROOT (node))
2455 depth = g_node_depth (node);
2456 for (ii = 2; ii < depth; ii++)
2459 if (E_IS_SOURCE (node->data)) {
2460 ESource *source = E_SOURCE (node->data);
2461 g_print ("\"%s\" ", e_source_get_display_name (source));
2462 g_print ("(%s)", e_source_get_uid (source));
2471 * e_source_registry_debug_dump:
2472 * @registry: an #ESourceRegistry
2473 * @extension_name: (allow-none): an extension name, or %NULL
2475 * Handy debugging function that uses e_source_registry_build_display_tree()
2476 * to print a tree of registered sources to standard output.
2481 e_source_registry_debug_dump (ESourceRegistry *registry,
2482 const gchar *extension_name)
2486 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2488 root = e_source_registry_build_display_tree (registry, extension_name);
2491 root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2492 (GNodeTraverseFunc) source_registry_debug_dump_cb, NULL);
2494 e_source_registry_free_display_tree (root);
2498 * e_source_registry_ref_builtin_address_book:
2499 * @registry: an #ESourceRegistry
2501 * Returns the built-in address book #ESource.
2503 * This #ESource is always present and makes for a safe fallback.
2505 * The returned #ESource is referenced for thread-safety and must be
2506 * unreferenced with g_object_unref() when finished with it.
2508 * Returns: (transfer full): the built-in address book #ESource
2513 e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
2518 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2520 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2521 source = e_source_registry_ref_source (registry, uid);
2522 g_return_val_if_fail (source != NULL, NULL);
2528 * e_source_registry_ref_default_address_book:
2529 * @registry: an #ESourceRegistry
2531 * Returns the #ESource most recently passed to
2532 * e_source_registry_set_default_address_book() either in this session
2533 * or a previous session, or else falls back to the built-in address book.
2535 * The returned #ESource is referenced for thread-safety and must be
2536 * unreferenced with g_object_unref() when finished with it.
2538 * Returns: (transfer full): the default address book #ESource
2543 e_source_registry_ref_default_address_book (ESourceRegistry *registry)
2549 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2551 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2552 uid = g_settings_get_string (registry->priv->settings, key);
2553 source = e_source_registry_ref_source (registry, uid);
2556 /* The built-in source is always present. */
2558 source = e_source_registry_ref_builtin_address_book (registry);
2560 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2566 * e_source_registry_set_default_address_book:
2567 * @registry: an #ESourceRegistry
2568 * @default_source: (allow-none): an address book #ESource, or %NULL
2570 * Sets @default_source as the default address book. If @default_source
2571 * is %NULL, the default address book is reset to the built-in address book.
2572 * This setting will persist across sessions until changed.
2577 e_source_registry_set_default_address_book (ESourceRegistry *registry,
2578 ESource *default_source)
2583 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2585 if (default_source != NULL) {
2586 g_return_if_fail (E_IS_SOURCE (default_source));
2587 uid = e_source_get_uid (default_source);
2589 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2592 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2593 g_settings_set_string (registry->priv->settings, key, uid);
2595 /* The GSettings::changed signal will trigger a "notify" signal
2596 * from the registry, so no need to call g_object_notify() here. */
2600 * e_source_registry_ref_builtin_calendar:
2601 * @registry: an #ESourceRegistry
2603 * Returns the built-in calendar #ESource.
2605 * This #ESource is always present and makes for a safe fallback.
2607 * The returned #ESource is referenced for thread-safety and must be
2608 * unreferenced with g_object_unref() when finished with it.
2610 * Returns: (transfer full): the built-in calendar #ESource
2615 e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
2620 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2622 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2623 source = e_source_registry_ref_source (registry, uid);
2624 g_return_val_if_fail (source != NULL, NULL);
2630 * e_source_registry_ref_default_calendar:
2631 * @registry: an #ESourceRegistry
2633 * Returns the #ESource most recently passed to
2634 * e_source_registry_set_default_calendar() either in this session
2635 * or a previous session, or else falls back to the built-in calendar.
2637 * The returned #ESource is referenced for thread-safety and must be
2638 * unreferenced with g_object_unref() when finished with it.
2640 * Returns: (transfer full): the default calendar #ESource
2645 e_source_registry_ref_default_calendar (ESourceRegistry *registry)
2651 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2653 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2654 uid = g_settings_get_string (registry->priv->settings, key);
2655 source = e_source_registry_ref_source (registry, uid);
2658 /* The built-in source is always present. */
2660 source = e_source_registry_ref_builtin_calendar (registry);
2662 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2668 * e_source_registry_set_default_calendar:
2669 * @registry: an #ESourceRegistry
2670 * @default_source: (allow-none): a calendar #ESource, or %NULL
2672 * Sets @default_source as the default calendar. If @default_source
2673 * is %NULL, the default calendar is reset to the built-in calendar.
2674 * This setting will persist across sessions until changed.
2679 e_source_registry_set_default_calendar (ESourceRegistry *registry,
2680 ESource *default_source)
2685 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2687 if (default_source != NULL) {
2688 g_return_if_fail (E_IS_SOURCE (default_source));
2689 uid = e_source_get_uid (default_source);
2691 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2694 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2695 g_settings_set_string (registry->priv->settings, key, uid);
2697 /* The GSettings::changed signal will trigger a "notify" signal
2698 * from the registry, so no need to call g_object_notify() here. */
2702 * e_source_registry_ref_builtin_mail_account:
2703 * @registry: an #ESourceRegistry
2705 * Returns the built-in mail account #ESource.
2707 * This #ESource is always present and makes for a safe fallback.
2709 * The returned #ESource is referenced for thread-safety and must be
2710 * unreferenced with g_object_unref() when finished with it.
2712 * Returns: (transfer full): the built-in mail account #ESource
2717 e_source_registry_ref_builtin_mail_account (ESourceRegistry *registry)
2722 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2724 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2725 source = e_source_registry_ref_source (registry, uid);
2726 g_return_val_if_fail (source != NULL, NULL);
2732 * e_source_registry_ref_default_mail_account:
2733 * @registry: an #ESourceRegistry
2735 * Returns the #ESource most recently passed to
2736 * e_source_registry_set_default_mail_account() either in this session
2737 * or a previous session, or else falls back to the built-in mail account.
2739 * The returned #ESource is referenced for thread-safety and must be
2740 * unreferenced with g_object_unref() when finished with it.
2742 * Returns: (transfer full): the default mail account #ESource
2747 e_source_registry_ref_default_mail_account (ESourceRegistry *registry)
2753 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2755 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2756 uid = g_settings_get_string (registry->priv->settings, key);
2757 source = e_source_registry_ref_source (registry, uid);
2760 /* The built-in source is always present. */
2762 source = e_source_registry_ref_builtin_mail_account (registry);
2764 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2770 * e_source_registry_set_default_mail_account:
2771 * @registry: an #ESourceRegistry
2772 * @default_source: (allow-none): a mail account #ESource, or %NULL
2774 * Sets @default_source as the default mail account. If @default_source
2775 * is %NULL, the default mail account is reset to the built-in mail account.
2776 * This setting will persist across sessions until changed.
2781 e_source_registry_set_default_mail_account (ESourceRegistry *registry,
2782 ESource *default_source)
2787 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2789 if (default_source != NULL) {
2790 g_return_if_fail (E_IS_SOURCE (default_source));
2791 uid = e_source_get_uid (default_source);
2793 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2796 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2797 g_settings_set_string (registry->priv->settings, key, uid);
2799 /* The GSettings::changed signal will trigger a "notify" signal
2800 * from the registry, so no need to call g_object_notify() here. */
2803 /* Helper for e_source_registry_ref_default_mail_identity() */
2805 source_registry_ref_any_mail_identity (ESourceRegistry *registry)
2809 const gchar *extension_name;
2812 /* First fallback: Return the mail identity named
2813 * by the default mail account. */
2815 source = e_source_registry_ref_default_mail_account (registry);
2817 /* This should never be NULL, but just to be safe. */
2818 if (source != NULL) {
2819 ESourceMailAccount *extension;
2821 extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
2822 extension = e_source_get_extension (source, extension_name);
2823 uid = e_source_mail_account_dup_identity_uid (extension);
2825 g_object_unref (source);
2830 source = e_source_registry_ref_source (registry, uid);
2837 /* Second fallback: Pick any available mail identity,
2838 * preferring enabled identities. */
2840 extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
2841 list = e_source_registry_list_sources (registry, extension_name);
2843 for (link = list; link != NULL; link = g_list_next (link)) {
2844 ESource *candidate = E_SOURCE (link->data);
2846 if (e_source_get_enabled (candidate)) {
2847 source = g_object_ref (candidate);
2852 if (source == NULL && list != NULL)
2853 source = g_object_ref (list->data);
2855 g_list_free_full (list, (GDestroyNotify) g_object_unref);
2861 * e_source_registry_ref_default_mail_identity:
2862 * @registry: an #ESourceRegistry
2864 * Returns the #ESource most recently passed to
2865 * e_source_registry_set_default_mail_identity() either in this session
2866 * or a previous session, or else falls back to the mail identity named
2867 * by the default mail account. If even that fails it returns any mail
2868 * identity from @registry, or %NULL if there are none.
2870 * The returned #ESource is referenced for thread-safety and must be
2871 * unreferenced with g_object_unref() when finished with it.
2873 * Returns: (transfer full): the default mail identity #ESource, or %NULL
2878 e_source_registry_ref_default_mail_identity (ESourceRegistry *registry)
2884 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2886 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
2887 uid = g_settings_get_string (registry->priv->settings, key);
2888 source = e_source_registry_ref_source (registry, uid);
2892 source = source_registry_ref_any_mail_identity (registry);
2898 * e_source_registry_set_default_mail_identity:
2899 * @registry: an #ESourceRegistry
2900 * @default_source: (allow-none): a mail identity #ESource, or %NULL
2902 * Sets @default_source as the default mail identity. If @default_source
2903 * is %NULL, the next request for the default mail identity will use the
2904 * fallbacks described in e_source_registry_get_default_mail_identity().
2909 e_source_registry_set_default_mail_identity (ESourceRegistry *registry,
2910 ESource *default_source)
2915 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2917 if (default_source != NULL) {
2918 g_return_if_fail (E_IS_SOURCE (default_source));
2919 uid = e_source_get_uid (default_source);
2921 uid = ""; /* no built-in mail identity */
2924 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
2925 g_settings_set_string (registry->priv->settings, key, uid);
2927 /* The GSettings::changed signal will trigger a "notify" signal
2928 * from the registry, so no need to call g_object_notify() here. */
2932 * e_source_registry_ref_builtin_memo_list:
2933 * @registry: an #ESourceRegistry
2935 * Returns the built-in memo list #ESource.
2937 * This #ESource is always present and makes for a safe fallback.
2939 * The returned #ESource is referenced for thread-safety and must be
2940 * unreferenced with g_object_unref() when finished with it.
2942 * Returns: (transfer full): the built-in memo list #ESource
2947 e_source_registry_ref_builtin_memo_list (ESourceRegistry *registry)
2952 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2954 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
2955 source = e_source_registry_ref_source (registry, uid);
2956 g_return_val_if_fail (source != NULL, NULL);
2962 * e_source_registry_ref_default_memo_list:
2963 * @registry: an #ESourceRegistry
2965 * Returns the #ESource most recently passed to
2966 * e_source_registry_set_default_memo_list() either in this session
2967 * or a previous session, or else falls back to the built-in memo list.
2969 * The returned #ESource is referenced for thread-safety and must be
2970 * unreferenced with g_object_unref() when finished with it.
2972 * Returns: (transfer full): the default memo list #ESource
2977 e_source_registry_ref_default_memo_list (ESourceRegistry *registry)
2983 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2985 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
2986 uid = g_settings_get_string (registry->priv->settings, key);
2987 source = e_source_registry_ref_source (registry, uid);
2990 /* The built-in source is always present. */
2992 source = e_source_registry_ref_builtin_memo_list (registry);
2994 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3000 * e_source_registry_set_default_memo_list:
3001 * @registry: an #ESourceRegistry
3002 * @default_source: (allow-none): a memo list #ESource, or %NULL
3004 * Sets @default_source as the default memo list. If @default_source
3005 * is %NULL, the default memo list is reset to the built-in memo list.
3006 * This setting will persist across sessions until changed.
3011 e_source_registry_set_default_memo_list (ESourceRegistry *registry,
3012 ESource *default_source)
3017 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3019 if (default_source != NULL) {
3020 g_return_if_fail (E_IS_SOURCE (default_source));
3021 uid = e_source_get_uid (default_source);
3023 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3026 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3027 g_settings_set_string (registry->priv->settings, key, uid);
3029 /* The GSettings::changed signal will trigger a "notify" signal
3030 * from the registry, so no need to call g_object_notify() here. */
3034 * e_source_registry_ref_builtin_task_list:
3035 * @registry: an #ESourceRegistry
3037 * Returns the built-in task list #ESource.
3039 * This #ESource is always present and makes for a safe fallback.
3041 * The returned #ESource is referenced for thread-safety and must be
3042 * unreferenced with g_object_unref() when finished with it.
3044 * Returns: (transfer full): the built-in task list #ESource
3049 e_source_registry_ref_builtin_task_list (ESourceRegistry *registry)
3054 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3056 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3057 source = e_source_registry_ref_source (registry, uid);
3058 g_return_val_if_fail (source != NULL, NULL);
3064 * e_source_registry_ref_default_task_list:
3065 * @registry: an #ESourceRegistry
3067 * Returns the #ESource most recently passed to
3068 * e_source_registry_set_default_task_list() either in this session
3069 * or a previous session, or else falls back to the built-in task list.
3071 * The returned #ESource is referenced for thread-safety and must be
3072 * unreferenced with g_object_unref() when finished with it.
3074 * Returns: (transfer full): the default task list #ESource
3079 e_source_registry_ref_default_task_list (ESourceRegistry *registry)
3085 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3087 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3088 uid = g_settings_get_string (registry->priv->settings, key);
3089 source = e_source_registry_ref_source (registry, uid);
3092 /* The built-in source is always present. */
3094 source = e_source_registry_ref_builtin_task_list (registry);
3096 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3102 * e_source_registry_set_default_task_list:
3103 * @registry: an #ESourceRegistry
3104 * @default_source: (allow-none): a task list #ESource, or %NULL
3106 * Sets @default_source as the default task list. If @default_source
3107 * is %NULL, the default task list is reset to the built-in task list.
3108 * This setting will persist across sessions until changed.
3113 e_source_registry_set_default_task_list (ESourceRegistry *registry,
3114 ESource *default_source)
3119 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3121 if (default_source != NULL) {
3122 g_return_if_fail (E_IS_SOURCE (default_source));
3123 uid = e_source_get_uid (default_source);
3125 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3128 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3129 g_settings_set_string (registry->priv->settings, key, uid);
3131 /* The GSettings::changed signal will trigger a "notify" signal
3132 * from the registry, so no need to call g_object_notify() here. */
3136 * e_source_registry_ref_default_for_extension_name:
3137 * @registry: an #ESourceRegistry
3138 * @extension_name: an extension_name
3140 * This is a convenience function to return a default #ESource based on
3141 * @extension_name. This only works with a subset of extension names.
3143 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3144 * returns the current default address book, or else falls back to the
3145 * built-in address book.
3147 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function returns
3148 * the current default calendar, or else falls back to the built-in calendar.
3150 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3151 * returns the current default mail account, or else falls back to the
3152 * built-in mail account.
3154 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3155 * returns the current default mail identity, or else falls back to the
3156 * mail identity named by the current default mail account.
3158 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function returns
3159 * the current default memo list, or else falls back to the built-in memo list.
3161 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function returns
3162 * the current default task list, or else falls back to the built-in task list.
3164 * For all other values of @extension_name, the function returns %NULL.
3166 * The returned #ESource is referenced for thread-safety and must be
3167 * unreferenced with g_object_unref() when finished with it.
3169 * Returns: (transfer full): the default #ESource based on @extension_name
3174 e_source_registry_ref_default_for_extension_name (ESourceRegistry *registry,
3175 const gchar *extension_name)
3177 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3178 g_return_val_if_fail (extension_name != NULL, NULL);
3180 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3181 return e_source_registry_ref_default_address_book (registry);
3183 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3184 return e_source_registry_ref_default_calendar (registry);
3186 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3187 return e_source_registry_ref_default_mail_account (registry);
3189 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3190 return e_source_registry_ref_default_mail_identity (registry);
3192 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3193 return e_source_registry_ref_default_memo_list (registry);
3195 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3196 return e_source_registry_ref_default_task_list (registry);
3202 * e_source_registry_set_default_for_extension_name:
3203 * @registry: an #ESourceRegistry
3204 * @extension_name: an extension name
3205 * @default_source: (allow-none): an #ESource, or %NULL
3207 * This is a convenience function to set a default #ESource based on
3208 * @extension_name. This only works with a subset of extension names.
3210 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3211 * sets @default_source as the default address book. If @default_source
3212 * is %NULL, the default address book is reset to the built-in address book.
3214 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function sets
3215 * @default_source as the default calendar. If @default_source is %NULL,
3216 * the default calendar is reset to the built-in calendar.
3218 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3219 * sets @default_source as the default mail account. If @default_source
3220 * is %NULL, the default mail account is reset to the built-in mail account.
3222 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3223 * sets @default_source as the default mail identity. If @default_source
3224 * is %NULL, the next request for the default mail identity will return
3225 * the mail identity named by the default mail account.
3227 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function sets
3228 * @default_source as the default memo list. If @default_source is %NULL,
3229 * the default memo list is reset to the built-in memo list.
3231 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function sets
3232 * @default_source as the default task list. If @default_source is %NULL,
3233 * the default task list is reset to the built-in task list.
3235 * For all other values of @extension_name, the function does nothing.
3240 e_source_registry_set_default_for_extension_name (ESourceRegistry *registry,
3241 const gchar *extension_name,
3242 ESource *default_source)
3244 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3245 g_return_if_fail (extension_name != NULL);
3247 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3248 e_source_registry_set_default_address_book (
3249 registry, default_source);
3251 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3252 e_source_registry_set_default_calendar (
3253 registry, default_source);
3255 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3256 e_source_registry_set_default_mail_account (
3257 registry, default_source);
3259 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3260 e_source_registry_set_default_mail_identity (
3261 registry, default_source);
3263 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3264 e_source_registry_set_default_memo_list (
3265 registry, default_source);
3267 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3268 e_source_registry_set_default_task_list (
3269 registry, default_source);