From b9bb6e2300a529516f51d67523ee4f84533f365d Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 9 Aug 2010 14:48:35 +0100 Subject: [PATCH] Add IndividualAggregator.link_personas() and .unlink_individual() API These methods allow persistent linking and unlinking of Personas, compared to the transient linking which editing Individual.personas provides. This allows for an interface to preview the properties of a newly linked Individual before committing the changes using IndividualAggregator.link_personas(). --- folks/individual-aggregator.vala | 82 ++++++++++++++++++++++++++++++++++++++++ folks/individual.vala | 6 +++ 2 files changed, 88 insertions(+) diff --git a/folks/individual-aggregator.vala b/folks/individual-aggregator.vala index 63145e9..3af1fc5 100644 --- a/folks/individual-aggregator.vala +++ b/folks/individual-aggregator.vala @@ -36,6 +36,12 @@ public errordomain Folks.IndividualAggregatorError * Adding a {@link Persona} to a {@link PersonaStore} failed. */ ADD_FAILED, + + /** + * An operation which required the use of a writeable store failed because no + * writeable store was available. + */ + NO_WRITEABLE_STORE, } /** @@ -505,4 +511,80 @@ public class Folks.IndividualAggregator : Object { yield persona.store.remove_persona (persona); } + + /* FIXME: This should be GLib.List, but Vala won't allow it */ + public async void link_personas (void *_personas) + throws GLib.Error + { + unowned GLib.List personas = (GLib.List) _personas; + + if (this.writeable_store == null) + { + throw new IndividualAggregatorError.NO_WRITEABLE_STORE ( + "Can't link personas with no writeable store."); + } + + /* Don't bother linking if it's just one Persona */ + if (personas.next == null) + return; + + /* Create a new persona in the writeable store which links together the + * given personas */ + /* FIXME: We hardcode this to use the key-file backend for now */ + assert (this.writeable_store.type_id == "key-file"); + + HashTable> protocols = + new HashTable> (str_hash, str_equal); + personas.foreach ((p) => + { + unowned Persona persona = (Persona) p; + + if (!(Persona is IMable)) + return; + + ((IMable) persona).im_addresses.foreach ((k, v) => + { + unowned string protocol = (string) k; + unowned GenericArray addresses = (GenericArray) v; + + GenericArray existing_addresses = + protocols.lookup (protocol); + if (existing_addresses == null) + { + existing_addresses = new GenericArray (); + protocols.insert (protocol, existing_addresses); + } + + addresses.foreach ((a) => + { + unowned string address = (string) a; + existing_addresses.add (address); + }); + }); + }); + + Value addresses_value = Value (typeof (HashTable)); + addresses_value.set_boxed (protocols); + + HashTable details = + new HashTable (str_hash, str_equal); + details.insert ("im-addresses", addresses_value); + + yield this.add_persona_from_details (null, this.writeable_store.type_id, + this.writeable_store.id, details); + } + + public async void unlink_individual (Individual individual) throws GLib.Error + { + /* Remove all the Personas from writeable PersonaStores + * We have to iterate manually since using foreach() requires a sync + * lambda function, meaning we can't yield on the remove_persona() call */ + unowned GLib.List i; + for (i = individual.personas; i != null; i = i.next) + { + unowned Persona persona = (Persona) i.data; + if (persona.store == this.writeable_store) + yield this.writeable_store.remove_persona (persona); + } + } } diff --git a/folks/individual.vala b/folks/individual.vala index 8f629d6..49bbcc9 100644 --- a/folks/individual.vala +++ b/folks/individual.vala @@ -150,6 +150,12 @@ public class Folks.Individual : Object, * * Changing the set of personas may cause updates to the aggregated properties * provided by the Individual, resulting in property notifications for them. + * + * Changing the set of personas will not cause permanent linking/unlinking of + * the added/removed personas to/from this Individual. To do that, call + * {@link IndividualAggregator.link_personas} or + * {@link IndividualAggregator.unlink_individual}, which will ensure the link + * changes are written to the appropriate backend. */ public GLib.List personas { -- 2.7.4