[folks] core: Add NameDetails.change_*() methods



commit 0eb80decfd43b5488c3ad7f97dd13bfb540a67d0
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sun Aug 28 22:06:57 2011 +0100

    core: Add NameDetails.change_*() methods
    
    This allows the names of an implementing class to be changed asynchronously
    with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala   |   17 ++--
 backends/eds/lib/edsf-persona.vala         |   50 +++++++++----
 backends/libsocialweb/lib/swf-persona.vala |   41 ++++++++--
 backends/tracker/lib/trf-persona.vala      |   55 ++++++++++----
 folks/individual.vala                      |  110 +++++++++++++++++++---------
 folks/name-details.vala                    |   62 ++++++++++++++++
 po/POTFILES.in                             |    1 +
 po/POTFILES.skip                           |    1 +
 8 files changed, 255 insertions(+), 82 deletions(-)
---
diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala
index a7d2eaf..53b432d 100644
--- a/backends/eds/lib/edsf-persona-store.vala
+++ b/backends/eds/lib/edsf-persona-store.vala
@@ -1030,7 +1030,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore
     }
 
   internal async void _set_full_name (Edsf.Persona persona,
-      string full_name)
+      string full_name) throws PropertyError
     {
       if (persona.full_name == full_name)
         return;
@@ -1041,13 +1041,14 @@ public class Edsf.PersonaStore : Folks.PersonaStore
           contact.set (E.Contact.field_id ("full_name"), full_name);
           yield this._addressbook.modify_contact (contact, null);
         }
-      catch (GLib.Error error)
+      catch (GLib.Error e)
         {
-          GLib.warning ("Can't update full name: %s\n", error.message);
+          throw this.e_client_error_to_property_error ("full-name", e);
         }
     }
 
   internal async void _set_nickname (Edsf.Persona persona, string nickname)
+      throws PropertyError
     {
       if (persona.nickname == nickname)
         return;
@@ -1058,9 +1059,9 @@ public class Edsf.PersonaStore : Folks.PersonaStore
           contact.set (E.Contact.field_id ("nickname"), nickname);
           yield this._addressbook.modify_contact (contact, null);
         }
-      catch (GLib.Error error)
+      catch (GLib.Error e)
         {
-          GLib.warning ("Can't update nickname: %s\n", error.message);
+          throw this.e_client_error_to_property_error ("nickname", e);
         }
     }
 
@@ -1096,7 +1097,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore
     }
 
   internal async void _set_structured_name (Edsf.Persona persona,
-      StructuredName? sname)
+      StructuredName? sname) throws PropertyError
     {
       if (persona.structured_name != null &&
           persona.structured_name.equal (sname))
@@ -1108,9 +1109,9 @@ public class Edsf.PersonaStore : Folks.PersonaStore
           yield this._set_contact_name (contact, sname);
           yield this._addressbook.modify_contact (contact, null);
         }
-      catch (GLib.Error error)
+      catch (GLib.Error e)
         {
-          GLib.warning ("Can't update structured name: %s\n", error.message);
+          throw this.e_client_error_to_property_error ("structured-name", e);
         }
     }
 
diff --git a/backends/eds/lib/edsf-persona.vala b/backends/eds/lib/edsf-persona.vala
index cff1ea5..bb8470f 100644
--- a/backends/eds/lib/edsf-persona.vala
+++ b/backends/eds/lib/edsf-persona.vala
@@ -311,10 +311,19 @@ public class Edsf.Persona : Folks.Persona,
   public StructuredName? structured_name
     {
       get { return this._structured_name; }
-      set
-        {
-          ((Edsf.PersonaStore) this.store)._set_structured_name (this, value);
-        }
+      set { this.change_structured_name.begin (value); }
+    }
+
+  /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public async void change_structured_name (StructuredName? structured_name)
+      throws PropertyError
+    {
+      yield ((Edsf.PersonaStore) this.store)._set_structured_name (this,
+          structured_name);
     }
 
   /**
@@ -324,7 +333,7 @@ public class Edsf.Persona : Folks.Persona,
    */
   public string contact_id { get; private set; }
 
