2 * Copyright (C) 2010 Collabora Ltd.
4 * This library is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 2.1 of the License, or
7 * (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library. If not, see <http://www.gnu.org/licenses/>.
18 * Travis Reitter <travis.reitter@collabora.co.uk>
26 public class Tpf.Persona : Folks.Persona, Alias, Avatar, Folks.Capabilities,
27 Groups, Presence, Favourite
29 private HashTable<string, bool> _groups;
30 private bool _is_favourite;
33 public override string alias { get; set; }
35 /* interface Avatar */
36 public override File avatar { get; set; }
38 /* interface Capabilities */
39 public override CapabilitiesFlags capabilities { get; private set; }
41 /* interface Presence */
42 public override Folks.PresenceType presence_type { get; private set; }
43 public override string presence_message { get; private set; }
45 /* interface Favourite */
46 public override bool is_favourite
48 get { return this._is_favourite; }
52 if (this._is_favourite == value)
55 ((Tpf.PersonaStore) this.store).change_is_favourite (this, value);
56 this._is_favourite = value;
60 /* interface Groups */
61 public HashTable<string, bool> groups
63 get { return this._groups; }
67 value.foreach ((k, v) =>
69 var group = (string) k;
70 if (this._groups.lookup (group) == false)
71 this._change_group (group, true);
74 this._groups.foreach ((k, v) =>
76 var group = (string) k;
77 if (value.lookup (group) == false)
78 this._change_group (group, true);
83 public void change_group (string group, bool is_member)
85 if (_change_group (group, is_member))
87 ((Tpf.PersonaStore) this.store).change_group_membership (this, group,
90 this.group_changed (group, is_member);
94 private bool _change_group (string group, bool is_member)
100 if (this._groups.lookup (group) != true)
102 this._groups.insert (group, true);
107 changed = this._groups.remove (group);
112 public Contact contact { get; construct; }
114 public Persona (Contact contact, PersonaStore store) throws Tp.Error
116 /* FIXME: There is the possibility of a crash in the error condition below
117 * due to bgo#604299, where the C self variable isn't initialised until we
118 * chain up to the Object constructor, below. */
119 var uid = contact.get_identifier ();
120 if (uid == null || uid == "")
121 throw new Tp.Error.INVALID_ARGUMENT ("contact has an invalid UID");
123 var account = account_for_connection (contact.get_connection ());
124 var account_id = ((Proxy) account).object_path;
125 /* this isn't meant to convey any real information, so no need to escape
126 * existing delimiters */
127 var iid = "telepathy:" + account_id + ":" + uid;
129 var alias = contact.get_alias ();
130 if (alias == null || alias == "")
133 /* TODO: implement something like Empathy's tp_caps_to_capabilities() and
134 * fill in the capabilities as appropriate */
135 debug ("capabilities not implemented");
137 Object (alias: alias,
143 this._groups = new HashTable<string, bool> (str_hash, str_equal);
145 contact.notify["avatar-file"].connect ((s, p) =>
147 this.contact_notify_avatar ();
149 this.contact_notify_avatar ();
151 contact.notify["presence-message"].connect ((s, p) =>
153 this.contact_notify_presence_message ();
155 contact.notify["presence-type"].connect ((s, p) =>
157 this.contact_notify_presence_type ();
159 this.contact_notify_presence_message ();
160 this.contact_notify_presence_type ();
162 this.store.group_members_changed.connect ((s, group, added, removed) =>
164 if (added.find (this) != null)
165 this._change_group (group, true);
167 if (removed.find (this) != null)
168 this._change_group (group, false);
171 this.store.group_removed.connect ((s, group, error) =>
174 warning ("group invalidated: %s", error.message);
176 this._change_group (group, false);
180 private static Account? account_for_connection (Connection conn)
182 var manager = AccountManager.dup ();
183 unowned GLib.List<Account> accounts = manager.get_valid_accounts ();
185 Account account_found = null;
186 accounts.foreach ((l) =>
188 var account = (Account) l;
189 if (account.get_connection () == conn)
191 account_found = account;
196 return account_found;
199 private void contact_notify_presence_message ()
201 this.presence_message = this.contact.get_presence_message ();
204 private void contact_notify_presence_type ()
206 this.presence_type = folks_presence_type_from_tp (
207 this.contact.get_presence_type ());
210 private static PresenceType folks_presence_type_from_tp (
211 Tp.ConnectionPresenceType type)
215 case Tp.ConnectionPresenceType.AVAILABLE:
216 return PresenceType.AVAILABLE;
217 case Tp.ConnectionPresenceType.AWAY:
218 return PresenceType.AWAY;
219 case Tp.ConnectionPresenceType.BUSY:
220 return PresenceType.BUSY;
221 case Tp.ConnectionPresenceType.ERROR:
222 return PresenceType.ERROR;
223 case Tp.ConnectionPresenceType.EXTENDED_AWAY:
224 return PresenceType.EXTENDED_AWAY;
225 case Tp.ConnectionPresenceType.HIDDEN:
226 return PresenceType.HIDDEN;
227 case Tp.ConnectionPresenceType.OFFLINE:
228 return PresenceType.OFFLINE;
229 case Tp.ConnectionPresenceType.UNKNOWN:
230 return PresenceType.UNKNOWN;
231 case Tp.ConnectionPresenceType.UNSET:
232 return PresenceType.UNSET;
234 return PresenceType.UNKNOWN;
238 private void contact_notify_avatar ()
240 var file = this.contact.get_avatar_file ();
241 if (this.avatar != file)