[evolution-data-server] Bug 777207 - Allow e-mail address change for GOA configured accounts



commit 68a9a7281fa2e045e1a338e7ad58ea82b8477c55
Author: Milan Crha <mcrha redhat com>
Date:   Tue Jan 17 18:18:48 2017 +0100

    Bug 777207 - Allow e-mail address change for GOA configured accounts

 src/libedataserver/e-source-goa.c                  |  232 +++++++++++++++++++-
 src/libedataserver/e-source-goa.h                  |    8 +
 .../module-gnome-online-accounts.c                 |  133 ++++++++++--
 3 files changed, 351 insertions(+), 22 deletions(-)
---
diff --git a/src/libedataserver/e-source-goa.c b/src/libedataserver/e-source-goa.c
index 980e915..4efccf1 100644
--- a/src/libedataserver/e-source-goa.c
+++ b/src/libedataserver/e-source-goa.c
@@ -47,13 +47,17 @@ struct _ESourceGoaPrivate {
        gchar *account_id;
        gchar *calendar_url;
        gchar *contacts_url;
+       gchar *name;
+       gchar *address;
 };
 
 enum {
        PROP_0,
        PROP_ACCOUNT_ID,
        PROP_CALENDAR_URL,
-       PROP_CONTACTS_URL
+       PROP_CONTACTS_URL,
+       PROP_NAME,
+       PROP_ADDRESS
 };
 
 G_DEFINE_TYPE (
@@ -85,6 +89,18 @@ source_goa_set_property (GObject *object,
                                E_SOURCE_GOA (object),
                                g_value_get_string (value));
                        return;
+
+               case PROP_NAME:
+                       e_source_goa_set_name (
+                               E_SOURCE_GOA (object),
+                               g_value_get_string (value));
+                       return;
+
+               case PROP_ADDRESS:
+                       e_source_goa_set_address (
+                               E_SOURCE_GOA (object),
+                               g_value_get_string (value));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -117,6 +133,20 @@ source_goa_get_property (GObject *object,
                                e_source_goa_dup_contacts_url (
                                E_SOURCE_GOA (object)));
                        return;
+
+               case PROP_NAME:
+                       g_value_take_string (
+                               value,
+                               e_source_goa_dup_name (
+                               E_SOURCE_GOA (object)));
+                       return;
+
+               case PROP_ADDRESS:
+                       g_value_take_string (
+                               value,
+                               e_source_goa_dup_address (
+                               E_SOURCE_GOA (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -132,6 +162,8 @@ source_goa_finalize (GObject *object)
        g_free (priv->account_id);
        g_free (priv->calendar_url);
        g_free (priv->contacts_url);
+       g_free (priv->name);
+       g_free (priv->address);
 
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (e_source_goa_parent_class)->finalize (object);
@@ -191,6 +223,32 @@ e_source_goa_class_init (ESourceGoaClass *class)
                        G_PARAM_CONSTRUCT |
                        G_PARAM_STATIC_STRINGS |
                        E_SOURCE_PARAM_SETTING));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_NAME,
+               g_param_spec_string (
+                       "name",
+                       "Name",
+                       "GNOME Online Account's original Name",
+                       NULL,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS |
+                       E_SOURCE_PARAM_SETTING));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_ADDRESS,
+               g_param_spec_string (
+                       "address",
+                       "Address",
+                       "GNOME Online Account's original Address",
+                       NULL,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS |
+                       E_SOURCE_PARAM_SETTING));
 }
 
 static void
@@ -457,3 +515,175 @@ e_source_goa_set_contacts_url (ESourceGoa *extension,
 
        g_object_notify (G_OBJECT (extension), "contacts-url");
 }