-  private string _full_name;
+  private string _full_name = "";
   /**
    * { inheritDoc}
    *
@@ -334,13 +343,20 @@ public class Edsf.Persona : Folks.Persona,
   public string full_name
     {
       get { return this._full_name; }
-      set
-        {
-          ((Edsf.PersonaStore) this.store)._set_full_name (this, value);
-        }
+      set { this.change_full_name.begin (value); }
     }
 
-  private string _nickname;
+  /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public async void change_full_name (string full_name) throws PropertyError
+    {
+      yield ((Edsf.PersonaStore) this.store)._set_full_name (this, full_name);
+    }
+
+  private string _nickname = "";
   /**
    * { inheritDoc}
    *
@@ -350,11 +366,17 @@ public class Edsf.Persona : Folks.Persona,
   public string nickname
     {
       get { return this._nickname; }
+      set { this.change_nickname.begin (value); }
+    }
 
-      set
-        {
-          ((Edsf.PersonaStore) this.store)._set_nickname (this, value);
-        }
+  /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public async void change_nickname (string nickname) throws PropertyError
+    {
+      yield ((Edsf.PersonaStore) this.store)._set_nickname (this, nickname);
     }
 
   private Gender _gender;
diff --git a/backends/libsocialweb/lib/swf-persona.vala b/backends/libsocialweb/lib/swf-persona.vala
index 16c9a87..50e25bc 100644
--- a/backends/libsocialweb/lib/swf-persona.vala
+++ b/backends/libsocialweb/lib/swf-persona.vala
@@ -85,24 +85,40 @@ public class Swf.Persona : Folks.Persona,
       set { this.change_avatar.begin (value); } /* not writeable */
     }
 
+  private StructuredName? _structured_name = null;
+
   /**
    * { inheritDoc}
    */
-  public StructuredName? structured_name { get; private set; }
+  [CCode (notify = false)]
+  public StructuredName? structured_name
+    {
+      get { return this._structured_name; }
+      set { this.change_structured_name.begin (value); } /* not writeable */
+    }
+
+  private string _full_name = "";
 
   /**
    * { inheritDoc}
    */
-  public string full_name { get; private set; }
+  [CCode (notify = false)]
+  public string full_name
+    {
+      get { return this._full_name; }
+      set { this.change_full_name.begin (value); } /* not writeable */
+    }
+
+  private string _nickname = "";
 
-  private string _nickname;
   /**
    * { inheritDoc}
    */
+  [CCode (notify = false)]
   public string nickname
     {
       get { return this._nickname; }
-      private set {}
+      set { this.change_nickname.begin (value); } /* not writeable */
     }
 
   private Gender _gender = Gender.UNSPECIFIED;
@@ -321,13 +337,22 @@ public class Swf.Persona : Folks.Persona,
       var structured_name = new StructuredName.simple (
           contact.get_value ("n.family"), contact.get_value ("n.given"));
       if (!structured_name.is_empty ())
-        this.structured_name = structured_name;
+        {
+          this._structured_name = structured_name;
+          this.notify_property ("structured-name");
+        }
       else if (this.structured_name != null)
-        this.structured_name = null;
+        {
+          this._structured_name = null;
+          this.notify_property ("structured-name");
+        }
 
       var full_name = contact.get_value ("fn");
-      if (this.full_name != full_name)
-        this.full_name = full_name;
+      if (this._full_name != full_name)
+        {
+          this._full_name = full_name;
+          this.notify_property ("full-name");
+        }
 
       var urls = new HashSet<UrlFieldDetails> (
           (GLib.HashFunc) UrlFieldDetails.hash,
diff --git a/backends/tracker/lib/trf-persona.vala b/backends/tracker/lib/trf-persona.vala
index 5c15217..12c0745 100644
--- a/backends/tracker/lib/trf-persona.vala
+++ b/backends/tracker/lib/trf-persona.vala
@@ -78,18 +78,21 @@ public class Trf.Persona : Folks.Persona,
    *
    * See { link Folks.NameDetails.nickname}.
    */
+  [CCode (notify = false)]
   public string nickname
     {
       get { return this._nickname; }
+      set { this.change_nickname.begin (value); }
+    }
 
-      set
-        {
-          if (this._nickname == value)
-            return;
-          this._nickname = value;
-          this.notify_property ("nickname");
-          ((Trf.PersonaStore) this.store)._set_nickname (this, value);
-        }
+  /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public async void change_nickname (string nickname) throws PropertyError
+    {
+      yield ((Trf.PersonaStore) this.store)._set_nickname (this, nickname);
     }
 
   /**
@@ -172,26 +175,44 @@ public class Trf.Persona : Folks.Persona,
   /**
    * { inheritDoc}
    */
+  [CCode (notify = false)]
   public StructuredName? structured_name
     {
       get { return this._structured_name; }
-      public set
-        {
-          ((Trf.PersonaStore) this.store)._set_structured_name (this, value);
-        }
+      set { this.change_structured_name.begin (value); }
     }
 
-  private string _full_name;
   /**
    * { inheritDoc}
+   *
+   * @since UNRELEASED
    */
+  public async void change_structured_name (StructuredName? structured_name)
+      throws PropertyError
+    {
+      yield ((Trf.PersonaStore) this.store)._set_structured_name (this,
+          structured_name);
+    }
+
+  private string _full_name = "";
+  /**
+   * { inheritDoc}
+   */
+  [CCode (notify = false)]
   public string full_name
     {
       get { return this._full_name; }
-      public set
-        {
-          ((Trf.PersonaStore) this.store)._set_full_name (this, value);
-        }
+      set { this.change_full_name.begin (value); }
+    }
+
+  /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public async void change_full_name (string full_name) throws PropertyError
+    {
+      yield ((Trf.PersonaStore) this.store)._set_full_name (this, full_name);
     }
 
   private Gender _gender;
diff --git a/folks/individual.vala b/folks/individual.vala
index d4cc203..c82d04c 100644
--- a/folks/individual.vala
+++ b/folks/individual.vala
@@ -268,66 +268,99 @@ public class Folks.Individual : Object,
       this.notify_property ("alias");
     }
 
