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/>
21 * @include: libedataserver/libedataserver.h
22 * @short_description: Hierarchical data sources
24 * An #ESource (or "data source") is a description of a file or network
25 * location where data can be obtained (such as a mail account), or a
26 * description of a resource at that location (such as a mail folder).
28 * In more concrete terms, it's an interface for a key file. All such
29 * key files have a main group named [Data Source]. The keys in a
30 * [Data Source] group map to #GObject properties in an #ESource.
32 * Additional groups in the key file are referred to as "extensions".
33 * #ESourceExtension serves as the base class for writing interfaces
34 * for these additional key file groups. The keys in one of these
35 * key file groups map to #GObject properties in some custom subclass
36 * of #ESourceExtension which was written specifically for that key
37 * file group. For example, a key file might include a group named
38 * [Calendar], whose keys map to #GObject properties in an extension
39 * class named #ESourceCalendar.
41 * Each #ESource contains an internal dictionary of extension objects,
42 * accessible by their key file group name. e_source_get_extension()
43 * can look up extension objects by name.
45 * An #ESource is identified by a unique identifier string, or "UID",
46 * which is also the basename of the corresponding key file. Additional
47 * files related to the #ESource, such as cache files, are usually kept
48 * in a directory named after the UID of the #ESource. Similarly, the
49 * password for an account described by an #ESource is kept in GNOME
50 * Keyring under the UID of the #ESource. This makes finding these
51 * additional resources simple.
53 * Several extensions for common information such as authentication
54 * details are built into libedataserver (#ESourceAuthentication, for
55 * example). Backend modules may also define their own extensions for
56 * information and settings unique to the backend. #ESourceExtension
57 * subclasses written for specific backends are generally not available
58 * to applications and shared libraries. This is by design, to try and
59 * keep backend-specific knowledge from creeping into places it doesn't
67 #include <glib/gi18n-lib.h>
69 /* Private D-Bus classes. */
70 #include <e-dbus-source.h>
72 #include "e-data-server-util.h"
73 #include "e-source-extension.h"
76 /* built-in extension types */
77 #include "e-source-address-book.h"
78 #include "e-source-alarms.h"
79 #include "e-source-authentication.h"
80 #include "e-source-autocomplete.h"
81 #include "e-source-calendar.h"
82 #include "e-source-camel.h"
83 #include "e-source-collection.h"
84 #include "e-source-goa.h"
85 #include "e-source-mail-account.h"
86 #include "e-source-mail-composition.h"
87 #include "e-source-mail-identity.h"
88 #include "e-source-mail-signature.h"
89 #include "e-source-mail-submission.h"
90 #include "e-source-mail-transport.h"
91 #include "e-source-mdn.h"
92 #include "e-source-offline.h"
93 #include "e-source-openpgp.h"
94 #include "e-source-refresh.h"
95 #include "e-source-resource.h"
96 #include "e-source-revision-guards.h"
97 #include "e-source-security.h"
98 #include "e-source-selectable.h"
99 #include "e-source-smime.h"
100 #include "e-source-uoa.h"
101 #include "e-source-webdav.h"
103 #define E_SOURCE_GET_PRIVATE(obj) \
104 (G_TYPE_INSTANCE_GET_PRIVATE \
105 ((obj), E_TYPE_SOURCE, ESourcePrivate))
107 #define PRIMARY_GROUP_NAME "Data Source"
109 typedef struct _AsyncContext AsyncContext;
111 struct _ESourcePrivate {
112 GDBusObject *dbus_object;
113 GMainContext *main_context;
118 GMutex property_lock;
125 /* The lock guards the key file and hash table. */
129 GHashTable *extensions;
132 gboolean initialized;
135 struct _AsyncContext {
136 ESource *scratch_source;
148 PROP_REMOTE_CREATABLE,
149 PROP_REMOTE_DELETABLE,
160 static guint signals[LAST_SIGNAL];
162 /* Forward Declarations */
163 static void e_source_initable_init (GInitableIface *interface);
165 G_DEFINE_TYPE_WITH_CODE (
169 G_IMPLEMENT_INTERFACE (
171 e_source_initable_init))
174 async_context_free (AsyncContext *async_context)
176 if (async_context->scratch_source != NULL)
177 g_object_unref (async_context->scratch_source);
179 g_free (async_context->access_token);
181 g_slice_free (AsyncContext, async_context);
185 source_find_extension_classes_rec (GType parent_type,
186 GHashTable *hash_table)
189 guint n_children, ii;
191 children = g_type_children (parent_type, &n_children);
193 for (ii = 0; ii < n_children; ii++) {
194 GType type = children[ii];
195 ESourceExtensionClass *class;
198 /* Recurse over the child's children. */
199 source_find_extension_classes_rec (type, hash_table);
201 /* Skip abstract types. */
202 if (G_TYPE_IS_ABSTRACT (type))
205 class = g_type_class_ref (type);
206 key = (gpointer) class->name;
209 g_hash_table_insert (hash_table, key, class);
211 g_type_class_unref (class);
218 source_find_extension_classes (void)
220 GHashTable *hash_table;
222 hash_table = g_hash_table_new_full (
223 (GHashFunc) g_str_hash,
224 (GEqualFunc) g_str_equal,
225 (GDestroyNotify) NULL,
226 (GDestroyNotify) g_type_class_unref);
228 source_find_extension_classes_rec (
229 E_TYPE_SOURCE_EXTENSION, hash_table);
235 source_localized_hack (GKeyFile *key_file,
236 const gchar *group_name,
238 const gchar *new_value)
240 const gchar * const *language_names;
243 /* XXX If we're changing a string key that has translations,
244 * set "key[$CURRENT_LOCALE]" (if available) to the new
245 * value so g_key_file_get_locale_string() will pick it
246 * up. This is not a perfect solution however. When a
247 * different locale is used the value may revert to its
248 * original localized string. Good enough for now. */
250 language_names = g_get_language_names ();
252 for (ii = 0; language_names[ii] != NULL; ii++) {
253 gboolean has_localized_key;
254 gchar *localized_key;
256 localized_key = g_strdup_printf (
257 "%s[%s]", key, language_names[ii]);
258 has_localized_key = g_key_file_has_key (
259 key_file, group_name, localized_key, NULL);
261 if (has_localized_key)
262 g_key_file_set_string (
263 key_file, group_name,
264 localized_key, new_value);
266 g_free (localized_key);
268 if (has_localized_key)
272 g_key_file_set_string (key_file, group_name, key, new_value);
276 source_set_key_file_from_property (GObject *object,
279 const gchar *group_name)
285 pvalue = g_slice_new0 (GValue);
286 g_value_init (pvalue, pspec->value_type);
287 g_object_get_property (object, pspec->name, pvalue);
289 svalue = g_slice_new0 (GValue);
290 g_value_init (svalue, G_TYPE_STRING);
292 key = e_source_parameter_to_key (pspec->name);
294 /* For the most part we can just transform any supported
295 * property type to a string, with a couple exceptions. */
297 /* Transforming a boolean GValue to a string results in
298 * "TRUE" or "FALSE" (all uppercase), but GKeyFile only
299 * recognizes "true" or "false" (all lowercase). So we
300 * have to use g_key_file_set_boolean(). */
301 if (G_VALUE_HOLDS_BOOLEAN (pvalue)) {
302 gboolean v_boolean = g_value_get_boolean (pvalue);
303 g_key_file_set_boolean (key_file, group_name, key, v_boolean);
305 /* Store UIN64 in hexa */
306 } else if (G_VALUE_HOLDS_UINT64 (pvalue)) {
309 v_str = g_strdup_printf (
310 "%016" G_GINT64_MODIFIER "X",
311 g_value_get_uint64 (pvalue));
312 g_key_file_set_string (key_file, group_name, key, v_str);
315 /* String GValues may contain characters that need escaping. */
316 } else if (G_VALUE_HOLDS_STRING (pvalue)) {
317 const gchar *v_string = g_value_get_string (pvalue);
319 if (v_string == NULL)
322 /* Special case for localized "DisplayName" keys. */
323 source_localized_hack (key_file, group_name, key, v_string);
325 /* Transforming an enum GValue to a string results in
326 * the GEnumValue name. We want the shorter nickname. */
327 } else if (G_VALUE_HOLDS_ENUM (pvalue)) {
328 GParamSpecEnum *enum_pspec;
329 GEnumClass *enum_class;
330 GEnumValue *enum_value;
333 enum_pspec = G_PARAM_SPEC_ENUM (pspec);
334 enum_class = enum_pspec->enum_class;
336 value = g_value_get_enum (pvalue);
337 enum_value = g_enum_get_value (enum_class, value);
339 if (enum_value == NULL) {
340 value = enum_pspec->default_value;
341 enum_value = g_enum_get_value (enum_class, value);
344 if (enum_value != NULL)
345 g_key_file_set_string (
346 key_file, group_name, key,
347 enum_value->value_nick);
349 } else if (G_VALUE_HOLDS (pvalue, G_TYPE_STRV)) {
350 const gchar **strv = g_value_get_boxed (pvalue);
354 length = g_strv_length ((gchar **) strv);
355 g_key_file_set_string_list (
356 key_file, group_name, key, strv, length);
358 /* For GValues holding a GFile object we save the URI. */
359 } else if (G_VALUE_HOLDS (pvalue, G_TYPE_FILE)) {
360 GFile *file = g_value_get_object (pvalue);
364 uri = g_file_get_uri (file);
365 g_key_file_set_string (
366 key_file, group_name, key,
367 (uri != NULL) ? uri : "");
370 } else if (g_value_transform (pvalue, svalue)) {
371 const gchar *value = g_value_get_string (svalue);
372 g_key_file_set_value (key_file, group_name, key, value);
376 g_value_unset (pvalue);
377 g_value_unset (svalue);
378 g_slice_free (GValue, pvalue);
379 g_slice_free (GValue, svalue);
383 source_set_property_from_key_file (GObject *object,
386 const gchar *group_name)
390 GError *error = NULL;
392 value = g_slice_new0 (GValue);
393 key = e_source_parameter_to_key (pspec->name);
395 if (G_IS_PARAM_SPEC_CHAR (pspec) ||
396 G_IS_PARAM_SPEC_UCHAR (pspec) ||
397 G_IS_PARAM_SPEC_INT (pspec) ||
398 G_IS_PARAM_SPEC_UINT (pspec) ||
399 G_IS_PARAM_SPEC_LONG (pspec) ||
400 G_IS_PARAM_SPEC_ULONG (pspec)) {
403 v_int = g_key_file_get_integer (
404 key_file, group_name, key, &error);
406 g_value_init (value, G_TYPE_INT);
407 g_value_set_int (value, v_int);
410 } else if (G_IS_PARAM_SPEC_INT64 (pspec)) {
413 v_int64 = g_key_file_get_int64 (
414 key_file, group_name, key, &error);
416 g_value_init (value, G_TYPE_INT64);
417 g_value_set_int64 (value, v_int64);
420 } else if (G_IS_PARAM_SPEC_UINT64 (pspec)) {
424 v_str = g_key_file_get_string (
425 key_file, group_name, key, &error);
427 v_uint64 = g_ascii_strtoull (v_str, NULL, 16);
429 g_value_init (value, G_TYPE_UINT64);
430 g_value_set_uint64 (value, v_uint64);
435 } else if (G_IS_PARAM_SPEC_BOOLEAN (pspec)) {
438 v_boolean = g_key_file_get_boolean (
439 key_file, group_name, key, &error);
441 g_value_init (value, G_TYPE_BOOLEAN);
442 g_value_set_boolean (value, v_boolean);
445 } else if (G_IS_PARAM_SPEC_ENUM (pspec)) {
448 nick = g_key_file_get_string (
449 key_file, group_name, key, &error);
451 GParamSpecEnum *enum_pspec;
452 GEnumValue *enum_value;
454 enum_pspec = G_PARAM_SPEC_ENUM (pspec);
455 enum_value = g_enum_get_value_by_nick (
456 enum_pspec->enum_class, nick);
457 if (enum_value != NULL) {
458 g_value_init (value, pspec->value_type);
459 g_value_set_enum (value, enum_value->value);
464 } else if (G_IS_PARAM_SPEC_FLOAT (pspec) ||
465 G_IS_PARAM_SPEC_DOUBLE (pspec)) {
468 v_double = g_key_file_get_double (
469 key_file, group_name, key, &error);
471 g_value_init (value, G_TYPE_DOUBLE);
472 g_value_set_double (value, v_double);
475 } else if (G_IS_PARAM_SPEC_STRING (pspec)) {
478 /* Get the localized string if present. */
479 v_string = g_key_file_get_locale_string (
480 key_file, group_name, key, NULL, &error);
482 g_value_init (value, G_TYPE_STRING);
483 g_value_take_string (value, v_string);
486 } else if (g_type_is_a (pspec->value_type, G_TYPE_STRV)) {
489 strv = g_key_file_get_string_list (
490 key_file, group_name, key, NULL, &error);
492 g_value_init (value, G_TYPE_STRV);
493 g_value_take_boxed (value, strv);
496 } else if (g_type_is_a (pspec->value_type, G_TYPE_FILE)) {
499 /* Create the GFile from the URI string. */
500 uri = g_key_file_get_locale_string (
501 key_file, group_name, key, NULL, &error);
504 if (uri != NULL && *uri != '\0')
505 file = g_file_new_for_uri (uri);
506 g_value_init (value, pspec->value_type);
507 g_value_take_object (value, file);
513 "No GKeyFile-to-GValue converter defined "
514 "for type '%s'", G_PARAM_SPEC_TYPE_NAME (pspec));
517 /* If a value could not be retrieved from the key
518 * file, restore the property to its default value. */
520 g_value_init (value, pspec->value_type);
521 g_param_value_set_default (pspec, value);
522 g_error_free (error);
525 if (G_IS_VALUE (value)) {
526 g_object_set_property (object, pspec->name, value);
527 g_value_unset (value);
530 g_slice_free (GValue, value);
535 source_load_from_key_file (GObject *object,
537 const gchar *group_name)
540 GParamSpec **properties;
541 guint n_properties, ii;
543 class = G_OBJECT_GET_CLASS (object);
544 properties = g_object_class_list_properties (class, &n_properties);
546 g_object_freeze_notify (object);
548 for (ii = 0; ii < n_properties; ii++) {
549 if (properties[ii]->flags & E_SOURCE_PARAM_SETTING) {
550 source_set_property_from_key_file (
551 object, properties[ii], key_file, group_name);
555 g_object_thaw_notify (object);
561 source_save_to_key_file (GObject *object,
563 const gchar *group_name)
566 GParamSpec **properties;
567 guint n_properties, ii;
569 class = G_OBJECT_GET_CLASS (object);
570 properties = g_object_class_list_properties (class, &n_properties);
572 for (ii = 0; ii < n_properties; ii++) {
573 if (properties[ii]->flags & E_SOURCE_PARAM_SETTING) {
574 source_set_key_file_from_property (
575 object, properties[ii], key_file, group_name);
583 source_parse_dbus_data (ESource *source,
587 EDBusObject *dbus_object;
588 EDBusSource *dbus_source;
595 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
597 dbus_source = e_dbus_object_get_source (dbus_object);
598 data = e_dbus_source_dup_data (dbus_source);
599 g_object_unref (dbus_source);
601 g_return_val_if_fail (data != NULL, FALSE);
603 key_file = source->priv->key_file;
605 success = g_key_file_load_from_data (
606 key_file, data, strlen (data),
607 G_KEY_FILE_KEEP_COMMENTS |
608 G_KEY_FILE_KEEP_TRANSLATIONS,
617 /* Make sure the key file has a [Data Source] group. */
618 if (!g_key_file_has_group (key_file, PRIMARY_GROUP_NAME)) {
620 error, G_KEY_FILE_ERROR,
621 G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
622 _("Source file is missing a [%s] group"),
627 /* Load key file values from the [Data Source] group and from
628 * any other groups for which an extension object has already
629 * been created. Note that not all the extension classes may
630 * be registered at this point, so avoid attempting to create
631 * new extension objects here. Extension objects are created
632 * on-demand in e_source_get_extension(). */
634 source_load_from_key_file (
635 G_OBJECT (source), key_file, PRIMARY_GROUP_NAME);
637 g_hash_table_iter_init (&iter, source->priv->extensions);
638 while (g_hash_table_iter_next (&iter, &group_name, &extension))
639 source_load_from_key_file (extension, key_file, group_name);
645 source_notify_dbus_data_cb (EDBusSource *dbus_source,
649 GError *error = NULL;
651 g_rec_mutex_lock (&source->priv->lock);
653 /* Since the source data came from a GKeyFile structure on the
654 * server-side, this should never fail. But we'll print error
655 * messages to the terminal just in case. */
656 if (!source_parse_dbus_data (source, &error)) {
657 g_return_if_fail (error != NULL);
658 g_warning ("%s", error->message);
659 g_error_free (error);
662 g_rec_mutex_unlock (&source->priv->lock);
666 source_idle_changed_cb (gpointer user_data)
668 ESource *source = E_SOURCE (user_data);
670 /* If the ESource is still initializing itself in a different
671 * thread, skip the signal emission and try again on the next
672 * main loop iteration. This is a busy wait but it should be
673 * a very short wait. */
674 if (!source->priv->initialized)
677 g_mutex_lock (&source->priv->changed_lock);
678 if (source->priv->changed != NULL) {
679 g_source_unref (source->priv->changed);
680 source->priv->changed = NULL;
682 g_mutex_unlock (&source->priv->changed_lock);
684 g_signal_emit (source, signals[CHANGED], 0);
690 source_set_dbus_object (ESource *source,
691 EDBusObject *dbus_object)
693 /* D-Bus object will be NULL when configuring a new source. */
694 if (dbus_object == NULL)
697 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
698 g_return_if_fail (source->priv->dbus_object == NULL);
700 source->priv->dbus_object = g_object_ref (dbus_object);
704 source_set_main_context (ESource *source,
705 GMainContext *main_context)
707 g_return_if_fail (source->priv->main_context == NULL);
709 source->priv->main_context =
710 (main_context != NULL) ?
711 g_main_context_ref (main_context) :
712 g_main_context_ref_thread_default ();
716 source_set_uid (ESource *source,
719 /* The "uid" argument will usually be NULL unless called
720 * from e_source_new_with_uid(). If NULL, we'll pick up
721 * a UID in source_initable_init(). */
723 g_return_if_fail (source->priv->uid == NULL);
725 source->priv->uid = g_strdup (uid);
729 source_set_property (GObject *object,
734 switch (property_id) {
735 case PROP_DBUS_OBJECT:
736 source_set_dbus_object (
738 g_value_get_object (value));
741 case PROP_DISPLAY_NAME:
742 e_source_set_display_name (
744 g_value_get_string (value));
748 e_source_set_enabled (
750 g_value_get_boolean (value));
753 case PROP_MAIN_CONTEXT:
754 source_set_main_context (
756 g_value_get_boxed (value));
760 e_source_set_parent (
762 g_value_get_string (value));
768 g_value_get_string (value));
772 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
776 source_get_property (GObject *object,
781 switch (property_id) {
782 case PROP_DBUS_OBJECT:
783 g_value_take_object (
784 value, e_source_ref_dbus_object (
788 case PROP_DISPLAY_NAME:
789 g_value_take_string (
790 value, e_source_dup_display_name (
795 g_value_set_boolean (
796 value, e_source_get_enabled (
800 case PROP_MAIN_CONTEXT:
802 value, e_source_ref_main_context (
807 g_value_take_string (
808 value, e_source_dup_parent (
812 case PROP_REMOTE_CREATABLE:
813 g_value_set_boolean (
814 value, e_source_get_remote_creatable (
818 case PROP_REMOTE_DELETABLE:
819 g_value_set_boolean (
820 value, e_source_get_remote_deletable (
825 g_value_set_boolean (
826 value, e_source_get_removable (
831 g_value_take_string (
832 value, e_source_dup_uid (
837 g_value_set_boolean (
838 value, e_source_get_writable (
843 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
847 source_dispose (GObject *object)
849 ESourcePrivate *priv;
851 priv = E_SOURCE_GET_PRIVATE (object);
853 if (priv->dbus_object != NULL) {
854 EDBusObject *dbus_object;
855 EDBusSource *dbus_source;
857 dbus_object = E_DBUS_OBJECT (priv->dbus_object);
859 dbus_source = e_dbus_object_get_source (dbus_object);
860 if (dbus_source != NULL) {
861 g_signal_handlers_disconnect_matched (
862 dbus_source, G_SIGNAL_MATCH_DATA,
863 0, 0, NULL, NULL, object);
864 g_object_unref (dbus_source);
867 g_object_unref (priv->dbus_object);
868 priv->dbus_object = NULL;
871 if (priv->main_context != NULL) {
872 g_main_context_unref (priv->main_context);
873 priv->main_context = NULL;
876 /* XXX Maybe not necessary to acquire the lock? */
877 g_mutex_lock (&priv->changed_lock);
878 if (priv->changed != NULL) {
879 g_source_destroy (priv->changed);
880 g_source_unref (priv->changed);
881 priv->changed = NULL;
883 g_mutex_unlock (&priv->changed_lock);
885 g_hash_table_remove_all (priv->extensions);
887 /* Chain up to parent's dispose() method. */
888 G_OBJECT_CLASS (e_source_parent_class)->dispose (object);
892 source_finalize (GObject *object)
894 ESourcePrivate *priv;
896 priv = E_SOURCE_GET_PRIVATE (object);
898 g_mutex_clear (&priv->changed_lock);
899 g_mutex_clear (&priv->property_lock);
901 g_free (priv->display_name);
902 g_free (priv->collate_key);
903 g_free (priv->parent);
906 g_key_file_free (priv->key_file);
907 g_rec_mutex_clear (&priv->lock);
908 g_hash_table_destroy (priv->extensions);
910 /* Chain up to parent's finalize() method. */
911 G_OBJECT_CLASS (e_source_parent_class)->finalize (object);
915 source_notify (GObject *object,
918 if ((pspec->flags & E_SOURCE_PARAM_SETTING) != 0)
919 e_source_changed (E_SOURCE (object));
923 source_remove_sync (ESource *source,
924 GCancellable *cancellable,
927 EDBusSourceRemovable *dbus_interface = NULL;
928 GDBusObject *dbus_object;
931 dbus_object = e_source_ref_dbus_object (source);
932 if (dbus_object != NULL) {
934 e_dbus_object_get_source_removable (
935 E_DBUS_OBJECT (dbus_object));
936 g_object_unref (dbus_object);
939 if (dbus_interface == NULL) {
942 G_IO_ERROR_PERMISSION_DENIED,
943 _("Data source '%s' is not removable"),
944 e_source_get_display_name (source));
948 success = e_dbus_source_removable_call_remove_sync (
949 dbus_interface, cancellable, error);
951 g_object_unref (dbus_interface);
956 /* Helper for source_remove() */
958 source_remove_thread (GSimpleAsyncResult *simple,
960 GCancellable *cancellable)
962 GError *error = NULL;
964 e_source_remove_sync (E_SOURCE (object), cancellable, &error);
967 g_simple_async_result_take_error (simple, error);
971 source_remove (ESource *source,
972 GCancellable *cancellable,
973 GAsyncReadyCallback callback,
976 GSimpleAsyncResult *simple;
978 simple = g_simple_async_result_new (
979 G_OBJECT (source), callback, user_data, source_remove);
981 g_simple_async_result_set_check_cancellable (simple, cancellable);
983 g_simple_async_result_run_in_thread (
984 simple, source_remove_thread,
985 G_PRIORITY_DEFAULT, cancellable);
987 g_object_unref (simple);
991 source_remove_finish (ESource *source,
992 GAsyncResult *result,
995 GSimpleAsyncResult *simple;
997 g_return_val_if_fail (
998 g_simple_async_result_is_valid (
999 result, G_OBJECT (source), source_remove), FALSE);
1001 simple = G_SIMPLE_ASYNC_RESULT (result);
1003 /* Assume success unless a GError is set. */
1004 return !g_simple_async_result_propagate_error (simple, error);
1008 source_write_sync (ESource *source,
1009 GCancellable *cancellable,
1012 EDBusSourceWritable *dbus_interface = NULL;
1013 GDBusObject *dbus_object;
1017 dbus_object = e_source_ref_dbus_object (source);
1018 if (dbus_object != NULL) {
1020 e_dbus_object_get_source_writable (
1021 E_DBUS_OBJECT (dbus_object));
1022 g_object_unref (dbus_object);
1025 if (dbus_interface == NULL) {
1028 G_IO_ERROR_PERMISSION_DENIED,
1029 _("Data source '%s' is not writable"),
1030 e_source_get_display_name (source));
1034 data = e_source_to_string (source, NULL);
1036 success = e_dbus_source_writable_call_write_sync (
1037 dbus_interface, data, cancellable, error);
1041 g_object_unref (dbus_interface);
1046 /* Helper for source_write() */
1048 source_write_thread (GSimpleAsyncResult *simple,
1050 GCancellable *cancellable)
1052 GError *error = NULL;
1054 e_source_write_sync (E_SOURCE (object), cancellable, &error);
1057 g_simple_async_result_take_error (simple, error);
1061 source_write (ESource *source,
1062 GCancellable *cancellable,
1063 GAsyncReadyCallback callback,
1066 GSimpleAsyncResult *simple;
1068 simple = g_simple_async_result_new (
1069 G_OBJECT (source), callback, user_data, source_write);
1071 g_simple_async_result_set_check_cancellable (simple, cancellable);
1073 g_simple_async_result_run_in_thread (
1074 simple, source_write_thread,
1075 G_PRIORITY_DEFAULT, cancellable);
1077 g_object_unref (simple);
1081 source_write_finish (ESource *source,
1082 GAsyncResult *result,
1085 GSimpleAsyncResult *simple;
1087 g_return_val_if_fail (
1088 g_simple_async_result_is_valid (
1089 result, G_OBJECT (source), source_write), FALSE);
1091 simple = G_SIMPLE_ASYNC_RESULT (result);
1093 /* Assume success unless a GError is set. */
1094 return !g_simple_async_result_propagate_error (simple, error);
1098 source_remote_create_sync (ESource *source,
1099 ESource *scratch_source,
1100 GCancellable *cancellable,
1103 EDBusSourceRemoteCreatable *dbus_interface = NULL;
1104 GDBusObject *dbus_object;
1108 dbus_object = e_source_ref_dbus_object (source);
1109 if (dbus_object != NULL) {
1111 e_dbus_object_get_source_remote_creatable (
1112 E_DBUS_OBJECT (dbus_object));
1113 g_object_unref (dbus_object);
1116 if (dbus_interface == NULL) {
1119 G_IO_ERROR_NOT_SUPPORTED,
1120 _("Data source '%s' does not "
1121 "support creating remote resources"),
1122 e_source_get_display_name (source));
1126 uid = e_source_dup_uid (scratch_source);
1127 data = e_source_to_string (scratch_source, NULL);
1129 success = e_dbus_source_remote_creatable_call_create_sync (
1130 dbus_interface, uid, data, cancellable, error);
1135 g_object_unref (dbus_interface);
1140 /* Helper for source_remote_create() */
1142 source_remote_create_thread (GSimpleAsyncResult *simple,
1144 GCancellable *cancellable)
1146 AsyncContext *async_context;
1147 GError *error = NULL;
1149 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1151 e_source_remote_create_sync (
1153 async_context->scratch_source,
1154 cancellable, &error);
1157 g_simple_async_result_take_error (simple, error);
1161 source_remote_create (ESource *source,
1162 ESource *scratch_source,
1163 GCancellable *cancellable,
1164 GAsyncReadyCallback callback,
1167 GSimpleAsyncResult *simple;
1168 AsyncContext *async_context;
1170 async_context = g_slice_new0 (AsyncContext);
1171 async_context->scratch_source = g_object_ref (scratch_source);
1173 simple = g_simple_async_result_new (
1174 G_OBJECT (source), callback,
1175 user_data, source_remote_create);
1177 g_simple_async_result_set_check_cancellable (simple, cancellable);
1179 g_simple_async_result_set_op_res_gpointer (
1180 simple, async_context, (GDestroyNotify) async_context_free);
1182 g_simple_async_result_run_in_thread (
1183 simple, source_remote_create_thread,
1184 G_PRIORITY_DEFAULT, cancellable);
1186 g_object_unref (simple);
1190 source_remote_create_finish (ESource *source,
1191 GAsyncResult *result,
1194 GSimpleAsyncResult *simple;
1196 g_return_val_if_fail (
1197 g_simple_async_result_is_valid (
1198 result, G_OBJECT (source), source_remote_create), FALSE);
1200 simple = G_SIMPLE_ASYNC_RESULT (result);
1202 /* Assume success unless a GError is set. */
1203 return !g_simple_async_result_propagate_error (simple, error);
1207 source_remote_delete_sync (ESource *source,
1208 GCancellable *cancellable,
1211 EDBusSourceRemoteDeletable *dbus_interface = NULL;
1212 GDBusObject *dbus_object;
1215 dbus_object = e_source_ref_dbus_object (source);
1216 if (dbus_object != NULL) {
1218 e_dbus_object_get_source_remote_deletable (
1219 E_DBUS_OBJECT (dbus_object));
1220 g_object_unref (dbus_object);
1223 if (dbus_interface == NULL) {
1226 G_IO_ERROR_NOT_SUPPORTED,
1227 _("Data source '%s' does not "
1228 "support deleting remote resources"),
1229 e_source_get_display_name (source));
1233 success = e_dbus_source_remote_deletable_call_delete_sync (
1234 dbus_interface, cancellable, error);
1236 g_object_unref (dbus_interface);
1241 /* Helper for source_remote_delete() */
1243 source_remote_delete_thread (GSimpleAsyncResult *simple,
1245 GCancellable *cancellable)
1247 GError *error = NULL;
1249 e_source_remote_delete_sync (
1250 E_SOURCE (object), cancellable, &error);
1253 g_simple_async_result_take_error (simple, error);
1257 source_remote_delete (ESource *source,
1258 GCancellable *cancellable,
1259 GAsyncReadyCallback callback,
1262 GSimpleAsyncResult *simple;
1264 simple = g_simple_async_result_new (
1265 G_OBJECT (source), callback,
1266 user_data, source_remote_delete);
1268 g_simple_async_result_set_check_cancellable (simple, cancellable);
1270 g_simple_async_result_run_in_thread (
1271 simple, source_remote_delete_thread,
1272 G_PRIORITY_DEFAULT, cancellable);
1274 g_object_unref (simple);
1278 source_remote_delete_finish (ESource *source,
1279 GAsyncResult *result,
1282 GSimpleAsyncResult *simple;
1284 g_return_val_if_fail (
1285 g_simple_async_result_is_valid (
1286 result, G_OBJECT (source), source_remote_delete), FALSE);
1288 simple = G_SIMPLE_ASYNC_RESULT (result);
1290 /* Assume success unless a GError is set. */
1291 return !g_simple_async_result_propagate_error (simple, error);
1295 source_get_oauth2_access_token_sync (ESource *source,
1296 GCancellable *cancellable,
1297 gchar **out_access_token,
1298 gint *out_expires_in,
1301 EDBusSourceOAuth2Support *dbus_interface = NULL;
1302 GDBusObject *dbus_object;
1305 dbus_object = e_source_ref_dbus_object (source);
1306 if (dbus_object != NULL) {
1308 e_dbus_object_get_source_oauth2_support (
1309 E_DBUS_OBJECT (dbus_object));
1310 g_object_unref (dbus_object);
1313 if (dbus_interface == NULL) {
1316 G_IO_ERROR_NOT_SUPPORTED,
1317 _("Data source '%s' does not "
1318 "support OAuth 2.0 authentication"),
1319 e_source_get_display_name (source));
1323 success = e_dbus_source_oauth2_support_call_get_access_token_sync (
1324 dbus_interface, out_access_token,
1325 out_expires_in, cancellable, error);
1327 g_object_unref (dbus_interface);
1332 /* Helper for source_get_oauth2_access_token() */
1334 source_get_oauth2_access_token_thread (GSimpleAsyncResult *simple,
1336 GCancellable *cancellable)
1338 AsyncContext *async_context;
1339 GError *error = NULL;
1341 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1343 e_source_get_oauth2_access_token_sync (
1344 E_SOURCE (object), cancellable,
1345 &async_context->access_token,
1346 &async_context->expires_in,
1350 g_simple_async_result_take_error (simple, error);
1354 source_get_oauth2_access_token (ESource *source,
1355 GCancellable *cancellable,
1356 GAsyncReadyCallback callback,
1359 GSimpleAsyncResult *simple;
1360 AsyncContext *async_context;
1362 async_context = g_slice_new0 (AsyncContext);
1364 simple = g_simple_async_result_new (
1365 G_OBJECT (source), callback, user_data,
1366 source_get_oauth2_access_token);
1368 g_simple_async_result_set_check_cancellable (simple, cancellable);
1370 g_simple_async_result_set_op_res_gpointer (
1371 simple, async_context, (GDestroyNotify) async_context_free);
1373 g_simple_async_result_run_in_thread (
1374 simple, source_get_oauth2_access_token_thread,
1375 G_PRIORITY_DEFAULT, cancellable);
1377 g_object_unref (simple);
1381 source_get_oauth2_access_token_finish (ESource *source,
1382 GAsyncResult *result,
1383 gchar **out_access_token,
1384 gint *out_expires_in,
1387 GSimpleAsyncResult *simple;
1388 AsyncContext *async_context;
1390 g_return_val_if_fail (
1391 g_simple_async_result_is_valid (
1392 result, G_OBJECT (source),
1393 source_get_oauth2_access_token), FALSE);
1395 simple = G_SIMPLE_ASYNC_RESULT (result);
1396 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1398 if (g_simple_async_result_propagate_error (simple, error))
1401 g_return_val_if_fail (async_context->access_token != NULL, FALSE);
1403 if (out_access_token != NULL) {
1404 *out_access_token = async_context->access_token;
1405 async_context->access_token = NULL;
1408 if (out_expires_in != NULL)
1409 *out_expires_in = async_context->expires_in;
1415 source_initable_init (GInitable *initable,
1416 GCancellable *cancellable,
1420 gboolean success = TRUE;
1422 source = E_SOURCE (initable);
1424 /* The D-Bus object has the unique identifier (UID). */
1425 if (source->priv->dbus_object != NULL) {
1426 EDBusObject *dbus_object;
1427 EDBusSource *dbus_source;
1429 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
1431 /* An EDBusObject lacking an EDBusSource
1432 * interface indicates a programmer error. */
1433 dbus_source = e_dbus_object_get_source (dbus_object);
1434 g_return_val_if_fail (E_DBUS_IS_SOURCE (dbus_source), FALSE);
1436 /* The UID never changes, so we can cache a copy.
1438 * XXX Note, EServerSideSource may have already set this
1439 * by way of the "uid" construct-only property, hence
1440 * the g_free() call. Not a problem, we'll just free
1441 * our UID string and set it to the same value again. */
1442 g_free (source->priv->uid);
1443 source->priv->uid = e_dbus_source_dup_uid (dbus_source);
1446 dbus_source, "notify::data",
1447 G_CALLBACK (source_notify_dbus_data_cb), source);
1449 success = source_parse_dbus_data (source, error);
1451 g_object_unref (dbus_source);
1453 /* No D-Bus object implies we're configuring a new source,
1454 * so generate a new unique identifier (UID) unless one was
1455 * explicitly provided through e_source_new_with_uid(). */
1456 } else if (source->priv->uid == NULL) {
1457 source->priv->uid = e_uid_new ();
1460 /* Try to avoid a spurious "changed" emission. */
1461 g_mutex_lock (&source->priv->changed_lock);
1462 if (source->priv->changed != NULL) {
1463 g_source_destroy (source->priv->changed);
1464 g_source_unref (source->priv->changed);
1465 source->priv->changed = NULL;
1467 g_mutex_unlock (&source->priv->changed_lock);
1469 source->priv->initialized = TRUE;
1475 e_source_class_init (ESourceClass *class)
1477 GObjectClass *object_class;
1479 g_type_class_add_private (class, sizeof (ESourcePrivate));
1481 object_class = G_OBJECT_CLASS (class);
1482 object_class->set_property = source_set_property;
1483 object_class->get_property = source_get_property;
1484 object_class->dispose = source_dispose;
1485 object_class->finalize = source_finalize;
1486 object_class->notify = source_notify;
1488 class->remove_sync = source_remove_sync;
1489 class->remove = source_remove;
1490 class->remove_finish = source_remove_finish;
1491 class->write_sync = source_write_sync;
1492 class->write = source_write;
1493 class->write_finish = source_write_finish;
1494 class->remote_create_sync = source_remote_create_sync;
1495 class->remote_create = source_remote_create;
1496 class->remote_create_finish = source_remote_create_finish;
1497 class->remote_delete_sync = source_remote_delete_sync;
1498 class->remote_delete = source_remote_delete;
1499 class->remote_delete_finish = source_remote_delete_finish;
1500 class->get_oauth2_access_token_sync = source_get_oauth2_access_token_sync;
1501 class->get_oauth2_access_token = source_get_oauth2_access_token;
1502 class->get_oauth2_access_token_finish = source_get_oauth2_access_token_finish;
1504 g_object_class_install_property (
1507 g_param_spec_object (
1510 "The D-Bus object for the data source",
1513 G_PARAM_CONSTRUCT_ONLY |
1514 G_PARAM_STATIC_STRINGS));
1516 g_object_class_install_property (
1519 g_param_spec_string (
1522 "The human-readable name of the data source",
1526 G_PARAM_STATIC_STRINGS |
1527 E_SOURCE_PARAM_SETTING));
1529 g_object_class_install_property (
1532 g_param_spec_boolean (
1535 "Whether the data source is enabled",
1539 G_PARAM_STATIC_STRINGS |
1540 E_SOURCE_PARAM_SETTING));
1542 g_object_class_install_property (
1545 g_param_spec_boxed (
1548 "The main loop context on "
1549 "which to attach event sources",
1550 G_TYPE_MAIN_CONTEXT,
1552 G_PARAM_CONSTRUCT_ONLY |
1553 G_PARAM_STATIC_STRINGS));
1555 g_object_class_install_property (
1558 g_param_spec_string (
1561 "The unique identity of the parent data source",
1564 G_PARAM_STATIC_STRINGS |
1565 E_SOURCE_PARAM_SETTING));
1567 g_object_class_install_property (
1569 PROP_REMOTE_CREATABLE,
1570 g_param_spec_boolean (
1573 "Whether the data source "
1574 "can create remote resources",
1577 G_PARAM_STATIC_STRINGS));
1579 g_object_class_install_property (
1581 PROP_REMOTE_DELETABLE,
1582 g_param_spec_boolean (
1585 "Whether the data source "
1586 "can delete remote resources",
1589 G_PARAM_STATIC_STRINGS));
1591 g_object_class_install_property (
1594 g_param_spec_boolean (
1597 "Whether the data source is removable",
1600 G_PARAM_STATIC_STRINGS));
1602 g_object_class_install_property (
1605 g_param_spec_string (
1608 "The unique identity of the data source",
1611 G_PARAM_CONSTRUCT_ONLY |
1612 G_PARAM_STATIC_STRINGS));
1614 g_object_class_install_property (
1617 g_param_spec_boolean (
1620 "Whether the data source is writable",
1623 G_PARAM_STATIC_STRINGS));
1627 * @source: the #ESource that received the signal
1629 * The ::changed signal is emitted when a property in @source or
1630 * one of its extension objects changes. A common use for this
1631 * signal is to notify a #GtkTreeModel containing data collected
1632 * from #ESource<!-- -->s that it needs to update a row.
1634 signals[CHANGED] = g_signal_new (
1636 G_TYPE_FROM_CLASS (class),
1637 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
1638 G_STRUCT_OFFSET (ESourceClass, changed),
1640 g_cclosure_marshal_VOID__VOID,
1643 /* Register built-in ESourceExtension types. */
1644 g_type_ensure (E_TYPE_SOURCE_ADDRESS_BOOK);
1645 g_type_ensure (E_TYPE_SOURCE_ALARMS);
1646 g_type_ensure (E_TYPE_SOURCE_AUTHENTICATION);
1647 g_type_ensure (E_TYPE_SOURCE_AUTOCOMPLETE);
1648 g_type_ensure (E_TYPE_SOURCE_CALENDAR);
1649 g_type_ensure (E_TYPE_SOURCE_COLLECTION);
1650 g_type_ensure (E_TYPE_SOURCE_GOA);
1651 g_type_ensure (E_TYPE_SOURCE_MAIL_ACCOUNT);
1652 g_type_ensure (E_TYPE_SOURCE_MAIL_COMPOSITION);
1653 g_type_ensure (E_TYPE_SOURCE_MAIL_IDENTITY);
1654 g_type_ensure (E_TYPE_SOURCE_MAIL_SIGNATURE);
1655 g_type_ensure (E_TYPE_SOURCE_MAIL_SUBMISSION);
1656 g_type_ensure (E_TYPE_SOURCE_MAIL_TRANSPORT);
1657 g_type_ensure (E_TYPE_SOURCE_MDN);
1658 g_type_ensure (E_TYPE_SOURCE_MEMO_LIST);
1659 g_type_ensure (E_TYPE_SOURCE_OFFLINE);
1660 g_type_ensure (E_TYPE_SOURCE_OPENPGP);
1661 g_type_ensure (E_TYPE_SOURCE_REFRESH);
1662 g_type_ensure (E_TYPE_SOURCE_RESOURCE);
1663 g_type_ensure (E_TYPE_SOURCE_REVISION_GUARDS);
1664 g_type_ensure (E_TYPE_SOURCE_SECURITY);
1665 g_type_ensure (E_TYPE_SOURCE_SELECTABLE);
1666 g_type_ensure (E_TYPE_SOURCE_SMIME);
1667 g_type_ensure (E_TYPE_SOURCE_TASK_LIST);
1668 g_type_ensure (E_TYPE_SOURCE_UOA);
1669 g_type_ensure (E_TYPE_SOURCE_WEBDAV);
1673 e_source_initable_init (GInitableIface *interface)
1675 interface->init = source_initable_init;
1679 e_source_init (ESource *source)
1681 GHashTable *extensions;
1683 /* Don't do this as part of class initialization because it
1684 * loads Camel modules and can screw up introspection, which
1685 * occurs at compile-time before Camel modules are installed. */
1686 e_source_camel_register_types ();
1688 extensions = g_hash_table_new_full (
1689 (GHashFunc) g_str_hash,
1690 (GEqualFunc) g_str_equal,
1691 (GDestroyNotify) g_free,
1692 (GDestroyNotify) g_object_unref);
1694 source->priv = E_SOURCE_GET_PRIVATE (source);
1695 g_mutex_init (&source->priv->changed_lock);
1696 g_mutex_init (&source->priv->property_lock);
1697 source->priv->key_file = g_key_file_new ();
1698 source->priv->extensions = extensions;
1700 g_rec_mutex_init (&source->priv->lock);
1705 * @dbus_object: (allow-none): a #GDBusObject or %NULL
1706 * @main_context: (allow-none): a #GMainContext or %NULL
1707 * @error: return location for a #GError, or %NULL
1709 * Creates a new #ESource instance.
1711 * The #ESource::changed signal will be emitted from @main_context if given,
1712 * or else from the thread-default #GMainContext at the time this function is
1715 * The only time the function should be called outside of #ESourceRegistry
1716 * is to create a so-called "scratch" #ESource for editing in a Properties
1717 * window or an account setup assistant.
1719 * FIXME: Elaborate on scratch sources.
1721 * Returns: a new #ESource, or %NULL on error
1726 e_source_new (GDBusObject *dbus_object,
1727 GMainContext *main_context,
1730 if (dbus_object != NULL)
1731 g_return_val_if_fail (E_DBUS_IS_OBJECT (dbus_object), NULL);
1733 return g_initable_new (
1734 E_TYPE_SOURCE, NULL, error,
1735 "dbus-object", dbus_object,
1736 "main-context", main_context,
1741 * e_source_new_with_uid:
1742 * @uid: a new unique identifier string
1743 * @main_context: (allow-none): a #GMainContext or %NULL
1744 * @error: return location for a #GError, or %NULL
1746 * Creates a new "scratch" #ESource with a predetermined unique identifier.
1748 * The #ESource::changed signal will be emitted from @main_context if given,
1749 * or else from the thread-default #GMainContext at the time this function is
1752 * Returns: a new scratch #ESource, or %NULL on error
1757 e_source_new_with_uid (const gchar *uid,
1758 GMainContext *main_context,
1761 g_return_val_if_fail (uid != NULL, NULL);
1763 return g_initable_new (
1764 E_TYPE_SOURCE, NULL, error,
1765 "main-context", main_context,
1771 * @source: an #ESource
1773 * Generates a hash value for @source. This function is intended for
1774 * easily hashing an #ESource to add to a #GHashTable or similar data
1777 * Returns: a hash value for @source.
1782 e_source_hash (ESource *source)
1786 g_return_val_if_fail (E_IS_SOURCE (source), 0);
1788 uid = e_source_get_uid (source);
1790 return g_str_hash (uid);
1795 * @source1: the first #ESource
1796 * @source2: the second #ESource
1798 * Checks two #ESource instances for equality. #ESource instances are
1799 * equal if their unique identifier strings are equal.
1801 * Returns: %TRUE if @source1 and @source2 are equal
1806 e_source_equal (ESource *source1,
1809 const gchar *uid1, *uid2;
1811 g_return_val_if_fail (E_IS_SOURCE (source1), FALSE);
1812 g_return_val_if_fail (E_IS_SOURCE (source2), FALSE);
1814 if (source1 == source2)
1817 uid1 = e_source_get_uid (source1);
1818 uid2 = e_source_get_uid (source2);
1820 return g_str_equal (uid1, uid2);
1825 * @source: an #ESource
1827 * Emits the #ESource::changed signal from an idle callback in
1828 * @source's #ESource:main-context.
1830 * This function is primarily intended for use by #ESourceExtension
1831 * when emitting a #GObject::notify signal on one of its properties.
1836 e_source_changed (ESource *source)
1838 g_return_if_fail (E_IS_SOURCE (source));
1840 g_mutex_lock (&source->priv->changed_lock);
1841 if (source->priv->changed == NULL) {
1842 source->priv->changed = g_idle_source_new ();
1843 g_source_set_callback (
1844 source->priv->changed,
1845 source_idle_changed_cb,
1846 source, (GDestroyNotify) NULL);
1848 source->priv->changed,
1849 source->priv->main_context);
1851 g_mutex_unlock (&source->priv->changed_lock);
1856 * @source: an #ESource
1858 * Returns the unique identifier string for @source.
1860 * Returns: the UID for @source
1865 e_source_get_uid (ESource *source)
1867 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1869 return source->priv->uid;
1874 * @source: an #ESource
1876 * Thread-safe variation of e_source_get_uid().
1877 * Use this function when accessing @source from multiple threads.
1879 * The returned string should be freed with g_free() when no longer needed.
1881 * Returns: a newly-allocated copy of #ESource:uid
1886 e_source_dup_uid (ESource *source)
1888 const gchar *protected;
1891 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1893 /* Perhaps we don't need to lock the mutex since
1894 * this is a read-only property but it can't hurt. */
1896 g_mutex_lock (&source->priv->property_lock);
1898 protected = e_source_get_uid (source);
1899 duplicate = g_strdup (protected);
1901 g_mutex_unlock (&source->priv->property_lock);
1907 * e_source_get_parent:
1908 * @source: an #ESource
1910 * Returns the unique identifier string of the parent #ESource.
1912 * Returns: the UID of the parent #ESource
1917 e_source_get_parent (ESource *source)
1919 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1921 return source->priv->parent;
1925 * e_source_dup_parent:
1926 * @source: an #ESource
1928 * Thread-safe variation of e_source_get_parent().
1929 * Use this function when accessing @source from multiple threads.
1931 * The returned string should be freed with g_free() when no longer needed.
1933 * Returns: a newly-allocated copy of #ESource:parent
1938 e_source_dup_parent (ESource *source)
1940 const gchar *protected;
1943 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1945 g_mutex_lock (&source->priv->property_lock);
1947 protected = e_source_get_parent (source);
1948 duplicate = g_strdup (protected);
1950 g_mutex_unlock (&source->priv->property_lock);
1956 * e_source_set_parent:
1957 * @source: an #ESource
1958 * @parent: (allow-none): the UID of the parent #ESource, or %NULL
1960 * Identifies the parent of @source by its unique identifier string.
1961 * This can only be set prior to adding @source to an #ESourceRegistry.
1963 * The internal copy of #ESource:parent is automatically stripped of leading
1964 * and trailing whitespace. If the resulting string is empty, %NULL is set
1970 e_source_set_parent (ESource *source,
1971 const gchar *parent)
1973 g_return_if_fail (E_IS_SOURCE (source));
1975 g_mutex_lock (&source->priv->property_lock);
1977 if (g_strcmp0 (source->priv->parent, parent) == 0) {
1978 g_mutex_unlock (&source->priv->property_lock);
1982 g_free (source->priv->parent);
1983 source->priv->parent = e_util_strdup_strip (parent);
1985 g_mutex_unlock (&source->priv->property_lock);
1987 g_object_notify (G_OBJECT (source), "parent");
1991 * e_source_get_enabled:
1992 * @source: an #ESource
1994 * Returns %TRUE if @source is enabled.
1996 * An application should try to honor this setting if at all possible,
1997 * even if it does not provide a way to change the setting through its
1998 * user interface. Disabled data sources should generally be hidden.
2001 * This function does not take into account @source's ancestors in the
2002 * #ESource hierarchy, each of which have their own enabled state. If
2003 * any of @source's ancestors are disabled, then @source itself should
2004 * be treated as disabled. Use e_source_registry_check_enabled() to
2005 * easily check for this.
2008 * Returns: whether @source is enabled
2013 e_source_get_enabled (ESource *source)
2015 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2017 return source->priv->enabled;
2021 * e_source_set_enabled:
2022 * @source: an #ESource
2023 * @enabled: whether to enable @source
2025 * Enables or disables @source.
2027 * An application should try to honor this setting if at all possible,
2028 * even if it does not provide a way to change the setting through its
2029 * user interface. Disabled data sources should generally be hidden.
2034 e_source_set_enabled (ESource *source,
2037 g_return_if_fail (E_IS_SOURCE (source));
2039 if (source->priv->enabled == enabled)
2042 source->priv->enabled = enabled;
2044 g_object_notify (G_OBJECT (source), "enabled");
2048 * e_source_get_writable:
2049 * @source: an #ESource
2051 * Returns whether the D-Bus service will accept changes to @source.
2052 * If @source is not writable, calls to e_source_write() will fail.
2054 * Returns: whether @source is writable
2059 e_source_get_writable (ESource *source)
2061 EDBusObject *dbus_object;
2062 EDBusSourceWritable *dbus_source;
2064 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2066 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
2067 dbus_source = e_dbus_object_peek_source_writable (dbus_object);
2069 return (dbus_source != NULL);
2073 * e_source_get_removable:
2074 * @source: an #ESource
2076 * Returns whether the D-Bus service will allow @source to be removed.
2077 * If @source is not writable, calls to e_source_remove() will fail.
2079 * Returns: whether @source is removable
2084 e_source_get_removable (ESource *source)
2086 EDBusObject *dbus_object;
2087 EDBusSourceRemovable *dbus_source;
2089 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2091 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
2092 dbus_source = e_dbus_object_peek_source_removable (dbus_object);
2094 return (dbus_source != NULL);
2098 * e_source_get_remote_creatable:
2099 * @source: an #ESource
2101 * Returns whether new resources can be created on a remote server by
2102 * calling e_source_remote_create() on @source.
2104 * Generally this is only %TRUE if @source has an #ESourceCollection
2105 * extension, which means there is an #ECollectionBackend in the D-Bus
2106 * service that can handle create requests. If @source does not have
2107 * this capability, calls to e_source_remote_create() will fail.
2109 * Returns: whether @source can create remote resources
2114 e_source_get_remote_creatable (ESource *source)
2116 EDBusObject *dbus_object;
2117 EDBusSourceRemoteCreatable *dbus_source;
2119 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2121 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
2122 dbus_source = e_dbus_object_peek_source_remote_creatable (dbus_object);
2124 return (dbus_source != NULL);
2128 * e_source_get_remote_deletable:
2129 * @source: an #ESource
2131 * Returns whether the resource represented by @source can be deleted
2132 * from a remote server by calling e_source_remote_delete().
2134 * Generally this is only %TRUE if @source is a child of an #ESource
2135 * which has an #ESourceCollection extension, which means there is an
2136 * #ECollectionBackend in the D-Bus service that can handle delete
2137 * requests. If @source does not have this capability, calls to
2138 * e_source_remote_delete() will fail.
2140 * Returns: whether @source can delete remote resources
2145 e_source_get_remote_deletable (ESource *source)
2147 EDBusObject *dbus_object;
2148 EDBusSourceRemoteDeletable *dbus_source;
2150 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2152 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
2153 dbus_source = e_dbus_object_peek_source_remote_deletable (dbus_object);
2155 return (dbus_source != NULL);
2159 * e_source_get_extension:
2160 * @source: an #ESource
2161 * @extension_name: an extension name
2163 * Returns an instance of some #ESourceExtension subclass which registered
2164 * itself under @extension_name. If no such instance exists within @source,
2165 * one will be created. It is the caller's responsibility to know which
2166 * subclass is being returned.
2168 * If you just want to test for the existence of an extension within @source
2169 * without creating it, use e_source_has_extension().
2171 * Extension instances are owned by their #ESource and should not be
2172 * referenced directly. Instead, reference the #ESource instance and
2173 * use this function to fetch the extension instance as needed.
2175 * Returns: (type ESourceExtension) (transfer none): an instance of some
2176 * #ESourceExtension subclass
2181 e_source_get_extension (ESource *source,
2182 const gchar *extension_name)
2184 ESourceExtension *extension;
2185 GHashTable *hash_table;
2188 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2189 g_return_val_if_fail (extension_name != NULL, NULL);
2191 g_rec_mutex_lock (&source->priv->lock);
2193 /* Check if we already have the extension. */
2194 extension = g_hash_table_lookup (
2195 source->priv->extensions, extension_name);
2196 if (extension != NULL)
2199 /* Find all subclasses of ESourceExtensionClass. */
2200 hash_table = source_find_extension_classes ();
2201 class = g_hash_table_lookup (hash_table, extension_name);
2203 /* Create a new instance of the appropriate GType. */
2204 if (class != NULL) {
2205 extension = g_object_new (
2206 G_TYPE_FROM_CLASS (class),
2207 "source", source, NULL);
2208 source_load_from_key_file (
2209 G_OBJECT (extension),
2210 source->priv->key_file,
2212 g_hash_table_insert (
2213 source->priv->extensions,
2214 g_strdup (extension_name), extension);
2216 /* XXX Tie this into a debug setting for ESources. */
2219 "No registered GType for ESource "
2220 "extension '%s'", extension_name);
2224 g_hash_table_destroy (hash_table);
2227 g_rec_mutex_unlock (&source->priv->lock);
2233 * e_source_has_extension:
2234 * @source: an #ESource
2235 * @extension_name: an extension name
2237 * Checks whether @source has an #ESourceExtension with the given name.
2239 * Returns: %TRUE if @source has such an extension, %FALSE if not
2244 e_source_has_extension (ESource *source,
2245 const gchar *extension_name)
2247 ESourceExtension *extension;
2249 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2250 g_return_val_if_fail (extension_name != NULL, FALSE);
2252 g_rec_mutex_lock (&source->priv->lock);
2254 /* Two cases to check for, either one is good enough:
2255 * 1) Our internal GKeyFile has a group named 'extension_name'.
2256 * 2) Our 'extensions' table has an entry for 'extension_name'.
2258 * We have to check both data structures in case a new extension
2259 * not present in the GKeyFile was instantiated, but we have not
2260 * yet updated our internal GKeyFile. A common occurrence when
2261 * editing a brand new data source.
2263 * When checking the GKeyFile we want to actually fetch the
2264 * extension with e_source_get_extension() to make sure it's
2265 * a registered extension name and not just an arbitrary key
2266 * file group name. */
2268 if (g_key_file_has_group (source->priv->key_file, extension_name)) {
2269 extension = e_source_get_extension (source, extension_name);
2271 GHashTable *hash_table = source->priv->extensions;
2272 extension = g_hash_table_lookup (hash_table, extension_name);
2275 g_rec_mutex_unlock (&source->priv->lock);
2277 return (extension != NULL);
2281 * e_source_ref_dbus_object:
2282 * @source: an #ESource
2284 * Returns the #GDBusObject that was passed to e_source_new().
2286 * The returned #GDBusObject is referenced for thread-safety and must be
2287 * unreferenced with g_object_unref() when finished with it.
2289 * Returns: (transfer full): the #GDBusObject for @source, or %NULL
2294 e_source_ref_dbus_object (ESource *source)
2296 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2298 if (source->priv->dbus_object == NULL)
2301 return g_object_ref (source->priv->dbus_object);
2305 * e_source_ref_main_context:
2306 * @source: an #ESource
2308 * Returns the #GMainContext on which event sources for @source are to
2311 * The returned #GMainContext is referenced for thread-safety and must be
2312 * unreferenced with g_main_context_unref() when finished with it.
2314 * Returns: (transfer full): a #GMainContext
2319 e_source_ref_main_context (ESource *source)
2321 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2323 return g_main_context_ref (source->priv->main_context);
2327 * e_source_get_display_name:
2328 * @source: an #ESource
2330 * Returns the display name for @source. Use the display name to
2331 * represent the #ESource in a user interface.
2333 * Returns: the display name for @source
2338 e_source_get_display_name (ESource *source)
2340 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2342 return source->priv->display_name;
2346 * e_source_dup_display_name:
2347 * @source: an #ESource
2349 * Thread-safe variation of e_source_get_display_name().
2350 * Use this function when accessing @source from multiple threads.
2352 * The returned string should be freed with g_free() when no longer needed.
2354 * Returns: a newly-allocated copy of #ESource:display-name
2359 e_source_dup_display_name (ESource *source)
2361 const gchar *protected;
2364 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2366 g_mutex_lock (&source->priv->property_lock);
2368 protected = e_source_get_display_name (source);
2369 duplicate = g_strdup (protected);
2371 g_mutex_unlock (&source->priv->property_lock);
2377 * e_source_set_display_name:
2378 * @source: an #ESource
2379 * @display_name: a display name
2381 * Sets the display name for @source. The @display_name argument must be a
2382 * valid UTF-8 string. Use the display name to represent the #ESource in a
2385 * The internal copy of @display_name is automatically stripped of leading
2386 * and trailing whitespace.
2391 e_source_set_display_name (ESource *source,
2392 const gchar *display_name)
2394 g_return_if_fail (E_IS_SOURCE (source));
2395 g_return_if_fail (display_name != NULL);
2396 g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
2398 g_mutex_lock (&source->priv->property_lock);
2400 if (g_strcmp0 (source->priv->display_name, display_name) == 0) {
2401 g_mutex_unlock (&source->priv->property_lock);
2405 g_free (source->priv->display_name);
2406 source->priv->display_name = g_strdup (display_name);
2408 /* Strip leading and trailing whitespace. */
2409 g_strstrip (source->priv->display_name);
2411 /* This is used in e_source_compare_by_display_name(). */
2412 g_free (source->priv->collate_key);
2413 source->priv->collate_key = g_utf8_collate_key (display_name, -1);
2415 g_mutex_unlock (&source->priv->property_lock);
2417 g_object_notify (G_OBJECT (source), "display-name");
2421 * e_source_compare_by_display_name:
2422 * @source1: the first #ESource
2423 * @source2: the second #ESource
2425 * Compares two #ESource instances by their display names. Useful for
2426 * ordering sources in a user interface.
2428 * Returns: a negative value if @source1 compares before @source2, zero if
2429 * they compare equal, or a positive value if @source1 compares
2435 e_source_compare_by_display_name (ESource *source1,
2439 source1->priv->collate_key,
2440 source2->priv->collate_key);
2444 * e_source_to_string:
2445 * @source: an #ESource
2446 * @length: (allow-none): return location for the length of the returned
2449 * Outputs the current contents of @source as a key file string.
2450 * Free the returned string with g_free().
2452 * Returns: a newly-allocated string
2457 e_source_to_string (ESource *source,
2460 GHashTableIter iter;
2462 gpointer group_name;
2466 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2468 g_rec_mutex_lock (&source->priv->lock);
2470 key_file = source->priv->key_file;
2472 source_save_to_key_file (
2473 G_OBJECT (source), key_file, PRIMARY_GROUP_NAME);
2475 g_hash_table_iter_init (&iter, source->priv->extensions);
2476 while (g_hash_table_iter_next (&iter, &group_name, &extension))
2477 source_save_to_key_file (extension, key_file, group_name);
2479 data = g_key_file_to_data (key_file, length, NULL);
2481 g_rec_mutex_unlock (&source->priv->lock);
2487 * e_source_parameter_to_key:
2488 * @param_name: a #GParamSpec name
2490 * Converts a #GParamSpec name (e.g. "foo-bar" or "foo_bar")
2491 * to "CamelCase" for use as a #GKeyFile key (e.g. "FooBar").
2493 * This function is made public only to aid in account migration.
2494 * Applications should not need to use this.
2499 e_source_parameter_to_key (const gchar *param_name)
2501 gboolean uppercase = TRUE;
2505 g_return_val_if_fail (param_name != NULL, NULL);
2507 key = cp = g_malloc0 (strlen (param_name) + 1);
2509 for (ii = 0; param_name[ii] != '\0'; ii++) {
2510 if (g_ascii_isalnum (param_name[ii]) && uppercase) {
2511 *cp++ = g_ascii_toupper (param_name[ii]);
2513 } else if (param_name[ii] == '-' || param_name[ii] == '_')
2516 *cp++ = param_name[ii];
2523 * e_source_remove_sync:
2524 * @source: the #ESource to be removed
2525 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2526 * @error: return location for a #GError, or %NULL
2528 * Requests the D-Bus service to delete the key files for @source and all of
2529 * its descendants and broadcast their removal to all clients. The @source
2530 * must be #ESource:removable.
2532 * If an error occurs, the functon will set @error and return %FALSE.
2534 * Returns: %TRUE on success, %FALSE on failure
2539 e_source_remove_sync (ESource *source,
2540 GCancellable *cancellable,
2543 ESourceClass *class;
2545 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2547 class = E_SOURCE_GET_CLASS (source);
2548 g_return_val_if_fail (class->remove_sync != NULL, FALSE);
2550 return class->remove_sync (source, cancellable, error);
2555 * @source: the #ESource to be removed
2556 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2557 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2559 * @user_data: (closure): data to pass to the callback function
2561 * Asynchronously requests the D-Bus service to delete the key files for
2562 * @source and all of its descendants and broadcast their removal to all
2563 * clients. The @source must be #ESource:removable.
2565 * When the operation is finished, @callback will be called. You can then
2566 * call e_source_remove_finish() to get the result of the operation.
2571 e_source_remove (ESource *source,
2572 GCancellable *cancellable,
2573 GAsyncReadyCallback callback,
2576 ESourceClass *class;
2578 g_return_if_fail (E_IS_SOURCE (source));
2580 class = E_SOURCE_GET_CLASS (source);
2581 g_return_if_fail (class->remove != NULL);
2583 class->remove (source, cancellable, callback, user_data);
2587 * e_source_remove_finish:
2588 * @source: the #ESource to be removed
2589 * @result: a #GAsyncResult
2590 * @error: return location for a #GError, or %NULL
2592 * Finishes the operation started with e_source_remove(). If an
2593 * error occurred, the function will set @error and return %FALSE.
2595 * Returns: %TRUE on success, %FALSE of failure
2600 e_source_remove_finish (ESource *source,
2601 GAsyncResult *result,
2604 ESourceClass *class;
2606 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2607 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2609 class = E_SOURCE_GET_CLASS (source);
2610 g_return_val_if_fail (class->remove_finish != NULL, FALSE);
2612 return class->remove_finish (source, result, error);
2616 * e_source_write_sync:
2617 * @source: a writable #ESource
2618 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2619 * @error: return location for a #GError, or %NULL
2621 * Submits the current contents of @source to the D-Bus service to be
2622 * written to disk and broadcast to other clients. The @source must
2623 * be #ESource:writable.
2625 * If an error occurs, the functon will set @error and return %FALSE.
2627 * Returns: %TRUE on success, %FALSE on failure
2632 e_source_write_sync (ESource *source,
2633 GCancellable *cancellable,
2636 ESourceClass *class;
2638 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2640 class = E_SOURCE_GET_CLASS (source);
2641 g_return_val_if_fail (class->write_sync != NULL, FALSE);
2643 return class->write_sync (source, cancellable, error);
2648 * @source: a writable #ESource
2649 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2650 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2652 * @user_data: (closure): data to pass to the callback function
2654 * Asynchronously submits the current contents of @source to the D-Bus
2655 * service to be written to disk and broadcast to other clients. The
2656 * @source must be #ESource:writable.
2658 * When the operation is finished, @callback will be called. You can then
2659 * call e_source_write_finish() to get the result of the operation.
2664 e_source_write (ESource *source,
2665 GCancellable *cancellable,
2666 GAsyncReadyCallback callback,
2669 ESourceClass *class;
2671 g_return_if_fail (E_IS_SOURCE (source));
2673 class = E_SOURCE_GET_CLASS (source);
2674 g_return_if_fail (class->write != NULL);
2676 class->write (source, cancellable, callback, user_data);
2680 * e_source_write_finish:
2681 * @source: a writable #ESource
2682 * @result: a #GAsyncResult
2683 * @error: return location for a #GError, or %NULL
2685 * Finishes the operation started with e_source_write(). If an
2686 * error occurred, the function will set @error and return %FALSE.
2688 * Returns: %TRUE on success, %FALSE on failure
2693 e_source_write_finish (ESource *source,
2694 GAsyncResult *result,
2697 ESourceClass *class;
2699 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2700 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2702 class = E_SOURCE_GET_CLASS (source);
2703 g_return_val_if_fail (class->write_finish != NULL, FALSE);
2705 return class->write_finish (source, result, error);
2709 * e_source_remote_create_sync:
2710 * @source: an #ESource
2711 * @scratch_source: an #ESource describing the resource to create
2712 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2713 * @error: return location for a #GError, or %NULL
2715 * Creates a new remote resource by picking out relevant details from
2716 * @scratch_source. The @scratch_source must be an #ESource with no
2717 * #GDBusObject. The @source must be #ESource:remote-creatable.
2719 * The details required to create the resource vary by #ECollectionBackend,
2720 * but in most cases the @scratch_source need only define the resource type
2721 * (address book, calendar, etc.), a display name for the resource, and
2722 * possibly a server-side path or ID for the resource.
2724 * If an error occurs, the function will set @error and return %FALSE.
2726 * Returns: %TRUE on success, %FALSE on failure
2731 e_source_remote_create_sync (ESource *source,
2732 ESource *scratch_source,
2733 GCancellable *cancellable,
2736 ESourceClass *class;
2738 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2739 g_return_val_if_fail (E_IS_SOURCE (scratch_source), FALSE);
2741 class = E_SOURCE_GET_CLASS (source);
2742 g_return_val_if_fail (class->remote_create_sync != NULL, FALSE);
2744 return class->remote_create_sync (
2745 source, scratch_source, cancellable, error);
2749 * e_source_remote_create:
2750 * @source: an #ESource
2751 * @scratch_source: an #ESource describing the resource to create
2752 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2753 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2755 * @user_data: (closure): data to pass to the callback function
2757 * Asynchronously creates a new remote resource by picking out relevant
2758 * details from @scratch_source. The @scratch_source must be an #ESource
2759 * with no #GDBusObject. The @source must be #ESource:remote-creatable.
2761 * The details required to create the resource vary by #ECollectionBackend,
2762 * but in most cases the @scratch_source need only define the resource type
2763 * (address book, calendar, etc.), a display name for the resource, and
2764 * possibly a server-side path or ID for the resource.
2766 * When the operation is finished, @callback will be called. You can then
2767 * call 3_source_remote_create_finish() to get the result of the operation.
2772 e_source_remote_create (ESource *source,
2773 ESource *scratch_source,
2774 GCancellable *cancellable,
2775 GAsyncReadyCallback callback,
2778 ESourceClass *class;
2780 g_return_if_fail (E_IS_SOURCE (source));
2781 g_return_if_fail (E_IS_SOURCE (scratch_source));
2783 class = E_SOURCE_GET_CLASS (source);
2784 g_return_if_fail (class->remote_create != NULL);
2786 class->remote_create (
2787 source, scratch_source,
2788 cancellable, callback, user_data);
2792 * e_source_remote_create_finish:
2793 * @source: an #ESource
2794 * @result: a #GAsyncResult
2795 * @error: return location for a #GError, or %NULL
2797 * Finishes the operation started with e_source_remote_create(). If
2798 * an error occurred, the function will set @error and return %FALSE.
2800 * Returns: %TRUE on success, %FALSE on failure
2805 e_source_remote_create_finish (ESource *source,
2806 GAsyncResult *result,
2809 ESourceClass *class;
2811 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2813 class = E_SOURCE_GET_CLASS (source);
2814 g_return_val_if_fail (class->remote_create_finish != NULL, FALSE);
2816 return class->remote_create_finish (source, result, error);
2820 * e_source_remote_delete_sync:
2821 * @source: an #ESource
2822 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2823 * @error: return location for a #GError, or %NULL
2825 * Deletes the resource represented by @source from a remote server.
2826 * The @source must be #ESource:remote-deletable. This will also delete
2827 * the key file for @source and broadcast its removal to all clients,
2828 * similar to e_source_remove_sync().
2830 * If an error occurs, the function will set @error and return %FALSE.
2832 * Returns: %TRUE on success, %FALSE on failure
2837 e_source_remote_delete_sync (ESource *source,
2838 GCancellable *cancellable,
2841 ESourceClass *class;
2843 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2845 class = E_SOURCE_GET_CLASS (source);
2846 g_return_val_if_fail (class->remote_delete_sync != NULL, FALSE);
2848 return class->remote_delete_sync (source, cancellable, error);
2852 * e_source_remote_delete:
2853 * @source: an #ESource
2854 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2855 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2857 * @user_data: (closure): data to pass to the callback function
2859 * Asynchronously deletes the resource represented by @source from a remote
2860 * server. The @source must be #ESource:remote-deletable. This will also
2861 * delete the key file for @source and broadcast its removal to all clients,
2862 * similar to e_source_remove().
2864 * When the operation is finished, @callback will be called. You can then
2865 * call e_source_remote_delete_finish() to get the result of the operation.
2870 e_source_remote_delete (ESource *source,
2871 GCancellable *cancellable,
2872 GAsyncReadyCallback callback,
2875 ESourceClass *class;
2877 g_return_if_fail (E_IS_SOURCE (source));
2879 class = E_SOURCE_GET_CLASS (source);
2880 g_return_if_fail (class->remote_delete != NULL);
2882 class->remote_delete (source, cancellable, callback, user_data);
2886 * e_source_remote_delete_finish:
2887 * @source: an #ESource
2888 * @result: a #GAsyncResult
2889 * @error: return location for a #GError, or %NULL
2891 * Finishes the operation started with e_source_remote_delete(). If
2892 * an error occurred, the function will set @error and return %FALSE.
2894 * Returns: %TRUE on success, %FALSE on failure
2899 e_source_remote_delete_finish (ESource *source,
2900 GAsyncResult *result,
2903 ESourceClass *class;
2905 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2907 class = E_SOURCE_GET_CLASS (source);
2908 g_return_val_if_fail (class->remote_delete_finish != NULL, FALSE);
2910 return class->remote_delete_finish (source, result, error);
2914 * e_source_get_oauth2_access_token_sync:
2915 * @source: an #ESource
2916 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2917 * @out_access_token: (allow-none): return location for the access token,
2919 * @out_expires_in: (allow-none): return location for the token expiry,
2921 * @error: return location for a #GError, or %NULL
2923 * Obtains the OAuth 2.0 access token for @source along with its expiry
2924 * in seconds from the current time (or 0 if unknown). The @source must
2925 * have #ESource:supports-oauth2 set for this to work.
2927 * Free the returned access token with g_free() when finished with it.
2928 * If an error occurs, the function will set @error and return %FALSE.
2930 * Returns: %TRUE on success, %FALSE on failure
2935 e_source_get_oauth2_access_token_sync (ESource *source,
2936 GCancellable *cancellable,
2937 gchar **out_access_token,
2938 gint *out_expires_in,
2941 ESourceClass *class;
2943 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2945 class = E_SOURCE_GET_CLASS (source);
2946 g_return_val_if_fail (
2947 class->get_oauth2_access_token_sync != NULL, FALSE);
2949 return class->get_oauth2_access_token_sync (
2950 source, cancellable, out_access_token, out_expires_in, error);
2954 * e_source_get_oauth2_access_token:
2955 * @source: an #ESource
2956 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2957 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2959 * @user_data: (closure): data to pass to the callback function
2961 * Asynchronously obtains the OAuth 2.0 access token for @source along
2962 * with its expiry in seconds from the current time (or 0 if unknown).
2963 * The @source must have #ESource:supports-oauth2 set for this to work.
2965 * When the operation is finished, @callback will be called. You can then
2966 * call e_source_get_oauth2_access_token_finish() to get the result of the
2972 e_source_get_oauth2_access_token (ESource *source,
2973 GCancellable *cancellable,
2974 GAsyncReadyCallback callback,
2977 ESourceClass *class;
2979 g_return_if_fail (E_IS_SOURCE (source));
2981 class = E_SOURCE_GET_CLASS (source);
2982 g_return_if_fail (class->get_oauth2_access_token != NULL);
2984 return class->get_oauth2_access_token (
2985 source, cancellable, callback, user_data);
2989 * e_source_get_oauth2_access_token_finish:
2990 * @source: an #ESource
2991 * @result: a #GAsyncResult
2992 * @out_access_token: (allow-none): return location for the access token,
2994 * @out_expires_in: (allow-none): return location for the token expiry,
2996 * @error: return location for a #GError, or %NULL
2998 * Finishes the operation started with e_source_get_oauth2_access_token().
3000 * Free the returned access token with g_free() when finished with it.
3001 * If an error occurred, the function will set @error and return %FALSE.
3003 * Returns: %TRUE on success, %FALSE on failure
3008 e_source_get_oauth2_access_token_finish (ESource *source,
3009 GAsyncResult *result,
3010 gchar **out_access_token,
3011 gint *out_expires_in,
3014 ESourceClass *class;
3016 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
3017 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
3019 class = E_SOURCE_GET_CLASS (source);
3020 g_return_val_if_fail (
3021 class->get_oauth2_access_token_finish != NULL, FALSE);
3023 return class->get_oauth2_access_token_finish (
3024 source, result, out_access_token, out_expires_in, error);