+
+/**
+ * e_source_goa_get_name:
+ * @extension: an #ESourceGoa
+ *
+ * Returns the original Name of the GNOME Online Account associated
+ * with the #ESource to which @extension belongs. Can be %NULL or an empty
+ * string when not filled.
+ *
+ * Returns: the associated GNOME Online Account's Name
+ *
+ * Since: 3.24
+ **/
+const gchar *
+e_source_goa_get_name (ESourceGoa *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_GOA (extension), NULL);
+
+       return extension->priv->name;
+}
+
+/**
+ * e_source_goa_dup_name:
+ * @extension: an #ESourceGoa
+ *
+ * Thread-safe variation of e_source_goa_get_name().
+ * Use this function when accessing @extension from multiple threads.
+ *
+ * The returned string should be freed with g_free() when no longer needed.
+ *
+ * Returns: a newly-allocated copy of #ESourceGoa:name
+ *
+ * Since: 3.24
+ **/
+gchar *
+e_source_goa_dup_name (ESourceGoa *extension)
+{
+       const gchar *protected;
+       gchar *duplicate;
+
+       g_return_val_if_fail (E_IS_SOURCE_GOA (extension), NULL);
+
+       e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
+
+       protected = e_source_goa_get_name (extension);
+       duplicate = g_strdup (protected);
+
+       e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
+
+       return duplicate;
+}
+
+/**
+ * e_source_goa_set_name:
+ * @extension: an #ESourceGoa
+ * @name: (nullable): the associated GNOME Online Account's Name, or %NULL
+ *
+ * Sets the Name of the GNOME Online Account associated
+ * with the #ESource to which @extension belongs.
+ *
+ * The internal copy of @name is automatically stripped of leading
+ * and trailing whitespace. If the resulting string is empty, %NULL is set
+ * instead.
+ *
+ * Since: 3.24
+ **/
+void
+e_source_goa_set_name (ESourceGoa *extension,
+                      const gchar *name)
+{
+       g_return_if_fail (E_IS_SOURCE_GOA (extension));
+
+       e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
+
+       if (g_strcmp0 (extension->priv->name, name) == 0) {
+               e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
+               return;
+       }
+
+       g_free (extension->priv->name);
+       extension->priv->name = e_util_strdup_strip (name);
+
+       e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
+
+       g_object_notify (G_OBJECT (extension), "name");
+}
+
+/**
+ * e_source_goa_get_address:
+ * @extension: an #ESourceGoa
+ *
+ * Returns the original Address of the GNOME Online Account associated
+ * with the #ESource to which @extension belongs. Can be %NULL or an empty
+ * string when not filled.
+ *
+ * Returns: the associated GNOME Online Account's Address
+ *
+ * Since: 3.24
+ **/
+const gchar *
+e_source_goa_get_address (ESourceGoa *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_GOA (extension), NULL);
+
+       return extension->priv->address;
+}
+
+/**
+ * e_source_goa_dup_address:
+ * @extension: an #ESourceGoa
+ *
+ * Thread-safe variation of e_source_goa_get_address().
+ * Use this function when accessing @extension from multiple threads.
+ *
+ * The returned string should be freed with g_free() when no longer needed.
+ *
+ * Returns: a newly-allocated copy of #ESourceGoa:address
+ *
+ * Since: 3.24
+ **/
+gchar *
+e_source_goa_dup_address (ESourceGoa *extension)
+{
+       const gchar *protected;
+       gchar *duplicate;
+
+       g_return_val_if_fail (E_IS_SOURCE_GOA (extension), NULL);
+
+       e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
+
+       protected = e_source_goa_get_address (extension);
+       duplicate = g_strdup (protected);
+
+       e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
+
+       return duplicate;
+}
+
+/**
+ * e_source_goa_set_address:
+ * @extension: an #ESourceGoa
+ * @address: (nullable): the associated GNOME Online Account's Address, or %NULL
+ *
+ * Sets the Address of the GNOME Online Account associated
+ * with the #ESource to which @extension belongs.
+ *
+ * The internal copy of @address is automatically stripped of leading
+ * and trailing whitespace. If the resulting string is empty, %NULL is set
+ * instead.
+ *
+ * Since: 3.24
+ **/
+void
+e_source_goa_set_address (ESourceGoa *extension,
+                         const gchar *address)
+{
+       g_return_if_fail (E_IS_SOURCE_GOA (extension));
+
+       e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
+
+       if (g_strcmp0 (extension->priv->address, address) == 0) {
+               e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
+               return;
+       }
+
+       g_free (extension->priv->address);
+       extension->priv->address = e_util_strdup_strip (address);
+
+       e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
+
+       g_object_notify (G_OBJECT (extension), "address");
+}
diff --git a/src/libedataserver/e-source-goa.h b/src/libedataserver/e-source-goa.h
index 9501f5c..4ed7055 100644
--- a/src/libedataserver/e-source-goa.h
+++ b/src/libedataserver/e-source-goa.h
@@ -90,6 +90,14 @@ const gchar *        e_source_goa_get_contacts_url   (ESourceGoa *extension);
 gchar *                e_source_goa_dup_contacts_url   (ESourceGoa *extension);
 void           e_source_goa_set_contacts_url   (ESourceGoa *extension,
                                                 const gchar *contacts_url);