+  private StructuredName? _structured_name = null;
+
   /**
    * { inheritDoc}
    */
-  public StructuredName? structured_name { get; private set; }
+  [CCode (notify = false)]
+  public StructuredName? structured_name
+    {
+      get { return this._structured_name; }
+      set { this.change_structured_name.begin (value); } /* not writeable */
+    }
+
+  private string _full_name = "";
 
   /**
    * { inheritDoc}
    */
-  public string full_name { get; private set; }
+  [CCode (notify = false)]
+  public string full_name
+    {
+      get { return this._full_name; }
+      set { this.change_full_name.begin (value); } /* not writeable */
+    }
 
   /**
    * { inheritDoc}
    */
+  [CCode (notify = false)]
   public string nickname
     {
       get { return this._nickname; }
+      set { this.change_nickname.begin (value); }
+    }
 
-      set
+  /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public async void change_nickname (string nickname) throws PropertyError
+    {
+      // Normalise null values to the empty string
+      if (nickname == null)
         {
-          // Normalise null values to the empty string
-          if (value == null)
-            value = "";
+          nickname = "";
+        }
 
-          if (this._nickname == value)
-            return;
+      if (this._nickname == nickname)
+        {
+          return;
+        }
 
-          this._nickname = value;
+      debug ("Setting nickname of individual '%s' to '%s'â", this.id, nickname);
 
-          debug ("Setting nickname of individual '%s' to '%s'â", this.id,
-              value);
+      PropertyError? persona_error = null;
+      var nickname_changed = false;
 
-          /* First, try to write it to only the writeable Personasâ */
-          var nickname_changed = false;
-          foreach (var p in this._persona_set)
+      /* Try to write it to only the writeable Personas which have "nickname"
+       * as a writeable property. */
+      foreach (var p in this._persona_set)
+        {
+          var n = p as NameDetails;
+          if (n != null && p.store.is_writeable == true &&
+              "nickname" in p.writeable_properties)
             {
-              if (p is NameDetails &&
-                  ((Persona) p).store.is_writeable == true)
+              try
                 {
-                  debug ("    written to writeable persona '%s'",
-                      ((Persona) p).uid);
-                  ((NameDetails) p).nickname = value;
+                  yield n.change_nickname (nickname);
+                  debug ("    written to writeable persona '%s'", p.uid);
                   nickname_changed = true;
                 }
-            }
-
-          /* âbut if there are no writeable Personas, we have to fall back to
-           * writing it to every Persona. */
-          if (nickname_changed == false)
-            {
-              foreach (var p in this._persona_set)
+              catch (PropertyError e)
                 {
-                  if (p is NameDetails)
+                  /* Store the first error so we can throw it if setting the
+                   * nickname fails on every other persona. */
+                  if (persona_error == null)
                     {
-                      debug ("    written to non-writeable persona '%s'",
-                          ((Persona) p).uid);
-                      ((NameDetails) p).nickname = value;
+                      persona_error = e;
                     }
                 }
             }
         }
+
+      /* Failure? */
+      if (nickname_changed == false)
+        {
+          assert (persona_error != null);
+          throw persona_error;
+        }
+
+      /* Update our copy of the nickname. */
+      this._nickname = nickname;
+      this.notify_property ("nickname");
     }
 
   private Gender _gender = Gender.UNSPECIFIED;
