4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
20 * SECTION: e-source-registry
21 * @include: libedataserver/libedataserver.h
22 * @short_description: A central repository for data sources
24 * The #ESourceRegistry is a global singleton store for all #ESource
25 * instances. It uses file monitors to react to key file creation and
26 * deletion events, either constructing an #ESource instance from the
27 * newly created key file, or removing from the logical #ESource
28 * hierarchy the instance corresponding to the deleted key file.
30 * The #ESourceRegistry can be queried for individual #ESource instances
31 * by their unique identifier string or key file path, for collections of
32 * #ESource instances having a particular extension, or for all available
35 * The #ESourceRegistry API also provides a front-end for the
36 * "org.gnome.Evolution.DefaultSources" #GSettings schema which tracks
37 * which #ESource instances are designated to be the user's default address
38 * book, calendar, memo list and task list for desktop integration.
41 #include "e-source-registry.h"
44 #include <glib/gstdio.h>
45 #include <glib/gi18n-lib.h>
47 /* XXX Yeah, yeah... */
48 #define GCR_API_SUBJECT_TO_CHANGE
50 #include <gcr/gcr-base.h>
52 /* Private D-Bus classes. */
53 #include <e-dbus-source.h>
54 #include <e-dbus-source-manager.h>
56 #include <libedataserver/e-marshal.h>
57 #include <libedataserver/e-data-server-util.h>
58 #include <libedataserver/e-source-collection.h>
60 /* Needed for the defaults API. */
61 #include <libedataserver/e-source-address-book.h>
62 #include <libedataserver/e-source-calendar.h>
63 #include <libedataserver/e-source-mail-account.h>
64 #include <libedataserver/e-source-mail-identity.h>
66 #include "e-dbus-authenticator.h"
68 #define E_SOURCE_REGISTRY_GET_PRIVATE(obj) \
69 (G_TYPE_INSTANCE_GET_PRIVATE \
70 ((obj), E_TYPE_SOURCE_REGISTRY, ESourceRegistryPrivate))
72 #define DBUS_OBJECT_PATH "/org/gnome/evolution/dataserver/SourceManager"
73 #define GSETTINGS_SCHEMA "org.gnome.Evolution.DefaultSources"
75 /* Built-in data source UIDs. */
76 #define E_SOURCE_BUILTIN_ADDRESS_BOOK_UID "system-address-book"
77 #define E_SOURCE_BUILTIN_CALENDAR_UID "system-calendar"
78 #define E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID "local"
79 #define E_SOURCE_BUILTIN_MEMO_LIST_UID "system-memo-list"
80 #define E_SOURCE_BUILTIN_TASK_LIST_UID "system-task-list"
82 /* GSettings keys for default data sources. */
83 #define E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY "default-address-book"
84 #define E_SETTINGS_DEFAULT_CALENDAR_KEY "default-calendar"
85 #define E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY "default-mail-account"
86 #define E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY "default-mail-identity"
87 #define E_SETTINGS_DEFAULT_MEMO_LIST_KEY "default-memo-list"
88 #define E_SETTINGS_DEFAULT_TASK_LIST_KEY "default-task-list"
90 /* This forces the GType to be registered in a way that
91 * avoids a "statement with no effect" compiler warning.
92 * FIXME Use g_type_ensure() once we require GLib 2.34. */
93 #define REGISTER_TYPE(type) \
94 (g_type_class_unref (g_type_class_ref (type)))
96 typedef struct _AsyncContext AsyncContext;
97 typedef struct _AuthContext AuthContext;
98 typedef struct _SourceClosure SourceClosure;
99 typedef struct _ThreadClosure ThreadClosure;
101 struct _ESourceRegistryPrivate {
102 GMainContext *main_context;
104 GThread *manager_thread;
105 ThreadClosure *thread_closure;
107 GDBusObjectManager *dbus_object_manager;
108 EDBusSourceManager *dbus_source_manager;
110 GHashTable *object_path_table;
111 GMutex *object_path_table_lock;
114 GMutex *sources_lock;
119 struct _AsyncContext {
121 GList *list_of_sources;
122 ESourceAuthenticator *auth;
125 /* Used in e_source_registry_authenticate_sync() */
126 struct _AuthContext {
127 ESourceAuthenticator *auth;
128 EDBusAuthenticator *dbus_auth;
129 GCancellable *cancellable;
130 GMainLoop *main_loop;
131 ESourceAuthenticationResult auth_result;
132 GcrSecretExchange *secret_exchange;
133 gboolean authenticating;
138 struct _SourceClosure {
139 ESourceRegistry *registry;
143 struct _ThreadClosure {
144 ESourceRegistry *registry;
145 GMainContext *main_context;
146 GMainLoop *main_loop;
147 GCond *main_loop_cond;
148 GMutex *main_loop_mutex;
154 PROP_DEFAULT_ADDRESS_BOOK,
155 PROP_DEFAULT_CALENDAR,
156 PROP_DEFAULT_MAIL_ACCOUNT,
157 PROP_DEFAULT_MAIL_IDENTITY,
158 PROP_DEFAULT_MEMO_LIST,
159 PROP_DEFAULT_TASK_LIST
171 /* Forward Declarations */
172 static void source_registry_add_source (ESourceRegistry *registry,
174 static void e_source_registry_initable_init (GInitableIface *interface);
176 static guint signals[LAST_SIGNAL];
178 /* By default, the GAsyncInitable interface calls GInitable.init()
179 * from a separate thread, so we only have to override GInitable. */
180 G_DEFINE_TYPE_WITH_CODE (
184 G_IMPLEMENT_INTERFACE (
185 G_TYPE_INITABLE, e_source_registry_initable_init)
186 G_IMPLEMENT_INTERFACE (
187 G_TYPE_ASYNC_INITABLE, NULL))
190 async_context_free (AsyncContext *async_context)
192 if (async_context->source != NULL)
193 g_object_unref (async_context->source);
196 async_context->list_of_sources,
197 (GDestroyNotify) g_object_unref);
199 if (async_context->auth != NULL)
200 g_object_unref (async_context->auth);
202 g_slice_free (AsyncContext, async_context);
206 auth_context_free (AuthContext *auth_context)
208 if (auth_context->auth != NULL)
209 g_object_unref (auth_context->auth);
211 if (auth_context->dbus_auth != NULL)
212 g_object_unref (auth_context->dbus_auth);
214 if (auth_context->cancellable != NULL)
215 g_object_unref (auth_context->cancellable);
217 if (auth_context->main_loop != NULL)
218 g_main_loop_unref (auth_context->main_loop);
220 if (auth_context->secret_exchange != NULL)
221 g_object_unref (auth_context->secret_exchange);
223 g_slice_free (AuthContext, auth_context);
227 source_closure_free (SourceClosure *closure)
229 g_object_unref (closure->registry);
230 g_object_unref (closure->source);
232 g_slice_free (SourceClosure, closure);
236 thread_closure_free (ThreadClosure *closure)
238 /* The registry member is not referenced. */
240 g_main_context_unref (closure->main_context);
241 g_main_loop_unref (closure->main_loop);
242 g_cond_free (closure->main_loop_cond);
243 g_mutex_free (closure->main_loop_mutex);
245 /* The GError should be NULL at this point,
246 * regardless of whether an error occurred. */
247 g_warn_if_fail (closure->error == NULL);
249 g_slice_free (ThreadClosure, closure);
253 source_registry_object_path_table_insert (ESourceRegistry *registry,
254 const gchar *object_path,
257 g_return_if_fail (object_path != NULL);
258 g_return_if_fail (E_IS_SOURCE (source));
260 g_mutex_lock (registry->priv->object_path_table_lock);
262 g_hash_table_insert (
263 registry->priv->object_path_table,
264 g_strdup (object_path),
265 g_object_ref (source));
267 g_mutex_unlock (registry->priv->object_path_table_lock);
271 source_registry_object_path_table_lookup (ESourceRegistry *registry,
272 const gchar *object_path)
276 g_return_val_if_fail (object_path != NULL, NULL);
278 g_mutex_lock (registry->priv->object_path_table_lock);
280 source = g_hash_table_lookup (
281 registry->priv->object_path_table, object_path);
283 g_object_ref (source);
285 g_mutex_unlock (registry->priv->object_path_table_lock);
291 source_registry_object_path_table_remove (ESourceRegistry *registry,
292 const gchar *object_path)
296 g_return_val_if_fail (object_path != NULL, FALSE);
298 g_mutex_lock (registry->priv->object_path_table_lock);
300 removed = g_hash_table_remove (
301 registry->priv->object_path_table, object_path);
303 g_mutex_unlock (registry->priv->object_path_table_lock);
309 source_registry_sources_insert (ESourceRegistry *registry,
314 uid = e_source_get_uid (source);
315 g_return_if_fail (uid != NULL);
317 g_mutex_lock (registry->priv->sources_lock);
319 g_hash_table_insert (
320 registry->priv->sources,
321 g_strdup (uid), g_object_ref (source));
323 g_mutex_unlock (registry->priv->sources_lock);
327 source_registry_sources_remove (ESourceRegistry *registry,
333 uid = e_source_get_uid (source);
334 g_return_val_if_fail (uid != NULL, FALSE);
336 g_mutex_lock (registry->priv->sources_lock);
338 removed = g_hash_table_remove (registry->priv->sources, uid);
340 g_mutex_unlock (registry->priv->sources_lock);
346 source_registry_sources_lookup (ESourceRegistry *registry,
351 g_return_val_if_fail (uid != NULL, NULL);
353 g_mutex_lock (registry->priv->sources_lock);
355 source = g_hash_table_lookup (registry->priv->sources, uid);
358 g_object_ref (source);
360 g_mutex_unlock (registry->priv->sources_lock);
366 source_registry_sources_get_values (ESourceRegistry *registry)
370 g_mutex_lock (registry->priv->sources_lock);
372 values = g_hash_table_get_values (registry->priv->sources);
374 g_list_foreach (values, (GFunc) g_object_ref, NULL);
376 g_mutex_unlock (registry->priv->sources_lock);
382 source_registry_sources_build_tree (ESourceRegistry *registry)
389 g_mutex_lock (registry->priv->sources_lock);
391 root = g_node_new (NULL);
392 index = g_hash_table_new (g_str_hash, g_str_equal);
394 /* Add a GNode for each ESource to the index. */
395 g_hash_table_iter_init (&iter, registry->priv->sources);
396 while (g_hash_table_iter_next (&iter, &key, &value)) {
397 ESource *source = g_object_ref (value);
398 g_hash_table_insert (index, key, g_node_new (source));
401 /* Traverse the index and link the nodes together. */
402 g_hash_table_iter_init (&iter, index);
403 while (g_hash_table_iter_next (&iter, NULL, &value)) {
407 const gchar *parent_uid;
409 source_node = (GNode *) value;
410 source = E_SOURCE (source_node->data);
411 parent_uid = e_source_get_parent (source);
413 if (parent_uid == NULL || *parent_uid == '\0') {
416 parent_node = g_hash_table_lookup (index, parent_uid);
417 g_warn_if_fail (parent_node != NULL);
420 /* Should never be NULL, but just to be safe. */
421 if (parent_node != NULL)
422 g_node_append (parent_node, source_node);
425 g_hash_table_destroy (index);
427 g_mutex_unlock (registry->priv->sources_lock);
433 source_registry_settings_changed_cb (GSettings *settings,
435 ESourceRegistry *registry)
437 /* We define a property name that matches every key in
438 * the "org.gnome.Evolution.DefaultSources" schema. */
439 g_object_notify (G_OBJECT (registry), key);
443 source_registry_source_changed_idle_cb (gpointer user_data)
445 SourceClosure *closure = user_data;
449 signals[SOURCE_CHANGED], 0,
456 source_registry_source_notify_enabled_idle_cb (gpointer user_data)
458 SourceClosure *closure = user_data;
460 if (e_source_get_enabled (closure->source))
463 signals[SOURCE_ENABLED], 0,
468 signals[SOURCE_DISABLED], 0,
475 source_registry_source_changed_cb (ESource *source,
476 ESourceRegistry *registry)
478 GSource *idle_source;
479 SourceClosure *closure;
481 closure = g_slice_new0 (SourceClosure);
482 closure->registry = g_object_ref (registry);
483 closure->source = g_object_ref (source);
485 idle_source = g_idle_source_new ();
486 g_source_set_callback (
488 source_registry_source_changed_idle_cb,
489 closure, (GDestroyNotify) source_closure_free);
490 g_source_attach (idle_source, registry->priv->main_context);
491 g_source_unref (idle_source);
495 source_registry_source_notify_enabled_cb (ESource *source,
497 ESourceRegistry *registry)
499 GSource *idle_source;
500 SourceClosure *closure;
502 closure = g_slice_new0 (SourceClosure);
503 closure->registry = g_object_ref (registry);
504 closure->source = g_object_ref (source);
506 idle_source = g_idle_source_new ();
507 g_source_set_callback (
509 source_registry_source_notify_enabled_idle_cb,
510 closure, (GDestroyNotify) source_closure_free);
511 g_source_attach (idle_source, registry->priv->main_context);
512 g_source_unref (idle_source);
516 source_registry_new_source (ESourceRegistry *registry,
517 GDBusObject *dbus_object)
519 GMainContext *main_context;
521 const gchar *object_path;
522 GError *error = NULL;
524 /* We don't want the ESource emitting "changed" signals from
525 * the manager thread, so we pass it the same main context the
526 * registry uses for scheduling signal emissions. */
527 main_context = registry->priv->main_context;
528 source = e_source_new (dbus_object, main_context, &error);
529 object_path = g_dbus_object_get_object_path (dbus_object);
531 /* The likelihood of an error here is slim, so it's
532 * sufficient to just print a warning if one occurs. */
534 g_warn_if_fail (source == NULL);
536 "ESourceRegistry: Failed to create a "
537 "data source object for path '%s': %s",
538 object_path, error->message);
539 g_error_free (error);
543 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
545 /* Add the ESource to the object path table immediately. */
546 source_registry_object_path_table_insert (
547 registry, object_path, source);
553 source_registry_unref_source (ESource *source)
555 g_signal_handlers_disconnect_matched (
556 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
557 source_registry_source_changed_cb, NULL);
559 g_signal_handlers_disconnect_matched (
560 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
561 source_registry_source_notify_enabled_cb, NULL);
563 g_object_unref (source);
567 source_registry_add_source (ESourceRegistry *registry,
572 uid = e_source_get_uid (source);
573 g_return_if_fail (uid != NULL);
575 g_mutex_lock (registry->priv->sources_lock);
577 /* Check if we already have this source in the registry. */
578 if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
579 g_mutex_unlock (registry->priv->sources_lock);
585 G_CALLBACK (source_registry_source_changed_cb),
589 source, "notify::enabled",
590 G_CALLBACK (source_registry_source_notify_enabled_cb),
593 g_mutex_unlock (registry->priv->sources_lock);
595 source_registry_sources_insert (registry, source);
597 g_signal_emit (registry, signals[SOURCE_ADDED], 0, source);
601 source_registry_remove_source (ESourceRegistry *registry,
604 g_object_ref (source);
606 if (source_registry_sources_remove (registry, source))
607 g_signal_emit (registry, signals[SOURCE_REMOVED], 0, source);
609 g_object_unref (source);
613 source_registry_object_added_idle_cb (gpointer user_data)
615 SourceClosure *closure = user_data;
617 source_registry_add_source (closure->registry, closure->source);
623 source_registry_object_added_cb (GDBusObjectManager *object_manager,
624 GDBusObject *dbus_object,
625 ESourceRegistry *registry)
627 SourceClosure *closure;
628 GSource *idle_source;
631 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
633 source = source_registry_new_source (registry, dbus_object);
634 g_return_if_fail (source != NULL);
636 /* Schedule a callback on the ESourceRegistry's GMainContext. */
638 closure = g_slice_new0 (SourceClosure);
639 closure->registry = g_object_ref (registry);
640 closure->source = g_object_ref (source);
642 idle_source = g_idle_source_new ();
643 g_source_set_callback (
645 source_registry_object_added_idle_cb,
646 closure, (GDestroyNotify) source_closure_free);
647 g_source_attach (idle_source, registry->priv->main_context);
648 g_source_unref (idle_source);
650 g_object_unref (source);
654 source_registry_object_removed_idle_cb (gpointer user_data)
656 SourceClosure *closure = user_data;
658 source_registry_remove_source (closure->registry, closure->source);
664 source_registry_object_removed_cb (GDBusObjectManager *manager,
665 GDBusObject *dbus_object,
666 ESourceRegistry *registry)
668 SourceClosure *closure;
669 GSource *idle_source;
671 const gchar *object_path;
673 /* Find the corresponding ESource in the object path table.
674 * Note that the lookup returns a new ESource reference. */
675 object_path = g_dbus_object_get_object_path (dbus_object);
676 source = source_registry_object_path_table_lookup (
677 registry, object_path);
678 g_return_if_fail (E_IS_SOURCE (source));
680 /* Remove the ESource from the object path table immediately. */
681 source_registry_object_path_table_remove (registry, object_path);
683 /* Schedule a callback on the ESourceRegistry's GMainContext. */
685 closure = g_slice_new0 (SourceClosure);
686 closure->registry = g_object_ref (registry);
687 closure->source = g_object_ref (source);
689 idle_source = g_idle_source_new ();
690 g_source_set_callback (
692 source_registry_object_removed_idle_cb,
693 closure, (GDestroyNotify) source_closure_free);
694 g_source_attach (idle_source, registry->priv->main_context);
695 g_source_unref (idle_source);
697 g_object_unref (source);
701 source_registry_object_manager_running (gpointer data)
703 ThreadClosure *closure = data;
705 g_mutex_lock (closure->main_loop_mutex);
706 g_cond_broadcast (closure->main_loop_cond);
707 g_mutex_unlock (closure->main_loop_mutex);
713 source_registry_object_manager_thread (gpointer data)
715 GDBusObjectManager *object_manager;
716 ThreadClosure *closure = data;
717 GSource *idle_source;
719 gulong object_added_id = 0;
720 gulong object_removed_id = 0;
722 /* GDBusObjectManagerClient grabs the thread-default GMainContext
723 * at creation time and only emits signals from that GMainContext.
724 * Running it in a separate thread prevents its signal emissions
725 * from being inhibited by someone overriding the thread-default
728 /* This becomes the GMainContext that GDBusObjectManagerClient
729 * will emit signals from. Make it the thread-default context
730 * for this thread before creating the client. */
731 g_main_context_push_thread_default (closure->main_context);
733 object_manager = e_dbus_object_manager_client_new_for_bus_sync (
735 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
736 SOURCES_DBUS_SERVICE_NAME,
738 NULL, &closure->error);
742 ((object_manager != NULL) && (closure->error == NULL)) ||
743 ((object_manager == NULL) && (closure->error != NULL)));
745 /* If we failed to create the GDBusObjectManagerClient, skip
746 * straight to the main loop. The GError will be propagated
747 * back to the caller, the main loop will terminate, and the
748 * partially-initialized ESourceRegistry will be destroyed. */
749 if (object_manager == NULL)
752 /* Give the registry a handle to the object manager. */
753 closure->registry->priv->dbus_object_manager =
754 g_object_ref (object_manager);
756 /* Now populate the registry with an initial set of ESources. */
758 list = g_dbus_object_manager_get_objects (object_manager);
760 for (link = list; link != NULL; link = g_list_next (link)) {
761 GDBusObject *dbus_object;
764 dbus_object = G_DBUS_OBJECT (link->data);
766 source = source_registry_new_source (
767 closure->registry, dbus_object);
769 if (source != NULL) {
770 source_registry_add_source (
771 closure->registry, source);
772 g_object_unref (source);
776 g_list_free_full (list, (GDestroyNotify) g_object_unref);
778 /* Listen for D-Bus object additions and removals. */
780 object_added_id = g_signal_connect (
781 object_manager, "object-added",
782 G_CALLBACK (source_registry_object_added_cb),
785 object_removed_id = g_signal_connect (
786 object_manager, "object-removed",
787 G_CALLBACK (source_registry_object_removed_cb),
791 /* Schedule a one-time idle callback to broadcast through a
792 * condition variable that our main loop is up and running. */
794 idle_source = g_idle_source_new ();
795 g_source_set_callback (
797 source_registry_object_manager_running,
798 closure, (GDestroyNotify) NULL);
799 g_source_attach (idle_source, closure->main_context);
800 g_source_unref (idle_source);
802 /* Now we mostly idle here for the rest of the session. */
804 g_main_loop_run (closure->main_loop);
806 /* Clean up and exit. */
808 if (object_manager != NULL) {
809 g_signal_handler_disconnect (object_manager, object_added_id);
810 g_signal_handler_disconnect (object_manager, object_removed_id);
811 g_object_unref (object_manager);
814 g_main_context_pop_thread_default (closure->main_context);
820 source_registry_set_property (GObject *object,
825 switch (property_id) {
826 case PROP_DEFAULT_ADDRESS_BOOK:
827 e_source_registry_set_default_address_book (
828 E_SOURCE_REGISTRY (object),
829 g_value_get_object (value));
832 case PROP_DEFAULT_CALENDAR:
833 e_source_registry_set_default_calendar (
834 E_SOURCE_REGISTRY (object),
835 g_value_get_object (value));
838 case PROP_DEFAULT_MAIL_ACCOUNT:
839 e_source_registry_set_default_mail_account (
840 E_SOURCE_REGISTRY (object),
841 g_value_get_object (value));
844 case PROP_DEFAULT_MAIL_IDENTITY:
845 e_source_registry_set_default_mail_identity (
846 E_SOURCE_REGISTRY (object),
847 g_value_get_object (value));
850 case PROP_DEFAULT_MEMO_LIST:
851 e_source_registry_set_default_memo_list (
852 E_SOURCE_REGISTRY (object),
853 g_value_get_object (value));
856 case PROP_DEFAULT_TASK_LIST:
857 e_source_registry_set_default_task_list (
858 E_SOURCE_REGISTRY (object),
859 g_value_get_object (value));
863 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
867 source_registry_get_property (GObject *object,
872 switch (property_id) {
873 case PROP_DEFAULT_ADDRESS_BOOK:
874 g_value_take_object (
876 e_source_registry_ref_default_address_book (
877 E_SOURCE_REGISTRY (object)));
880 case PROP_DEFAULT_CALENDAR:
881 g_value_take_object (
883 e_source_registry_ref_default_calendar (
884 E_SOURCE_REGISTRY (object)));
887 case PROP_DEFAULT_MAIL_ACCOUNT:
888 g_value_take_object (
890 e_source_registry_ref_default_mail_account (
891 E_SOURCE_REGISTRY (object)));
894 case PROP_DEFAULT_MAIL_IDENTITY:
895 g_value_take_object (
897 e_source_registry_ref_default_mail_identity (
898 E_SOURCE_REGISTRY (object)));
901 case PROP_DEFAULT_MEMO_LIST:
902 g_value_take_object (
904 e_source_registry_ref_default_memo_list (
905 E_SOURCE_REGISTRY (object)));
908 case PROP_DEFAULT_TASK_LIST:
909 g_value_take_object (
911 e_source_registry_ref_default_task_list (
912 E_SOURCE_REGISTRY (object)));
916 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
920 source_registry_dispose (GObject *object)
922 ESourceRegistryPrivate *priv;
924 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
926 /* Terminate the manager thread first. */
927 if (priv->manager_thread != NULL) {
928 g_main_loop_quit (priv->thread_closure->main_loop);
929 g_thread_join (priv->manager_thread);
930 thread_closure_free (priv->thread_closure);
931 priv->manager_thread = NULL;
932 priv->thread_closure = NULL;
935 if (priv->main_context != NULL) {
936 g_main_context_unref (priv->main_context);
937 priv->main_context = NULL;
940 if (priv->dbus_object_manager != NULL) {
941 g_object_unref (priv->dbus_object_manager);
942 priv->dbus_object_manager = NULL;
945 if (priv->dbus_source_manager != NULL) {
946 g_object_unref (priv->dbus_source_manager);
947 priv->dbus_source_manager = NULL;
950 g_hash_table_remove_all (priv->object_path_table);
952 g_hash_table_remove_all (priv->sources);
954 if (priv->settings != NULL) {
955 g_object_unref (priv->settings);
956 priv->settings = NULL;
959 /* Chain up to parent's finalize() method. */
960 G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
964 source_registry_finalize (GObject *object)
966 ESourceRegistryPrivate *priv;
968 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
970 g_hash_table_destroy (priv->object_path_table);
971 g_mutex_free (priv->object_path_table_lock);
973 g_hash_table_destroy (priv->sources);
974 g_mutex_free (priv->sources_lock);
976 /* Chain up to parent's finalize() method. */
977 G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
981 source_registry_initable_init (GInitable *initable,
982 GCancellable *cancellable,
985 ESourceRegistry *registry;
986 ThreadClosure *closure;
988 registry = E_SOURCE_REGISTRY (initable);
990 closure = g_slice_new0 (ThreadClosure);
991 closure->registry = registry; /* do not reference */
992 closure->main_context = g_main_context_new ();
993 /* It's important to pass 'is_running=FALSE' here because
994 * we wait for the main loop to start running as a way of
995 * synchronizing with the manager thread. */
996 closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
997 closure->main_loop_cond = g_cond_new ();
998 closure->main_loop_mutex = g_mutex_new ();
1000 registry->priv->thread_closure = closure;
1002 registry->priv->manager_thread = g_thread_create (
1003 source_registry_object_manager_thread,
1004 closure, TRUE /* joinable */, error);
1006 if (registry->priv->manager_thread == NULL)
1009 /* Wait for notification that the manager
1010 * thread's main loop has been started. */
1011 g_mutex_lock (closure->main_loop_mutex);
1012 while (!g_main_loop_is_running (closure->main_loop))
1014 closure->main_loop_cond,
1015 closure->main_loop_mutex);
1016 g_mutex_unlock (closure->main_loop_mutex);
1018 /* Check for error in the manager thread. */
1019 if (closure->error != NULL) {
1020 g_propagate_error (error, closure->error);
1021 closure->error = NULL;
1025 /* The registry should now be populated with sources. */
1026 g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);
1028 /* The EDBusSourceManagerProxy is just another D-Bus interface
1029 * that resides at the same object path. It's unrelated to the
1030 * GDBusObjectManagerClient and doesn't need its own thread. */
1031 registry->priv->dbus_source_manager =
1032 e_dbus_source_manager_proxy_new_for_bus_sync (
1034 G_DBUS_PROXY_FLAGS_NONE,
1035 SOURCES_DBUS_SERVICE_NAME,
1037 cancellable, error);
1039 if (registry->priv->dbus_source_manager == NULL)
1046 e_source_registry_class_init (ESourceRegistryClass *class)
1048 GObjectClass *object_class;
1050 g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
1052 object_class = G_OBJECT_CLASS (class);
1053 object_class->set_property = source_registry_set_property;
1054 object_class->get_property = source_registry_get_property;
1055 object_class->dispose = source_registry_dispose;
1056 object_class->finalize = source_registry_finalize;
1058 /* The property names correspond to the key names in the
1059 * "org.gnome.Evolution.DefaultSources" GSettings schema. */
1062 * ESourceRegistry:default-address-book:
1064 * The default address book #ESource.
1066 g_object_class_install_property (
1068 PROP_DEFAULT_ADDRESS_BOOK,
1069 g_param_spec_object (
1070 "default-address-book",
1071 "Default Address Book",
1072 "The default address book ESource",
1075 G_PARAM_STATIC_STRINGS));
1078 * ESourceRegistry:default-calendar:
1080 * The default calendar #ESource.
1082 g_object_class_install_property (
1084 PROP_DEFAULT_CALENDAR,
1085 g_param_spec_object (
1088 "The default calendar ESource",
1091 G_PARAM_STATIC_STRINGS));
1094 * ESourceRegistry:default-mail-account:
1096 * The default mail account #ESource.
1098 g_object_class_install_property (
1100 PROP_DEFAULT_MAIL_ACCOUNT,
1101 g_param_spec_object (
1102 "default-mail-account",
1103 "Default Mail Account",
1104 "The default mail account ESource",
1107 G_PARAM_STATIC_STRINGS));
1110 * ESourceRegistry:default-mail-identity:
1112 * The default mail identity #ESource.
1114 g_object_class_install_property (
1116 PROP_DEFAULT_MAIL_IDENTITY,
1117 g_param_spec_object (
1118 "default-mail-identity",
1119 "Default Mail Identity",
1120 "The default mail identity ESource",
1123 G_PARAM_STATIC_STRINGS));
1126 * ESourceRegistry:default-memo-list:
1128 * The default memo list #ESource.
1130 g_object_class_install_property (
1132 PROP_DEFAULT_MEMO_LIST,
1133 g_param_spec_object (
1134 "default-memo-list",
1135 "Default Memo List",
1136 "The default memo list ESource",
1139 G_PARAM_STATIC_STRINGS));
1142 * ESourceRegistry:default-task-list:
1144 * The default task list #ESource.
1146 g_object_class_install_property (
1148 PROP_DEFAULT_TASK_LIST,
1149 g_param_spec_object (
1150 "default-task-list",
1151 "Default Task List",
1152 "The default task list ESource",
1155 G_PARAM_STATIC_STRINGS));
1158 * ESourceRegistry::source-added:
1159 * @registry: the #ESourceRegistry which emitted the signal
1160 * @source: the newly-added #ESource
1162 * Emitted when an #ESource is added to @registry.
1164 signals[SOURCE_ADDED] = g_signal_new (
1166 G_OBJECT_CLASS_TYPE (object_class),
1168 G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
1170 g_cclosure_marshal_VOID__OBJECT,
1175 * ESourceRegistry::source-changed:
1176 * @registry: the #ESourceRegistry which emitted the signal
1177 * @source: the #ESource that changed
1179 * Emitted when an #ESource registered with @registry emits
1180 * its #ESource::changed signal.
1182 signals[SOURCE_CHANGED] = g_signal_new (
1184 G_OBJECT_CLASS_TYPE (object_class),
1186 G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
1188 g_cclosure_marshal_VOID__OBJECT,
1193 * ESourceRegistry::source-removed:
1194 * @registry: the #ESourceRegistry which emitted the signal
1195 * @source: the #ESource that got removed
1197 * Emitted when an #ESource is removed from @registry.
1199 signals[SOURCE_REMOVED] = g_signal_new (
1201 G_OBJECT_CLASS_TYPE (object_class),
1203 G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
1205 g_cclosure_marshal_VOID__OBJECT,
1210 * ESourceRegistry::source-enabled:
1211 * @registry: the #ESourceRegistry which emitted the signal
1212 * @source: the #ESource that got enabled
1214 * Emitted when an #ESource #ESource:enabled property becomes %TRUE.
1216 signals[SOURCE_ENABLED] = g_signal_new (
1218 G_OBJECT_CLASS_TYPE (object_class),
1220 G_STRUCT_OFFSET (ESourceRegistryClass, source_enabled),
1222 g_cclosure_marshal_VOID__OBJECT,
1227 * ESourceRegistry::source-disabled:
1228 * @registry: the #ESourceRegistry which emitted the signal
1229 * @source: the #ESource that got disabled
1231 * Emitted when an #ESource #ESource:enabled property becomes %FALSE.
1233 signals[SOURCE_DISABLED] = g_signal_new (
1235 G_OBJECT_CLASS_TYPE (object_class),
1237 G_STRUCT_OFFSET (ESourceRegistryClass, source_disabled),
1239 g_cclosure_marshal_VOID__OBJECT,
1245 e_source_registry_initable_init (GInitableIface *interface)
1247 interface->init = source_registry_initable_init;
1251 e_source_registry_init (ESourceRegistry *registry)
1253 registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
1255 /* This is so the object manager thread can schedule signal
1256 * emissions on the thread-default context for this thread. */
1257 registry->priv->main_context = g_main_context_ref_thread_default ();
1259 /* D-Bus object path -> ESource */
1260 registry->priv->object_path_table =
1261 g_hash_table_new_full (
1262 (GHashFunc) g_str_hash,
1263 (GEqualFunc) g_str_equal,
1264 (GDestroyNotify) g_free,
1265 (GDestroyNotify) g_object_unref);
1267 registry->priv->object_path_table_lock = g_mutex_new ();
1269 /* UID string -> ESource */
1270 registry->priv->sources = g_hash_table_new_full (
1271 (GHashFunc) g_str_hash,
1272 (GEqualFunc) g_str_equal,
1273 (GDestroyNotify) g_free,
1274 (GDestroyNotify) source_registry_unref_source);
1276 registry->priv->sources_lock = g_mutex_new ();
1278 registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
1281 registry->priv->settings, "changed",
1282 G_CALLBACK (source_registry_settings_changed_cb), registry);
1286 * e_source_registry_new_sync:
1287 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1288 * @error: return location for a #GError, or %NULL
1290 * Creates a new #ESourceRegistry front-end for the registry D-Bus service.
1291 * If an error occurs in connecting to the D-Bus service, the function sets
1292 * @error and returns %NULL.
1294 * Returns: a new #ESourceRegistry, or %NULL
1299 e_source_registry_new_sync (GCancellable *cancellable,
1302 /* XXX Work around http://bugzilla.gnome.org/show_bug.cgi?id=683519
1303 * until GObject's type initialization deadlock issue is fixed.
1304 * Apparently only the synchronous instantiation is affected. */
1305 REGISTER_TYPE (G_TYPE_DBUS_CONNECTION);
1307 return g_initable_new (
1308 E_TYPE_SOURCE_REGISTRY,
1309 cancellable, error, NULL);
1313 * e_source_registry_new:
1314 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1315 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1317 * @user_data: (closure): data to pass to the callback function
1319 * Asynchronously creates a new #ESourceRegistry front-end for the registry
1322 * When the operation is finished, @callback will be called. You can then
1323 * call e_source_registry_new_finish() to get the result of the operation.
1328 e_source_registry_new (GCancellable *cancellable,
1329 GAsyncReadyCallback callback,
1332 g_async_initable_new_async (
1333 E_TYPE_SOURCE_REGISTRY,
1334 G_PRIORITY_DEFAULT, cancellable,
1335 callback, user_data, NULL);
1339 * e_source_registry_new_finish:
1340 * @result: a #GAsyncResult
1341 * @error: return location for a #GError, or %NULL
1343 * Finishes the operation started with e_source_registry_new_finish().
1344 * If an error occurs in connecting to the D-Bus service, the function
1345 * sets @error and returns %NULL.
1347 * Returns: a new #ESourceRegistry, or %NULL
1352 e_source_registry_new_finish (GAsyncResult *result,
1355 GObject *source_object;
1358 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1360 source_object = g_async_result_get_source_object (result);
1361 g_return_val_if_fail (source_object != NULL, NULL);
1363 object = g_async_initable_new_finish (
1364 G_ASYNC_INITABLE (source_object), result, error);
1366 g_object_unref (source_object);
1368 return (object != NULL) ? E_SOURCE_REGISTRY (object) : NULL;
1371 /* Helper for e_source_registry_authenticate() */
1373 source_registry_authenticate_thread (GSimpleAsyncResult *simple,
1375 GCancellable *cancellable)
1377 AsyncContext *async_context;
1378 GError *error = NULL;
1380 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1382 e_source_registry_authenticate_sync (
1383 E_SOURCE_REGISTRY (object),
1384 async_context->source,
1385 async_context->auth,
1386 cancellable, &error);
1389 g_simple_async_result_take_error (simple, error);
1392 /* Helper for e_source_registry_authenticate_sync() */
1394 source_registry_authenticate_respond_cb (AuthContext *auth_context)
1396 ESourceAuthenticationResult auth_result;
1397 GError *non_fatal_error = NULL;
1399 g_return_val_if_fail (auth_context->authenticating, FALSE);
1401 auth_result = auth_context->auth_result;
1403 /* Allow the next authentication attempt to proceed. */
1404 auth_context->authenticating = FALSE;
1406 /* Send the server a status update based on the authentication
1407 * result. Note, we don't really care if the D-Bus message gets
1408 * through to the server at this point. If it doesn't, the auth
1409 * session will either time out on its own or the authentication
1410 * dialog will eventually be dismissed by the user. */
1412 /* If we were cancelled from our side, we have a bit of a dilemma.
1413 * We need to tell the server to cancel the authentication session,
1414 * but that involves making a synchronous D-Bus call, which we are
1415 * not supposed to do if we know we've been cancelled. But if we
1416 * don't tell the server, the authentication session will be left
1417 * to timeout on its own (which may take minutes), and meanwhile
1418 * all other authentication requests are blocked. So choose the
1419 * lesser evil and make the synchronous call but without passing
1420 * the already-cancelled GCancellable. */
1421 if (g_cancellable_is_cancelled (auth_context->cancellable)) {
1422 e_dbus_authenticator_call_cancel_sync (
1423 auth_context->dbus_auth,
1424 NULL, &non_fatal_error);
1425 g_main_loop_quit (auth_context->main_loop);
1426 auth_context->success = FALSE;
1428 /* If an error occurred while attempting to authenticate,
1429 * tell the server to cancel the authentication session. */
1430 } else if (auth_result == E_SOURCE_AUTHENTICATION_ERROR) {
1431 e_dbus_authenticator_call_cancel_sync (
1432 auth_context->dbus_auth,
1433 auth_context->cancellable,
1435 g_main_loop_quit (auth_context->main_loop);
1436 auth_context->success = FALSE;
1438 /* If the password was accepted, let the server know so it
1439 * can close any authentication dialogs and save the user
1440 * provided password to the keyring. */
1441 } else if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
1442 e_dbus_authenticator_call_accepted_sync (
1443 auth_context->dbus_auth,
1444 auth_context->cancellable,
1446 g_main_loop_quit (auth_context->main_loop);
1447 auth_context->success = TRUE;
1449 /* If the password was rejected, let the server know so it can
1450 * indicate failure and request a different password, and then
1451 * wait for the next "response" signal. */
1453 e_dbus_authenticator_call_rejected_sync (
1454 auth_context->dbus_auth,
1455 auth_context->cancellable,
1459 /* Leave breadcrumbs if something went wrong,
1460 * but don't fail the whole operation over it. */
1461 if (non_fatal_error != NULL) {
1462 g_warning ("%s: %s", G_STRFUNC, non_fatal_error->message);
1463 g_error_free (non_fatal_error);
1469 /* Helper for e_source_registry_authenticate_sync() */
1471 source_registry_authenticate_authenticate_cb (EDBusAuthenticator *dbus_auth,
1472 const gchar *encrypted_secret,
1473 AuthContext *auth_context)
1475 GSource *idle_source;
1476 GMainContext *main_context;
1478 gboolean valid_secret;
1480 /* We should only get one secret at a time. */
1481 g_return_if_fail (!auth_context->authenticating);
1483 valid_secret = gcr_secret_exchange_receive (
1484 auth_context->secret_exchange, encrypted_secret);
1485 g_return_if_fail (valid_secret);
1487 auth_context->authenticating = TRUE;
1489 /* This avoids revealing the password in a stack trace. */
1490 password = g_string_new (
1491 gcr_secret_exchange_get_secret (
1492 auth_context->secret_exchange, NULL));
1494 /* Try authenticating with the given password. We have to
1495 * call this synchronously because some authenticators use
1496 * mutexes to serialize I/O operations and are not prepared
1497 * to make authentication attempts from a different thread.
1499 * Unfortunately this means we won't notice server-side
1500 * dismissals while the main loop is blocked. We respond
1501 * to the server from a low-priority idle callback so that
1502 * any pending "dismissed" signals get handled first. */
1504 auth_context->auth_result =
1505 e_source_authenticator_try_password_sync (
1506 auth_context->auth, password,
1507 auth_context->cancellable,
1508 auth_context->error);
1510 idle_source = g_idle_source_new ();
1511 main_context = g_main_context_get_thread_default ();
1512 g_source_set_callback (
1513 idle_source, (GSourceFunc)
1514 source_registry_authenticate_respond_cb,
1515 auth_context, NULL);
1516 g_source_attach (idle_source, main_context);
1517 g_source_unref (idle_source);
1519 g_string_free (password, TRUE);
1522 /* Helper for e_source_registry_authenticate_sync() */
1524 source_registry_authenticate_dismissed_cb (EDBusAuthenticator *dbus_auth,
1525 AuthContext *auth_context)
1527 /* Be careful not to overwrite an existing error in case this
1528 * is called after e_source_authenticator_try_password_sync()
1529 * but prior to the idle callback. */
1530 if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
1531 /* XXX Use a separate error code for dismissals? */
1532 g_set_error_literal (
1533 auth_context->error,
1534 G_IO_ERROR, G_IO_ERROR_CANCELLED,
1535 _("The user declined to authenticate"));
1536 auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
1539 g_main_loop_quit (auth_context->main_loop);
1540 auth_context->success = FALSE;
1543 /* Helper for e_source_registry_authenticate_sync() */
1545 source_registry_call_authenticate_for_source (ESourceRegistry *registry,
1546 ESourceAuthenticator *auth,
1548 gchar **out_object_path,
1549 GCancellable *cancellable,
1552 ESource *collection;
1554 gchar *prompt_title = NULL;
1555 gchar *prompt_message = NULL;
1556 gchar *prompt_description = NULL;
1559 /* If the source is a member of a collection, we want to store
1560 * the password under the UID of the "collection" source so it
1561 * will apply to the entire collection.
1563 * XXX This assumes all sources in a collection share a single
1564 * password. If that turns out not to be true in all cases
1565 * we could maybe add a "SharedPassword: true/false" key to
1566 * [Collection] and apply it here.
1568 collection = e_source_registry_find_extension (
1569 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1570 if (collection != NULL)
1571 source = collection;
1573 g_object_ref (source);
1575 uid = e_source_get_uid (source);
1577 e_source_authenticator_get_prompt_strings (
1581 &prompt_description);
1583 success = e_dbus_source_manager_call_authenticate_sync (
1584 registry->priv->dbus_source_manager, uid,
1585 prompt_title, prompt_message, prompt_description,
1586 out_object_path, cancellable, error);
1588 g_free (prompt_title);
1589 g_free (prompt_message);
1590 g_free (prompt_description);
1592 g_object_unref (source);
1598 * e_source_registry_authenticate_sync:
1599 * @registry: an #ESourceRegistry
1600 * @source: an #ESource
1601 * @auth: an #ESourceAuthenticator
1602 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1603 * @error: return location for a #GError, or %NULL
1605 * Authenticates @source, using @auth to handle the authentication
1606 * attempts. The operation loops until authentication is successful or
1607 * the user aborts further authentication attempts. If an error occurs,
1608 * the function will set @error and return %FALSE.
1610 * Note that @source need not have a #GDBusObject, which means this
1611 * function can test authentication on a scratch #ESource.
1613 * Only backend implementations and data source editors should call this
1614 * function. The intent is for basic client applications to not have to
1615 * deal with authentication at all.
1617 * Returns: %TRUE on success, %FALSE on failure
1622 e_source_registry_authenticate_sync (ESourceRegistry *registry,
1624 ESourceAuthenticator *auth,
1625 GCancellable *cancellable,
1628 AuthContext *auth_context;
1629 GMainContext *main_context;
1630 EDBusAuthenticator *dbus_auth;
1631 gchar *encryption_key;
1632 gchar *object_path = NULL;
1635 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1636 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1637 g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth), FALSE);
1639 /* This extracts authentication prompt details for the ESource
1640 * before initiating an authentication session with the server,
1641 * so split it out of the main algorithm for clarity's sake. */
1642 success = source_registry_call_authenticate_for_source (
1643 registry, auth, source, &object_path, cancellable, error);
1646 g_warn_if_fail (object_path == NULL);
1650 g_return_val_if_fail (object_path != NULL, FALSE);
1652 main_context = g_main_context_new ();
1653 g_main_context_push_thread_default (main_context);
1655 dbus_auth = e_dbus_authenticator_proxy_new_for_bus_sync (
1657 G_DBUS_PROXY_FLAGS_NONE,
1658 SOURCES_DBUS_SERVICE_NAME,
1659 object_path, cancellable, error);
1661 g_free (object_path);
1663 if (dbus_auth == NULL) {
1668 auth_context = g_slice_new0 (AuthContext);
1669 auth_context->auth = g_object_ref (auth);
1670 auth_context->dbus_auth = dbus_auth; /* takes ownership */
1671 auth_context->main_loop = g_main_loop_new (main_context, FALSE);
1672 auth_context->error = error;
1674 /* This just needs to be something other than
1675 * E_SOURCE_AUTHENTICATION_ERROR so we don't trip
1676 * up source_registry_authenticate_dismissed_cb(). */
1677 auth_context->auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
1679 if (G_IS_CANCELLABLE (cancellable))
1680 auth_context->cancellable = g_object_ref (cancellable);
1682 auth_context->secret_exchange =
1683 gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1);
1686 dbus_auth, "authenticate",
1687 G_CALLBACK (source_registry_authenticate_authenticate_cb),
1691 dbus_auth, "dismissed",
1692 G_CALLBACK (source_registry_authenticate_dismissed_cb),
1695 encryption_key = gcr_secret_exchange_begin (
1696 auth_context->secret_exchange);
1698 /* Signal the D-Bus server that we're ready to begin the
1699 * authentication session. This must happen AFTER we've
1700 * connected to the response signal since the server may
1701 * already have a response ready and waiting for us. */
1702 success = e_dbus_authenticator_call_ready_sync (
1703 dbus_auth, encryption_key, cancellable, error);
1705 g_free (encryption_key);
1708 g_main_loop_run (auth_context->main_loop);
1709 success = auth_context->success;
1712 auth_context_free (auth_context);
1715 g_main_context_pop_thread_default (main_context);
1716 g_main_context_unref (main_context);
1722 * e_source_registry_authenticate:
1723 * @registry: an #ESourceRegistry
1724 * @source: an #ESource
1725 * @auth: an #ESourceAuthenticator
1726 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1727 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1729 * @user_data: (closure): data to pass to the callback function
1731 * Asynchronously authenticates @source, using @auth to handle the
1732 * authentication attempts. The operation loops until authentication
1733 * is successful or the user aborts further authentication attempts.
1735 * Note that @source need not have a #GDBusObject, which means this
1736 * function can test authentication on a scratch #ESource.
1738 * When the operation is finished, @callback will be called. You can then
1739 * call e_source_registry_authenticate_finish() to get the result of the
1742 * Only backend implementations and data source editors should call this
1743 * function. The intent is for basic client applications to not have to
1744 * deal with authentication at all.
1749 e_source_registry_authenticate (ESourceRegistry *registry,
1751 ESourceAuthenticator *auth,
1752 GCancellable *cancellable,
1753 GAsyncReadyCallback callback,
1756 GSimpleAsyncResult *simple;
1757 AsyncContext *async_context;
1759 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1760 g_return_if_fail (E_IS_SOURCE (source));
1761 g_return_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth));
1763 async_context = g_slice_new0 (AsyncContext);
1764 async_context->source = g_object_ref (source);
1765 async_context->auth = g_object_ref (auth);
1767 simple = g_simple_async_result_new (
1768 G_OBJECT (registry), callback, user_data,
1769 e_source_registry_authenticate);
1771 g_simple_async_result_set_check_cancellable (simple, cancellable);
1773 g_simple_async_result_set_op_res_gpointer (
1774 simple, async_context, (GDestroyNotify) async_context_free);
1776 g_simple_async_result_run_in_thread (
1777 simple, source_registry_authenticate_thread,
1778 G_PRIORITY_DEFAULT, cancellable);
1780 g_object_unref (simple);
1784 * e_source_registry_authenticate_finish:
1785 * @registry: an #ESourceRegistry
1786 * @result: a #GAsyncResult
1787 * @error: return location for a #GError, or %NULL
1789 * Finishes the operation started with e_source_registry_authenticate().
1790 * If an error occurred, the function will set @error and return %FALSE.
1792 * Returns: %TRUE on success, %FALSE on failure
1797 e_source_registry_authenticate_finish (ESourceRegistry *registry,
1798 GAsyncResult *result,
1801 GSimpleAsyncResult *simple;
1803 g_return_val_if_fail (
1804 g_simple_async_result_is_valid (
1805 result, G_OBJECT (registry),
1806 e_source_registry_authenticate), FALSE);
1808 simple = G_SIMPLE_ASYNC_RESULT (result);
1810 /* Assume success unless a GError is set. */
1811 return !g_simple_async_result_propagate_error (simple, error);
1814 /* Helper for e_source_registry_commit_source() */
1816 source_registry_commit_source_thread (GSimpleAsyncResult *simple,
1818 GCancellable *cancellable)
1820 AsyncContext *async_context;
1821 GError *error = NULL;
1823 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1825 e_source_registry_commit_source_sync (
1826 E_SOURCE_REGISTRY (object),
1827 async_context->source,
1828 cancellable, &error);
1831 g_simple_async_result_take_error (simple, error);
1835 * e_source_registry_commit_source_sync:
1836 * @registry: an #ESourceRegistry
1837 * @source: an #ESource with changes to commit
1838 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1839 * @error: return location for #GError, or %NULL
1841 * This is a convenience function intended for use with graphical
1842 * #ESource editors. Call this function when the user is finished
1843 * making changes to @source.
1845 * If @source has a #GDBusObject, its contents are submitted to the D-Bus
1846 * service through e_source_write_sync().
1848 * If @source does NOT have a #GDBusObject (implying it's a scratch
1849 * #ESource), its contents are submitted to the D-Bus service through
1850 * either e_source_remote_create_sync() if @source is to be a collection
1851 * member, or e_source_registry_create_sources_sync() if @source to be an
1852 * independent data source.
1854 * If an error occurs, the function will set @error and return %FALSE.
1856 * Returns: %TRUE on success, %FALSE on failure
1861 e_source_registry_commit_source_sync (ESourceRegistry *registry,
1863 GCancellable *cancellable,
1866 GDBusObject *dbus_object;
1867 ESource *collection_source;
1868 gboolean collection_member;
1871 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1872 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1874 dbus_object = e_source_ref_dbus_object (source);
1876 collection_source = e_source_registry_find_extension (
1877 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1880 (collection_source != NULL) &&
1881 (collection_source != source);
1883 if (dbus_object != NULL) {
1884 success = e_source_write_sync (source, cancellable, error);
1885 g_object_unref (dbus_object);
1887 } else if (collection_member) {
1888 success = e_source_remote_create_sync (
1889 collection_source, source, cancellable, error);
1892 GList *list = g_list_prepend (NULL, source);
1893 success = e_source_registry_create_sources_sync (
1894 registry, list, cancellable, error);
1898 if (collection_source != NULL)
1899 g_object_unref (collection_source);
1905 * e_source_registry_commit_source:
1906 * @registry: an #ESourceRegistry
1907 * @source: an #ESource with changes to commit
1908 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1909 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1911 * @user_data: (closure): data to pass to the callback function
1913 * See e_source_registry_commit_source_sync() for details.
1915 * When the operation is finished, @callback will be called. You can then
1916 * call e_source_registry_commit_source_finish() to get the result of the
1922 e_source_registry_commit_source (ESourceRegistry *registry,
1924 GCancellable *cancellable,
1925 GAsyncReadyCallback callback,
1928 GSimpleAsyncResult *simple;
1929 AsyncContext *async_context;
1931 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1932 g_return_if_fail (E_IS_SOURCE (source));
1934 async_context = g_slice_new0 (AsyncContext);
1935 async_context->source = g_object_ref (source);
1937 simple = g_simple_async_result_new (
1938 G_OBJECT (registry), callback, user_data,
1939 e_source_registry_commit_source);
1941 g_simple_async_result_set_check_cancellable (simple, cancellable);
1943 g_simple_async_result_set_op_res_gpointer (
1944 simple, async_context, (GDestroyNotify) async_context_free);
1946 g_simple_async_result_run_in_thread (
1947 simple, source_registry_commit_source_thread,
1948 G_PRIORITY_DEFAULT, cancellable);
1950 g_object_unref (simple);
1954 * e_source_registry_commit_source_finish:
1955 * @registry: an #ESourceRegistry
1956 * @result: a #GAsyncResult
1957 * @error: return location for a #GError, or %NULL
1959 * Finishes the operation started with e_source_registry_commit_source().
1961 * If an error occurred, the function will set @error and return %FALSE.
1963 * Returns: %TRUE on success, %FALSE on failure
1968 e_source_registry_commit_source_finish (ESourceRegistry *registry,
1969 GAsyncResult *result,
1972 GSimpleAsyncResult *simple;
1974 g_return_val_if_fail (
1975 g_simple_async_result_is_valid (
1976 result, G_OBJECT (registry),
1977 e_source_registry_commit_source), FALSE);
1979 simple = G_SIMPLE_ASYNC_RESULT (result);
1981 /* Assume success unless a GError is set. */
1982 return !g_simple_async_result_propagate_error (simple, error);
1985 /* Helper for e_source_registry_create_sources() */
1987 source_registry_create_sources_thread (GSimpleAsyncResult *simple,
1989 GCancellable *cancellable)
1991 AsyncContext *async_context;
1992 GError *error = NULL;
1994 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1996 e_source_registry_create_sources_sync (
1997 E_SOURCE_REGISTRY (object),
1998 async_context->list_of_sources,
1999 cancellable, &error);
2002 g_simple_async_result_take_error (simple, error);
2006 * e_source_registry_create_sources_sync:
2007 * @registry: an #ESourceRegistry
2008 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2010 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2011 * @error: return location for a #GError, or %NULL
2013 * Requests the D-Bus service create new key files for each #ESource in
2014 * @list_of_sources. Each list element must be a scratch #ESource with
2017 * If an error occurs, the function will set @error and return %FALSE.
2019 * Returns: %TRUE on success, %FALSE on failure
2024 e_source_registry_create_sources_sync (ESourceRegistry *registry,
2025 GList *list_of_sources,
2026 GCancellable *cancellable,
2029 GVariantBuilder builder;
2034 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2036 /* Verify the list elements are all ESources. */
2037 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2038 g_return_val_if_fail (E_IS_SOURCE (link->data), FALSE);
2040 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
2042 for (link = list_of_sources; link != NULL; link = g_list_next (link)) {
2047 source = E_SOURCE (link->data);
2048 uid = e_source_get_uid (source);
2050 source_data = e_source_to_string (source, NULL);
2051 g_variant_builder_add (&builder, "{ss}", uid, source_data);
2052 g_free (source_data);
2055 variant = g_variant_builder_end (&builder);
2057 /* This function sinks the floating GVariant reference. */
2058 success = e_dbus_source_manager_call_create_sources_sync (
2059 registry->priv->dbus_source_manager,
2060 variant, cancellable, error);
2062 g_variant_builder_clear (&builder);
2068 * e_source_registry_create_sources:
2069 * @registry: an #ESourceRegistry
2070 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2072 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2073 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2075 * @user_data: (closure): data to pass to the callback function
2077 * Asynchronously requests the D-Bus service create new key files for each
2078 * #ESource in @list_of_sources. Each list element must be a scratch
2079 * #ESource with no #GDBusObject.
2081 * When the operation is finished, @callback will be called. You can then
2082 * call e_source_registry_create_sources_finish() to get the result of the
2088 e_source_registry_create_sources (ESourceRegistry *registry,
2089 GList *list_of_sources,
2090 GCancellable *cancellable,
2091 GAsyncReadyCallback callback,
2094 GSimpleAsyncResult *simple;
2095 AsyncContext *async_context;
2098 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2100 /* Verify the list elements are all ESources. */
2101 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2102 g_return_if_fail (E_IS_SOURCE (link->data));
2104 async_context = g_slice_new0 (AsyncContext);
2105 async_context->list_of_sources = g_list_copy (list_of_sources);
2108 async_context->list_of_sources,
2109 (GFunc) g_object_ref, NULL);
2111 simple = g_simple_async_result_new (
2112 G_OBJECT (registry), callback, user_data,
2113 e_source_registry_create_sources);
2115 g_simple_async_result_set_check_cancellable (simple, cancellable);
2117 g_simple_async_result_set_op_res_gpointer (
2118 simple, async_context, (GDestroyNotify) async_context_free);
2120 g_simple_async_result_run_in_thread (
2121 simple, source_registry_create_sources_thread,
2122 G_PRIORITY_DEFAULT, cancellable);
2124 g_object_unref (simple);
2128 * e_source_registry_create_sources_finish:
2129 * @registry: an #ESourceRegistry
2130 * @result: a #GAsyncResult
2131 * @error: return location for a #GError, or %NULL
2133 * Finishes the operation started with e_source_registry_create_sources().
2135 * If an error occurred, the function will set @error and return %FALSE.
2137 * Returns: %TRUE on success, %FALSE on failure
2142 e_source_registry_create_sources_finish (ESourceRegistry *registry,
2143 GAsyncResult *result,
2146 GSimpleAsyncResult *simple;
2148 g_return_val_if_fail (
2149 g_simple_async_result_is_valid (
2150 result, G_OBJECT (registry),
2151 e_source_registry_create_sources), FALSE);
2153 simple = G_SIMPLE_ASYNC_RESULT (result);
2155 /* Assume success unless a GError is set. */
2156 return !g_simple_async_result_propagate_error (simple, error);
2160 * e_source_registry_ref_source:
2161 * @registry: an #ESourceRegistry
2162 * @uid: a unique identifier string
2164 * Looks up an #ESource in @registry by its unique identifier string.
2166 * The returned #ESource is referenced for thread-safety and must be
2167 * unreferenced with g_object_unref() when finished with it.
2169 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2174 e_source_registry_ref_source (ESourceRegistry *registry,
2177 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2178 g_return_val_if_fail (uid != NULL, NULL);
2180 return source_registry_sources_lookup (registry, uid);
2184 * e_source_registry_list_sources:
2185 * @registry: an #ESourceRegistry
2186 * @extension_name: (allow-none): an extension name, or %NULL
2188 * Returns a list of registered sources, sorted by display name. If
2189 * @extension_name is given, restrict the list to sources having that
2192 * The sources returned in the list are referenced for thread-safety.
2193 * They must each be unreferenced with g_object_unref() when finished
2194 * when them. Free the returned list itself with g_list_free().
2196 * An easy way to free the list properly in one step is as follows:
2199 * g_list_free_full (list, g_object_unref);
2202 * Returns: (element-type ESource) (transfer full): a sorted list of sources
2207 e_source_registry_list_sources (ESourceRegistry *registry,
2208 const gchar *extension_name)
2211 GQueue trash = G_QUEUE_INIT;
2213 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2215 list = g_list_sort (
2216 source_registry_sources_get_values (registry),
2217 (GCompareFunc) e_source_compare_by_display_name);
2219 if (extension_name == NULL)
2222 for (link = list; link != NULL; link = g_list_next (link)) {
2223 ESource *source = E_SOURCE (link->data);
2225 if (!e_source_has_extension (source, extension_name)) {
2226 g_queue_push_tail (&trash, link);
2227 g_object_unref (source);
2231 /* We do want pop_head() here, not pop_head_link(). */
2232 while ((link = g_queue_pop_head (&trash)) != NULL)
2233 list = g_list_delete_link (list, link);
2239 * e_source_registry_check_enabled:
2240 * @registry: an #ESourceRegistry
2241 * @source: an #ESource
2243 * Determines whether @source is "effectively" enabled by examining its
2244 * own #ESource:enabled property as well as those of its ancestors in the
2245 * #ESource hierarchy. If all examined #ESource:enabled properties are
2246 * %TRUE, then the function returns %TRUE. If any are %FALSE, then the
2247 * function returns %FALSE.
2249 * Use this function instead of e_source_get_enabled() to determine
2250 * things like whether to display an #ESource in a user interface or
2251 * whether to act on the data set described by the #ESource.
2253 * Returns: whether @source is "effectively" enabled
2258 e_source_registry_check_enabled (ESourceRegistry *registry,
2264 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2265 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2267 enabled = e_source_get_enabled (source);
2268 parent_uid = e_source_dup_parent (source);
2270 while (enabled && parent_uid != NULL) {
2273 parent = e_source_registry_ref_source (registry, parent_uid);
2275 g_free (parent_uid);
2278 if (parent != NULL) {
2279 enabled = e_source_get_enabled (parent);
2280 parent_uid = e_source_dup_parent (parent);
2281 g_object_unref (parent);
2285 g_free (parent_uid);
2291 * e_source_registry_find_extension:
2292 * @registry: an #ESourceRegistry
2293 * @source: an #ESource
2294 * @extension_name: the extension name to find
2296 * Examines @source and its ancestors and returns the "deepest" #ESource
2297 * having an #ESourceExtension with the given @extension_name. If neither
2298 * @source nor any of its ancestors have such an extension, the function
2301 * This function is useful in cases when an #ESourceExtension is meant to
2302 * apply to both the #ESource it belongs to and the #ESource's descendants.
2304 * A common example is the #ESourceCollection extension, where descendants
2305 * of an #ESource having an #ESourceCollection extension are implied to be
2306 * members of that collection. In that example, this function can be used
2307 * to test whether @source is a member of a collection.
2309 * The returned #ESource is referenced for thread-safety and must be
2310 * unreferenced with g_object_unref() when finished with it.
2312 * Note the function returns the #ESource containing the #ESourceExtension
2313 * instead of the #ESourceExtension itself because extension instances are
2314 * not to be referenced directly (see e_source_get_extension()).
2316 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2321 e_source_registry_find_extension (ESourceRegistry *registry,
2323 const gchar *extension_name)
2325 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2326 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2327 g_return_val_if_fail (extension_name != NULL, NULL);
2329 g_object_ref (source);
2331 while (!e_source_has_extension (source, extension_name)) {
2334 uid = e_source_dup_parent (source);
2336 g_object_unref (source);
2340 source = e_source_registry_ref_source (registry, uid);
2351 /* Helper for e_source_registry_build_display_tree() */
2353 source_registry_compare_nodes (GNode *node_a,
2356 ESource *source_a = E_SOURCE (node_a->data);
2357 ESource *source_b = E_SOURCE (node_b->data);
2358 const gchar *uid_a, *uid_b;
2360 uid_a = e_source_get_uid (source_a);
2361 uid_b = e_source_get_uid (source_b);
2363 /* Sanity check, with runtime warnings. */
2364 if (uid_a == NULL) {
2365 g_warn_if_reached ();
2368 if (uid_b == NULL) {
2369 g_warn_if_reached ();
2373 /* The built-in "local-stub" source comes first at depth 1. */
2375 if (g_strcmp0 (uid_a, "local-stub") == 0)
2378 if (g_strcmp0 (uid_b, "local-stub") == 0)
2381 /* The built-in "system-*" sources come first at depth 2. */
2383 if (g_str_has_prefix (uid_a, "system-"))
2386 if (g_str_has_prefix (uid_b, "system-"))
2389 return e_source_compare_by_display_name (source_a, source_b);
2392 /* Helper for e_source_registry_build_display_tree() */
2394 source_registry_prune_nodes (GNode *node,
2395 const gchar *extension_name)
2397 GQueue queue = G_QUEUE_INIT;
2400 /* Unlink all the child nodes and place them in a queue. */
2401 while ((child_node = g_node_first_child (node)) != NULL) {
2402 g_node_unlink (child_node);
2403 g_queue_push_tail (&queue, child_node);
2406 /* Sort the queue by source name. */
2408 &queue, (GCompareDataFunc)
2409 source_registry_compare_nodes, NULL);
2411 /* Pop nodes off the head of the queue until the queue is empty.
2412 * If the node has either its own children or the given extension
2413 * name, put it back under the parent node (preserving the sorted
2414 * order). Otherwise delete the node and its descendants. */
2415 while ((child_node = g_queue_pop_head (&queue)) != NULL) {
2416 ESource *child = E_SOURCE (child_node->data);
2417 gboolean append_child_node = FALSE;
2419 if (extension_name == NULL)
2420 append_child_node = e_source_get_enabled (child);
2422 else if (e_source_has_extension (child, extension_name))
2423 append_child_node = e_source_get_enabled (child);
2425 else if (g_node_first_child (child_node) != NULL)
2426 append_child_node = e_source_get_enabled (child);
2428 if (append_child_node)
2429 g_node_append (node, child_node);
2431 e_source_registry_free_display_tree (child_node);
2438 * e_source_registry_build_display_tree:
2439 * @registry: an #ESourceRegistry
2440 * @extension_name: (allow-none): an extension name, or %NULL
2442 * Returns a single #GNode tree of registered sources that can be used to
2443 * populate a #GtkTreeModel. (The root #GNode is just an empty placeholder.)
2445 * Similar to e_source_registry_list_sources(), an @extension_name can be
2446 * given to restrict the tree to sources having that extension name. Parents
2447 * of matched sources are included in the tree regardless of whether they have
2448 * an extension named @extension_name.
2450 * Disabled leaf nodes are automatically excluded from the #GNode tree.
2452 * The sources returned in the tree are referenced for thread-safety.
2453 * They must each be unreferenced with g_object_unref() when finished
2454 * with them. Free the returned tree itself with g_node_destroy().
2455 * For convenience, e_source_registry_free_display_tree() does all
2458 * Returns: (element-type ESource) (transfer full): a tree of sources,
2459 * arranged for display
2464 e_source_registry_build_display_tree (ESourceRegistry *registry,
2465 const gchar *extension_name)
2469 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2471 /* Assemble all data sources into a tree. */
2472 root = source_registry_sources_build_tree (registry);
2474 /* Prune unwanted nodes from the copied source trees.
2475 * This must be done in "post" order (children first)
2476 * since it reorders and deletes child nodes. */
2478 root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
2479 (GNodeTraverseFunc) source_registry_prune_nodes,
2480 (gpointer) extension_name);
2485 /* Helper for e_source_registry_free_display_tree() */
2487 source_registry_unref_nodes (GNode *node)
2489 while (node != NULL) {
2490 if (node->children != NULL)
2491 source_registry_unref_nodes (node->children);
2492 if (node->data != NULL)
2493 g_object_unref (node->data);
2499 * e_source_registry_free_display_tree:
2500 * @display_tree: a tree of sources, arranged for display
2502 * Convenience function to free a #GNode tree of registered
2503 * sources created by e_source_registry_build_display_tree().
2508 e_source_registry_free_display_tree (GNode *display_tree)
2510 g_return_if_fail (display_tree != NULL);
2512 /* XXX This would be easier if GLib had something like
2513 * g_node_destroy_full() which took a GDestroyNotify.
2514 * Then the tree would not have to be traversed twice. */
2516 source_registry_unref_nodes (display_tree);
2517 g_node_destroy (display_tree);
2520 /* Helper for e_source_registry_debug_dump() */
2522 source_registry_debug_dump_cb (GNode *node)
2526 /* Root node is an empty placeholder. */
2527 if (G_NODE_IS_ROOT (node))
2530 depth = g_node_depth (node);
2531 for (ii = 2; ii < depth; ii++)
2534 if (E_IS_SOURCE (node->data)) {
2535 ESource *source = E_SOURCE (node->data);
2536 g_print ("\"%s\" ", e_source_get_display_name (source));
2537 g_print ("(%s)", e_source_get_uid (source));
2546 * e_source_registry_debug_dump:
2547 * @registry: an #ESourceRegistry
2548 * @extension_name: (allow-none): an extension name, or %NULL
2550 * Handy debugging function that uses e_source_registry_build_display_tree()
2551 * to print a tree of registered sources to standard output.
2556 e_source_registry_debug_dump (ESourceRegistry *registry,
2557 const gchar *extension_name)
2561 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2563 root = e_source_registry_build_display_tree (registry, extension_name);
2566 root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2567 (GNodeTraverseFunc) source_registry_debug_dump_cb, NULL);
2569 e_source_registry_free_display_tree (root);
2573 * e_source_registry_ref_builtin_address_book:
2574 * @registry: an #ESourceRegistry
2576 * Returns the built-in address book #ESource.
2578 * This #ESource is always present and makes for a safe fallback.
2580 * The returned #ESource is referenced for thread-safety and must be
2581 * unreferenced with g_object_unref() when finished with it.
2583 * Returns: (transfer full): the built-in address book #ESource
2588 e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
2593 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2595 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2596 source = e_source_registry_ref_source (registry, uid);
2597 g_return_val_if_fail (source != NULL, NULL);
2603 * e_source_registry_ref_default_address_book:
2604 * @registry: an #ESourceRegistry
2606 * Returns the #ESource most recently passed to
2607 * e_source_registry_set_default_address_book() either in this session
2608 * or a previous session, or else falls back to the built-in address book.
2610 * The returned #ESource is referenced for thread-safety and must be
2611 * unreferenced with g_object_unref() when finished with it.
2613 * Returns: (transfer full): the default address book #ESource
2618 e_source_registry_ref_default_address_book (ESourceRegistry *registry)
2624 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2626 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2627 uid = g_settings_get_string (registry->priv->settings, key);
2628 source = e_source_registry_ref_source (registry, uid);
2631 /* The built-in source is always present. */
2633 source = e_source_registry_ref_builtin_address_book (registry);
2635 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2641 * e_source_registry_set_default_address_book:
2642 * @registry: an #ESourceRegistry
2643 * @default_source: (allow-none): an address book #ESource, or %NULL
2645 * Sets @default_source as the default address book. If @default_source
2646 * is %NULL, the default address book is reset to the built-in address book.
2647 * This setting will persist across sessions until changed.
2652 e_source_registry_set_default_address_book (ESourceRegistry *registry,
2653 ESource *default_source)
2658 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2660 if (default_source != NULL) {
2661 g_return_if_fail (E_IS_SOURCE (default_source));
2662 uid = e_source_get_uid (default_source);
2664 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2667 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2668 g_settings_set_string (registry->priv->settings, key, uid);
2670 /* The GSettings::changed signal will trigger a "notify" signal
2671 * from the registry, so no need to call g_object_notify() here. */
2675 * e_source_registry_ref_builtin_calendar:
2676 * @registry: an #ESourceRegistry
2678 * Returns the built-in calendar #ESource.
2680 * This #ESource is always present and makes for a safe fallback.
2682 * The returned #ESource is referenced for thread-safety and must be
2683 * unreferenced with g_object_unref() when finished with it.
2685 * Returns: (transfer full): the built-in calendar #ESource
2690 e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
2695 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2697 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2698 source = e_source_registry_ref_source (registry, uid);
2699 g_return_val_if_fail (source != NULL, NULL);
2705 * e_source_registry_ref_default_calendar:
2706 * @registry: an #ESourceRegistry
2708 * Returns the #ESource most recently passed to
2709 * e_source_registry_set_default_calendar() either in this session
2710 * or a previous session, or else falls back to the built-in calendar.
2712 * The returned #ESource is referenced for thread-safety and must be
2713 * unreferenced with g_object_unref() when finished with it.
2715 * Returns: (transfer full): the default calendar #ESource
2720 e_source_registry_ref_default_calendar (ESourceRegistry *registry)
2726 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2728 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2729 uid = g_settings_get_string (registry->priv->settings, key);
2730 source = e_source_registry_ref_source (registry, uid);
2733 /* The built-in source is always present. */
2735 source = e_source_registry_ref_builtin_calendar (registry);
2737 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2743 * e_source_registry_set_default_calendar:
2744 * @registry: an #ESourceRegistry
2745 * @default_source: (allow-none): a calendar #ESource, or %NULL
2747 * Sets @default_source as the default calendar. If @default_source
2748 * is %NULL, the default calendar is reset to the built-in calendar.
2749 * This setting will persist across sessions until changed.
2754 e_source_registry_set_default_calendar (ESourceRegistry *registry,
2755 ESource *default_source)
2760 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2762 if (default_source != NULL) {
2763 g_return_if_fail (E_IS_SOURCE (default_source));
2764 uid = e_source_get_uid (default_source);
2766 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2769 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2770 g_settings_set_string (registry->priv->settings, key, uid);
2772 /* The GSettings::changed signal will trigger a "notify" signal
2773 * from the registry, so no need to call g_object_notify() here. */
2777 * e_source_registry_ref_builtin_mail_account:
2778 * @registry: an #ESourceRegistry
2780 * Returns the built-in mail account #ESource.
2782 * This #ESource is always present and makes for a safe fallback.
2784 * The returned #ESource is referenced for thread-safety and must be
2785 * unreferenced with g_object_unref() when finished with it.
2787 * Returns: (transfer full): the built-in mail account #ESource
2792 e_source_registry_ref_builtin_mail_account (ESourceRegistry *registry)
2797 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2799 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2800 source = e_source_registry_ref_source (registry, uid);
2801 g_return_val_if_fail (source != NULL, NULL);
2807 * e_source_registry_ref_default_mail_account:
2808 * @registry: an #ESourceRegistry
2810 * Returns the #ESource most recently passed to
2811 * e_source_registry_set_default_mail_account() either in this session
2812 * or a previous session, or else falls back to the built-in mail account.
2814 * The returned #ESource is referenced for thread-safety and must be
2815 * unreferenced with g_object_unref() when finished with it.
2817 * Returns: (transfer full): the default mail account #ESource
2822 e_source_registry_ref_default_mail_account (ESourceRegistry *registry)
2828 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2830 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2831 uid = g_settings_get_string (registry->priv->settings, key);
2832 source = e_source_registry_ref_source (registry, uid);
2835 /* The built-in source is always present. */
2837 source = e_source_registry_ref_builtin_mail_account (registry);
2839 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2845 * e_source_registry_set_default_mail_account:
2846 * @registry: an #ESourceRegistry
2847 * @default_source: (allow-none): a mail account #ESource, or %NULL
2849 * Sets @default_source as the default mail account. If @default_source
2850 * is %NULL, the default mail account is reset to the built-in mail account.
2851 * This setting will persist across sessions until changed.
2856 e_source_registry_set_default_mail_account (ESourceRegistry *registry,
2857 ESource *default_source)
2862 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2864 if (default_source != NULL) {
2865 g_return_if_fail (E_IS_SOURCE (default_source));
2866 uid = e_source_get_uid (default_source);
2868 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2871 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2872 g_settings_set_string (registry->priv->settings, key, uid);
2874 /* The GSettings::changed signal will trigger a "notify" signal
2875 * from the registry, so no need to call g_object_notify() here. */
2878 /* Helper for e_source_registry_ref_default_mail_identity() */
2880 source_registry_ref_any_mail_identity (ESourceRegistry *registry)
2884 const gchar *extension_name;
2887 /* First fallback: Return the mail identity named
2888 * by the default mail account. */
2890 source = e_source_registry_ref_default_mail_account (registry);
2892 /* This should never be NULL, but just to be safe. */
2893 if (source != NULL) {
2894 ESourceMailAccount *extension;
2896 extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
2897 extension = e_source_get_extension (source, extension_name);
2898 uid = e_source_mail_account_dup_identity_uid (extension);
2900 g_object_unref (source);
2905 source = e_source_registry_ref_source (registry, uid);
2912 /* Second fallback: Pick any available mail identity,
2913 * preferring enabled identities. */
2915 extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
2916 list = e_source_registry_list_sources (registry, extension_name);
2918 for (link = list; link != NULL; link = g_list_next (link)) {
2919 ESource *candidate = E_SOURCE (link->data);
2921 if (e_source_get_enabled (candidate)) {
2922 source = g_object_ref (candidate);
2927 if (source == NULL && list != NULL)
2928 source = g_object_ref (list->data);
2930 g_list_free_full (list, (GDestroyNotify) g_object_unref);
2936 * e_source_registry_ref_default_mail_identity:
2937 * @registry: an #ESourceRegistry
2939 * Returns the #ESource most recently passed to
2940 * e_source_registry_set_default_mail_identity() either in this session
2941 * or a previous session, or else falls back to the mail identity named
2942 * by the default mail account. If even that fails it returns any mail
2943 * identity from @registry, or %NULL if there are none.
2945 * The returned #ESource is referenced for thread-safety and must be
2946 * unreferenced with g_object_unref() when finished with it.
2948 * Returns: (transfer full): the default mail identity #ESource, or %NULL
2953 e_source_registry_ref_default_mail_identity (ESourceRegistry *registry)
2959 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2961 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
2962 uid = g_settings_get_string (registry->priv->settings, key);
2963 source = e_source_registry_ref_source (registry, uid);
2967 source = source_registry_ref_any_mail_identity (registry);
2973 * e_source_registry_set_default_mail_identity:
2974 * @registry: an #ESourceRegistry
2975 * @default_source: (allow-none): a mail identity #ESource, or %NULL
2977 * Sets @default_source as the default mail identity. If @default_source
2978 * is %NULL, the next request for the default mail identity will use the
2979 * fallbacks described in e_source_registry_get_default_mail_identity().
2984 e_source_registry_set_default_mail_identity (ESourceRegistry *registry,
2985 ESource *default_source)
2990 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2992 if (default_source != NULL) {
2993 g_return_if_fail (E_IS_SOURCE (default_source));
2994 uid = e_source_get_uid (default_source);
2996 uid = ""; /* no built-in mail identity */
2999 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
3000 g_settings_set_string (registry->priv->settings, key, uid);
3002 /* The GSettings::changed signal will trigger a "notify" signal
3003 * from the registry, so no need to call g_object_notify() here. */
3007 * e_source_registry_ref_builtin_memo_list:
3008 * @registry: an #ESourceRegistry
3010 * Returns the built-in memo list #ESource.
3012 * This #ESource is always present and makes for a safe fallback.
3014 * The returned #ESource is referenced for thread-safety and must be
3015 * unreferenced with g_object_unref() when finished with it.
3017 * Returns: (transfer full): the built-in memo list #ESource
3022 e_source_registry_ref_builtin_memo_list (ESourceRegistry *registry)
3027 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3029 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3030 source = e_source_registry_ref_source (registry, uid);
3031 g_return_val_if_fail (source != NULL, NULL);
3037 * e_source_registry_ref_default_memo_list:
3038 * @registry: an #ESourceRegistry
3040 * Returns the #ESource most recently passed to
3041 * e_source_registry_set_default_memo_list() either in this session
3042 * or a previous session, or else falls back to the built-in memo list.
3044 * The returned #ESource is referenced for thread-safety and must be
3045 * unreferenced with g_object_unref() when finished with it.
3047 * Returns: (transfer full): the default memo list #ESource
3052 e_source_registry_ref_default_memo_list (ESourceRegistry *registry)
3058 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3060 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3061 uid = g_settings_get_string (registry->priv->settings, key);
3062 source = e_source_registry_ref_source (registry, uid);
3065 /* The built-in source is always present. */
3067 source = e_source_registry_ref_builtin_memo_list (registry);
3069 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3075 * e_source_registry_set_default_memo_list:
3076 * @registry: an #ESourceRegistry
3077 * @default_source: (allow-none): a memo list #ESource, or %NULL
3079 * Sets @default_source as the default memo list. If @default_source
3080 * is %NULL, the default memo list is reset to the built-in memo list.
3081 * This setting will persist across sessions until changed.
3086 e_source_registry_set_default_memo_list (ESourceRegistry *registry,
3087 ESource *default_source)
3092 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3094 if (default_source != NULL) {
3095 g_return_if_fail (E_IS_SOURCE (default_source));
3096 uid = e_source_get_uid (default_source);
3098 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3101 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3102 g_settings_set_string (registry->priv->settings, key, uid);
3104 /* The GSettings::changed signal will trigger a "notify" signal
3105 * from the registry, so no need to call g_object_notify() here. */
3109 * e_source_registry_ref_builtin_task_list:
3110 * @registry: an #ESourceRegistry
3112 * Returns the built-in task list #ESource.
3114 * This #ESource is always present and makes for a safe fallback.
3116 * The returned #ESource is referenced for thread-safety and must be
3117 * unreferenced with g_object_unref() when finished with it.
3119 * Returns: (transfer full): the built-in task list #ESource
3124 e_source_registry_ref_builtin_task_list (ESourceRegistry *registry)
3129 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3131 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3132 source = e_source_registry_ref_source (registry, uid);
3133 g_return_val_if_fail (source != NULL, NULL);
3139 * e_source_registry_ref_default_task_list:
3140 * @registry: an #ESourceRegistry
3142 * Returns the #ESource most recently passed to
3143 * e_source_registry_set_default_task_list() either in this session
3144 * or a previous session, or else falls back to the built-in task list.
3146 * The returned #ESource is referenced for thread-safety and must be
3147 * unreferenced with g_object_unref() when finished with it.
3149 * Returns: (transfer full): the default task list #ESource
3154 e_source_registry_ref_default_task_list (ESourceRegistry *registry)
3160 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3162 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3163 uid = g_settings_get_string (registry->priv->settings, key);
3164 source = e_source_registry_ref_source (registry, uid);
3167 /* The built-in source is always present. */
3169 source = e_source_registry_ref_builtin_task_list (registry);
3171 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3177 * e_source_registry_set_default_task_list:
3178 * @registry: an #ESourceRegistry
3179 * @default_source: (allow-none): a task list #ESource, or %NULL
3181 * Sets @default_source as the default task list. If @default_source
3182 * is %NULL, the default task list is reset to the built-in task list.
3183 * This setting will persist across sessions until changed.
3188 e_source_registry_set_default_task_list (ESourceRegistry *registry,
3189 ESource *default_source)
3194 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3196 if (default_source != NULL) {
3197 g_return_if_fail (E_IS_SOURCE (default_source));
3198 uid = e_source_get_uid (default_source);
3200 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3203 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3204 g_settings_set_string (registry->priv->settings, key, uid);
3206 /* The GSettings::changed signal will trigger a "notify" signal
3207 * from the registry, so no need to call g_object_notify() here. */
3211 * e_source_registry_ref_default_for_extension_name:
3212 * @registry: an #ESourceRegistry
3213 * @extension_name: an extension_name
3215 * This is a convenience function to return a default #ESource based on
3216 * @extension_name. This only works with a subset of extension names.
3218 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3219 * returns the current default address book, or else falls back to the
3220 * built-in address book.
3222 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function returns
3223 * the current default calendar, or else falls back to the built-in calendar.
3225 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3226 * returns the current default mail account, or else falls back to the
3227 * built-in mail account.
3229 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3230 * returns the current default mail identity, or else falls back to the
3231 * mail identity named by the current default mail account.
3233 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function returns
3234 * the current default memo list, or else falls back to the built-in memo list.
3236 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function returns
3237 * the current default task list, or else falls back to the built-in task list.
3239 * For all other values of @extension_name, the function returns %NULL.
3241 * The returned #ESource is referenced for thread-safety and must be
3242 * unreferenced with g_object_unref() when finished with it.
3244 * Returns: (transfer full): the default #ESource based on @extension_name
3249 e_source_registry_ref_default_for_extension_name (ESourceRegistry *registry,
3250 const gchar *extension_name)
3252 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3253 g_return_val_if_fail (extension_name != NULL, NULL);
3255 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3256 return e_source_registry_ref_default_address_book (registry);
3258 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3259 return e_source_registry_ref_default_calendar (registry);
3261 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3262 return e_source_registry_ref_default_mail_account (registry);
3264 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3265 return e_source_registry_ref_default_mail_identity (registry);
3267 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3268 return e_source_registry_ref_default_memo_list (registry);
3270 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3271 return e_source_registry_ref_default_task_list (registry);
3277 * e_source_registry_set_default_for_extension_name:
3278 * @registry: an #ESourceRegistry
3279 * @extension_name: an extension name
3280 * @default_source: (allow-none): an #ESource, or %NULL
3282 * This is a convenience function to set a default #ESource based on
3283 * @extension_name. This only works with a subset of extension names.
3285 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3286 * sets @default_source as the default address book. If @default_source
3287 * is %NULL, the default address book is reset to the built-in address book.
3289 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function sets
3290 * @default_source as the default calendar. If @default_source is %NULL,
3291 * the default calendar is reset to the built-in calendar.
3293 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3294 * sets @default_source as the default mail account. If @default_source
3295 * is %NULL, the default mail account is reset to the built-in mail account.
3297 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3298 * sets @default_source as the default mail identity. If @default_source
3299 * is %NULL, the next request for the default mail identity will return
3300 * the mail identity named by the default mail account.
3302 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function sets
3303 * @default_source as the default memo list. If @default_source is %NULL,
3304 * the default memo list is reset to the built-in memo list.
3306 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function sets
3307 * @default_source as the default task list. If @default_source is %NULL,
3308 * the default task list is reset to the built-in task list.
3310 * For all other values of @extension_name, the function does nothing.
3315 e_source_registry_set_default_for_extension_name (ESourceRegistry *registry,
3316 const gchar *extension_name,
3317 ESource *default_source)
3319 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3320 g_return_if_fail (extension_name != NULL);
3322 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3323 e_source_registry_set_default_address_book (
3324 registry, default_source);
3326 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3327 e_source_registry_set_default_calendar (
3328 registry, default_source);
3330 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3331 e_source_registry_set_default_mail_account (
3332 registry, default_source);
3334 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3335 e_source_registry_set_default_mail_identity (
3336 registry, default_source);
3338 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3339 e_source_registry_set_default_memo_list (
3340 registry, default_source);
3342 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3343 e_source_registry_set_default_task_list (
3344 registry, default_source);