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-security.h"
97 #include "e-source-selectable.h"
98 #include "e-source-smime.h"
99 #include "e-source-webdav.h"
101 #define E_SOURCE_GET_PRIVATE(obj) \
102 (G_TYPE_INSTANCE_GET_PRIVATE \
103 ((obj), E_TYPE_SOURCE, ESourcePrivate))
105 /* This forces the GType to be registered in a way that
106 * avoids a "statement with no effect" compiler warning. */
107 #define REGISTER_TYPE(type) \
108 (g_type_class_unref (g_type_class_ref (type)))
110 #define PRIMARY_GROUP_NAME "Data Source"
112 typedef struct _AsyncContext AsyncContext;
114 struct _ESourcePrivate {
115 GDBusObject *dbus_object;
116 GMainContext *main_context;
119 GMutex *changed_lock;
121 GMutex *property_lock;
128 /* The lock guards the key file and hash table. */
131 GStaticRecMutex lock;
132 GHashTable *extensions;
135 gboolean initialized;
138 struct _AsyncContext {
139 ESource *scratch_source;
149 PROP_REMOTE_CREATABLE,
150 PROP_REMOTE_DELETABLE,
161 static guint signals[LAST_SIGNAL];
163 /* Forward Declarations */
164 static void e_source_initable_init (GInitableIface *interface);
166 G_DEFINE_TYPE_WITH_CODE (
170 G_IMPLEMENT_INTERFACE (
172 e_source_initable_init))
175 async_context_free (AsyncContext *async_context)
177 if (async_context->scratch_source != NULL)
178 g_object_unref (async_context->scratch_source);
180 g_slice_free (AsyncContext, async_context);
184 source_find_extension_classes_rec (GType parent_type,
185 GHashTable *hash_table)
188 guint n_children, ii;
190 children = g_type_children (parent_type, &n_children);
192 for (ii = 0; ii < n_children; ii++) {
193 GType type = children[ii];
194 ESourceExtensionClass *class;
197 /* Recurse over the child's children. */
198 source_find_extension_classes_rec (type, hash_table);
200 /* Skip abstract types. */
201 if (G_TYPE_IS_ABSTRACT (type))
204 class = g_type_class_ref (type);
205 key = (gpointer) class->name;
208 g_hash_table_insert (hash_table, key, class);
210 g_type_class_unref (class);
217 source_find_extension_classes (void)
219 GHashTable *hash_table;
221 hash_table = g_hash_table_new_full (
222 (GHashFunc) g_str_hash,
223 (GEqualFunc) g_str_equal,
224 (GDestroyNotify) NULL,
225 (GDestroyNotify) g_type_class_unref);
227 source_find_extension_classes_rec (
228 E_TYPE_SOURCE_EXTENSION, hash_table);
234 source_localized_hack (GKeyFile *key_file,
235 const gchar *group_name,
237 const gchar *new_value)
239 const gchar * const *language_names;
242 /* XXX If we're changing a string key that has translations,
243 * set "key[$CURRENT_LOCALE]" (if available) to the new
244 * value so g_key_file_get_locale_string() will pick it
245 * up. This is not a perfect solution however. When a
246 * different locale is used the value may revert to its
247 * original localized string. Good enough for now. */
249 language_names = g_get_language_names ();
251 for (ii = 0; language_names[ii] != NULL; ii++) {
252 gboolean has_localized_key;
253 gchar *localized_key;
255 localized_key = g_strdup_printf (
256 "%s[%s]", key, language_names[ii]);
257 has_localized_key = g_key_file_has_key (
258 key_file, group_name, localized_key, NULL);
260 if (has_localized_key)
261 g_key_file_set_string (
262 key_file, group_name,
263 localized_key, new_value);
265 g_free (localized_key);
267 if (has_localized_key)
271 g_key_file_set_string (key_file, group_name, key, new_value);
275 source_set_key_file_from_property (GObject *object,
278 const gchar *group_name)
284 pvalue = g_slice_new0 (GValue);
285 g_value_init (pvalue, pspec->value_type);
286 g_object_get_property (object, pspec->name, pvalue);
288 svalue = g_slice_new0 (GValue);
289 g_value_init (svalue, G_TYPE_STRING);
291 key = e_source_parameter_to_key (pspec->name);
293 /* For the most part we can just transform any supported
294 * property type to a string, with a couple exceptions. */
296 /* Transforming a boolean GValue to a string results in
297 * "TRUE" or "FALSE" (all uppercase), but GKeyFile only
298 * recognizes "true" or "false" (all lowercase). So we
299 * have to use g_key_file_set_boolean(). */
300 if (G_VALUE_HOLDS_BOOLEAN (pvalue)) {
301 gboolean v_boolean = g_value_get_boolean (pvalue);
302 g_key_file_set_boolean (key_file, group_name, key, v_boolean);
304 /* Store UIN64 in hexa */
305 } else if (G_VALUE_HOLDS_UINT64 (pvalue)) {
308 v_str = g_strdup_printf (
309 "%016" G_GINT64_MODIFIER "X",
310 g_value_get_uint64 (pvalue));
311 g_key_file_set_string (key_file, group_name, key, v_str);
314 /* String GValues may contain characters that need escaping. */
315 } else if (G_VALUE_HOLDS_STRING (pvalue)) {
316 const gchar *v_string = g_value_get_string (pvalue);
318 if (v_string == NULL)
321 /* Special case for localized "DisplayName" keys. */
322 source_localized_hack (key_file, group_name, key, v_string);
324 /* Transforming an enum GValue to a string results in
325 * the GEnumValue name. We want the shorter nickname. */
326 } else if (G_VALUE_HOLDS_ENUM (pvalue)) {
327 GParamSpecEnum *enum_pspec;
328 GEnumClass *enum_class;
329 GEnumValue *enum_value;
332 enum_pspec = G_PARAM_SPEC_ENUM (pspec);
333 enum_class = enum_pspec->enum_class;
335 value = g_value_get_enum (pvalue);
336 enum_value = g_enum_get_value (enum_class, value);
338 if (enum_value == NULL) {
339 value = enum_pspec->default_value;
340 enum_value = g_enum_get_value (enum_class, value);
343 if (enum_value != NULL)
344 g_key_file_set_string (
345 key_file, group_name, key,
346 enum_value->value_nick);
348 } else if (G_VALUE_HOLDS (pvalue, G_TYPE_STRV)) {
349 const gchar **strv = g_value_get_boxed (pvalue);
353 length = g_strv_length ((gchar **) strv);
354 g_key_file_set_string_list (
355 key_file, group_name, key, strv, length);
357 /* For GValues holding a GFile object we save the URI. */
358 } else if (G_VALUE_HOLDS (pvalue, G_TYPE_FILE)) {
359 GFile *file = g_value_get_object (pvalue);
363 uri = g_file_get_uri (file);
364 g_key_file_set_string (
365 key_file, group_name, key,
366 (uri != NULL) ? uri : "");
369 } else if (g_value_transform (pvalue, svalue)) {
370 const gchar *value = g_value_get_string (svalue);
371 g_key_file_set_value (key_file, group_name, key, value);
375 g_value_unset (pvalue);
376 g_value_unset (svalue);
377 g_slice_free (GValue, pvalue);
378 g_slice_free (GValue, svalue);
382 source_set_property_from_key_file (GObject *object,
385 const gchar *group_name)
389 GError *error = NULL;
391 value = g_slice_new0 (GValue);
392 key = e_source_parameter_to_key (pspec->name);
394 if (G_IS_PARAM_SPEC_CHAR (pspec) ||
395 G_IS_PARAM_SPEC_UCHAR (pspec) ||
396 G_IS_PARAM_SPEC_INT (pspec) ||
397 G_IS_PARAM_SPEC_UINT (pspec) ||
398 G_IS_PARAM_SPEC_LONG (pspec) ||
399 G_IS_PARAM_SPEC_ULONG (pspec)) {
402 v_int = g_key_file_get_integer (
403 key_file, group_name, key, &error);
405 g_value_init (value, G_TYPE_INT);
406 g_value_set_int (value, v_int);
409 } else if (G_IS_PARAM_SPEC_INT64 (pspec)) {
412 v_int64 = g_key_file_get_int64 (
413 key_file, group_name, key, &error);
415 g_value_init (value, G_TYPE_INT64);
416 g_value_set_int64 (value, v_int64);
419 } else if (G_IS_PARAM_SPEC_UINT64 (pspec)) {
423 v_str = g_key_file_get_string (
424 key_file, group_name, key, &error);
426 v_uint64 = g_ascii_strtoull (v_str, NULL, 16);
428 g_value_init (value, G_TYPE_UINT64);
429 g_value_set_uint64 (value, v_uint64);
434 } else if (G_IS_PARAM_SPEC_BOOLEAN (pspec)) {
437 v_boolean = g_key_file_get_boolean (
438 key_file, group_name, key, &error);
440 g_value_init (value, G_TYPE_BOOLEAN);
441 g_value_set_boolean (value, v_boolean);
444 } else if (G_IS_PARAM_SPEC_ENUM (pspec)) {
447 nick = g_key_file_get_string (
448 key_file, group_name, key, &error);
450 GParamSpecEnum *enum_pspec;
451 GEnumValue *enum_value;
453 enum_pspec = G_PARAM_SPEC_ENUM (pspec);
454 enum_value = g_enum_get_value_by_nick (
455 enum_pspec->enum_class, nick);
456 if (enum_value != NULL) {
457 g_value_init (value, pspec->value_type);
458 g_value_set_enum (value, enum_value->value);
463 } else if (G_IS_PARAM_SPEC_FLOAT (pspec) ||
464 G_IS_PARAM_SPEC_DOUBLE (pspec)) {
467 v_double = g_key_file_get_double (
468 key_file, group_name, key, &error);
470 g_value_init (value, G_TYPE_DOUBLE);
471 g_value_set_double (value, v_double);
474 } else if (G_IS_PARAM_SPEC_STRING (pspec)) {
477 /* Get the localized string if present. */
478 v_string = g_key_file_get_locale_string (
479 key_file, group_name, key, NULL, &error);
481 g_value_init (value, G_TYPE_STRING);
482 g_value_take_string (value, v_string);
485 } else if (g_type_is_a (pspec->value_type, G_TYPE_STRV)) {
488 strv = g_key_file_get_string_list (
489 key_file, group_name, key, NULL, &error);
491 g_value_init (value, G_TYPE_STRV);
492 g_value_take_boxed (value, strv);
495 } else if (g_type_is_a (pspec->value_type, G_TYPE_FILE)) {
498 /* Create the GFile from the URI string. */
499 uri = g_key_file_get_locale_string (
500 key_file, group_name, key, NULL, &error);
503 if (uri != NULL && *uri != '\0')
504 file = g_file_new_for_uri (uri);
505 g_value_init (value, pspec->value_type);
506 g_value_take_object (value, file);
512 "No GKeyFile-to-GValue converter defined "
513 "for type '%s'", G_PARAM_SPEC_TYPE_NAME (pspec));
516 /* If a value could not be retrieved from the key
517 * file, restore the property to its default value. */
519 g_value_init (value, pspec->value_type);
520 g_param_value_set_default (pspec, value);
521 g_error_free (error);
524 if (G_IS_VALUE (value)) {
525 g_object_set_property (object, pspec->name, value);
526 g_value_unset (value);
529 g_slice_free (GValue, value);
534 source_load_from_key_file (GObject *object,
536 const gchar *group_name)
539 GParamSpec **properties;
540 guint n_properties, ii;
542 class = G_OBJECT_GET_CLASS (object);
543 properties = g_object_class_list_properties (class, &n_properties);
545 g_object_freeze_notify (object);
547 for (ii = 0; ii < n_properties; ii++) {
548 if (properties[ii]->flags & E_SOURCE_PARAM_SETTING) {
549 source_set_property_from_key_file (
550 object, properties[ii], key_file, group_name);
554 g_object_thaw_notify (object);
560 source_save_to_key_file (GObject *object,
562 const gchar *group_name)
565 GParamSpec **properties;
566 guint n_properties, ii;
568 class = G_OBJECT_GET_CLASS (object);
569 properties = g_object_class_list_properties (class, &n_properties);
571 for (ii = 0; ii < n_properties; ii++) {
572 if (properties[ii]->flags & E_SOURCE_PARAM_SETTING) {
573 source_set_key_file_from_property (
574 object, properties[ii], key_file, group_name);
582 source_parse_dbus_data (ESource *source,
586 EDBusObject *dbus_object;
587 EDBusSource *dbus_source;
594 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
596 dbus_source = e_dbus_object_get_source (dbus_object);
597 data = e_dbus_source_dup_data (dbus_source);
598 g_object_unref (dbus_source);
600 g_return_val_if_fail (data != NULL, FALSE);
602 key_file = source->priv->key_file;
604 success = g_key_file_load_from_data (
605 key_file, data, strlen (data),
606 G_KEY_FILE_KEEP_COMMENTS |
607 G_KEY_FILE_KEEP_TRANSLATIONS,
616 /* Make sure the key file has a [Data Source] group. */
617 if (!g_key_file_has_group (key_file, PRIMARY_GROUP_NAME)) {
619 error, G_KEY_FILE_ERROR,
620 G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
621 _("Source file is missing a [%s] group"),
626 /* Load key file values from the [Data Source] group and from
627 * any other groups for which an extension object has already
628 * been created. Note that not all the extension classes may
629 * be registered at this point, so avoid attempting to create
630 * new extension objects here. Extension objects are created
631 * on-demand in e_source_get_extension(). */
633 source_load_from_key_file (
634 G_OBJECT (source), key_file, PRIMARY_GROUP_NAME);
636 g_hash_table_iter_init (&iter, source->priv->extensions);
637 while (g_hash_table_iter_next (&iter, &group_name, &extension))
638 source_load_from_key_file (extension, key_file, group_name);
644 source_notify_dbus_data_cb (EDBusSource *dbus_source,
648 GError *error = NULL;
650 g_static_rec_mutex_lock (&source->priv->lock);
652 /* Since the source data came from a GKeyFile structure on the
653 * server-side, this should never fail. But we'll print error
654 * messages to the terminal just in case. */
655 if (!source_parse_dbus_data (source, &error)) {
656 g_return_if_fail (error != NULL);
657 g_warning ("%s", error->message);
658 g_error_free (error);
661 g_static_rec_mutex_unlock (&source->priv->lock);
665 source_idle_changed_cb (gpointer user_data)
667 ESource *source = E_SOURCE (user_data);
669 /* If the ESource is still initializing itself in a different
670 * thread, skip the signal emission and try again on the next
671 * main loop iteration. This is a busy wait but it should be
672 * a very short wait. */
673 if (!source->priv->initialized)
676 g_mutex_lock (source->priv->changed_lock);
677 if (source->priv->changed != NULL) {
678 g_source_unref (source->priv->changed);
679 source->priv->changed = NULL;
681 g_mutex_unlock (source->priv->changed_lock);
683 g_signal_emit (source, signals[CHANGED], 0);
689 source_set_dbus_object (ESource *source,
690 EDBusObject *dbus_object)
692 /* D-Bus object will be NULL when configuring a new source. */
693 if (dbus_object == NULL)
696 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
697 g_return_if_fail (source->priv->dbus_object == NULL);
699 source->priv->dbus_object = g_object_ref (dbus_object);
703 source_set_main_context (ESource *source,
704 GMainContext *main_context)
706 g_return_if_fail (source->priv->main_context == NULL);
708 source->priv->main_context =
709 (main_context != NULL) ?
710 g_main_context_ref (main_context) :
711 g_main_context_ref_thread_default ();
715 source_set_property (GObject *object,
720 switch (property_id) {
721 case PROP_DBUS_OBJECT:
722 source_set_dbus_object (
724 g_value_get_object (value));
727 case PROP_DISPLAY_NAME:
728 e_source_set_display_name (
730 g_value_get_string (value));
734 e_source_set_enabled (
736 g_value_get_boolean (value));
739 case PROP_MAIN_CONTEXT:
740 source_set_main_context (
742 g_value_get_boxed (value));
746 e_source_set_parent (
748 g_value_get_string (value));
752 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
756 source_get_property (GObject *object,
761 switch (property_id) {
762 case PROP_DBUS_OBJECT:
763 g_value_take_object (
764 value, e_source_ref_dbus_object (
768 case PROP_DISPLAY_NAME:
769 g_value_take_string (
770 value, e_source_dup_display_name (
775 g_value_set_boolean (
776 value, e_source_get_enabled (
780 case PROP_MAIN_CONTEXT:
782 value, e_source_ref_main_context (
787 g_value_take_string (
788 value, e_source_dup_parent (
792 case PROP_REMOTE_CREATABLE:
793 g_value_set_boolean (
794 value, e_source_get_remote_creatable (
798 case PROP_REMOTE_DELETABLE:
799 g_value_set_boolean (
800 value, e_source_get_remote_deletable (
805 g_value_set_boolean (
806 value, e_source_get_removable (
811 g_value_take_string (
812 value, e_source_dup_uid (
817 g_value_set_boolean (
818 value, e_source_get_writable (
823 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
827 source_dispose (GObject *object)
829 ESourcePrivate *priv;
831 priv = E_SOURCE_GET_PRIVATE (object);
833 if (priv->dbus_object != NULL) {
834 EDBusObject *dbus_object;
835 EDBusSource *dbus_source;
837 dbus_object = E_DBUS_OBJECT (priv->dbus_object);
839 dbus_source = e_dbus_object_get_source (dbus_object);
840 if (dbus_source != NULL) {
841 g_signal_handlers_disconnect_matched (
842 dbus_source, G_SIGNAL_MATCH_DATA,
843 0, 0, NULL, NULL, object);
844 g_object_unref (dbus_source);
847 g_object_unref (priv->dbus_object);
848 priv->dbus_object = NULL;
851 if (priv->main_context != NULL) {
852 g_main_context_unref (priv->main_context);
853 priv->main_context = NULL;
856 /* XXX Maybe not necessary to acquire the lock? */
857 g_mutex_lock (priv->changed_lock);
858 if (priv->changed != NULL) {
859 g_source_destroy (priv->changed);
860 g_source_unref (priv->changed);
861 priv->changed = NULL;
863 g_mutex_unlock (priv->changed_lock);
865 g_hash_table_remove_all (priv->extensions);
867 /* Chain up to parent's dispose() method. */
868 G_OBJECT_CLASS (e_source_parent_class)->dispose (object);
872 source_finalize (GObject *object)
874 ESourcePrivate *priv;
876 priv = E_SOURCE_GET_PRIVATE (object);
878 g_mutex_free (priv->changed_lock);
879 g_mutex_free (priv->property_lock);
881 g_free (priv->display_name);
882 g_free (priv->collate_key);
883 g_free (priv->parent);
886 g_key_file_free (priv->key_file);
887 g_static_rec_mutex_free (&priv->lock);
888 g_hash_table_destroy (priv->extensions);
890 /* Chain up to parent's finalize() method. */
891 G_OBJECT_CLASS (e_source_parent_class)->finalize (object);
895 source_notify (GObject *object,
898 if ((pspec->flags & E_SOURCE_PARAM_SETTING) != 0)
899 e_source_changed (E_SOURCE (object));
903 source_remove_sync (ESource *source,
904 GCancellable *cancellable,
907 EDBusObject *dbus_object;
908 EDBusSourceRemovable *dbus_source;
911 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
913 dbus_source = e_dbus_object_get_source_removable (dbus_object);
915 if (dbus_source == NULL) {
918 G_IO_ERROR_PERMISSION_DENIED,
919 _("Data source '%s' is not removable"),
920 e_source_get_display_name (source));
924 success = e_dbus_source_removable_call_remove_sync (
925 dbus_source, cancellable, error);
927 g_object_unref (dbus_source);
932 /* Helper for source_remove() */
934 source_remove_thread (GSimpleAsyncResult *simple,
936 GCancellable *cancellable)
938 GError *error = NULL;
940 e_source_remove_sync (E_SOURCE (object), cancellable, &error);
943 g_simple_async_result_take_error (simple, error);
947 source_remove (ESource *source,
948 GCancellable *cancellable,
949 GAsyncReadyCallback callback,
952 GSimpleAsyncResult *simple;
954 simple = g_simple_async_result_new (
955 G_OBJECT (source), callback, user_data, source_remove);
957 g_simple_async_result_set_check_cancellable (simple, cancellable);
959 g_simple_async_result_run_in_thread (
960 simple, source_remove_thread,
961 G_PRIORITY_DEFAULT, cancellable);
963 g_object_unref (simple);
967 source_remove_finish (ESource *source,
968 GAsyncResult *result,
971 GSimpleAsyncResult *simple;
973 g_return_val_if_fail (
974 g_simple_async_result_is_valid (
975 result, G_OBJECT (source), source_remove), FALSE);
977 simple = G_SIMPLE_ASYNC_RESULT (result);
979 /* Assume success unless a GError is set. */
980 return !g_simple_async_result_propagate_error (simple, error);
984 source_write_sync (ESource *source,
985 GCancellable *cancellable,
988 EDBusObject *dbus_object;
989 EDBusSourceWritable *dbus_source;
993 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
995 dbus_source = e_dbus_object_get_source_writable (dbus_object);
997 if (dbus_source == NULL) {
1000 G_IO_ERROR_PERMISSION_DENIED,
1001 _("Data source '%s' is not writable"),
1002 e_source_get_display_name (source));
1006 data = e_source_to_string (source, NULL);
1008 success = e_dbus_source_writable_call_write_sync (
1009 dbus_source, data, cancellable, error);
1013 g_object_unref (dbus_source);
1018 /* Helper for source_write() */
1020 source_write_thread (GSimpleAsyncResult *simple,
1022 GCancellable *cancellable)
1024 GError *error = NULL;
1026 e_source_write_sync (E_SOURCE (object), cancellable, &error);
1029 g_simple_async_result_take_error (simple, error);
1033 source_write (ESource *source,
1034 GCancellable *cancellable,
1035 GAsyncReadyCallback callback,
1038 GSimpleAsyncResult *simple;
1040 simple = g_simple_async_result_new (
1041 G_OBJECT (source), callback, user_data, source_write);
1043 g_simple_async_result_set_check_cancellable (simple, cancellable);
1045 g_simple_async_result_run_in_thread (
1046 simple, source_write_thread,
1047 G_PRIORITY_DEFAULT, cancellable);
1049 g_object_unref (simple);
1053 source_write_finish (ESource *source,
1054 GAsyncResult *result,
1057 GSimpleAsyncResult *simple;
1059 g_return_val_if_fail (
1060 g_simple_async_result_is_valid (
1061 result, G_OBJECT (source), source_write), FALSE);
1063 simple = G_SIMPLE_ASYNC_RESULT (result);
1065 /* Assume success unless a GError is set. */
1066 return !g_simple_async_result_propagate_error (simple, error);
1070 source_remote_create_sync (ESource *source,
1071 ESource *scratch_source,
1072 GCancellable *cancellable,
1075 EDBusSourceRemoteCreatable *dbus_interface = NULL;
1076 GDBusObject *dbus_object;
1080 dbus_object = e_source_ref_dbus_object (source);
1081 if (dbus_object != NULL) {
1083 e_dbus_object_get_source_remote_creatable (
1084 E_DBUS_OBJECT (dbus_object));
1085 g_object_unref (dbus_object);
1088 if (dbus_interface == NULL) {
1091 G_IO_ERROR_NOT_SUPPORTED,
1092 _("Data source '%s' does not "
1093 "support creating remote resources"),
1094 e_source_get_display_name (source));
1098 uid = e_source_dup_uid (scratch_source);
1099 data = e_source_to_string (scratch_source, NULL);
1101 success = e_dbus_source_remote_creatable_call_create_sync (
1102 dbus_interface, uid, data, cancellable, error);
1107 g_object_unref (dbus_interface);
1112 /* Helper for source_remote_create() */
1114 source_remote_create_thread (GSimpleAsyncResult *simple,
1116 GCancellable *cancellable)
1118 AsyncContext *async_context;
1119 GError *error = NULL;
1121 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1123 e_source_remote_create_sync (
1125 async_context->scratch_source,
1126 cancellable, &error);
1129 g_simple_async_result_take_error (simple, error);
1133 source_remote_create (ESource *source,
1134 ESource *scratch_source,
1135 GCancellable *cancellable,
1136 GAsyncReadyCallback callback,
1139 GSimpleAsyncResult *simple;
1140 AsyncContext *async_context;
1142 async_context = g_slice_new0 (AsyncContext);
1143 async_context->scratch_source = g_object_ref (scratch_source);
1145 simple = g_simple_async_result_new (
1146 G_OBJECT (source), callback,
1147 user_data, source_remote_create);
1149 g_simple_async_result_set_check_cancellable (simple, cancellable);
1151 g_simple_async_result_set_op_res_gpointer (
1152 simple, async_context, (GDestroyNotify) async_context_free);
1154 g_simple_async_result_run_in_thread (
1155 simple, source_remote_create_thread,
1156 G_PRIORITY_DEFAULT, cancellable);
1158 g_object_unref (simple);
1162 source_remote_create_finish (ESource *source,
1163 GAsyncResult *result,
1166 GSimpleAsyncResult *simple;
1168 g_return_val_if_fail (
1169 g_simple_async_result_is_valid (
1170 result, G_OBJECT (source), source_remote_create), FALSE);
1172 simple = G_SIMPLE_ASYNC_RESULT (result);
1174 /* Assume success unless a GError is set. */
1175 return !g_simple_async_result_propagate_error (simple, error);
1179 source_remote_delete_sync (ESource *source,
1180 GCancellable *cancellable,
1183 EDBusSourceRemoteDeletable *dbus_interface = NULL;
1184 GDBusObject *dbus_object;
1187 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1189 dbus_object = e_source_ref_dbus_object (source);
1190 if (dbus_object != NULL) {
1192 e_dbus_object_get_source_remote_deletable (
1193 E_DBUS_OBJECT (dbus_object));
1194 g_object_unref (dbus_object);
1197 if (dbus_interface == NULL) {
1200 G_IO_ERROR_NOT_SUPPORTED,
1201 _("Data source '%s' does not "
1202 "support deleting remote resources"),
1203 e_source_get_display_name (source));
1207 success = e_dbus_source_remote_deletable_call_delete_sync (
1208 dbus_interface, cancellable, error);
1210 g_object_unref (dbus_interface);
1215 /* Helper for source_remote_delete() */
1217 source_remote_delete_thread (GSimpleAsyncResult *simple,
1219 GCancellable *cancellable)
1221 GError *error = NULL;
1223 e_source_remote_delete_sync (
1224 E_SOURCE (object), cancellable, &error);
1227 g_simple_async_result_take_error (simple, error);
1231 source_remote_delete (ESource *source,
1232 GCancellable *cancellable,
1233 GAsyncReadyCallback callback,
1236 GSimpleAsyncResult *simple;
1238 simple = g_simple_async_result_new (
1239 G_OBJECT (source), callback,
1240 user_data, source_remote_delete);
1242 g_simple_async_result_set_check_cancellable (simple, cancellable);
1244 g_simple_async_result_run_in_thread (
1245 simple, source_remote_delete_thread,
1246 G_PRIORITY_DEFAULT, cancellable);
1248 g_object_unref (simple);
1252 source_remote_delete_finish (ESource *source,
1253 GAsyncResult *result,
1256 GSimpleAsyncResult *simple;
1258 g_return_val_if_fail (
1259 g_simple_async_result_is_valid (
1260 result, G_OBJECT (source), source_remote_delete), FALSE);
1262 simple = G_SIMPLE_ASYNC_RESULT (result);
1264 /* Assume success unless a GError is set. */
1265 return !g_simple_async_result_propagate_error (simple, error);
1269 source_initable_init (GInitable *initable,
1270 GCancellable *cancellable,
1274 gboolean success = TRUE;
1276 source = E_SOURCE (initable);
1278 /* The D-Bus object has the unique identifier (UID). */
1279 if (source->priv->dbus_object != NULL) {
1280 EDBusObject *dbus_object;
1281 EDBusSource *dbus_source;
1283 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
1285 /* An EDBusObject lacking an EDBusSource
1286 * interface indicates a programmer error. */
1287 dbus_source = e_dbus_object_get_source (dbus_object);
1288 g_return_val_if_fail (E_DBUS_IS_SOURCE (dbus_source), FALSE);
1290 /* Allow authentication prompts for a data source
1291 * when a new client-side proxy object is created.
1292 * The thought being if you cancel an authentication
1293 * prompt you won't be bothered again until you start
1294 * (or restart) a new E-D-S client app.
1296 * Failure here is non-fatal, ignore errors.
1298 * XXX Only GDBusProxy objects may call this. Sources
1299 * created server-side can't invoke remote methods.
1301 if (G_IS_DBUS_PROXY (dbus_source))
1302 e_dbus_source_call_allow_auth_prompt_sync (
1303 dbus_source, cancellable, NULL);
1305 /* The UID never changes, so we can cache a copy. */
1306 source->priv->uid = e_dbus_source_dup_uid (dbus_source);
1309 dbus_source, "notify::data",
1310 G_CALLBACK (source_notify_dbus_data_cb), source);
1312 success = source_parse_dbus_data (source, error);
1314 g_object_unref (dbus_source);
1316 /* No D-Bus object implies we're configuring a new source,
1317 * so generate a new unique identifier (UID) for it. */
1319 source->priv->uid = e_uid_new ();
1322 /* Try to avoid a spurious "changed" emission. */
1323 g_mutex_lock (source->priv->changed_lock);
1324 if (source->priv->changed != NULL) {
1325 g_source_destroy (source->priv->changed);
1326 g_source_unref (source->priv->changed);
1327 source->priv->changed = NULL;
1329 g_mutex_unlock (source->priv->changed_lock);
1331 source->priv->initialized = TRUE;
1337 e_source_class_init (ESourceClass *class)
1339 GObjectClass *object_class;
1341 g_type_class_add_private (class, sizeof (ESourcePrivate));
1343 object_class = G_OBJECT_CLASS (class);
1344 object_class->set_property = source_set_property;
1345 object_class->get_property = source_get_property;
1346 object_class->dispose = source_dispose;
1347 object_class->finalize = source_finalize;
1348 object_class->notify = source_notify;
1350 class->remove_sync = source_remove_sync;
1351 class->remove = source_remove;
1352 class->remove_finish = source_remove_finish;
1353 class->write_sync = source_write_sync;
1354 class->write = source_write;
1355 class->write_finish = source_write_finish;
1356 class->remote_create_sync = source_remote_create_sync;
1357 class->remote_create = source_remote_create;
1358 class->remote_create_finish = source_remote_create_finish;
1359 class->remote_delete_sync = source_remote_delete_sync;
1360 class->remote_delete = source_remote_delete;
1361 class->remote_delete_finish = source_remote_delete_finish;
1363 g_object_class_install_property (
1366 g_param_spec_object (
1369 "The D-Bus object for the data source",
1372 G_PARAM_CONSTRUCT_ONLY |
1373 G_PARAM_STATIC_STRINGS));
1375 g_object_class_install_property (
1378 g_param_spec_string (
1381 "The human-readable name of the data source",
1385 G_PARAM_STATIC_STRINGS |
1386 E_SOURCE_PARAM_SETTING));
1388 g_object_class_install_property (
1391 g_param_spec_boolean (
1394 "Whether the data source is enabled",
1398 G_PARAM_STATIC_STRINGS |
1399 E_SOURCE_PARAM_SETTING));
1401 g_object_class_install_property (
1404 g_param_spec_boxed (
1407 "The GMainContext used for signal emissions",
1408 G_TYPE_MAIN_CONTEXT,
1410 G_PARAM_CONSTRUCT_ONLY |
1411 G_PARAM_STATIC_STRINGS));
1413 g_object_class_install_property (
1416 g_param_spec_string (
1419 "The unique identity of the parent data source",
1422 G_PARAM_STATIC_STRINGS |
1423 E_SOURCE_PARAM_SETTING));
1425 g_object_class_install_property (
1427 PROP_REMOTE_CREATABLE,
1428 g_param_spec_boolean (
1431 "Whether the data source "
1432 "can create remote resources",
1435 G_PARAM_STATIC_STRINGS));
1437 g_object_class_install_property (
1439 PROP_REMOTE_DELETABLE,
1440 g_param_spec_boolean (
1443 "Whether the data source "
1444 "can delete remote resources",
1447 G_PARAM_STATIC_STRINGS));
1449 g_object_class_install_property (
1452 g_param_spec_boolean (
1455 "Whether the data source is removable",
1458 G_PARAM_STATIC_STRINGS));
1460 g_object_class_install_property (
1463 g_param_spec_string (
1466 "The unique identity of the data source",
1469 G_PARAM_STATIC_STRINGS));
1471 g_object_class_install_property (
1474 g_param_spec_boolean (
1477 "Whether the data source is writable",
1480 G_PARAM_STATIC_STRINGS));
1484 * @source: the #ESource that received the signal
1486 * The ::changed signal is emitted when a property in @source or
1487 * one of its extension objects changes. A common use for this
1488 * signal is to notify a #GtkTreeModel containing data collected
1489 * from #ESource<!-- -->s that it needs to update a row.
1491 signals[CHANGED] = g_signal_new (
1493 G_TYPE_FROM_CLASS (class),
1494 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
1495 G_STRUCT_OFFSET (ESourceClass, changed),
1497 g_cclosure_marshal_VOID__VOID,
1500 /* Register built-in ESourceExtension types. */
1501 REGISTER_TYPE (E_TYPE_SOURCE_ADDRESS_BOOK);
1502 REGISTER_TYPE (E_TYPE_SOURCE_ALARMS);
1503 REGISTER_TYPE (E_TYPE_SOURCE_AUTHENTICATION);
1504 REGISTER_TYPE (E_TYPE_SOURCE_AUTOCOMPLETE);
1505 REGISTER_TYPE (E_TYPE_SOURCE_CALENDAR);
1506 REGISTER_TYPE (E_TYPE_SOURCE_COLLECTION);
1507 REGISTER_TYPE (E_TYPE_SOURCE_GOA);
1508 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_ACCOUNT);
1509 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_COMPOSITION);
1510 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_IDENTITY);
1511 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_SIGNATURE);
1512 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_SUBMISSION);
1513 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_TRANSPORT);
1514 REGISTER_TYPE (E_TYPE_SOURCE_MDN);
1515 REGISTER_TYPE (E_TYPE_SOURCE_MEMO_LIST);
1516 REGISTER_TYPE (E_TYPE_SOURCE_OFFLINE);
1517 REGISTER_TYPE (E_TYPE_SOURCE_OPENPGP);
1518 REGISTER_TYPE (E_TYPE_SOURCE_REFRESH);
1519 REGISTER_TYPE (E_TYPE_SOURCE_RESOURCE);
1520 REGISTER_TYPE (E_TYPE_SOURCE_SECURITY);
1521 REGISTER_TYPE (E_TYPE_SOURCE_SELECTABLE);
1522 REGISTER_TYPE (E_TYPE_SOURCE_SMIME);
1523 REGISTER_TYPE (E_TYPE_SOURCE_TASK_LIST);
1524 REGISTER_TYPE (E_TYPE_SOURCE_WEBDAV);
1528 e_source_initable_init (GInitableIface *interface)
1530 interface->init = source_initable_init;
1534 e_source_init (ESource *source)
1536 GHashTable *extensions;
1538 /* Don't do this as part of class initialization because it
1539 * loads Camel modules and can screw up introspection, which
1540 * occurs at compile-time before Camel modules are installed. */
1541 e_source_camel_register_types ();
1543 extensions = g_hash_table_new_full (
1544 (GHashFunc) g_str_hash,
1545 (GEqualFunc) g_str_equal,
1546 (GDestroyNotify) g_free,
1547 (GDestroyNotify) g_object_unref);
1549 source->priv = E_SOURCE_GET_PRIVATE (source);
1550 source->priv->changed_lock = g_mutex_new ();
1551 source->priv->property_lock = g_mutex_new ();
1552 source->priv->key_file = g_key_file_new ();
1553 source->priv->extensions = extensions;
1555 g_static_rec_mutex_init (&source->priv->lock);
1560 * @dbus_object: (allow-none): a #GDBusObject or %NULL
1561 * @main_context: (allow-none): a #GMainContext or %NULL
1562 * @error: return location for a #GError, or %NULL
1564 * Creates a new #ESource instance.
1566 * The #ESource::changed signal will be emitted from @main_context if given,
1567 * or else from the thread-default #GMainContext at the time this function is
1570 * The only time the function should be called outside of #ESourceRegistry
1571 * is to create a so-called "scratch" #ESource for editing in a Properties
1572 * window or an account setup assistant.
1574 * FIXME: Elaborate on scratch sources.
1576 * Returns: a new #ESource, or %NULL on error
1581 e_source_new (GDBusObject *dbus_object,
1582 GMainContext *main_context,
1585 if (dbus_object != NULL)
1586 g_return_val_if_fail (E_DBUS_IS_OBJECT (dbus_object), NULL);
1588 return g_initable_new (
1589 E_TYPE_SOURCE, NULL, error,
1590 "dbus-object", dbus_object,
1591 "main-context", main_context,
1597 * @source: an #ESource
1599 * Generates a hash value for @source. This function is intended for
1600 * easily hashing an #ESource to add to a #GHashTable or similar data
1603 * Returns: a hash value for @source.
1608 e_source_hash (ESource *source)
1612 g_return_val_if_fail (E_IS_SOURCE (source), 0);
1614 uid = e_source_get_uid (source);
1616 return g_str_hash (uid);
1621 * @source1: the first #ESource
1622 * @source2: the second #ESource
1624 * Checks two #ESource instances for equality. #ESource instances are
1625 * equal if their unique identifier strings are equal.
1627 * Returns: %TRUE if @source1 and @source2 are equal
1632 e_source_equal (ESource *source1,
1635 const gchar *uid1, *uid2;
1637 g_return_val_if_fail (E_IS_SOURCE (source1), FALSE);
1638 g_return_val_if_fail (E_IS_SOURCE (source2), FALSE);
1640 if (source1 == source2)
1643 uid1 = e_source_get_uid (source1);
1644 uid2 = e_source_get_uid (source2);
1646 return g_str_equal (uid1, uid2);
1651 * @source: an #ESource
1653 * Emits the #ESource::changed signal from an idle callback in
1654 * @source's #ESource:main-context.
1656 * This function is primarily intended for use by #ESourceExtension
1657 * when emitting a #GObject::notify signal on one of its properties.
1662 e_source_changed (ESource *source)
1664 g_return_if_fail (E_IS_SOURCE (source));
1666 g_mutex_lock (source->priv->changed_lock);
1667 if (source->priv->changed == NULL) {
1668 source->priv->changed = g_idle_source_new ();
1669 g_source_set_callback (
1670 source->priv->changed,
1671 source_idle_changed_cb,
1672 source, (GDestroyNotify) NULL);
1674 source->priv->changed,
1675 source->priv->main_context);
1677 g_mutex_unlock (source->priv->changed_lock);
1682 * @source: an #ESource
1684 * Returns the unique identifier string for @source.
1686 * Returns: the UID for @source
1691 e_source_get_uid (ESource *source)
1693 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1695 return source->priv->uid;
1700 * @source: an #ESource
1702 * Thread-safe variation of e_source_get_uid().
1703 * Use this function when accessing @source from multiple threads.
1705 * The returned string should be freed with g_free() when no longer needed.
1707 * Returns: a newly-allocated copy of #ESource:uid
1712 e_source_dup_uid (ESource *source)
1714 const gchar *protected;
1717 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1719 /* Perhaps we don't need to lock the mutex since
1720 * this is a read-only property but it can't hurt. */
1722 g_mutex_lock (source->priv->property_lock);
1724 protected = e_source_get_uid (source);
1725 duplicate = g_strdup (protected);
1727 g_mutex_unlock (source->priv->property_lock);
1733 * e_source_get_parent:
1734 * @source: an #ESource
1736 * Returns the unique identifier string of the parent #ESource.
1738 * Returns: the UID of the parent #ESource
1743 e_source_get_parent (ESource *source)
1745 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1747 return source->priv->parent;
1751 * e_source_dup_parent:
1752 * @source: an #ESource
1754 * Thread-safe variation of e_source_get_parent().
1755 * Use this function when accessing @source from multiple threads.
1757 * The returned string should be freed with g_free() when no longer needed.
1759 * Returns: a newly-allocated copy of #ESource:parent
1764 e_source_dup_parent (ESource *source)
1766 const gchar *protected;
1769 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1771 g_mutex_lock (source->priv->property_lock);
1773 protected = e_source_get_parent (source);
1774 duplicate = g_strdup (protected);
1776 g_mutex_unlock (source->priv->property_lock);
1782 * e_source_set_parent:
1783 * @source: an #ESource
1784 * @parent: (allow-none): the UID of the parent #ESource, or %NULL
1786 * Identifies the parent of @source by its unique identifier string.
1787 * This can only be set prior to adding @source to an #ESourceRegistry.
1789 * The internal copy of #ESource:parent is automatically stripped of leading
1790 * and trailing whitespace. If the resulting string is empty, %NULL is set
1796 e_source_set_parent (ESource *source,
1797 const gchar *parent)
1799 g_return_if_fail (E_IS_SOURCE (source));
1801 g_mutex_lock (source->priv->property_lock);
1803 if (g_strcmp0 (source->priv->parent, parent) == 0) {
1804 g_mutex_unlock (source->priv->property_lock);
1808 g_free (source->priv->parent);
1809 source->priv->parent = e_util_strdup_strip (parent);
1811 g_mutex_unlock (source->priv->property_lock);
1813 g_object_notify (G_OBJECT (source), "parent");
1817 * e_source_get_enabled:
1818 * @source: an #ESource
1820 * Returns %TRUE if @source is enabled.
1822 * An application should try to honor this setting if at all possible,
1823 * even if it does not provide a way to change the setting through its
1824 * user interface. Disabled data sources should generally be hidden.
1826 * Returns: whether @source is enabled
1831 e_source_get_enabled (ESource *source)
1833 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1835 return source->priv->enabled;
1839 * e_source_set_enabled:
1840 * @source: an #ESource
1841 * @enabled: whether to enable @source
1843 * Enables or disables @source.
1845 * An application should try to honor this setting if at all possible,
1846 * even if it does not provide a way to change the setting through its
1847 * user interface. Disabled data sources should generally be hidden.
1852 e_source_set_enabled (ESource *source,
1855 g_return_if_fail (E_IS_SOURCE (source));
1857 if (source->priv->enabled == enabled)
1860 source->priv->enabled = enabled;
1862 g_object_notify (G_OBJECT (source), "enabled");
1866 * e_source_get_writable:
1867 * @source: an #ESource
1869 * Returns whether the D-Bus service will accept changes to @source.
1870 * If @source is not writable, calls to e_source_write() will fail.
1872 * Returns: whether @source is writable
1877 e_source_get_writable (ESource *source)
1879 EDBusObject *dbus_object;
1880 EDBusSourceWritable *dbus_source;
1882 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1884 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
1885 dbus_source = e_dbus_object_peek_source_writable (dbus_object);
1887 return (dbus_source != NULL);
1891 * e_source_get_removable:
1892 * @source: an #ESource
1894 * Returns whether the D-Bus service will allow @source to be removed.
1895 * If @source is not writable, calls to e_source_remove() will fail.
1897 * Returns: whether @source is removable
1902 e_source_get_removable (ESource *source)
1904 EDBusObject *dbus_object;
1905 EDBusSourceRemovable *dbus_source;
1907 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1909 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
1910 dbus_source = e_dbus_object_peek_source_removable (dbus_object);
1912 return (dbus_source != NULL);
1916 * e_source_get_remote_creatable:
1917 * @source: an #ESource
1919 * Returns whether new resources can be created on a remote server by
1920 * calling e_source_remote_create() on @source.
1922 * Generally this is only %TRUE if @source has an #ESourceCollection
1923 * extension, which means there is an #ECollectionBackend in the D-Bus
1924 * service that can handle create requests. If @source does not have
1925 * this capability, calls to e_source_remote_create() will fail.
1927 * Returns: whether @source can create remote resources
1932 e_source_get_remote_creatable (ESource *source)
1934 EDBusObject *dbus_object;
1935 EDBusSourceRemoteCreatable *dbus_source;
1937 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1939 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
1940 dbus_source = e_dbus_object_peek_source_remote_creatable (dbus_object);
1942 return (dbus_source != NULL);
1946 * e_source_get_remote_deletable:
1947 * @source: an #ESource
1949 * Returns whether the resource represented by @source can be deleted
1950 * from a remote server by calling e_source_remote_delete().
1952 * Generally this is only %TRUE if @source is a child of an #ESource
1953 * which has an #ESourceCollection extension, which means there is an
1954 * #ECollectionBackend in the D-Bus service that can handle delete
1955 * requests. If @source does not have this capability, calls to
1956 * e_source_remote_delete() will fail.
1958 * Returns: whether @source can delete remote resources
1963 e_source_get_remote_deletable (ESource *source)
1965 EDBusObject *dbus_object;
1966 EDBusSourceRemoteDeletable *dbus_source;
1968 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1970 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
1971 dbus_source = e_dbus_object_peek_source_remote_deletable (dbus_object);
1973 return (dbus_source != NULL);
1977 * e_source_get_extension:
1978 * @source: an #ESource
1979 * @extension_name: an extension name
1981 * Returns an instance of some #ESourceExtension subclass which registered
1982 * itself under @extension_name. If no such instance exists within @source,
1983 * one will be created. It is the caller's responsibility to know which
1984 * subclass is being returned.
1986 * If you just want to test for the existence of an extension within @source
1987 * without creating it, use e_source_has_extension().
1989 * Extension instances are owned by their #ESource and should not be
1990 * referenced directly. Instead, reference the #ESource instance and
1991 * use this function to fetch the extension instance as needed.
1993 * Returns: (type ESourceExtension) (transfer none): an instance of some
1994 * #ESourceExtension subclass
1999 e_source_get_extension (ESource *source,
2000 const gchar *extension_name)
2002 ESourceExtension *extension;
2003 GHashTable *hash_table;
2006 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2007 g_return_val_if_fail (extension_name != NULL, NULL);
2009 g_static_rec_mutex_lock (&source->priv->lock);
2011 /* Check if we already have the extension. */
2012 extension = g_hash_table_lookup (
2013 source->priv->extensions, extension_name);
2014 if (extension != NULL)
2017 /* Find all subclasses of ESourceExtensionClass. */
2018 hash_table = source_find_extension_classes ();
2019 class = g_hash_table_lookup (hash_table, extension_name);
2021 /* Create a new instance of the appropriate GType. */
2022 if (class != NULL) {
2023 extension = g_object_new (
2024 G_TYPE_FROM_CLASS (class),
2025 "source", source, NULL);
2026 source_load_from_key_file (
2027 G_OBJECT (extension),
2028 source->priv->key_file,
2030 g_hash_table_insert (
2031 source->priv->extensions,
2032 g_strdup (extension_name), extension);
2034 /* XXX Tie this into a debug setting for ESources. */
2037 "No registered GType for ESource "
2038 "extension '%s'", extension_name);
2042 g_hash_table_destroy (hash_table);
2045 g_static_rec_mutex_unlock (&source->priv->lock);
2051 * e_source_has_extension:
2052 * @source: an #ESource
2053 * @extension_name: an extension name
2055 * Checks whether @source has an #ESourceExtension with the given name.
2057 * Returns: %TRUE if @source has such an extension, %FALSE if not
2062 e_source_has_extension (ESource *source,
2063 const gchar *extension_name)
2065 ESourceExtension *extension;
2067 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2068 g_return_val_if_fail (extension_name != NULL, FALSE);
2070 g_static_rec_mutex_lock (&source->priv->lock);
2072 /* Two cases to check for, either one is good enough:
2073 * 1) Our internal GKeyFile has a group named 'extension_name'.
2074 * 2) Our 'extensions' table has an entry for 'extension_name'.
2076 * We have to check both data structures in case a new extension
2077 * not present in the GKeyFile was instantiated, but we have not
2078 * yet updated our internal GKeyFile. A common occurrence when
2079 * editing a brand new data source.
2081 * When checking the GKeyFile we want to actually fetch the
2082 * extension with e_source_get_extension() to make sure it's
2083 * a registered extension name and not just an arbitrary key
2084 * file group name. */
2086 if (g_key_file_has_group (source->priv->key_file, extension_name)) {
2087 extension = e_source_get_extension (source, extension_name);
2089 GHashTable *hash_table = source->priv->extensions;
2090 extension = g_hash_table_lookup (hash_table, extension_name);
2093 g_static_rec_mutex_unlock (&source->priv->lock);
2095 return (extension != NULL);
2099 * e_source_ref_dbus_object:
2100 * @source: an #ESource
2102 * Returns the #GDBusObject that was passed to e_source_new().
2104 * The returned #GDBusObject is referenced for thread-safety and must be
2105 * unreferenced with g_object_unref() when finished with it.
2107 * Returns: (transfer full): the #GDBusObject for @source, or %NULL
2112 e_source_ref_dbus_object (ESource *source)
2114 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2116 if (source->priv->dbus_object == NULL)
2119 return g_object_ref (source->priv->dbus_object);
2123 * e_source_ref_main_context:
2124 * @source: an #ESource
2126 * Returns the #GMainContext from which #ESource::changed signals are
2129 * The returned #GMainContext is referenced for thread-safety and must be
2130 * unreferenced with g_main_context_unref() when finished with it.
2132 * Returns: (transfer full): the #GMainContext for signal emissions
2137 e_source_ref_main_context (ESource *source)
2139 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2141 return g_main_context_ref (source->priv->main_context);
2145 * e_source_get_display_name:
2146 * @source: an #ESource
2148 * Returns the display name for @source. Use the display name to
2149 * represent the #ESource in a user interface.
2151 * Returns: the display name for @source
2156 e_source_get_display_name (ESource *source)
2158 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2160 return source->priv->display_name;
2164 * e_source_dup_display_name:
2165 * @source: an #ESource
2167 * Thread-safe variation of e_source_get_display_name().
2168 * Use this function when accessing @source from multiple threads.
2170 * The returned string should be freed with g_free() when no longer needed.
2172 * Returns: a newly-allocated copy of #ESource:display-name
2177 e_source_dup_display_name (ESource *source)
2179 const gchar *protected;
2182 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2184 g_mutex_lock (source->priv->property_lock);
2186 protected = e_source_get_display_name (source);
2187 duplicate = g_strdup (protected);
2189 g_mutex_unlock (source->priv->property_lock);
2195 * e_source_set_display_name:
2196 * @source: an #ESource
2197 * @display_name: a display name
2199 * Sets the display name for @source. The @display_name argument must be a
2200 * valid UTF-8 string. Use the display name to represent the #ESource in a
2203 * The internal copy of @display_name is automatically stripped of leading
2204 * and trailing whitespace.
2209 e_source_set_display_name (ESource *source,
2210 const gchar *display_name)
2212 g_return_if_fail (E_IS_SOURCE (source));
2213 g_return_if_fail (display_name != NULL);
2214 g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
2216 g_mutex_lock (source->priv->property_lock);
2218 if (g_strcmp0 (source->priv->display_name, display_name) == 0) {
2219 g_mutex_unlock (source->priv->property_lock);
2223 g_free (source->priv->display_name);
2224 source->priv->display_name = g_strdup (display_name);
2226 /* Strip leading and trailing whitespace. */
2227 g_strstrip (source->priv->display_name);
2229 /* This is used in e_source_compare_by_display_name(). */
2230 g_free (source->priv->collate_key);
2231 source->priv->collate_key = g_utf8_collate_key (display_name, -1);
2233 g_mutex_unlock (source->priv->property_lock);
2235 g_object_notify (G_OBJECT (source), "display-name");
2239 * e_source_compare_by_display_name:
2240 * @source1: the first #ESource
2241 * @source2: the second #ESource
2243 * Compares two #ESource instances by their display names. Useful for
2244 * ordering sources in a user interface.
2246 * Returns: a negative value if @source1 compares before @source2, zero if
2247 * they compare equal, or a positive value if @source1 compares
2253 e_source_compare_by_display_name (ESource *source1,
2257 source1->priv->collate_key,
2258 source2->priv->collate_key);
2262 * e_source_to_string:
2263 * @source: an #ESource
2264 * @length: (allow-none): return location for the length of the returned
2267 * Outputs the current contents of @source as a key file string.
2268 * Free the returned string with g_free().
2270 * Returns: a newly-allocated string
2275 e_source_to_string (ESource *source,
2278 GHashTableIter iter;
2280 gpointer group_name;
2284 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2286 g_static_rec_mutex_lock (&source->priv->lock);
2288 key_file = source->priv->key_file;
2290 source_save_to_key_file (
2291 G_OBJECT (source), key_file, PRIMARY_GROUP_NAME);
2293 g_hash_table_iter_init (&iter, source->priv->extensions);
2294 while (g_hash_table_iter_next (&iter, &group_name, &extension))
2295 source_save_to_key_file (extension, key_file, group_name);
2297 data = g_key_file_to_data (key_file, length, NULL);
2299 g_static_rec_mutex_unlock (&source->priv->lock);
2305 * e_source_parameter_to_key:
2306 * @param_name: a #GParamSpec name
2308 * Converts a #GParamSpec name (e.g. "foo-bar" or "foo_bar")
2309 * to "CamelCase" for use as a #GKeyFile key (e.g. "FooBar").
2311 * This function is made public only to aid in account migration.
2312 * Applications should not need to use this.
2317 e_source_parameter_to_key (const gchar *param_name)
2319 gboolean uppercase = TRUE;
2323 g_return_val_if_fail (param_name != NULL, NULL);
2325 key = cp = g_malloc0 (strlen (param_name) + 1);
2327 for (ii = 0; param_name[ii] != '\0'; ii++) {
2328 if (g_ascii_isalnum (param_name[ii]) && uppercase) {
2329 *cp++ = g_ascii_toupper (param_name[ii]);
2331 } else if (param_name[ii] == '-' || param_name[ii] == '_')
2334 *cp++ = param_name[ii];
2341 * e_source_remove_sync:
2342 * @source: the #ESource to be removed
2343 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2344 * @error: return location for a #GError, or %NULL
2346 * Requests the D-Bus service to delete the key files for @source and all of
2347 * its descendants and broadcast their removal to all clients. The @source
2348 * must be #ESource:removable.
2350 * If an error occurs, the functon will set @error and return %FALSE.
2352 * Returns: %TRUE on success, %FALSE on failure
2357 e_source_remove_sync (ESource *source,
2358 GCancellable *cancellable,
2361 ESourceClass *class;
2363 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2365 class = E_SOURCE_GET_CLASS (source);
2366 g_return_val_if_fail (class->remove_sync != NULL, FALSE);
2368 return class->remove_sync (source, cancellable, error);
2373 * @source: the #ESource to be removed
2374 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2375 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2377 * @user_data: (closure): data to pass to the callback function
2379 * Asynchronously requests the D-Bus service to delete the key files for
2380 * @source and all of its descendants and broadcast their removal to all
2381 * clients. The @source must be #ESource:removable.
2383 * When the operation is finished, @callback will be called. You can then
2384 * call e_source_remove_finish() to get the result of the operation.
2389 e_source_remove (ESource *source,
2390 GCancellable *cancellable,
2391 GAsyncReadyCallback callback,
2394 ESourceClass *class;
2396 g_return_if_fail (E_IS_SOURCE (source));
2398 class = E_SOURCE_GET_CLASS (source);
2399 g_return_if_fail (class->remove != NULL);
2401 class->remove (source, cancellable, callback, user_data);
2405 * e_source_remove_finish:
2406 * @source: the #ESource to be removed
2407 * @result: a #GAsyncResult
2408 * @error: return location for a #GError, or %NULL
2410 * Finishes the operation started with e_source_remove(). If an
2411 * error occurred, the function will set @error and return %FALSE.
2413 * Returns: %TRUE on success, %FALSE of failure
2418 e_source_remove_finish (ESource *source,
2419 GAsyncResult *result,
2422 ESourceClass *class;
2424 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2425 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2427 class = E_SOURCE_GET_CLASS (source);
2428 g_return_val_if_fail (class->remove_finish != NULL, FALSE);
2430 return class->remove_finish (source, result, error);
2434 * e_source_write_sync:
2435 * @source: a writable #ESource
2436 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2437 * @error: return location for a #GError, or %NULL
2439 * Submits the current contents of @source to the D-Bus service to be
2440 * written to disk and broadcast to other clients. The @source must
2441 * be #ESource:writable.
2443 * If an error occurs, the functon will set @error and return %FALSE.
2445 * Returns: %TRUE on success, %FALSE on failure
2450 e_source_write_sync (ESource *source,
2451 GCancellable *cancellable,
2454 ESourceClass *class;
2456 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2458 class = E_SOURCE_GET_CLASS (source);
2459 g_return_val_if_fail (class->write_sync != NULL, FALSE);
2461 return class->write_sync (source, cancellable, error);
2466 * @source: a writable #ESource
2467 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2468 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2470 * @user_data: (closure): data to pass to the callback function
2472 * Asynchronously submits the current contents of @source to the D-Bus
2473 * service to be written to disk and broadcast to other clients. The
2474 * @source must be #ESource:writable.
2476 * When the operation is finished, @callback will be called. You can then
2477 * call e_source_write_finish() to get the result of the operation.
2482 e_source_write (ESource *source,
2483 GCancellable *cancellable,
2484 GAsyncReadyCallback callback,
2487 ESourceClass *class;
2489 g_return_if_fail (E_IS_SOURCE (source));
2491 class = E_SOURCE_GET_CLASS (source);
2492 g_return_if_fail (class->write != NULL);
2494 class->write (source, cancellable, callback, user_data);
2498 * e_source_write_finish:
2499 * @source: a writable #ESource
2500 * @result: a #GAsyncResult
2501 * @error: return location for a #GError, or %NULL
2503 * Finishes the operation started with e_source_write(). If an
2504 * error occurred, the function will set @error and return %FALSE.
2506 * Returns: %TRUE on success, %FALSE on failure
2511 e_source_write_finish (ESource *source,
2512 GAsyncResult *result,
2515 ESourceClass *class;
2517 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2518 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2520 class = E_SOURCE_GET_CLASS (source);
2521 g_return_val_if_fail (class->write_finish != NULL, FALSE);
2523 return class->write_finish (source, result, error);
2527 * e_source_remote_create_sync:
2528 * @source: an #ESource
2529 * @scratch_source: an #ESource describing the resource to create
2530 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2531 * @error: return location for a #GError, or %NULL
2533 * Creates a new remote resource by picking out relevant details from
2534 * @scratch_source. The @scratch_source must be an #ESource with no
2535 * #GDBusObject. The @source must be #ESource:remote-creatable.
2537 * The details required to create the resource vary by #ECollectionBackend,
2538 * but in most cases the @scratch_source need only define the resource type
2539 * (address book, calendar, etc.), a display name for the resource, and
2540 * possibly a server-side path or ID for the resource.
2542 * If an error occurs, the function will set @error and return %FALSE.
2544 * Returns: %TRUE on success, %FALSE on failure
2549 e_source_remote_create_sync (ESource *source,
2550 ESource *scratch_source,
2551 GCancellable *cancellable,
2554 ESourceClass *class;
2556 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2557 g_return_val_if_fail (E_IS_SOURCE (scratch_source), FALSE);
2559 class = E_SOURCE_GET_CLASS (source);
2560 g_return_val_if_fail (class->remote_create_sync != NULL, FALSE);
2562 return class->remote_create_sync (
2563 source, scratch_source, cancellable, error);
2567 * e_source_remote_create:
2568 * @source: an #ESource
2569 * @scratch_source: an #ESource describing the resource to create
2570 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2571 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2573 * @user_data: (closure): data to pass to the callback function
2575 * Asynchronously creates a new remote resource by picking out relevant
2576 * details from @scratch_source. The @scratch_source must be an #ESource
2577 * with no #GDBusObject. The @source must be #ESource:remote-creatable.
2579 * The details required to create the resource vary by #ECollectionBackend,
2580 * but in most cases the @scratch_source need only define the resource type
2581 * (address book, calendar, etc.), a display name for the resource, and
2582 * possibly a server-side path or ID for the resource.
2584 * When the operation is finished, @callback will be called. You can then
2585 * call 3_source_remote_create_finish() to get the result of the operation.
2590 e_source_remote_create (ESource *source,
2591 ESource *scratch_source,
2592 GCancellable *cancellable,
2593 GAsyncReadyCallback callback,
2596 ESourceClass *class;
2598 g_return_if_fail (E_IS_SOURCE (source));
2599 g_return_if_fail (E_IS_SOURCE (scratch_source));
2601 class = E_SOURCE_GET_CLASS (source);
2602 g_return_if_fail (class->remote_create != NULL);
2604 class->remote_create (
2605 source, scratch_source,
2606 cancellable, callback, user_data);
2610 * e_source_remote_create_finish:
2611 * @source: an #ESource
2612 * @result: a #GAsyncResult
2613 * @error: return location for a #GError, or %NULL
2615 * Finishes the operation started with e_source_remote_create(). If
2616 * an error occurred, the function will set @error and return %FALSE.
2618 * Returns: %TRUE on success, %FALSE on failure
2623 e_source_remote_create_finish (ESource *source,
2624 GAsyncResult *result,
2627 ESourceClass *class;
2629 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2631 class = E_SOURCE_GET_CLASS (source);
2632 g_return_val_if_fail (class->remote_create_finish != NULL, FALSE);
2634 return class->remote_create_finish (source, result, error);
2638 * e_source_remote_delete_sync:
2639 * @source: an #ESource
2640 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2641 * @error: return location for a #GError, or %NULL
2643 * Deletes the resource represented by @source from a remote server.
2644 * The @source must be #ESource:remote-deletable. This will also delete
2645 * the key file for @source and broadcast its removal to all clients,
2646 * similar to e_source_remove_sync().
2648 * If an error occurs, the function will set @error and return %FALSE.
2650 * Returns: %TRUE on success, %FALSE on failure
2655 e_source_remote_delete_sync (ESource *source,
2656 GCancellable *cancellable,
2659 ESourceClass *class;
2661 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2663 class = E_SOURCE_GET_CLASS (source);
2664 g_return_val_if_fail (class->remote_delete_sync != NULL, FALSE);
2666 return class->remote_delete_sync (source, cancellable, error);
2670 * e_source_remote_delete:
2671 * @source: an #ESource
2672 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2673 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2675 * @user_data: (closure): data to pass to the callback function
2677 * Asynchronously deletes the resource represented by @source from a remote
2678 * server. The @source must be #ESource:remote-deletable. This will also
2679 * delete the key file for @source and broadcast its removal to all clients,
2680 * similar to e_source_remove().
2682 * When the operation is finished, @callback will be called. You can then
2683 * call e_source_remote_delete_finish() to get the result of the operation.
2688 e_source_remote_delete (ESource *source,
2689 GCancellable *cancellable,
2690 GAsyncReadyCallback callback,
2693 ESourceClass *class;
2695 g_return_if_fail (E_IS_SOURCE (source));
2697 class = E_SOURCE_GET_CLASS (source);
2698 g_return_if_fail (class->remote_delete != NULL);
2700 class->remote_delete (source, cancellable, callback, user_data);
2704 * e_source_remote_delete_finish:
2705 * @source: an #ESource
2706 * @result: a #GAsyncResult
2707 * @error: return location for a #GError, or %NULL
2709 * Finishes the operation started with e_source_remote_delete(). If
2710 * an error occurred, the function will set @error and return %FALSE.
2712 * Returns: %TRUE on success, %FALSE on failure
2717 e_source_remote_delete_finish (ESource *source,
2718 GAsyncResult *result,
2721 ESourceClass *class;
2723 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2725 class = E_SOURCE_GET_CLASS (source);
2726 g_return_val_if_fail (class->remote_delete_finish != NULL, FALSE);
2728 return class->remote_delete_finish (source, result, error);