After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 657510 - Add asynchronous property setter methods
Add asynchronous property setter methods
Status: RESOLVED FIXED
Product: folks
Classification: Platform
Component: libfolks
git master
Other All
: Normal major
: Future
Assigned To: folks-maint
folks-maint
Depends on:
Blocks: 657991
 
 
Reported: 2011-08-27 14:57 UTC by Philip Withnall
Modified: 2011-09-02 18:35 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Add asynchronous property setters to AliasDetails and ImDetails (19.54 KB, patch)
2011-08-27 16:31 UTC, Philip Withnall
reviewed Details | Review
Add asynchronous property setters (127.10 KB, patch)
2011-08-31 22:06 UTC, Philip Withnall
committed Details | Review

Description Philip Withnall 2011-08-27 14:57:48 UTC
Alex has been complaining about the way which setting properties is handled in folks. Currently, the approach is for the client to set the property using the GObject property setter, and then some time later (once the change has been written to disk or the network, or whatever) a notify signal will be emitted for that property. However, if setting the property fails (because the value's invalid, or the property's not actually writeable, or the backend has a hissy fit, etc.) no notify signal will ever be emitted. This requires clients to implement some kind of timeout for all property setting operations, and assume that they've failed after that timeout passes and no notification signal is received. Obviously, this is a bit rubbish.

I propose that we remedy this by adding asynchronous, failable property setting methods to each of the *Details interfaces. We can then strongly recommend that clients use those methods, rather than the GObject property setter, to set properties. We can maintain API compatibility by changing the GObject property setters to just .begin() these new methods, which should ensure we don't duplicate code with the new methods.

For example:

    public interface AliasDetails {
        public abstract string alias { get; set; }
        public async abstract void change_alias (string alias) throws Folks.PropertyError;
    }

    public errordomain PropertyError {
        NOT_WRITEABLE, /* classes could use this if only some of their personas support writing the property */
        /* Other errors can go here. See below for my ideas on how this fits in with bug #652659. */
    }

Classes which implement AliasDetails then become:

  [CCode (notify = false)]
  public string alias
    {
      get { return this._alias; }
      set { this.change_alias.begin (value); }
    }

  /**
   * {@inheritDoc}
   *
   * @since UNRELEASED
   */
  public async void change_alias (string alias) throws Folks.PropertyError
    {
      if (this._alias == alias)
        {
          return;
        }

      debug ("Setting alias of Kf.Persona '%s' to '%s'.", this.uid, alias);

      this._key_file.set_string (this.display_id, "__alias", alias);
      yield ((Kf.PersonaStore) this.store).save_key_file ();

      this._alias = alias;
      this.notify_property ("alias");
    }

I think this should take care of Alex's problem. New change_*() methods can be added to the other *Details interfaces similarly.

One other big consideration in the design of this API, and one which I'm not so sure it deals with nicely, is bug #652659. My current idea for fixing that bug is to use the API suggested in the report, and define the semantics such that any call to *Details.change_*() methods for a given persona, between a pair of calls to Persona.freeze_updates()/Persona.thaw_updates() for that persona, will only return (i.e. call its GAsyncReadyCallback) once Persona.thaw_updates() is called and all the updates have been pushed to the backing store. This way, each individual call to a *Details.change_*() method can return an error which is related to that specific property change; rather than having Persona.thaw_updates() return a single error which somehow relates to all property changes, or return an array of errors which the client code has to match back up with some list of pending property changes that it's kept. It would be nice if we could design the API such that the client code doesn't have to keep such a list of pending changes.

Corner cases like the following can be handled (I think) reasonably well by this design:
    my_persona.freeze_updates ();
    my_persona.change_alias ("alias one");
    my_persona.change_alias ("alias two");
    my_persona.thaw_updates ();
I suggest that upon calling change_alias() for the second time, the first async call to change_alias() will return immediately with an error code like PropertyError.OVERWRITTEN_BY_A_LATER_OPERATION; the second change_alias() call will only return after thaw_updates() has been called.

