Commit 6166dda1 authored by Philip Withnall's avatar Philip Withnall
Browse files

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
parent 6dd4365d
......@@ -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
=========================================================
......
......@@ -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);
}
}
......
......@@ -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);
}
/**
......
......@@ -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); }
}
/**
......@@ -269,6 +251,30 @@ public class Tpf.Persona : Folks.Persona,
return changed;
}
/**
* {@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.
*
......
......@@ -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."));
}
}
......@@ -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 ();
}
/**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment