[folks] core: Add GroupDetails.change_groups()



commit 6166dda19b16af130b61f61f3ae3b2a92a49cba7
Author: Philip Withnall <philip tecnocode co uk>
Date:   Tue Aug 30 23:24:58 2011 +0100

    core: Add GroupDetails.change_groups()
    
    This allows the groups of an implementing class to all be changed
    simultaneously, asynchronously and with proper error notification.
    
    Closes: bgo#657510

 NEWS                                     |    2 +
 backends/eds/lib/edsf-persona-store.vala |    6 ++--
 backends/eds/lib/edsf-persona.vala       |   17 +++++++---
 backends/telepathy/lib/tpf-persona.vala  |   46 +++++++++++++++------------
 folks/group-details.vala                 |   20 ++++++++++++
 folks/individual.vala                    |   51 +++++++++++++++++++++++++++---
 6 files changed, 109 insertions(+), 33 deletions(-)
---
diff --git a/NEWS b/NEWS
index c7f8104..0889982 100644
--- a/NEWS
+++ b/NEWS
@@ -6,12 +6,14 @@ Bugs fixed:
 * Bug 653777 â Would be nice to have a helper function to create a writable
   persona
 * Bug 657635 â Linking personas from different (e-d-s) stores is not working
+* Bug 657510 â Add asynchronous property setter methods
 
 API changes:
 * Add PersonaStore:always-writeable-properties property
 * Add IndividualAggregatorError.PROPERTY_NOT_WRITEABLE error
 * Add IndividualAggregator.ensure_individual_property_writeable()
 * Add Folks.PropertyError
+* Add *Details.change_*() virtual methods
 
 Overview of changes from libfolks 0.6.0 to libfolks 0.6.1
 =========================================================
diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala
index 9cf9274..92cad0a 100644
--- a/backends/eds/lib/edsf-persona-store.vala
+++ b/backends/eds/lib/edsf-persona-store.vala
@@ -1193,7 +1193,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore
     }
 
   internal async void _set_groups (Edsf.Persona persona,
-      Set<string> groups)
+      Set<string> groups) throws PropertyError
     {
       if (this._groups_supported == false)
         {
@@ -1207,9 +1207,9 @@ public class Edsf.PersonaStore : Folks.PersonaStore
           yield this._set_contact_groups (contact, groups);
           yield this._addressbook.modify_contact (contact, null);
         }
-      catch (GLib.Error error)
+      catch (GLib.Error e)
         {
-          GLib.warning ("Can't update groups: %s\n", error.message);
+          throw this.e_client_error_to_property_error ("groups", e);
         }
     }
 
diff --git a/backends/eds/lib/edsf-persona.vala b/backends/eds/lib/edsf-persona.vala
index e7ed2ed..a5c17de 100644
--- a/backends/eds/lib/edsf-persona.vala
+++ b/backends/eds/lib/edsf-persona.vala
@@ -500,10 +500,7 @@ public class Edsf.Persona : Folks.Persona,
   public Set<string> groups
     {
       get { return this._groups_ro; }
-      set
-        {
-          ((Edsf.PersonaStore) this.store)._set_groups (this, value);
-        }
+      set { this.change_groups.begin (value); }
     }
 
   /**
@@ -537,7 +534,17 @@ public class Edsf.Persona : Folks.Persona,
           new_groups.add (group);
         }
 
-      this.groups = new_groups;
+      yield this.change_groups (new_groups);
+    }
+
+  /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public async void change_groups (Set<string> groups) throws PropertyError
+    {
+      yield ((Edsf.PersonaStore) this.store)._set_groups (this, groups);
     }
 
   /**
diff --git a/backends/telepathy/lib/tpf-persona.vala b/backends/telepathy/lib/tpf-persona.vala
index 73aed69..f80ba44 100644
--- a/backends/telepathy/lib/tpf-persona.vala
+++ b/backends/telepathy/lib/tpf-persona.vala
@@ -209,29 +209,11 @@ public class Tpf.Persona : Folks.Persona,
    *
    * See { link Folks.GroupDetails.groups}.
    */
+  [CCode (notify = false)]
   public Set<string> groups
     {
       get { return this._groups_ro; }
-
-      set
-        {
-          foreach (var group in value)
-            {
-              if (this._groups.contains (group) == false)
-                this._change_group (group, true);
-            }
-
-          foreach (var group in this._groups)
-            {
-              if (value.contains (group) == false)
-                this._change_group (group, true);
-            }
-
-          /* Since we're only changing the members of this._groups, rather than
-           * replacing it with a new instance, we have to manually emit the
-           * notification. */
-          this.notify_property ("groups");
-        }
+      set { this.change_groups.begin (value); }
     }
 
   /**
@@ -270,6 +252,30 @@ public class Tpf.Persona : Folks.Persona,
     }
 
   /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public async void change_groups (Set<string> groups) throws PropertyError
+    {
+      Tpf.PersonaStore store = (Tpf.PersonaStore) this.store;
+
+      foreach (var group1 in groups)
+        {
+          if (this._groups.contains (group1) == false)
+            yield store._change_group_membership (this, group1, true);
+        }
+
+      foreach (var group2 in this._groups)
+        {
+          if (groups.contains (group2) == false)
+            yield store._change_group_membership (this, group2, false);
+        }
+
+      this.notify_property ("groups");
+    }
+
+  /**
    * The Telepathy contact represented by this persona.
    *
    * Note that this may be `null` if the { link PersonaStore} providing this
diff --git a/folks/group-details.vala b/folks/group-details.vala
index 44c5aa2..b283ef8 100644
--- a/folks/group-details.vala
+++ b/folks/group-details.vala
@@ -147,4 +147,24 @@ public interface Folks.GroupDetails : Object
    * @since 0.1.11
    */
   public async signal void group_changed (string group, bool is_member);
+
+  /**
+   * Change the contact's groups.
+   *
+   * It's preferred to call this rather than setting { link GroupDetails.groups}
+   * directly, as this method gives error notification and will only return once
+   * the groups have been written to the relevant backing store (or the
+   * operation's failed).
+   *
+   * @param groups the complete set of groups the contact should be a member of
+   * @throws PropertyError if setting the groups failed
+   * @since UNRELEASED
+   */
+  public virtual async void change_groups (Set<string> groups)
+      throws PropertyError
+    {
+      /* Default implementation. */
+      throw new PropertyError.NOT_WRITEABLE (
+          _("Groups are not writeable on this contact."));
+    }
 }
diff --git a/folks/individual.vala b/folks/individual.vala
index 9a2f212..d418032 100644
--- a/folks/individual.vala
+++ b/folks/individual.vala
@@ -564,19 +564,60 @@ public class Folks.Individual : Object,
   /**
    * { inheritDoc}
    */
+  [CCode (notify = false)]
   public Set<string> groups
     {
       get { return this._groups_ro; }
+      set { this.change_groups.begin (value); }
+    }
+
+  /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public async void change_groups (Set<string> groups) throws PropertyError
+    {
+      debug ("Setting '%s' groupsâ", this.id);
 
-      set
+      PropertyError? persona_error = null;
+      var groups_changed = false;
+
+      /* Try to write it to only the Personas which have "groups" as a
+       * writeable property. */
+      foreach (var p in this._persona_set)
         {
-          foreach (var p in this._persona_set)
+          var g = p as GroupDetails;
+          if (g != null && p.store.is_writeable == true &&
+              "groups" in p.writeable_properties)
             {
-              if (p is GroupDetails && ((Persona) p).store.is_writeable == true)
-                ((GroupDetails) p).groups = value;
+              try
+                {
+                  yield g.change_groups (groups);
+                  debug ("    written to persona '%s'", p.uid);
+                  groups_changed = true;
+                }
+              catch (PropertyError e)
+                {
+                  /* Store the first error so we can throw it if setting the
+                   * property fails on every other persona. */
+                  if (persona_error == null)
+                    {
+                      persona_error = e;
+                    }
+                }
             }
-          this._update_groups ();
         }
+
+      /* Failure? */
+      if (groups_changed == false)
+        {
+          assert (persona_error != null);
+          throw persona_error;
+        }
+
+      /* Update our copy of the property. */
+      this._update_groups ();
     }
 
   /**



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