Presence
{
private HashTable<string, bool> _groups;
- private GLib.List<Persona> _personas;
- private HashTable<PersonaStore, HashSet<Persona>> stores;
+ private GLib.List<Persona> _persona_list;
+ private HashSet<Persona> _persona_set;
+ private HashSet<PersonaStore> stores;
private bool _is_favourite;
private string _alias;
return;
this._alias = value;
- this._personas.foreach ((p) =>
+ this._persona_list.foreach ((p) =>
{
if (p is Alias && ((Persona) p).store.is_writeable == true)
((Alias) p).alias = value;
return;
this._is_favourite = value;
- this._personas.foreach ((p) =>
+ this._persona_list.foreach ((p) =>
{
if (p is Favourite && ((Persona) p).store.is_writeable == true)
((Favourite) p).is_favourite = value;
set
{
- this._personas.foreach ((p) =>
+ this._persona_list.foreach ((p) =>
{
if (p is Groups && ((Persona) p).store.is_writeable == true)
((Groups) p).groups = value;
*/
public GLib.List<Persona> personas
{
- get { return this._personas; }
+ get { return this._persona_list; }
set { this._set_personas (value, null); }
}
*/
public async void change_group (string group, bool is_member)
{
- this._personas.foreach ((p) =>
+ this._persona_list.foreach ((p) =>
{
if (p is Groups)
((Groups) p).change_group.begin (group, is_member);
*/
public Individual (GLib.List<Persona>? personas)
{
- Object (personas: personas);
-
- this.stores = new HashTable<PersonaStore, HashSet<Persona>> (direct_hash,
- direct_equal);
- this.stores_update ();
+ this._persona_set = new HashSet<Persona> (null, null);
+ this.stores = new HashSet<PersonaStore> (null, null);
+ this.personas = personas;
}
- private void stores_update ()
+ private void store_removed_cb (PersonaStore store)
{
- this._personas.foreach ((p) =>
+ Iterator<Persona> iter = this._persona_set.iterator ();
+ while (iter.next ())
{
- unowned Persona persona = (Persona) p;
- var store_is_new = false;
- var persona_set = this.stores.lookup (persona.store);
- if (persona_set == null)
- {
- persona_set = new HashSet<Persona> (direct_hash, direct_equal);
- store_is_new = true;
- }
-
- persona_set.add (persona);
+ Persona persona = iter.get ();
- if (store_is_new)
- {
- this.stores.insert (persona.store, persona_set);
-
- persona.store.removed.connect (this.store_removed_cb);
- persona.store.personas_changed.connect (
- this.store_personas_changed_cb);
- }
- });
- }
+ this._persona_list.remove (persona);
+ /* FIXME: bgo#624249 means GLib.List leaks item references.
+ * We probably eventually want to transition away from GLib.List
+ * and use Gee.LinkedList, but that would mean exposing libgee
+ * in the public API. */
+ g_object_unref (persona);
- private void store_removed_cb (PersonaStore store)
- {
- var persona_set = this.stores.lookup (store);
- if (persona_set != null)
- {
- foreach (var persona in persona_set)
- {
- this._personas.remove (persona);
- /* FIXME: bgo#624249 means GLib.List leaks item references.
- * We probably eventually want to transition away from GLib.List
- * and use Gee.LinkedList, but that would mean exposing libgee
- * in the public API. */
- g_object_unref (persona);
- }
+ iter.remove ();
}
+
if (store != null)
this.stores.remove (store);
- if (this._personas.length () < 1 || this.stores.size () < 1)
+ if (this._persona_set.size < 1)
{
this.removed (null);
return;
Persona? actor,
Groups.ChangeReason reason)
{
- var persona_set = this.stores.lookup (store);
removed.foreach ((data) =>
{
unowned Persona p = (Persona) data;
- if (persona_set.remove (p))
+ if (this._persona_set.remove (p))
{
- this._personas.remove (p);
+ this._persona_list.remove (p);
/* FIXME: bgo#624249 means GLib.List leaks item references */
g_object_unref (p);
}
});
- if (this._personas.length () < 1)
+ if (this._persona_set.size < 1)
{
this.removed (null);
return;
* "groups-changed" on the store (with the set of personas), to allow the
* back-end to optimize it (like Telepathy will for MembersChanged for the
* groups channel list) */
- this._personas.foreach ((p) =>
+ this._persona_list.foreach ((p) =>
{
if (p is Groups)
{
var presence_type = Folks.PresenceType.UNSET;
/* Choose the most available presence from our personas */
- this._personas.foreach ((p) =>
+ this._persona_list.foreach ((p) =>
{
if (p is Presence)
{
{
bool favourite = false;
- this._personas.foreach ((p) =>
+ this._persona_list.foreach ((p) =>
{
if (favourite == false && p is Favourite)
{
string alias = null;
bool alias_is_display_id = false;
- foreach (Persona p in this._personas)
+ foreach (Persona p in this._persona_list)
{
if (p is Alias)
{
{
/* We have to pick a UID, since none of the personas have an alias
* available. Pick the UID from the first persona in the list. */
- alias = this._personas.data.uid;
+ alias = this._persona_list.data.uid;
debug ("No aliases available for individual; using UID instead: %s",
alias);
}
{
File avatar = null;
- this._personas.foreach ((p) =>
+ this._persona_list.foreach ((p) =>
{
if (avatar == null && p is Avatar)
{
Individual? replacement_individual)
{
/* Disconnect from all our previous personas */
- this._personas.foreach ((p) =>
+ this._persona_list.foreach ((p) =>
{
unowned Persona persona = (Persona) p;
((Groups) p).group_changed.disconnect (
this.persona_group_changed_cb);
}
- });
-
- this._personas = new GLib.List<Persona> ();
- personas.foreach ((l) =>
- {
- this._personas.prepend ((Persona) l);
- });
- this._personas.reverse ();
- /* If all the personas have been removed, remove the individual */
- if (this._personas.length () < 1)
- {
- this.removed (replacement_individual);
- return;
- }
+ /* Disconnect from this persona's store */
+ if (this.stores.contains (persona.store))
+ {
+ persona.store.removed.disconnect (this.store_removed_cb);
+ persona.store.personas_changed.disconnect (
+ this.store_personas_changed_cb);
+ this.stores.remove (persona.store);
+ }
- /* TODO: base this upon our ID in permanent storage, once we have that
- */
- if (this.id == null && this._personas.data != null)
- this.id = this._personas.data.uid;
+ this._persona_set.remove (persona);
+ });
- /* Connect to all the new personas */
- this._personas.foreach ((p) =>
+ /* Connect to all the new Personas */
+ this._persona_list = new GLib.List<Persona> ();
+ personas.foreach ((p) =>
{
unowned Persona persona = (Persona) p;
+ this._persona_list.prepend (persona);
+
persona.notify["alias"].connect (this.notify_alias_cb);
persona.notify["avatar"].connect (this.notify_avatar_cb);
persona.notify["presence-message"].connect (this.notify_presence_cb);
((Groups) p).group_changed.connect (
this.persona_group_changed_cb);
}
+
+ /* Connect to this persona's store */
+ if (!this.stores.contains (persona.store))
+ {
+ persona.store.removed.connect (this.store_removed_cb);
+ persona.store.personas_changed.connect (
+ this.store_personas_changed_cb);
+ this.stores.add (persona.store);
+ }
+
+ this._persona_set.add (persona);
});
+ this._persona_list.reverse ();
+
+ /* If all the personas have been removed, remove the individual */
+ if (this._persona_set.size < 1)
+ {
+ this.removed (replacement_individual);
+ return;
+ }
+
+ /* TODO: base this upon our ID in permanent storage, once we have that
+ */
+ if (this.id == null && this._persona_list.data != null)
+ this.id = this._persona_list.data.uid;
+
/* Update our aggregated fields and notify the changes */
this.update_fields ();
}