I don't want to go too deep into solving bug #652659 in the course of fixing this bug, but I do think we need to make sure the solutions to both bugs work nicely together. I'm sure there's lots of things I haven't thought of, so I'd appreciate some feedback, especially on how nicely this will fit into the gnome-contacts model of making property changes.

For the moment, I'm working on a branch which will make the above changes to AliasDetails, and also port ImAddressDetails. If that turns out OK, and people are happy with the general design, I can go ahead and port other *Details interfaces.
Comment 1 Philip Withnall 2011-08-27 16:31:09 UTC
Created attachment 194929 [details] [review]
Add asynchronous property setters to AliasDetails and ImDetails

https://www.gitorious.org/folks/folks/commits/657510-property-setters

Here's my experiment with implementing this on AliasDetails and ImDetails. It seems to work out fairly well, although I'm not entirely sure about the error management. (Can we reasonably represent all possible errors in setting a property on an arbitrary persona using Folks.PropertyError?)
Comment 2 Philip Withnall 2011-08-27 18:07:06 UTC
(Note: Attachment #194929 [details] hasn't been tested properly, doesn't do error handling properly and was really just a way of seeing how well the API worked. Don't review it in detail please.)
Comment 3 Raul Gutierrez Segales 2011-08-28 08:56:39 UTC
Comment on attachment 194929 [details] [review]
Add asynchronous property setters to AliasDetails and ImDetails

>diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala
>index 4fe748a..cdd871d 100644
>--- a/backends/eds/lib/edsf-persona-store.vala
>+++ b/backends/eds/lib/edsf-persona-store.vala
>@@ -1091,7 +1091,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore
>     }
> 
>   internal async void _set_im_fds  (Edsf.Persona persona,
>-      MultiMap<string, ImFieldDetails> im_fds)
>+      MultiMap<string, ImFieldDetails> im_fds) throws PropertyError
>     {
>       if (Utils.multi_map_str_afd_equal (persona.im_addresses, im_fds))
>         return;
>@@ -1104,7 +1104,9 @@ public class Edsf.PersonaStore : Folks.PersonaStore
>         }
>       catch (GLib.Error error)
>         {
>-          GLib.warning ("Can't update IM addresses: %s\n", error.message);
>+          /* TODO: Proper error handling here */
>+          throw new PropertyError.INVALID_VALUE (
>+              "Can't update IM addresses: %s\n", error.message);

Translation? But I guess it could be defer for when we add proper eror handling. 

>diff --git a/backends/key-file/kf-persona.vala b/backends/key-file/kf-persona.vala
>index 1d3b349..4c5ec3a 100644
>--- a/backends/key-file/kf-persona.vala
>+++ b/backends/key-file/kf-persona.vala

....

>+          string[] addrs = (string[]) normalised_addresses.to_array ();
>+          addrs.length = normalised_addresses.size;

Really?!? Come on Vala!!
Comment 4 Raul Gutierrez Segales 2011-08-28 08:59:01 UTC
This is looking good, let me know if you need a hand to add the async change_* to some properties so we can land this soonish. As mentioned on IRC, I think we should worry about commit-style updates later on so we don't block Gnome Contacts on immediately benefiting from async setters.
Comment 5 Travis Reitter 2011-08-28 20:50:52 UTC
(In reply to comment #0)
> Alex has been complaining about the way which setting properties is handled in
> folks. Currently, the approach is for the client to set the property using the
> GObject property setter, and then some time later (once the change has been
> written to disk or the network, or whatever) a notify signal will be emitted
> for that property. However, if setting the property fails (because the value's
> invalid, or the property's not actually writeable, or the backend has a hissy
> fit, etc.) no notify signal will ever be emitted. This requires clients to
> implement some kind of timeout for all property setting operations, and assume
> that they've failed after that timeout passes and no notification signal is
> received. Obviously, this is a bit rubbish.
> 
> I propose that we remedy this by adding asynchronous, failable property setting
> methods to each of the *Details interfaces. We can then strongly recommend that
> clients use those methods, rather than the GObject property setter, to set
> properties. We can maintain API compatibility by changing the GObject property
> setters to just .begin() these new methods, which should ensure we don't
> duplicate code with the new methods.
> 
> For example:
> 
>     public interface AliasDetails {
>         public abstract string alias { get; set; }
>         public async abstract void change_alias (string alias) throws
> Folks.PropertyError;
>     }
> 
>     public errordomain PropertyError {
>         NOT_WRITEABLE, /* classes could use this if only some of their personas
> support writing the property */
>         /* Other errors can go here. See below for my ideas on how this fits in
> with bug #652659. */
>     }
> 
> Classes which implement AliasDetails then become:
> 
>   [CCode (notify = false)]
>   public string alias
>     {
>       get { return this._alias; }
>       set { this.change_alias.begin (value); }
>     }
> 
>   /**
>    * {@inheritDoc}
>    *
>    * @since UNRELEASED
>    */
>   public async void change_alias (string alias) throws Folks.PropertyError
>     {
>       if (this._alias == alias)
>         {
>           return;
>         }
> 
>       debug ("Setting alias of Kf.Persona '%s' to '%s'.", this.uid, alias);
> 
>       this._key_file.set_string (this.display_id, "__alias", alias);
>       yield ((Kf.PersonaStore) this.store).save_key_file ();
> 
>       this._alias = alias;
>       this.notify_property ("alias");
>     }
> 
> I think this should take care of Alex's problem. New change_*() methods can be
> added to the other *Details interfaces similarly.
> 
> One other big consideration in the design of this API, and one which I'm not so
> sure it deals with nicely, is bug #652659. My current idea for fixing that bug
> is to use the API suggested in the report, and define the semantics such that
> any call to *Details.change_*() methods for a given persona, between a pair of
> calls to Persona.freeze_updates()/Persona.thaw_updates() for that persona, will
> only return (i.e. call its GAsyncReadyCallback) once Persona.thaw_updates() is
> called and all the updates have been pushed to the backing store. This way,
> each individual call to a *Details.change_*() method can return an error which
> is related to that specific property change; rather than having
> Persona.thaw_updates() return a single error which somehow relates to all
> property changes, or return an array of errors which the client code has to
> match back up with some list of pending property changes that it's kept. It
> would be nice if we could design the API such that the client code doesn't have
> to keep such a list of pending changes.
> 
> Corner cases like the following can be handled (I think) reasonably well by
> this design:
>     my_persona.freeze_updates ();
>     my_persona.change_alias ("alias one");
>     my_persona.change_alias ("alias two");
>     my_persona.thaw_updates ();
> I suggest that upon calling change_alias() for the second time, the first async
> call to change_alias() will return immediately with an error code like
> PropertyError.OVERWRITTEN_BY_A_LATER_OPERATION; the second change_alias() call
> will only return after thaw_updates() has been called.
> 
> I don't want to go too deep into solving bug #652659 in the course of fixing
> this bug, but I do think we need to make sure the solutions to both bugs work
> nicely together. I'm sure there's lots of things I haven't thought of, so I'd
> appreciate some feedback, especially on how nicely this will fit into the
> gnome-contacts model of making property changes.
> 
> For the moment, I'm working on a branch which will make the above changes to
> AliasDetails, and also port ImAddressDetails. If that turns out OK, and people
> are happy with the general design, I can go ahead and port other *Details
> interfaces.

This all sounds fairly reasonable to me. Let's implement it (with a good number of test cases), use it in Gnome Contacts, and see how it all works out.
Comment 6 Alexander Larsson 2011-08-30 07:43:12 UTC
The property setting code in gnome-contacts funnels all property setting through a single function call, so that we can do some magic handling for faked primary personas. This doesn't really work well in a one-function-per-attribute change setup. Wouldn't it be possible to have a separate AsyncPropertySetter interface that personas could implement where you still pass in the property name when you set something async.
Comment 7 Philip Withnall 2011-08-30 18:37:51 UTC
(In reply to comment #6)
> The property setting code in gnome-contacts funnels all property setting
> through a single function call, so that we can do some magic handling for faked
> primary personas. This doesn't really work well in a one-function-per-attribute
> change setup. Wouldn't it be possible to have a separate AsyncPropertySetter
> interface that personas could implement where you still pass in the property
> name when you set something async.

How well would it work to pass a delegate to that function (which I think is ContactPane.set_persona_property(), right?)? The delegate would be called in place of persona.set_property() and would call the appropriate *Details.change_*() function on the persona.

This saves the (slight) cost of boxing and unboxing in a GValue, the lack of compile-time type-safety of using GValues and the lack of compile-time safety of passing property names as strings. Additionally, it gives more flexibility for gnome-contacts to handle certain properties differently if that's found to be necessary.

How does that sound? From taking a quick look at the gnome-contacts code (assuming I've been looking at the right bit) I think it should work reasonably well.
Comment 8 Alexander Larsson 2011-08-30 20:03:34 UTC
At the toplevel the property name is currently supplied by something like:

    add_detail_editor (layout,
		       TypeSet.general,
		       detail_set,
		       email != null ? new EmailFieldDetails (email.value, email.parameters) : new EmailFieldDetails(""),
		       "email-addresses",
		       _("Enter email address"));

Which constructs the widgetry (combo+entry+remove button) to edit the email address. Then all changes are eventually propagated down to 
ContactPane.set_persona_property(). It might be possible to make this use a delegate to set the result instead of passing in the property name, but I think that there is gonna be issues with getting rid of the GValue. I mean, what would the type of the delegate be?
Comment 9 Philip Withnall 2011-08-30 21:27:38 UTC
(In reply to comment #8)
> At the toplevel the property name is currently supplied by something like:
> 
>     add_detail_editor (layout,
>                TypeSet.general,
>                detail_set,
>                email != null ? new EmailFieldDetails (email.value,
> email.parameters) : new EmailFieldDetails(""),
>                "email-addresses",
>                _("Enter email address"));
> 
> Which constructs the widgetry (combo+entry+remove button) to edit the email
> address. Then all changes are eventually propagated down to 
> ContactPane.set_persona_property(). It might be possible to make this use a
> delegate to set the result instead of passing in the property name, but I think
> that there is gonna be issues with getting rid of the GValue. I mean, what
> would the type of the delegate be?

I think it should be possible by making the delegate generic. Even if that's not possible, though, and we have to continue to use GValues I think delegates should work.
Comment 10 Philip Withnall 2011-08-31 22:06:50 UTC
Created attachment 195353 [details] [review]
Add asynchronous property setters

https://www.gitorious.org/folks/folks/commits/657510-property-setters-rebase1

Here's a full and complete patch which makes the additions to every interface and all the relevant changes to the Persona subclasses.

It doesn't modify any of the test suites or add any new ones, but doesn't break any of the existing tests (which are exercising the same code). I think it would be more useful for me to spend time porting gnome-contacts to use these new functions rather than immediately porting all our tests. gnome-contacts will serve as a good test case, and more formal tests can be written later once I've beaten a hasty retreat^W^W^W^W^W^W.
Comment 11 Raul Gutierrez Segales 2011-09-01 11:06:16 UTC
(In reply to comment #10)
> Created an attachment (id=195353) [details] [review]
> Add asynchronous property setters
> 
> https://www.gitorious.org/folks/folks/commits/657510-property-setters-rebase1
> 
> Here's a full and complete patch which makes the additions to every interface
> and all the relevant changes to the Persona subclasses.
> 
> It doesn't modify any of the test suites or add any new ones, but doesn't break
> any of the existing tests (which are exercising the same code). I think it
> would be more useful for me to spend time porting gnome-contacts to use these
> new functions rather than immediately porting all our tests.

I totally agree - we can either extend/update the current properties test later on or add new ones.
Comment 12 Raul Gutierrez Segales 2011-09-01 13:25:48 UTC
Comment on attachment 195353 [details] [review]
Add asynchronous property setters

Looks good to me. Some comments below:

>+
>+          /* Commit the modification. */
>           yield this._addressbook.modify_contact (contact, null);
>+
>+          timeout_id = Timeout.add_seconds (this._property_change_timeout, () =>
>+            {
>+              /* Failure! Return to _commit_modified_property() without setting
>+               * received_notification. */
>+              received_notification = false;
>+
>+              if (has_yielded == true)
>+                {
>+                  this._commit_modified_property.callback ();
>+                }
>+
>+              return false;
>+            }, Priority.LOW);

I'd set the timeout before calling modify_contact () (just in case this one goes crazy). 

>+
>+          /* Remove the callbacks. */
>+          persona.disconnect (signal_id);
>+          GLib.Source.remove (timeout_id);
>+

I'd move these disconnects to final {} , if an exception is thrown from modify_contact () we'd miss out cleaning this up.
Comment 13 Philip Withnall 2011-09-01 17:33:58 UTC
(In reply to comment #12)
> I'd set the timeout before calling modify_contact () (just in case this one
> goes crazy). 

I considered that, but I don't think it's correct. Barring bugs in eds (which we shouldn't be attempting to fix in folks), modify_contact() should always return at some point, so we don't need a timeout for it. We only need timeouts for things which could potentially never return/happen, such as signal emissions.

> >+
> >+          /* Remove the callbacks. */
> >+          persona.disconnect (signal_id);
> >+          GLib.Source.remove (timeout_id);
> >+
> 
> I'd move these disconnects to final {} , if an exception is thrown from
> modify_contact () we'd miss out cleaning this up.

Good catch. I've pushed a fixup commit for this.
Comment 14 Travis Reitter 2011-09-01 23:44:32 UTC
Review of attachment 195353 [details] [review]:

This generally looks good to me (except for the timeout in Edsf.PersonaStore._commit_modified_property(), but I guess we can't avoid that).

However, 24 (sometimes 25) out of the 25 EDS tests fail for me. Apparently they work for you and Raul, so I'm guessing it's just something weird in my setup. And this happens with master anyhow, so it seems unrelated to this branch.

Also, the libsocialweb aggregation test fails. Please make sure this passes before merging. It's possible it's only on my side (see above). If so, disregard this.


+          _("Alias is not writeable on this contact."));

In this and all the other default implementations, it says "on this contact", when it should say "on this persona"


Other than those bits, I approve this for merging.
Comment 15 Philip Withnall 2011-09-02 18:35:36 UTC
Comment on attachment 195353 [details] [review]
Add asynchronous property setters

Committed with one additional change (the most recent commit) to fix the libsocialweb aggregation test. After discussion on IRC, the translatable strings have been left using “contact” because it's a neutral term used in current UIs (i.e. Empathy). Using “persona” or “individual” doesn't work because the interfaces are implemented by both types of object, so the strings would end up being wrong for one of them.

commit 17dcda00c5a993989bde31d0beca5338d5937c0f
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Fri Sep 2 19:27:33 2011 +0100

    key-file: Yield when setting properties on new personas
    
    This fixes the libsocialweb aggregation test.
    
    Helps: bgo#657510

 backends/key-file/kf-persona-store.vala |   22 ++++++++++++++++++----
 1 files changed, 18 insertions(+), 4 deletions(-)

commit bc0141fb8317caa614e930cfecbb4cf437797bc2
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Wed Aug 31 22:21:15 2011 +0100

    eds: Ensure that property changes are signalled before .change_*() returns
    
    We can't rely on E.BookClientView.objects_modified being emitted before
    E.BookClient.modify_contact() returns. In order to guarantee that the
    relevant properties will be notified before Edsf.Persona.change_*() returns,
    we therefore move all calls to modify_contact() into a new
    Edsf.PersonaStore._commit_modified_property() method, and block returning
    from that on receipt of a property change notification from e-d-s.
    
    However, we also add a timeout to _commit_modified_property() (defaulting to
    30 seconds), so that if we don't receive a property change notification in
    that time period, we error out from the .change_*() method.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala |  259 +++++++++++++-----------------
 1 files changed, 110 insertions(+), 149 deletions(-)

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(-)

commit 6dd4365dbbc2fd317f1fb6287d9a1b1d6d765e77
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Tue Aug 30 20:34:32 2011 +0100

    core: Add WebServiceDetails.change_web_service_addresses()
    
    This allows the web service addresses of an implementing class to be changed
    asynchronously with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala   |    4 +-
 backends/eds/lib/edsf-persona.vala         |   19 +++++--
 backends/key-file/kf-persona.vala          |   83 +++++++++++++++------------
 backends/libsocialweb/lib/swf-persona.vala |    6 +-
 backends/tracker/lib/trf-persona.vala      |   19 +++++-
 folks/individual.vala                      |    4 +-
 folks/web-service-details.vala             |   23 ++++++++
 po/POTFILES.in                             |    1 +
 po/POTFILES.skip                           |    1 +
 9 files changed, 110 insertions(+), 50 deletions(-)

commit a8f586f2cba4e46c0aba4190c8d0bb3c7575070e
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Tue Aug 30 20:20:23 2011 +0100

    core: Add UrlDetails.change_urls()
    
    This allows the URLs of an implementing class to be changed asynchronously
    with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala   |    6 +++---
 backends/eds/lib/edsf-persona.vala         |   15 +++++++++++----
 backends/libsocialweb/lib/swf-persona.vala |   19 ++++++++-----------
 backends/tracker/lib/trf-persona.vala      |   18 ++++++++++++++----
 folks/individual.vala                      |    8 ++------
 folks/url-details.vala                     |   22 ++++++++++++++++++++++
 po/POTFILES.in                             |    1 +
 po/POTFILES.skip                           |    1 +
 8 files changed, 62 insertions(+), 28 deletions(-)

commit 418a2f2338d131769f80b3d264b3b015c785114e
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Tue Aug 30 20:11:53 2011 +0100

    core: Add RoleDetails.change_roles()
    
    This allows the roles of an implementing class to be changed asynchronously
    with proper error notification.
    
    Helps: bgo#657510

 backends/tracker/lib/trf-persona.vala |   19 +++++++++++++++----
 folks/individual.vala                 |    9 ++-------
 folks/role-details.vala               |   22 ++++++++++++++++++++++
 3 files changed, 39 insertions(+), 11 deletions(-)

commit aa87b4cb56a9466d69c1ed87439cc860e6181379
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Tue Aug 30 20:03:00 2011 +0100

    core: Add PostalAddressDetails.change_postal_addresses()
    
    This allows the postal addresses of an implementing class to be changed
    asynchronously with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala |    7 +++----
 backends/eds/lib/edsf-persona.vala       |   17 +++++++++++++----
 backends/tracker/lib/trf-persona.vala    |   20 ++++++++++++++++----
 folks/individual.vala                    |    8 ++------
 folks/postal-address-details.vala        |   22 ++++++++++++++++++++++
 5 files changed, 56 insertions(+), 18 deletions(-)

commit 22866a6481fdd49d4aa8731da302d6cf6c8e4d17
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Tue Aug 30 19:55:32 2011 +0100

    core: Add PhoneDetails.change_phone_numbers()
    
    This allows the phone numbers of an implementing class to be changed
    asynchronously with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala |    6 +++---
 backends/eds/lib/edsf-persona.vala       |   16 ++++++++++++----
 backends/tracker/lib/trf-persona.vala    |   19 +++++++++++++++----
 folks/individual.vala                    |    8 ++------
 folks/phone-details.vala                 |   22 ++++++++++++++++++++++
 po/POTFILES.in                           |    1 +
 po/POTFILES.skip                         |    1 +
 7 files changed, 56 insertions(+), 17 deletions(-)

commit e0a2bd2e7abddf6e47d78809ba45caab62099de9
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Tue Aug 30 19:47:26 2011 +0100

    core: Add NoteDetails.change_notes()
    
    This allows the notes of an implementing class to be changed asynchronously
    with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala |    6 +++---
 backends/eds/lib/edsf-persona.vala       |   16 ++++++++++++----
 backends/tracker/lib/trf-persona.vala    |   17 +++++++++++++----
 folks/individual.vala                    |    9 ++-------
 folks/note-details.vala                  |   22 ++++++++++++++++++++++
 po/POTFILES.in                           |    1 +
 po/POTFILES.skip                         |    1 +
 7 files changed, 54 insertions(+), 18 deletions(-)

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(-)

commit e80b364c31817f4b2d3e3876ec5112d64ef90c80
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sun Aug 28 21:41:02 2011 +0100

    core: Make NameDetails.structured_name nullable
    
    It effectively was before; now it's official.

 backends/eds/lib/edsf-persona.vala          |    4 +-
 backends/libsocialweb/lib/swf-persona.vala  |    2 +-
 backends/tracker/lib/trf-persona-store.vala |   18 +++++---
 backends/tracker/lib/trf-persona.vala       |   61 +++++++++++++++++++++++----
 folks/individual.vala                       |    2 +-
 folks/name-details.vala                     |    2 +-
 6 files changed, 70 insertions(+), 19 deletions(-)

commit 825694c474ae97ef05434a812c5830364270c08f
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sun Aug 28 21:26:24 2011 +0100

    core: Add LocalIdDetails.change_local_ids()
    
    This allows the local IDs of an implementing class to be changed asynchronously
    with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala |    4 ++--
 backends/eds/lib/edsf-persona.vala       |   16 ++++++++++++----
 backends/tracker/lib/trf-persona.vala    |   22 ++++++++++++++++------
 folks/individual.vala                    |    9 ++-------
 folks/local-id-details.vala              |   22 ++++++++++++++++++++++
 po/POTFILES.in                           |    1 +
 po/POTFILES.skip                         |    1 +
 7 files changed, 56 insertions(+), 19 deletions(-)

commit 6130e1038959b358d00f62a57c36ab4093374136
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sun Aug 28 21:19:55 2011 +0100

    eds: Fix a typo in a doc comment

 backends/eds/lib/edsf-persona-store.vala |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

commit 55b9950994703e9f91dc6e03e961ac3c99bded28
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sun Aug 28 21:12:45 2011 +0100

    core: Add GenderDetails.change_gender()
    
    This allows the gender of an implementing class to be changed asynchronously
    with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala   |    4 ++--
 backends/eds/lib/edsf-persona.vala         |   15 +++++++++++----
 backends/libsocialweb/lib/swf-persona.vala |   16 +++++++++++++---
 backends/tracker/lib/trf-persona.vala      |   16 ++++++++++++----
 folks/gender-details.vala                  |   21 +++++++++++++++++++++
 folks/individual.vala                      |   14 +++++++-------
 po/POTFILES.in                             |    1 +
 po/POTFILES.skip                           |    1 +
 8 files changed, 68 insertions(+), 20 deletions(-)

commit 073dc310a0294bf5c26f2e31ebf4073a543db0f6
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sun Aug 28 20:19:09 2011 +0100

    core: Add FavouriteDetails.change_is_favourite()
    
    This allows the favouriteness of an implementing class to be changed
    asynchronously with proper error notification.
    
    Helps: bgo#657510

 backends/telepathy/lib/tpf-persona-store.vala |    8 ++--
 backends/telepathy/lib/tpf-persona.vala       |   26 ++++++++--
 backends/tracker/lib/trf-persona.vala         |   41 ++++++++++------
 folks/favourite-details.vala                  |   21 ++++++++
 folks/individual.vala                         |   65 ++++++++++++++++++++-----
 po/POTFILES.in                                |    1 +
 po/POTFILES.skip                              |    1 +
 7 files changed, 125 insertions(+), 38 deletions(-)

commit b5d1fdefc24dc5d7c5b94f1332cdb4e7dce80ade
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sun Aug 28 19:58:21 2011 +0100

    core: Add EmailDetails.change_email_addresses()
    
    This allows the e-mail addresses of an implementing class to be changed
    asynchronously with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala |    7 +++----
 backends/eds/lib/edsf-persona.vala       |   17 +++++++++++++----
 backends/tracker/lib/trf-persona.vala    |   19 +++++++++++++++----
 folks/email-details.vala                 |   22 ++++++++++++++++++++++
 folks/individual.vala                    |    8 ++------
 po/POTFILES.in                           |    1 +
 po/POTFILES.skip                         |    1 +
 7 files changed, 57 insertions(+), 18 deletions(-)

commit a5517e657d92d95e295714bb2be97a93261a9d1a
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sun Aug 28 19:46:58 2011 +0100

    core: Add BirthdayDetails.change_birthday() and .change_calendar_event_id()
    
    These allows the birthday (and its calendar event) of an implementing class
    to be changed asynchronously with proper error notification.
    
    Helps: bgo#657510

 backends/tracker/lib/trf-persona.vala |   19 +++++++++---
 folks/birthday-details.vala           |   42 ++++++++++++++++++++++++++++
 folks/individual.vala                 |   48 ++++++++++++++++++++++++++------
 po/POTFILES.in                        |    1 +
 po/POTFILES.skip                      |    1 +
 5 files changed, 97 insertions(+), 14 deletions(-)

commit 847acb0b13f12afc68745b28bf9fbb5f323cc9c9
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sun Aug 28 19:39:22 2011 +0100

    core: Make BirthdayDetails.birthday nullable
    
    It effectively was before; now it's official.

 backends/tracker/lib/trf-persona.vala |    4 ++--
 folks/birthday-details.vala           |    7 ++++---
 folks/individual.vala                 |    2 +-
 3 files changed, 7 insertions(+), 6 deletions(-)

commit a1db7b08184ee325bd5e8b22d6c361b784a3a2f2
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sun Aug 28 19:33:18 2011 +0100

    core: Add AvatarDetails.change_avatar()
    
    This allows the avatar of an implementing class to be changed asynchronously
    with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala   |   29 +++++++++++++++++++++------
 backends/eds/lib/edsf-persona.vala         |   19 ++++++++++++-----
 backends/libsocialweb/lib/swf-persona.vala |   19 ++++++++++++++---
 backends/telepathy/lib/tpf-persona.vala    |   18 +++++++++++++---
 backends/tracker/lib/trf-persona.vala      |   16 +++++++++++---
 folks/avatar-details.vala                  |   22 +++++++++++++++++++++
 folks/individual.vala                      |   16 ++++++++++++--
 po/POTFILES.in                             |    1 +
 po/POTFILES.skip                           |    1 +
 9 files changed, 113 insertions(+), 28 deletions(-)

commit e390bdd7b7a2b57260f94e0c0559d3a6f340d14c
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sat Aug 27 17:11:00 2011 +0100

    core: Add ImDetails.change_im_addresses()
    
    This allows the IM addresses of an implementing class to be changed
    asynchronously with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala   |    6 +-
 backends/eds/lib/edsf-persona.vala         |   16 +++-
 backends/key-file/kf-persona.vala          |  111 +++++++++++++++-------------
 backends/libsocialweb/lib/swf-persona.vala |    3 +-
 backends/telepathy/lib/tpf-persona.vala    |    3 +-
 backends/tracker/lib/trf-persona.vala      |   19 ++++-
 folks/im-details.vala                      |   21 +++++
 folks/individual.vala                      |    3 +-
 8 files changed, 117 insertions(+), 65 deletions(-)

commit ef3d3b73d80f7510f8817383a061f544b3ac0367
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sat Aug 27 15:58:30 2011 +0100

    core: Add AliasDetails.change_alias()
    
    This allows the alias of an implementing class to be changed asynchronously
    with proper error notification.
    
    Helps: bgo#657510

 backends/eds/lib/edsf-persona-store.vala |   72 ++++++++++++++++++++++++++++++
 backends/key-file/kf-persona.vala        |   26 +++++++---
 backends/telepathy/lib/tpf-persona.vala  |   25 ++++++++---
 folks/alias-details.vala                 |   21 +++++++++
 folks/individual.vala                    |   68 ++++++++++++++++++----------
 po/POTFILES.in                           |    1 +
 po/POTFILES.skip                         |    1 +
 7 files changed, 176 insertions(+), 38 deletions(-)

commit be2f014028b93c286886f3367b84ebf4a562ace8
Author: Philip Withnall <philip@tecnocode.co.uk>
Date:   Sat Aug 27 16:25:37 2011 +0100

    core: Add Folks.PropertyError
    
    Helps: bgo#657510

 NEWS               |    1 +
 folks/persona.vala |   31 +++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 0 deletions(-)