+const gchar *  e_source_goa_get_name           (ESourceGoa *extension);
+gchar *                e_source_goa_dup_name           (ESourceGoa *extension);
+void           e_source_goa_set_name           (ESourceGoa *extension,
+                                                const gchar *name);
+const gchar *  e_source_goa_get_address        (ESourceGoa *extension);
+gchar *                e_source_goa_dup_address        (ESourceGoa *extension);
+void           e_source_goa_set_address        (ESourceGoa *extension,
+                                                const gchar *address);
 
 G_END_DECLS
 
diff --git a/src/modules/gnome-online-accounts/module-gnome-online-accounts.c 
b/src/modules/gnome-online-accounts/module-gnome-online-accounts.c
index 071ec43..3e2cd3c 100644
--- a/src/modules/gnome-online-accounts/module-gnome-online-accounts.c
+++ b/src/modules/gnome-online-accounts/module-gnome-online-accounts.c
@@ -31,6 +31,9 @@
 #define E_GNOME_ONLINE_ACCOUNTS(obj) \
        (G_TYPE_CHECK_INSTANCE_CAST \
        ((obj), E_TYPE_GNOME_ONLINE_ACCOUNTS, EGnomeOnlineAccounts))
+#define E_IS_GNOME_ONLINE_ACCOUNTS(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_GNOME_ONLINE_ACCOUNTS))
 
 #define CAMEL_IMAP_PROVIDER_NAME    "imapx"
 #define CAMEL_SMTP_PROVIDER_NAME    "smtp"
@@ -644,6 +647,76 @@ gnome_online_accounts_config_mail_account (EGnomeOnlineAccounts *extension,
        e_server_side_source_set_removable (server_side_source, FALSE);
 }
 