@@ -1252,15 +1285,19 @@ public class Folks.Individual : Object,
                   if (this.structured_name == null ||
                       !this.structured_name.equal (new_value))
                     {
-                      this.structured_name = new_value;
+                      this._structured_name = new_value;
+                      this.notify_property ("structured-name");
                       return;
                     }
                 }
             }
         }
 
-      if (name_found == false)
-        this.structured_name = null;
+      if (name_found == false && this._structured_name != null)
+        {
+          this._structured_name = null;
+          this.notify_property ("structured-name");
+        }
     }
 
   private void _update_full_name ()
@@ -1281,8 +1318,11 @@ public class Folks.Individual : Object,
             }
         }
 
-      if (new_full_name != this.full_name)
-        this.full_name = new_full_name;
+      if (new_full_name != this._full_name)
+        {
+          this._full_name = new_full_name;
+          this.notify_property ("full-name");
+        }
     }
 
   private void _update_nickname ()
diff --git a/folks/name-details.vala b/folks/name-details.vala
index 22f9f2c..b1144d8 100644
--- a/folks/name-details.vala
+++ b/folks/name-details.vala
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Collabora Ltd.
+ * Copyright (C) 2011 Philip Withnall
  *
  * This library is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
@@ -17,6 +18,7 @@
  * Authors:
  *       Marco Barisione <marco barisione collabora co uk>
  *       Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *       Philip Withnall <philip tecnocode co uk>
  */
 
 using GLib;
@@ -223,6 +225,26 @@ public interface Folks.NameDetails : Object
   public abstract StructuredName? structured_name { get; set; }
 
   /**
+   * Change the contact's structured name.
+   *
+   * It's preferred to call this rather than setting
+   * { link NameDetails.structured_name} directly, as this method gives error
+   * notification and will only return once the name has been written to the
+   * relevant backing store (or the operation's failed).
+   *
+   * @param name the structured name (`null` to unset it)
+   * @throws PropertyError if setting the structured name failed
+   * @since UNRELEASED
+   */
+  public virtual async void change_structured_name (StructuredName? name)
+      throws PropertyError
+    {
+      /* Default implementation. */
+      throw new PropertyError.NOT_WRITEABLE (
+          _("Structured name is not writeable on this contact."));
+    }
+
+  /**
    * The full name of the contact.
    *
    * The full name is the name of the contact written in the way the contact
@@ -237,6 +259,26 @@ public interface Folks.NameDetails : Object
   public abstract string full_name { get; set; }
 
   /**
+   * Change the contact's full name.
+   *
+   * It's preferred to call this rather than setting
+   * { link NameDetails.full_name} directly, as this method gives error
+   * notification and will only return once the name has been written to the
+   * relevant backing store (or the operation's failed).
+   *
+   * @param full_name the full name (empty string to unset it)
+   * @throws PropertyError if setting the full name failed
+   * @since UNRELEASED
+   */
+  public virtual async void change_full_name (string full_name)
+      throws PropertyError
+    {
+      /* Default implementation. */
+      throw new PropertyError.NOT_WRITEABLE (
+          _("Full name is not writeable on this contact."));
+    }
+
+  /**
    * The nickname of the contact.
    *
    * The nickname is the name that the contact chose for himself. This is
@@ -250,4 +292,24 @@ public interface Folks.NameDetails : Object
    * @since 0.3.5
    */
   public abstract string nickname { get; set; }
+
+  /**
+   * Change the contact's nickname.
+   *
+   * It's preferred to call this rather than setting
+   * { link NameDetails.nickname} directly, as this method gives error
+   * notification and will only return once the name has been written to the
+   * relevant backing store (or the operation's failed).
+   *
+   * @param nickname the nickname (empty string to unset it)
+   * @throws PropertyError if setting the nickname failed
+   * @since UNRELEASED
+   */
+  public virtual async void change_nickname (string nickname)
+      throws PropertyError
+    {
+      /* Default implementation. */
+      throw new PropertyError.NOT_WRITEABLE (
+          _("Nickname is not writeable on this contact."));
+    }
 }
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e7c5446..7bce721 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -17,6 +17,7 @@ folks/gender-details.vala
 folks/im-details.vala
 folks/individual-aggregator.vala
 folks/local-id-details.vala
+folks/name-details.vala
 folks/postal-address-details.vala
 folks/role-details.vala
 tools/import-pidgin.vala
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 1133f89..2291af2 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -16,6 +16,7 @@ folks/gender-details.c
 folks/im-details.c
 folks/individual-aggregator.c
 folks/local-id-details.c
+folks/name-details.c
 folks/postal-address-details.c
 folks/role-details.c
 tools/import-pidgin.c



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