[folks] Rework unlinking in the IndividualAggregator
- From: Travis Reitter <treitter src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks] Rework unlinking in the IndividualAggregator
- Date: Wed, 11 Aug 2010 00:00:30 +0000 (UTC)
commit 2d94025a8586550316061d8c9cec4726bc42cc91
Author: Philip Withnall <philip withnall collabora co uk>
Date: Tue Aug 10 17:03:17 2010 +0100
Rework unlinking in the IndividualAggregator
Ensure it causes linked Individuals to be split apart and their Personas
which haven't been removed to be relinked.
folks/individual-aggregator.vala | 130 +++++++++++++++++++++++++++++++------
1 files changed, 109 insertions(+), 21 deletions(-)
---
diff --git a/folks/individual-aggregator.vala b/folks/individual-aggregator.vala
index bf1fd87..f431874 100644
--- a/folks/individual-aggregator.vala
+++ b/folks/individual-aggregator.vala
@@ -208,14 +208,9 @@ public class Folks.IndividualAggregator : Object
return type_id + ":" + id;
}
- private void personas_changed_cb (PersonaStore store,
- GLib.List<Persona>? added,
- GLib.List<Persona>? removed,
- string? message,
- Persona? actor,
- Groups.ChangeReason reason)
+ private GLib.List<Individual> add_personas (GLib.List<Persona> added)
{
- GLib.List<Individual> new_individuals = new GLib.List<Individual> ();
+ GLib.List<Individual> added_individuals = new GLib.List<Individual> ();
added.foreach ((p) =>
{
@@ -350,22 +345,53 @@ public class Folks.IndividualAggregator : Object
/* Add the new Individual to the aggregator */
final_individual.removed.connect (this.individual_removed_cb);
- new_individuals.prepend (final_individual);
+ added_individuals.prepend (final_individual);
this.individuals.insert (final_individual.id, final_individual);
});
+ /* FIXME: AAAARGH VALA GO AWAY */
+ foreach (Individual i in added_individuals)
+ i.ref ();
+ return added_individuals.copy ();
+ }
+
+ private void personas_changed_cb (PersonaStore store,
+ GLib.List<Persona>? added,
+ GLib.List<Persona>? removed,
+ string? message,
+ Persona? actor,
+ Groups.ChangeReason reason)
+ {
+ GLib.List<Individual> added_individuals = null,
+ removed_individuals = null;
+ GLib.List<Persona> relinked_personas = null;
+ HashSet<Persona> removed_personas = new HashSet<Persona> (direct_hash,
+ direct_equal);
+
+ if (added != null)
+ added_individuals = this.add_personas (added);
+
removed.foreach ((p) =>
{
unowned Persona persona = (Persona) p;
PersonaStoreTrust trust_level = persona.store.trust_level;
+ /* Build a hash table of the removed Personas so that we can quickly
+ * eliminate them from the list of Personas to relink, below. */
+ removed_personas.add (persona);
+
if (trust_level != PersonaStoreTrust.NONE)
- this.link_map.remove (persona.iid);
+ {
+ Individual ind = this.link_map.lookup (persona.iid);
+ removed_individuals.prepend (ind);
+ this.link_map.remove (persona.iid);
+ }
if (trust_level == PersonaStoreTrust.FULL)
{
- /* Remove maps from the Persona's linkable properties to the
- * Individual. */
+ /* Remove maps from the Persona's linkable properties to
+ * Individuals. Add the Individuals to a list of Individuals to be
+ * removed. */
foreach (string prop_name in persona.linkable_properties)
{
unowned ObjectClass pclass = persona.get_class ();
@@ -378,17 +404,53 @@ public class Folks.IndividualAggregator : Object
persona.linkable_property_to_links (prop_name, (l) =>
{
- this.link_map.remove ((string) l);
- });
+ this.link_map.remove ((string) l);
+ });
}
}
});
- /* Signal the addition of new individuals to the aggregator */
- if (new_individuals != null)
+ /* Remove the Individuals which were pointed to by the linkable properties
+ * of the removed Personas. We can then re-link the other Personas in
+ * those Individuals, since their links may have changed.
+ * Note that we remove the Individual from this.individuals, meaning that
+ * individual_removed_cb() ignores this Individual. This allows us to
+ * group together the IndividualAggregator.individuals_changed signals
+ * for all the removed Individuals. */
+ debug ("Removing Individuals due to removed links:");
+ foreach (Individual individual in removed_individuals)
+ {
+ /* Ensure we don't remove the same Individual twice */
+ if (this.individuals.lookup (individual.id) == null)
+ continue;
+
+ debug (" %s", individual.id);
+
+ /* Build a list of Personas which need relinking. Ensure we don't
+ * include any of the Personas which have just been removed. */
+ foreach (unowned Persona p in individual.personas)
+ {
+ if (removed_personas.contains (p) == false)
+ relinked_personas.prepend (p);
+ }
+
+ this.individuals.remove (individual.id);
+ individual.personas = null;
+ }
+
+ debug ("Relinking Personas:");
+ foreach (unowned Persona persona in relinked_personas)
+ debug (" %s", persona.uid);
+
+ /* FIXME: Vala is horrible with GLists */
+ added_individuals.concat (this.add_personas (relinked_personas));
+
+ /* Signal the addition of new individuals and removal of old ones to the
+ * aggregator */
+ if (added_individuals != null || removed_individuals != null)
{
- new_individuals.reverse ();
- this.individuals_changed (new_individuals, null, null, null, 0);
+ this.individuals_changed (added_individuals, removed_individuals,
+ null, null, 0);
}
}
@@ -413,9 +475,24 @@ public class Folks.IndividualAggregator : Object
private void individual_removed_cb (Individual i, Individual? replacement)
{
+ /* Only signal if the individual is still in this.individuals. This allows
+ * us to group removals together in, e.g., personas_changed_cb(). */
+ if (this.individuals.lookup (i.id) == null)
+ return;
+
var i_list = new GLib.List<Individual> ();
i_list.append (i);
+ if (replacement != null)
+ {
+ debug ("Individual '%s' removed (replaced by '%s')", i.alias,
+ replacement.alias);
+ }
+ else
+ {
+ debug ("Individual '%s' removed (not replaced)", i.alias);
+ }
+
this.individuals_changed (null, i_list, null, null, 0);
this.individuals.remove (i.id);
}
@@ -590,12 +667,23 @@ public class Folks.IndividualAggregator : Object
/* 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<unowned Persona> i;
- for (i = individual.personas; i != null; i = i.next)
+ debug ("Unlinking Individual '%s', deleting Personas:", individual.alias);
+
+ /* We have to take a copy of the Persona list before removing the
+ * Personas, as personas_changed_cb() (which is called as a result of
+ * calling writeable_store.remove_persona()) messes around with Persona
+ * lists. */
+ GLib.List<Persona> personas = individual.personas.copy ();
+ foreach (Persona p in personas)
+ p.ref ();
+
+ foreach (unowned Persona persona in personas)
{
- unowned Persona persona = (Persona) i.data;
if (persona.store == this.writeable_store)
- yield this.writeable_store.remove_persona (persona);
+ {
+ debug (" %s", persona.uid);
+ yield this.writeable_store.remove_persona (persona);
+ }
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]