+static gboolean
+e_goa_transform_only_when_original_same_cb (GBinding *binding,
+                                           const GValue *from_value,
+                                           GValue *to_value,
+                                           gpointer user_data)
+{
+       EGnomeOnlineAccounts *extension = user_data;
+       ESourceMailIdentity *mail_identity;
+       ESourceRegistryServer *registry_server;
+       ESource *collection, *source;
+       const gchar *new_value;
+       gboolean to_value_set = FALSE;
+
+       g_return_val_if_fail (E_IS_GNOME_ONLINE_ACCOUNTS (extension), TRUE);
+
+       new_value = g_value_get_string (from_value);
+       if (new_value && !*new_value)
+               new_value = NULL;
+
+       mail_identity = E_SOURCE_MAIL_IDENTITY (g_binding_get_target (binding));
+       source = e_source_extension_ref_source (E_SOURCE_EXTENSION (mail_identity));
+
+       registry_server = gnome_online_accounts_get_server (extension);
+       collection = e_source_registry_server_ref_source (registry_server, e_source_get_parent (source));
+
+       /* The collection can be NULL when the account was just created. */
+       if (source && collection) {
+               ESourceGoa *goa_extension;
+               gchar *set_value = NULL, *old_value = NULL;
+               const gchar *prop_name;
+               gboolean changed;
+
+               g_warn_if_fail (e_source_has_extension (collection, E_SOURCE_EXTENSION_GOA));
+
+               prop_name = g_binding_get_target_property (binding);
+               goa_extension = e_source_get_extension (collection, E_SOURCE_EXTENSION_GOA);
+
+               g_object_get (G_OBJECT (goa_extension), prop_name, &old_value, NULL);
+
+               changed = g_strcmp0 (old_value, new_value) != 0;
+
+               if (changed) {
+                       g_object_set (G_OBJECT (goa_extension), prop_name, new_value, NULL);
+
+                       g_object_get (G_OBJECT (mail_identity), prop_name, &set_value, NULL);
+
+                       if (g_strcmp0 (set_value, old_value) != 0) {
+                               to_value_set = TRUE;
+
+                               g_value_set_string (to_value, set_value);
+                       }
+               } else {
+                       g_object_get (G_OBJECT (mail_identity), prop_name, &set_value, NULL);
+                       to_value_set = TRUE;
+                       g_value_set_string (to_value, set_value);
+               }
+
+               g_free (set_value);
+               g_free (old_value);
+       }
+
+       g_clear_object (&collection);
+       g_clear_object (&source);
+
+       if (!to_value_set)
+               g_value_set_string (to_value, new_value);
+
+       return TRUE;
+}
+
 static void
 gnome_online_accounts_config_mail_identity (EGnomeOnlineAccounts *extension,
                                             ESource *source,
@@ -665,23 +738,23 @@ gnome_online_accounts_config_mail_identity (EGnomeOnlineAccounts *extension,
        extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
        mail_identity = e_source_get_extension (source, extension_name);
 
-       tmp = e_source_mail_identity_dup_address (mail_identity);
-       if (!tmp || !*tmp) {
-               /* Set the Name only if the mail is not set yet, because users can change the Name,
-                  even to an empty string, but the email is fixed with the one from GoaMail.
-               */
-               g_free (tmp);
-
-               tmp = goa_mail_dup_name (goa_mail);
-               if (tmp && *tmp)
-                       e_source_mail_identity_set_name (mail_identity, tmp);
-       }
-       g_free (tmp);
+       e_binding_bind_property_full (
+               goa_mail, "name",
+               mail_identity, "name",
+               G_BINDING_SYNC_CREATE,
+               e_goa_transform_only_when_original_same_cb,
+               NULL,
+               g_object_ref (extension),
+               g_object_unref);
 
-       e_binding_bind_property (
+       e_binding_bind_property_full (
                goa_mail, "email-address",
                mail_identity, "address",
-               G_BINDING_SYNC_CREATE);
+               G_BINDING_SYNC_CREATE,
+               e_goa_transform_only_when_original_same_cb,
+               NULL,
+               g_object_ref (extension),
+               g_object_unref);
 
        g_object_unref (goa_mail);
 
@@ -774,6 +847,7 @@ gnome_online_accounts_create_collection (EGnomeOnlineAccounts *extension,
                                          GoaObject *goa_object)
 {
        GoaAccount *goa_account;
+       GoaMail *goa_mail;
        ESourceRegistryServer *server;
        ESource *collection_source;
        ESource *mail_account_source = NULL;
@@ -791,17 +865,34 @@ gnome_online_accounts_create_collection (EGnomeOnlineAccounts *extension,
                extension, collection_source, goa_object);
        parent_uid = e_source_get_uid (collection_source);
 
-       if (goa_object_peek_mail (goa_object)) {
-               mail_account_source =
-                       gnome_online_accounts_new_source (extension);
+       goa_mail = goa_object_get_mail (goa_object);
+       if (goa_mail) {
+               ESourceGoa *goa_extension;
+               gchar *name = NULL, *address = NULL;
+
+               goa_extension = e_source_get_extension (collection_source, E_SOURCE_EXTENSION_GOA);
+
+               g_object_get (G_OBJECT (goa_mail),
+                       "name", &name,
+                       "email-address", &address,
+                       NULL);
+
+               g_object_set (G_OBJECT (goa_extension),
+                       "name", name,
+                       "address", address,
+                       NULL);
+
+               g_object_unref (goa_mail);
+               g_free (name);
+               g_free (address);
+
+               mail_account_source = gnome_online_accounts_new_source (extension);
                g_return_if_fail (E_IS_SOURCE (mail_account_source));
 
-               mail_identity_source =
-                       gnome_online_accounts_new_source (extension);
+               mail_identity_source = gnome_online_accounts_new_source (extension);
                g_return_if_fail (E_IS_SOURCE (mail_identity_source));
 
-               mail_transport_source =
-                       gnome_online_accounts_new_source (extension);
+               mail_transport_source = gnome_online_accounts_new_source (extension);
                g_return_if_fail (E_IS_SOURCE (mail_transport_source));
 
                /* Configure parent/child relationships. */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]