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 struct _ESourcePrivate {
113 GDBusObject *dbus_object;
114 GMainContext *main_context;
117 GMutex *changed_lock;
119 GMutex *property_lock;
126 /* The lock guards the key file and hash table. */
129 GStaticRecMutex lock;
130 GHashTable *extensions;
152 static guint signals[LAST_SIGNAL];
154 /* Forward Declarations */
155 static void e_source_initable_init (GInitableIface *interface);
157 G_DEFINE_TYPE_WITH_CODE (
161 G_IMPLEMENT_INTERFACE (
163 e_source_initable_init))
166 source_find_extension_classes_rec (GType parent_type,
167 GHashTable *hash_table)
170 guint n_children, ii;
172 children = g_type_children (parent_type, &n_children);
174 for (ii = 0; ii < n_children; ii++) {
175 GType type = children[ii];
176 ESourceExtensionClass *class;
179 /* Recurse over the child's children. */
180 source_find_extension_classes_rec (type, hash_table);
182 /* Skip abstract types. */
183 if (G_TYPE_IS_ABSTRACT (type))
186 class = g_type_class_ref (type);
187 key = (gpointer) class->name;
190 g_hash_table_insert (hash_table, key, class);
192 g_type_class_unref (class);
199 source_find_extension_classes (void)
201 GHashTable *hash_table;
203 hash_table = g_hash_table_new_full (
204 (GHashFunc) g_str_hash,
205 (GEqualFunc) g_str_equal,
206 (GDestroyNotify) NULL,
207 (GDestroyNotify) g_type_class_unref);
209 source_find_extension_classes_rec (
210 E_TYPE_SOURCE_EXTENSION, hash_table);
216 source_localized_hack (GKeyFile *key_file,
217 const gchar *group_name,
219 const gchar *new_value)
221 const gchar * const *language_names;
224 /* XXX If we're changing a string key that has translations,
225 * set "key[$CURRENT_LOCALE]" (if available) to the new
226 * value so g_key_file_get_locale_string() will pick it
227 * up. This is not a perfect solution however. When a
228 * different locale is used the value may revert to its
229 * original localized string. Good enough for now. */
231 language_names = g_get_language_names ();
233 for (ii = 0; language_names[ii] != NULL; ii++) {
234 gboolean has_localized_key;
235 gchar *localized_key;
237 localized_key = g_strdup_printf (
238 "%s[%s]", key, language_names[ii]);
239 has_localized_key = g_key_file_has_key (
240 key_file, group_name, localized_key, NULL);
242 if (has_localized_key)
243 g_key_file_set_string (
244 key_file, group_name,
245 localized_key, new_value);
247 g_free (localized_key);
249 if (has_localized_key)
253 g_key_file_set_string (key_file, group_name, key, new_value);
257 source_set_key_file_from_property (GObject *object,
260 const gchar *group_name)
266 pvalue = g_slice_new0 (GValue);
267 g_value_init (pvalue, pspec->value_type);
268 g_object_get_property (object, pspec->name, pvalue);
270 svalue = g_slice_new0 (GValue);
271 g_value_init (svalue, G_TYPE_STRING);
273 key = e_source_parameter_to_key (pspec->name);
275 /* For the most part we can just transform any supported
276 * property type to a string, with a couple exceptions. */
278 /* Transforming a boolean GValue to a string results in
279 * "TRUE" or "FALSE" (all uppercase), but GKeyFile only
280 * recognizes "true" or "false" (all lowercase). So we
281 * have to use g_key_file_set_boolean(). */
282 if (G_VALUE_HOLDS_BOOLEAN (pvalue)) {
283 gboolean v_boolean = g_value_get_boolean (pvalue);
284 g_key_file_set_boolean (key_file, group_name, key, v_boolean);
286 /* Store UIN64 in hexa */
287 } else if (G_VALUE_HOLDS_UINT64 (pvalue)) {
290 v_str = g_strdup_printf (
291 "%016" G_GINT64_MODIFIER "X",
292 g_value_get_uint64 (pvalue));
293 g_key_file_set_string (key_file, group_name, key, v_str);
296 /* String GValues may contain characters that need escaping. */
297 } else if (G_VALUE_HOLDS_STRING (pvalue)) {
298 const gchar *v_string = g_value_get_string (pvalue);
300 if (v_string == NULL)
303 /* Special case for localized "DisplayName" keys. */
304 source_localized_hack (key_file, group_name, key, v_string);
306 /* Transforming an enum GValue to a string results in
307 * the GEnumValue name. We want the shorter nickname. */
308 } else if (G_VALUE_HOLDS_ENUM (pvalue)) {
309 GParamSpecEnum *enum_pspec;
310 GEnumClass *enum_class;
311 GEnumValue *enum_value;
314 enum_pspec = G_PARAM_SPEC_ENUM (pspec);
315 enum_class = enum_pspec->enum_class;
317 value = g_value_get_enum (pvalue);
318 enum_value = g_enum_get_value (enum_class, value);
320 if (enum_value == NULL) {
321 value = enum_pspec->default_value;
322 enum_value = g_enum_get_value (enum_class, value);
325 if (enum_value != NULL)
326 g_key_file_set_string (
327 key_file, group_name, key,
328 enum_value->value_nick);
330 } else if (G_VALUE_HOLDS (pvalue, G_TYPE_STRV)) {
331 const gchar **strv = g_value_get_boxed (pvalue);
335 length = g_strv_length ((gchar **) strv);
336 g_key_file_set_string_list (
337 key_file, group_name, key, strv, length);
339 /* For GValues holding a GFile object we save the URI. */
340 } else if (G_VALUE_HOLDS (pvalue, G_TYPE_FILE)) {
341 GFile *file = g_value_get_object (pvalue);
345 uri = g_file_get_uri (file);
346 g_key_file_set_string (
347 key_file, group_name, key,
348 (uri != NULL) ? uri : "");
351 } else if (g_value_transform (pvalue, svalue)) {
352 const gchar *value = g_value_get_string (svalue);
353 g_key_file_set_value (key_file, group_name, key, value);
357 g_value_unset (pvalue);
358 g_value_unset (svalue);
359 g_slice_free (GValue, pvalue);
360 g_slice_free (GValue, svalue);
364 source_set_property_from_key_file (GObject *object,
367 const gchar *group_name)
371 GError *error = NULL;
373 value = g_slice_new0 (GValue);
374 key = e_source_parameter_to_key (pspec->name);
376 if (G_IS_PARAM_SPEC_CHAR (pspec) ||
377 G_IS_PARAM_SPEC_UCHAR (pspec) ||
378 G_IS_PARAM_SPEC_INT (pspec) ||
379 G_IS_PARAM_SPEC_UINT (pspec) ||
380 G_IS_PARAM_SPEC_LONG (pspec) ||
381 G_IS_PARAM_SPEC_ULONG (pspec)) {
384 v_int = g_key_file_get_integer (
385 key_file, group_name, key, &error);
387 g_value_init (value, G_TYPE_INT);
388 g_value_set_int (value, v_int);
391 } else if (G_IS_PARAM_SPEC_INT64 (pspec)) {
394 v_int64 = g_key_file_get_int64 (
395 key_file, group_name, key, &error);
397 g_value_init (value, G_TYPE_INT64);
398 g_value_set_int64 (value, v_int64);
401 } else if (G_IS_PARAM_SPEC_UINT64 (pspec)) {
405 v_str = g_key_file_get_string (
406 key_file, group_name, key, &error);
408 v_uint64 = g_ascii_strtoull (v_str, NULL, 16);
410 g_value_init (value, G_TYPE_UINT64);
411 g_value_set_uint64 (value, v_uint64);
416 } else if (G_IS_PARAM_SPEC_BOOLEAN (pspec)) {
419 v_boolean = g_key_file_get_boolean (
420 key_file, group_name, key, &error);
422 g_value_init (value, G_TYPE_BOOLEAN);
423 g_value_set_boolean (value, v_boolean);
426 } else if (G_IS_PARAM_SPEC_ENUM (pspec)) {
429 nick = g_key_file_get_string (
430 key_file, group_name, key, &error);
432 GParamSpecEnum *enum_pspec;
433 GEnumValue *enum_value;
435 enum_pspec = G_PARAM_SPEC_ENUM (pspec);
436 enum_value = g_enum_get_value_by_nick (
437 enum_pspec->enum_class, nick);
438 if (enum_value != NULL) {
439 g_value_init (value, pspec->value_type);
440 g_value_set_enum (value, enum_value->value);
445 } else if (G_IS_PARAM_SPEC_FLOAT (pspec) ||
446 G_IS_PARAM_SPEC_DOUBLE (pspec)) {
449 v_double = g_key_file_get_double (
450 key_file, group_name, key, &error);
452 g_value_init (value, G_TYPE_DOUBLE);
453 g_value_set_double (value, v_double);
456 } else if (G_IS_PARAM_SPEC_STRING (pspec)) {
459 /* Get the localized string if present. */
460 v_string = g_key_file_get_locale_string (
461 key_file, group_name, key, NULL, &error);
463 g_value_init (value, G_TYPE_STRING);
464 g_value_take_string (value, v_string);
467 } else if (g_type_is_a (pspec->value_type, G_TYPE_STRV)) {
470 strv = g_key_file_get_string_list (
471 key_file, group_name, key, NULL, &error);
473 g_value_init (value, G_TYPE_STRV);
474 g_value_take_boxed (value, strv);
477 } else if (g_type_is_a (pspec->value_type, G_TYPE_FILE)) {
480 /* Create the GFile from the URI string. */
481 uri = g_key_file_get_locale_string (
482 key_file, group_name, key, NULL, &error);
485 if (uri != NULL && *uri != '\0')
486 file = g_file_new_for_uri (uri);
487 g_value_init (value, pspec->value_type);
488 g_value_take_object (value, file);
494 "No GKeyFile-to-GValue converter defined "
495 "for type '%s'", G_PARAM_SPEC_TYPE_NAME (pspec));
498 /* If a value could not be retrieved from the key
499 * file, restore the property to its default value. */
501 g_value_init (value, pspec->value_type);
502 g_param_value_set_default (pspec, value);
503 g_error_free (error);
506 if (G_IS_VALUE (value)) {
507 g_object_set_property (object, pspec->name, value);
508 g_value_unset (value);
511 g_slice_free (GValue, value);
516 source_load_from_key_file (GObject *object,
518 const gchar *group_name)
521 GParamSpec **properties;
522 guint n_properties, ii;
524 class = G_OBJECT_GET_CLASS (object);
525 properties = g_object_class_list_properties (class, &n_properties);
527 g_object_freeze_notify (object);
529 for (ii = 0; ii < n_properties; ii++) {
530 if (properties[ii]->flags & E_SOURCE_PARAM_SETTING) {
531 source_set_property_from_key_file (
532 object, properties[ii], key_file, group_name);
536 g_object_thaw_notify (object);
542 source_save_to_key_file (GObject *object,
544 const gchar *group_name)
547 GParamSpec **properties;
548 guint n_properties, ii;
550 class = G_OBJECT_GET_CLASS (object);
551 properties = g_object_class_list_properties (class, &n_properties);
553 for (ii = 0; ii < n_properties; ii++) {
554 if (properties[ii]->flags & E_SOURCE_PARAM_SETTING) {
555 source_set_key_file_from_property (
556 object, properties[ii], key_file, group_name);
564 source_parse_dbus_data (ESource *source,
568 EDBusObject *dbus_object;
569 EDBusSource *dbus_source;
576 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
578 dbus_source = e_dbus_object_get_source (dbus_object);
579 data = e_dbus_source_dup_data (dbus_source);
580 g_object_unref (dbus_source);
582 g_return_val_if_fail (data != NULL, FALSE);
584 key_file = source->priv->key_file;
586 success = g_key_file_load_from_data (
587 key_file, data, strlen (data),
588 G_KEY_FILE_KEEP_COMMENTS |
589 G_KEY_FILE_KEEP_TRANSLATIONS,
598 /* Make sure the key file has a [Data Source] group. */
599 if (!g_key_file_has_group (key_file, PRIMARY_GROUP_NAME)) {
601 error, G_KEY_FILE_ERROR,
602 G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
603 _("Source file is missing a [%s] group"),
608 /* Load key file values from the [Data Source] group and from
609 * any other groups for which an extension object has already
610 * been created. Note that not all the extension classes may
611 * be registered at this point, so avoid attempting to create
612 * new extension objects here. Extension objects are created
613 * on-demand in e_source_get_extension(). */
615 source_load_from_key_file (
616 G_OBJECT (source), key_file, PRIMARY_GROUP_NAME);
618 g_hash_table_iter_init (&iter, source->priv->extensions);
619 while (g_hash_table_iter_next (&iter, &group_name, &extension))
620 source_load_from_key_file (extension, key_file, group_name);
626 source_notify_dbus_data_cb (EDBusSource *dbus_source,
630 GError *error = NULL;
632 g_static_rec_mutex_lock (&source->priv->lock);
634 /* Since the source data came from a GKeyFile structure on the
635 * server-side, this should never fail. But we'll print error
636 * messages to the terminal just in case. */
637 if (!source_parse_dbus_data (source, &error)) {
638 g_return_if_fail (error != NULL);
639 g_warning ("%s", error->message);
640 g_error_free (error);
643 g_static_rec_mutex_unlock (&source->priv->lock);
647 source_idle_changed_cb (gpointer user_data)
649 ESource *source = E_SOURCE (user_data);
651 g_mutex_lock (source->priv->changed_lock);
652 if (source->priv->changed != NULL) {
653 g_source_unref (source->priv->changed);
654 source->priv->changed = NULL;
656 g_mutex_unlock (source->priv->changed_lock);
658 g_signal_emit (source, signals[CHANGED], 0);
664 source_set_dbus_object (ESource *source,
665 EDBusObject *dbus_object)
667 /* D-Bus object will be NULL when configuring a new source. */
668 if (dbus_object == NULL)
671 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
672 g_return_if_fail (source->priv->dbus_object == NULL);
674 source->priv->dbus_object = g_object_ref (dbus_object);
678 source_set_main_context (ESource *source,
679 GMainContext *main_context)
681 g_return_if_fail (source->priv->main_context == NULL);
683 source->priv->main_context =
684 (main_context != NULL) ?
685 g_main_context_ref (main_context) :
686 g_main_context_ref_thread_default ();
690 source_set_property (GObject *object,
695 switch (property_id) {
696 case PROP_DBUS_OBJECT:
697 source_set_dbus_object (
699 g_value_get_object (value));
702 case PROP_DISPLAY_NAME:
703 e_source_set_display_name (
705 g_value_get_string (value));
709 e_source_set_enabled (
711 g_value_get_boolean (value));
714 case PROP_MAIN_CONTEXT:
715 source_set_main_context (
717 g_value_get_boxed (value));
721 e_source_set_parent (
723 g_value_get_string (value));
727 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
731 source_get_property (GObject *object,
736 switch (property_id) {
737 case PROP_DBUS_OBJECT:
738 g_value_take_object (
739 value, e_source_ref_dbus_object (
743 case PROP_DISPLAY_NAME:
744 g_value_take_string (
745 value, e_source_dup_display_name (
750 g_value_set_boolean (
751 value, e_source_get_enabled (
755 case PROP_MAIN_CONTEXT:
757 value, e_source_ref_main_context (
762 g_value_take_string (
763 value, e_source_dup_parent (
768 g_value_set_boolean (
769 value, e_source_get_removable (
774 g_value_take_string (
775 value, e_source_dup_uid (
780 g_value_set_boolean (
781 value, e_source_get_writable (
786 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
790 source_dispose (GObject *object)
792 ESourcePrivate *priv;
794 priv = E_SOURCE_GET_PRIVATE (object);
796 if (priv->dbus_object != NULL) {
797 EDBusObject *dbus_object;
798 EDBusSource *dbus_source;
800 dbus_object = E_DBUS_OBJECT (priv->dbus_object);
802 dbus_source = e_dbus_object_get_source (dbus_object);
803 if (dbus_source != NULL) {
804 g_signal_handlers_disconnect_matched (
805 dbus_source, G_SIGNAL_MATCH_DATA,
806 0, 0, NULL, NULL, object);
807 g_object_unref (dbus_source);
810 g_object_unref (priv->dbus_object);
811 priv->dbus_object = NULL;
814 if (priv->main_context != NULL) {
815 g_main_context_unref (priv->main_context);
816 priv->main_context = NULL;
819 /* XXX Maybe not necessary to acquire the lock? */
820 g_mutex_lock (priv->changed_lock);
821 if (priv->changed != NULL) {
822 g_source_destroy (priv->changed);
823 g_source_unref (priv->changed);
824 priv->changed = NULL;
826 g_mutex_unlock (priv->changed_lock);
828 g_hash_table_remove_all (priv->extensions);
830 /* Chain up to parent's dispose() method. */
831 G_OBJECT_CLASS (e_source_parent_class)->dispose (object);
835 source_finalize (GObject *object)
837 ESourcePrivate *priv;
839 priv = E_SOURCE_GET_PRIVATE (object);
841 g_mutex_free (priv->changed_lock);
842 g_mutex_free (priv->property_lock);
844 g_free (priv->display_name);
845 g_free (priv->collate_key);
846 g_free (priv->parent);
849 g_key_file_free (priv->key_file);
850 g_static_rec_mutex_free (&priv->lock);
851 g_hash_table_destroy (priv->extensions);
853 /* Chain up to parent's finalize() method. */
854 G_OBJECT_CLASS (e_source_parent_class)->finalize (object);
858 source_notify (GObject *object,
861 if ((pspec->flags & E_SOURCE_PARAM_SETTING) != 0)
862 e_source_changed (E_SOURCE (object));
866 source_remove_sync (ESource *source,
867 GCancellable *cancellable,
870 EDBusObject *dbus_object;
871 EDBusSourceRemovable *dbus_source;
874 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
876 dbus_source = e_dbus_object_get_source_removable (dbus_object);
878 if (dbus_source == NULL) {
881 G_IO_ERROR_PERMISSION_DENIED,
882 _("Data source '%s' is not removable"),
883 e_source_get_display_name (source));
887 success = e_dbus_source_removable_call_remove_sync (
888 dbus_source, cancellable, error);
890 g_object_unref (dbus_source);
895 /* Helper for source_remove() */
897 source_remove_thread (GSimpleAsyncResult *simple,
899 GCancellable *cancellable)
901 GError *error = NULL;
903 e_source_remove_sync (E_SOURCE (object), cancellable, &error);
906 g_simple_async_result_take_error (simple, error);
910 source_remove (ESource *source,
911 GCancellable *cancellable,
912 GAsyncReadyCallback callback,
915 GSimpleAsyncResult *simple;
917 simple = g_simple_async_result_new (
918 G_OBJECT (source), callback, user_data, source_remove);
920 g_simple_async_result_set_check_cancellable (simple, cancellable);
922 g_simple_async_result_run_in_thread (
923 simple, source_remove_thread,
924 G_PRIORITY_DEFAULT, cancellable);
926 g_object_unref (simple);
930 source_remove_finish (ESource *source,
931 GAsyncResult *result,
934 GSimpleAsyncResult *simple;
936 g_return_val_if_fail (
937 g_simple_async_result_is_valid (
938 result, G_OBJECT (source), source_remove), FALSE);
940 simple = G_SIMPLE_ASYNC_RESULT (result);
942 /* Assume success unless a GError is set. */
943 return !g_simple_async_result_propagate_error (simple, error);
947 source_write_sync (ESource *source,
948 GCancellable *cancellable,
951 EDBusObject *dbus_object;
952 EDBusSourceWritable *dbus_source;
956 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
958 dbus_source = e_dbus_object_get_source_writable (dbus_object);
960 if (dbus_source == NULL) {
963 G_IO_ERROR_PERMISSION_DENIED,
964 _("Data source '%s' is not writable"),
965 e_source_get_display_name (source));
969 data = e_source_to_string (source, NULL);
971 success = e_dbus_source_writable_call_write_sync (
972 dbus_source, data, cancellable, error);
976 g_object_unref (dbus_source);
981 /* Helper for source_write() */
983 source_write_thread (GSimpleAsyncResult *simple,
985 GCancellable *cancellable)
987 GError *error = NULL;
989 e_source_write_sync (E_SOURCE (object), cancellable, &error);
992 g_simple_async_result_take_error (simple, error);
996 source_write (ESource *source,
997 GCancellable *cancellable,
998 GAsyncReadyCallback callback,
1001 GSimpleAsyncResult *simple;
1003 simple = g_simple_async_result_new (
1004 G_OBJECT (source), callback, user_data, source_write);
1006 g_simple_async_result_set_check_cancellable (simple, cancellable);
1008 g_simple_async_result_run_in_thread (
1009 simple, source_write_thread,
1010 G_PRIORITY_DEFAULT, cancellable);
1012 g_object_unref (simple);
1016 source_write_finish (ESource *source,
1017 GAsyncResult *result,
1020 GSimpleAsyncResult *simple;
1022 g_return_val_if_fail (
1023 g_simple_async_result_is_valid (
1024 result, G_OBJECT (source), source_write), FALSE);
1026 simple = G_SIMPLE_ASYNC_RESULT (result);
1028 /* Assume success unless a GError is set. */
1029 return !g_simple_async_result_propagate_error (simple, error);
1033 source_initable_init (GInitable *initable,
1034 GCancellable *cancellable,
1038 gboolean success = TRUE;
1040 source = E_SOURCE (initable);
1042 /* The D-Bus object has the unique identifier (UID). */
1043 if (source->priv->dbus_object != NULL) {
1044 EDBusObject *dbus_object;
1045 EDBusSource *dbus_source;
1047 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
1049 /* An EDBusObject lacking an EDBusSource
1050 * interface indicates a programmer error. */
1051 dbus_source = e_dbus_object_get_source (dbus_object);
1052 g_return_val_if_fail (E_DBUS_IS_SOURCE (dbus_source), FALSE);
1054 /* Allow authentication prompts for a data source
1055 * when a new client-side proxy object is created.
1056 * The thought being if you cancel an authentication
1057 * prompt you won't be bothered again until you start
1058 * (or restart) a new E-D-S client app.
1060 * Failure here is non-fatal, ignore errors.
1062 * XXX Only GDBusProxy objects may call this. Sources
1063 * created server-side can't invoke remote methods.
1065 if (G_IS_DBUS_PROXY (dbus_source))
1066 e_dbus_source_call_allow_auth_prompt_sync (
1067 dbus_source, cancellable, NULL);
1069 /* The UID never changes, so we can cache a copy. */
1070 source->priv->uid = e_dbus_source_dup_uid (dbus_source);
1073 dbus_source, "notify::data",
1074 G_CALLBACK (source_notify_dbus_data_cb), source);
1076 success = source_parse_dbus_data (source, error);
1078 /* Avoid a spurious "changed" emission. */
1079 g_mutex_lock (source->priv->changed_lock);
1080 if (source->priv->changed != NULL) {
1081 g_source_destroy (source->priv->changed);
1082 g_source_unref (source->priv->changed);
1083 source->priv->changed = NULL;
1085 g_mutex_unlock (source->priv->changed_lock);
1087 g_object_unref (dbus_source);
1089 /* No D-Bus object implies we're configuring a new source,
1090 * so generate a new unique identifier (UID) for it. */
1092 source->priv->uid = e_uid_new ();
1099 e_source_class_init (ESourceClass *class)
1101 GObjectClass *object_class;
1103 g_type_class_add_private (class, sizeof (ESourcePrivate));
1105 object_class = G_OBJECT_CLASS (class);
1106 object_class->set_property = source_set_property;
1107 object_class->get_property = source_get_property;
1108 object_class->dispose = source_dispose;
1109 object_class->finalize = source_finalize;
1110 object_class->notify = source_notify;
1112 class->remove_sync = source_remove_sync;
1113 class->remove = source_remove;
1114 class->remove_finish = source_remove_finish;
1115 class->write_sync = source_write_sync;
1116 class->write = source_write;
1117 class->write_finish = source_write_finish;
1119 g_object_class_install_property (
1122 g_param_spec_object (
1125 "The D-Bus object for the data source",
1128 G_PARAM_CONSTRUCT_ONLY |
1129 G_PARAM_STATIC_STRINGS));
1131 g_object_class_install_property (
1134 g_param_spec_string (
1137 "The human-readable name of the data source",
1141 G_PARAM_STATIC_STRINGS |
1142 E_SOURCE_PARAM_SETTING));
1144 g_object_class_install_property (
1147 g_param_spec_boolean (
1150 "Whether the data source is enabled",
1154 G_PARAM_STATIC_STRINGS |
1155 E_SOURCE_PARAM_SETTING));
1157 g_object_class_install_property (
1160 g_param_spec_boxed (
1163 "The GMainContext used for signal emissions",
1164 G_TYPE_MAIN_CONTEXT,
1166 G_PARAM_CONSTRUCT_ONLY |
1167 G_PARAM_STATIC_STRINGS));
1169 g_object_class_install_property (
1172 g_param_spec_string (
1175 "The unique identity of the parent data source",
1178 G_PARAM_STATIC_STRINGS |
1179 E_SOURCE_PARAM_SETTING));
1181 g_object_class_install_property (
1184 g_param_spec_boolean (
1187 "Whether the data source is removable",
1190 G_PARAM_STATIC_STRINGS));
1192 g_object_class_install_property (
1195 g_param_spec_string (
1198 "The unique identity of the data source",
1201 G_PARAM_STATIC_STRINGS));
1203 g_object_class_install_property (
1206 g_param_spec_boolean (
1209 "Whether the data source is writable",
1212 G_PARAM_STATIC_STRINGS));
1216 * @source: the #ESource that received the signal
1218 * The ::changed signal is emitted when a property in @source or
1219 * one of its extension objects changes. A common use for this
1220 * signal is to notify a #GtkTreeModel containing data collected
1221 * from #ESource<!-- -->s that it needs to update a row.
1223 signals[CHANGED] = g_signal_new (
1225 G_TYPE_FROM_CLASS (class),
1226 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
1227 G_STRUCT_OFFSET (ESourceClass, changed),
1229 g_cclosure_marshal_VOID__VOID,
1232 /* Register built-in ESourceExtension types. */
1233 REGISTER_TYPE (E_TYPE_SOURCE_ADDRESS_BOOK);
1234 REGISTER_TYPE (E_TYPE_SOURCE_ALARMS);
1235 REGISTER_TYPE (E_TYPE_SOURCE_AUTHENTICATION);
1236 REGISTER_TYPE (E_TYPE_SOURCE_AUTOCOMPLETE);
1237 REGISTER_TYPE (E_TYPE_SOURCE_CALENDAR);
1238 REGISTER_TYPE (E_TYPE_SOURCE_COLLECTION);
1239 REGISTER_TYPE (E_TYPE_SOURCE_GOA);
1240 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_ACCOUNT);
1241 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_COMPOSITION);
1242 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_IDENTITY);
1243 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_SIGNATURE);
1244 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_SUBMISSION);
1245 REGISTER_TYPE (E_TYPE_SOURCE_MAIL_TRANSPORT);
1246 REGISTER_TYPE (E_TYPE_SOURCE_MDN);
1247 REGISTER_TYPE (E_TYPE_SOURCE_MEMO_LIST);
1248 REGISTER_TYPE (E_TYPE_SOURCE_OFFLINE);
1249 REGISTER_TYPE (E_TYPE_SOURCE_OPENPGP);
1250 REGISTER_TYPE (E_TYPE_SOURCE_REFRESH);
1251 REGISTER_TYPE (E_TYPE_SOURCE_RESOURCE);
1252 REGISTER_TYPE (E_TYPE_SOURCE_SECURITY);
1253 REGISTER_TYPE (E_TYPE_SOURCE_SELECTABLE);
1254 REGISTER_TYPE (E_TYPE_SOURCE_SMIME);
1255 REGISTER_TYPE (E_TYPE_SOURCE_TASK_LIST);
1256 REGISTER_TYPE (E_TYPE_SOURCE_WEBDAV);
1260 e_source_initable_init (GInitableIface *interface)
1262 interface->init = source_initable_init;
1266 e_source_init (ESource *source)
1268 GHashTable *extensions;
1270 /* Don't do this as part of class initialization because it
1271 * loads Camel modules and can screw up introspection, which
1272 * occurs at compile-time before Camel modules are installed. */
1273 e_source_camel_register_types ();
1275 extensions = g_hash_table_new_full (
1276 (GHashFunc) g_str_hash,
1277 (GEqualFunc) g_str_equal,
1278 (GDestroyNotify) g_free,
1279 (GDestroyNotify) g_object_unref);
1281 source->priv = E_SOURCE_GET_PRIVATE (source);
1282 source->priv->changed_lock = g_mutex_new ();
1283 source->priv->property_lock = g_mutex_new ();
1284 source->priv->key_file = g_key_file_new ();
1285 source->priv->extensions = extensions;
1287 g_static_rec_mutex_init (&source->priv->lock);
1292 * @dbus_object: (allow-none): a #GDBusObject or %NULL
1293 * @main_context: (allow-none): a #GMainContext or %NULL
1294 * @error: return location for a #GError, or %NULL
1296 * Creates a new #ESource instance.
1298 * The #ESource::changed signal will be emitted from @main_context if given,
1299 * or else from the thread-default #GMainContext at the time this function is
1302 * The only time the function should be called outside of #ESourceRegistry
1303 * is to create a so-called "scratch" #ESource for editing in a Properties
1304 * window or an account setup assistant.
1306 * FIXME: Elaborate on scratch sources.
1308 * Returns: a new #ESource, or %NULL on error
1313 e_source_new (GDBusObject *dbus_object,
1314 GMainContext *main_context,
1317 if (dbus_object != NULL)
1318 g_return_val_if_fail (E_DBUS_IS_OBJECT (dbus_object), NULL);
1320 return g_initable_new (
1321 E_TYPE_SOURCE, NULL, error,
1322 "dbus-object", dbus_object,
1323 "main-context", main_context,
1329 * @source: an #ESource
1331 * Generates a hash value for @source. This function is intended for
1332 * easily hashing an #ESource to add to a #GHashTable or similar data
1335 * Returns: a hash value for @source.
1340 e_source_hash (ESource *source)
1344 g_return_val_if_fail (E_IS_SOURCE (source), 0);
1346 uid = e_source_get_uid (source);
1348 return g_str_hash (uid);
1353 * @source1: the first #ESource
1354 * @source2: the second #ESource
1356 * Checks two #ESource instances for equality. #ESource instances are
1357 * equal if their unique identifier strings are equal.
1359 * Returns: %TRUE if @source1 and @source2 are equal
1364 e_source_equal (ESource *source1,
1367 const gchar *uid1, *uid2;
1369 g_return_val_if_fail (E_IS_SOURCE (source1), FALSE);
1370 g_return_val_if_fail (E_IS_SOURCE (source2), FALSE);
1372 if (source1 == source2)
1375 uid1 = e_source_get_uid (source1);
1376 uid2 = e_source_get_uid (source2);
1378 return g_str_equal (uid1, uid2);
1383 * @source: an #ESource
1385 * Emits the #ESource::changed signal from an idle callback in
1386 * @source's #ESource:main-context.
1388 * This function is primarily intended for use by #ESourceExtension
1389 * when emitting a #GObject::notify signal on one of its properties.
1394 e_source_changed (ESource *source)
1396 g_return_if_fail (E_IS_SOURCE (source));
1398 g_mutex_lock (source->priv->changed_lock);
1399 if (source->priv->changed == NULL) {
1400 source->priv->changed = g_idle_source_new ();
1401 g_source_set_callback (
1402 source->priv->changed,
1403 source_idle_changed_cb,
1404 source, (GDestroyNotify) NULL);
1406 source->priv->changed,
1407 source->priv->main_context);
1409 g_mutex_unlock (source->priv->changed_lock);
1414 * @source: an #ESource
1416 * Returns the unique identifier string for @source.
1418 * Returns: the UID for @source
1423 e_source_get_uid (ESource *source)
1425 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1427 return source->priv->uid;
1432 * @source: an #ESource
1434 * Thread-safe variation of e_source_get_uid().
1435 * Use this function when accessing @source from multiple threads.
1437 * The returned string should be freed with g_free() when no longer needed.
1439 * Returns: a newly-allocated copy of #ESource:uid
1444 e_source_dup_uid (ESource *source)
1446 const gchar *protected;
1449 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1451 /* Perhaps we don't need to lock the mutex since
1452 * this is a read-only property but it can't hurt. */
1454 g_mutex_lock (source->priv->property_lock);
1456 protected = e_source_get_uid (source);
1457 duplicate = g_strdup (protected);
1459 g_mutex_unlock (source->priv->property_lock);
1465 * e_source_get_parent:
1466 * @source: an #ESource
1468 * Returns the unique identifier string of the parent #ESource.
1470 * Returns: the UID of the parent #ESource
1475 e_source_get_parent (ESource *source)
1477 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1479 return source->priv->parent;
1483 * e_source_dup_parent:
1484 * @source: an #ESource
1486 * Thread-safe variation of e_source_get_parent().
1487 * Use this function when accessing @source from multiple threads.
1489 * The returned string should be freed with g_free() when no longer needed.
1491 * Returns: a newly-allocated copy of #ESource:parent
1496 e_source_dup_parent (ESource *source)
1498 const gchar *protected;
1501 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1503 g_mutex_lock (source->priv->property_lock);
1505 protected = e_source_get_parent (source);
1506 duplicate = g_strdup (protected);
1508 g_mutex_unlock (source->priv->property_lock);
1514 * e_source_set_parent:
1515 * @source: an #ESource
1516 * @parent: (allow-none): the UID of the parent #ESource, or %NULL
1518 * Identifies the parent of @source by its unique identifier string.
1519 * This can only be set prior to adding @source to an #ESourceRegistry.
1521 * The internal copy of #ESource:parent is automatically stripped of leading
1522 * and trailing whitespace. If the resulting string is empty, %NULL is set
1528 e_source_set_parent (ESource *source,
1529 const gchar *parent)
1531 g_return_if_fail (E_IS_SOURCE (source));
1533 g_mutex_lock (source->priv->property_lock);
1535 if (g_strcmp0 (source->priv->parent, parent) == 0) {
1536 g_mutex_unlock (source->priv->property_lock);
1540 g_free (source->priv->parent);
1541 source->priv->parent = e_util_strdup_strip (parent);
1543 g_mutex_unlock (source->priv->property_lock);
1545 g_object_notify (G_OBJECT (source), "parent");
1549 * e_source_get_enabled:
1550 * @source: an #ESource
1552 * Returns %TRUE if @source is enabled.
1554 * An application should try to honor this setting if at all possible,
1555 * even if it does not provide a way to change the setting through its
1556 * user interface. Disabled data sources should generally be hidden.
1558 * Returns: whether @source is enabled
1563 e_source_get_enabled (ESource *source)
1565 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1567 return source->priv->enabled;
1571 * e_source_set_enabled:
1572 * @source: an #ESource
1573 * @enabled: whether to enable @source
1575 * Enables or disables @source.
1577 * An application should try to honor this setting if at all possible,
1578 * even if it does not provide a way to change the setting through its
1579 * user interface. Disabled data sources should generally be hidden.
1584 e_source_set_enabled (ESource *source,
1587 g_return_if_fail (E_IS_SOURCE (source));
1589 if ((enabled ? 1 : 0) == (source->priv->enabled ? 1 : 0))
1592 source->priv->enabled = enabled;
1594 g_object_notify (G_OBJECT (source), "enabled");
1598 * e_source_get_writable:
1599 * @source: an #ESource
1601 * Returns whether the D-Bus service will accept changes to @source.
1602 * If @source is not writable, calls to e_source_write() will fail.
1604 * Returns: whether @source is writable
1609 e_source_get_writable (ESource *source)
1611 EDBusObject *dbus_object;
1612 EDBusSourceWritable *dbus_source;
1614 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1616 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
1617 dbus_source = e_dbus_object_peek_source_writable (dbus_object);
1619 return (dbus_source != NULL);
1623 * e_source_get_removable:
1624 * @source: an #ESource
1626 * Returns whether the D-Bus service will allow @source to be removed.
1627 * If @source is not writable, calls to e_source_remove() will fail.
1629 * Returns: whether @source is removable
1634 e_source_get_removable (ESource *source)
1636 EDBusObject *dbus_object;
1637 EDBusSourceRemovable *dbus_source;
1639 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1641 dbus_object = E_DBUS_OBJECT (source->priv->dbus_object);
1642 dbus_source = e_dbus_object_peek_source_removable (dbus_object);
1644 return (dbus_source != NULL);
1648 * e_source_get_extension:
1649 * @source: an #ESource
1650 * @extension_name: an extension name
1652 * Returns an instance of some #ESourceExtension subclass which registered
1653 * itself under @extension_name. If no such instance exists within @source,
1654 * one will be created. It is the caller's responsibility to know which
1655 * subclass is being returned.
1657 * If you just want to test for the existence of an extension within @source
1658 * without creating it, use e_source_has_extension().
1660 * Extension instances are owned by their #ESource and should not be
1661 * referenced directly. Instead, reference the #ESource instance and
1662 * use this function to fetch the extension instance as needed.
1664 * Returns: (type ESourceExtension) (transfer none): an instance of some
1665 * #ESourceExtension subclass
1670 e_source_get_extension (ESource *source,
1671 const gchar *extension_name)
1673 ESourceExtension *extension;
1674 GHashTable *hash_table;
1677 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1678 g_return_val_if_fail (extension_name != NULL, NULL);
1680 g_static_rec_mutex_lock (&source->priv->lock);
1682 /* Check if we already have the extension. */
1683 extension = g_hash_table_lookup (
1684 source->priv->extensions, extension_name);
1685 if (extension != NULL)
1688 /* Find all subclasses of ESourceExtensionClass. */
1689 hash_table = source_find_extension_classes ();
1690 class = g_hash_table_lookup (hash_table, extension_name);
1692 /* Create a new instance of the appropriate GType. */
1693 if (class != NULL) {
1694 extension = g_object_new (
1695 G_TYPE_FROM_CLASS (class),
1696 "source", source, NULL);
1697 source_load_from_key_file (
1698 G_OBJECT (extension),
1699 source->priv->key_file,
1701 g_hash_table_insert (
1702 source->priv->extensions,
1703 g_strdup (extension_name), extension);
1705 /* XXX Tie this into a debug setting for ESources. */
1708 "No registered GType for ESource "
1709 "extension '%s'", extension_name);
1713 g_hash_table_destroy (hash_table);
1716 g_static_rec_mutex_unlock (&source->priv->lock);
1722 * e_source_has_extension:
1723 * @source: an #ESource
1724 * @extension_name: an extension name
1726 * Checks whether @source has an #ESourceExtension with the given name.
1728 * Returns: %TRUE if @source has such an extension, %FALSE if not
1733 e_source_has_extension (ESource *source,
1734 const gchar *extension_name)
1736 ESourceExtension *extension;
1738 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1739 g_return_val_if_fail (extension_name != NULL, FALSE);
1741 g_static_rec_mutex_lock (&source->priv->lock);
1743 /* Two cases to check for, either one is good enough:
1744 * 1) Our internal GKeyFile has a group named 'extension_name'.
1745 * 2) Our 'extensions' table has an entry for 'extension_name'.
1747 * We have to check both data structures in case a new extension
1748 * not present in the GKeyFile was instantiated, but we have not
1749 * yet updated our internal GKeyFile. A common occurrence when
1750 * editing a brand new data source.
1752 * When checking the GKeyFile we want to actually fetch the
1753 * extension with e_source_get_extension() to make sure it's
1754 * a registered extension name and not just an arbitrary key
1755 * file group name. */
1757 if (g_key_file_has_group (source->priv->key_file, extension_name)) {
1758 extension = e_source_get_extension (source, extension_name);
1760 GHashTable *hash_table = source->priv->extensions;
1761 extension = g_hash_table_lookup (hash_table, extension_name);
1764 g_static_rec_mutex_unlock (&source->priv->lock);
1766 return (extension != NULL);
1770 * e_source_ref_dbus_object:
1771 * @source: an #ESource
1773 * Returns the #GDBusObject that was passed to e_source_new().
1775 * The returned #GDBusObject is referenced for thread-safety and must be
1776 * unreferenced with g_object_unref() when finished with it.
1778 * Returns: (transfer full): the #GDBusObject for @source, or %NULL
1783 e_source_ref_dbus_object (ESource *source)
1785 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1787 if (source->priv->dbus_object == NULL)
1790 return g_object_ref (source->priv->dbus_object);
1794 * e_source_ref_main_context:
1795 * @source: an #ESource
1797 * Returns the #GMainContext from which #ESource::changed signals are
1800 * The returned #GMainContext is referenced for thread-safety and must be
1801 * unreferenced with g_main_context_unref() when finished with it.
1803 * Returns: (transfer full): the #GMainContext for signal emissions
1808 e_source_ref_main_context (ESource *source)
1810 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1812 return g_main_context_ref (source->priv->main_context);
1816 * e_source_get_display_name:
1817 * @source: an #ESource
1819 * Returns the display name for @source. Use the display name to
1820 * represent the #ESource in a user interface.
1822 * Returns: the display name for @source
1827 e_source_get_display_name (ESource *source)
1829 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1831 return source->priv->display_name;
1835 * e_source_dup_display_name:
1836 * @source: an #ESource
1838 * Thread-safe variation of e_source_get_display_name().
1839 * Use this function when accessing @source from multiple threads.
1841 * The returned string should be freed with g_free() when no longer needed.
1843 * Returns: a newly-allocated copy of #ESource:display-name
1848 e_source_dup_display_name (ESource *source)
1850 const gchar *protected;
1853 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1855 g_mutex_lock (source->priv->property_lock);
1857 protected = e_source_get_display_name (source);
1858 duplicate = g_strdup (protected);
1860 g_mutex_unlock (source->priv->property_lock);
1866 * e_source_set_display_name:
1867 * @source: an #ESource
1868 * @display_name: a display name
1870 * Sets the display name for @source. The @display_name argument must be a
1871 * valid UTF-8 string. Use the display name to represent the #ESource in a
1874 * The internal copy of @display_name is automatically stripped of leading
1875 * and trailing whitespace.
1880 e_source_set_display_name (ESource *source,
1881 const gchar *display_name)
1883 g_return_if_fail (E_IS_SOURCE (source));
1884 g_return_if_fail (display_name != NULL);
1885 g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
1887 g_mutex_lock (source->priv->property_lock);
1889 if (g_strcmp0 (source->priv->display_name, display_name) == 0) {
1890 g_mutex_unlock (source->priv->property_lock);
1894 g_free (source->priv->display_name);
1895 source->priv->display_name = g_strdup (display_name);
1897 /* Strip leading and trailing whitespace. */
1898 g_strstrip (source->priv->display_name);
1900 /* This is used in e_source_compare_by_display_name(). */
1901 g_free (source->priv->collate_key);
1902 source->priv->collate_key = g_utf8_collate_key (display_name, -1);
1904 g_mutex_unlock (source->priv->property_lock);
1906 g_object_notify (G_OBJECT (source), "display-name");
1910 * e_source_compare_by_display_name:
1911 * @source1: the first #ESource
1912 * @source2: the second #ESource
1914 * Compares two #ESource instances by their display names. Useful for
1915 * ordering sources in a user interface.
1917 * Returns: a negative value if @source1 compares before @source2, zero if
1918 * they compare equal, or a positive value if @source1 compares
1924 e_source_compare_by_display_name (ESource *source1,
1928 source1->priv->collate_key,
1929 source2->priv->collate_key);
1933 * e_source_to_string:
1934 * @source: an #ESource
1935 * @length: (allow-none): return location for the length of the returned
1938 * Outputs the current contents of @source as a key file string.
1939 * Free the returned string with g_free().
1941 * Returns: a newly-allocated string
1946 e_source_to_string (ESource *source,
1949 GHashTableIter iter;
1951 gpointer group_name;
1955 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1957 g_static_rec_mutex_lock (&source->priv->lock);
1959 key_file = source->priv->key_file;
1961 source_save_to_key_file (
1962 G_OBJECT (source), key_file, PRIMARY_GROUP_NAME);
1964 g_hash_table_iter_init (&iter, source->priv->extensions);
1965 while (g_hash_table_iter_next (&iter, &group_name, &extension))
1966 source_save_to_key_file (extension, key_file, group_name);
1968 data = g_key_file_to_data (key_file, length, NULL);
1970 g_static_rec_mutex_unlock (&source->priv->lock);
1976 * e_source_parameter_to_key:
1977 * @param_name: a #GParamSpec name
1979 * Converts a #GParamSpec name (e.g. "foo-bar" or "foo_bar")
1980 * to "CamelCase" for use as a #GKeyFile key (e.g. "FooBar").
1982 * This function is made public only to aid in account migration.
1983 * Applications should not need to use this.
1988 e_source_parameter_to_key (const gchar *param_name)
1990 gboolean uppercase = TRUE;
1994 g_return_val_if_fail (param_name != NULL, NULL);
1996 key = cp = g_malloc0 (strlen (param_name) + 1);
1998 for (ii = 0; param_name[ii] != '\0'; ii++) {
1999 if (g_ascii_isalnum (param_name[ii]) && uppercase) {
2000 *cp++ = g_ascii_toupper (param_name[ii]);
2002 } else if (param_name[ii] == '-' || param_name[ii] == '_')
2005 *cp++ = param_name[ii];
2012 * e_source_remove_sync:
2013 * @source: the #ESource to be removed
2014 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2015 * @error: return location for a #GError, or %NULL
2017 * Requests the D-Bus service to delete the key files for @source and all of
2018 * its descendants and broadcast their removal to all clients. If an error
2019 * occurs, the functon will set @error and return %FALSE.
2021 * Returns: %TRUE on success, %FALSE on failure
2026 e_source_remove_sync (ESource *source,
2027 GCancellable *cancellable,
2030 ESourceClass *class;
2032 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2034 class = E_SOURCE_GET_CLASS (source);
2035 g_return_val_if_fail (class->remove_sync != NULL, FALSE);
2037 return class->remove_sync (source, cancellable, error);
2042 * @source: the #ESource to be removed
2043 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2044 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2046 * @user_data: (closure): data to pass to the callback function
2048 * Asynchronously requests the D-Bus service to delete the key files for
2049 * @source all of its descendants and broadcast their removal to all clients.
2051 * When the operation is finished, @callback will be called. You can then
2052 * call e_source_remove_finish() to get the result of the operation.
2057 e_source_remove (ESource *source,
2058 GCancellable *cancellable,
2059 GAsyncReadyCallback callback,
2062 ESourceClass *class;
2064 g_return_if_fail (E_IS_SOURCE (source));
2066 class = E_SOURCE_GET_CLASS (source);
2067 g_return_if_fail (class->remove != NULL);
2069 class->remove (source, cancellable, callback, user_data);
2073 * e_source_remove_finish:
2074 * @source: the #ESource to be removed
2075 * @result: a #GAsyncResult
2076 * @error: return location for a #GError, or %NULL
2078 * Finishes the operation started with e_source_remove(). If an
2079 * error occured, the function will set @error and return %FALSE.
2081 * Returns: %TRUE on success, %FALSE of failure
2086 e_source_remove_finish (ESource *source,
2087 GAsyncResult *result,
2090 ESourceClass *class;
2092 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2093 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2095 class = E_SOURCE_GET_CLASS (source);
2096 g_return_val_if_fail (class->remove_finish != NULL, FALSE);
2098 return class->remove_finish (source, result, error);
2102 * e_source_write_sync:
2103 * @source: a writable #ESource
2104 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2105 * @error: return location for a #GError, or %NULL
2107 * Submits the current contents of @source to the D-Bus service to be
2108 * written to disk and broadcast to other clients. This can only be
2109 * called on #ESource:writable data sources.
2111 * Returns: %TRUE on success, %FALSE on failure
2116 e_source_write_sync (ESource *source,
2117 GCancellable *cancellable,
2120 ESourceClass *class;
2122 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2124 class = E_SOURCE_GET_CLASS (source);
2125 g_return_val_if_fail (class->write_sync != NULL, FALSE);
2127 return class->write_sync (source, cancellable, error);
2132 * @source: a writable #ESource
2133 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2134 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2136 * @user_data: (closure): data to pass to the callback function
2138 * Asynchronously submits the current contents of @source to the D-Bus
2139 * service to be written to disk and broadcast to other clients. This
2140 * can only be called on #ESource:writable data sources.
2142 * When the operation is finished, @callback will be called. You can then
2143 * call e_source_write_finish() to get the result of the operation.
2148 e_source_write (ESource *source,
2149 GCancellable *cancellable,
2150 GAsyncReadyCallback callback,
2153 ESourceClass *class;
2155 g_return_if_fail (E_IS_SOURCE (source));
2157 class = E_SOURCE_GET_CLASS (source);
2158 g_return_if_fail (class->write != NULL);
2160 class->write (source, cancellable, callback, user_data);
2164 * e_source_write_finish:
2165 * @source: a writable #ESource
2166 * @result: a #GAsyncResult
2167 * @error: return location for a #GError, or %NULL
2169 * Finishes the operation started with e_source_write(). If an
2170 * error occurred, the function will set @error and return %FALSE.
2172 * Returns: %TRUE on success, %FALSE on failure
2177 e_source_write_finish (ESource *source,
2178 GAsyncResult *result,
2181 ESourceClass *class;
2183 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2184 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2186 class = E_SOURCE_GET_CLASS (source);
2187 g_return_val_if_fail (class->write_finish != NULL, FALSE);
2189 return class->write_finish (source, result, error);