2 * Copyright (C) 2012 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 * Jeremy Whiting <jeremy.whiting@collabora.co.uk>
20 * Based on kf-persona-store.vala by:
21 * Travis Reitter <travis.reitter@collabora.co.uk>
22 * Philip Withnall <philip.withnall@collabora.co.uk>
28 using Folks.Backends.Ofono;
31 * A persona store which is associated with a single Ofono device. It will
32 * create a {@link Persona} for each contact on the SIM card phonebook.
36 public class Folks.Backends.Ofono.PersonaStore : Folks.PersonaStore
38 private HashMap<string, Persona> _personas;
39 private Map<string, Persona> _personas_ro;
40 private bool _is_prepared = false;
41 private bool _prepare_pending = false;
42 private bool _is_quiescent = false;
44 private static string[] _always_writeable_properties = {};
45 private ObjectPath? _path = null;
47 private org.ofono.Phonebook? _ofono_phonebook = null;
52 public override string type_id { get { return BACKEND_NAME; } }
57 public override MaybeBool can_add_personas
59 get { return MaybeBool.FALSE; }
65 public override MaybeBool can_alias_personas
67 get { return MaybeBool.FALSE; }
73 public override MaybeBool can_group_personas
75 get { return MaybeBool.FALSE; }
81 public override MaybeBool can_remove_personas
83 get { return MaybeBool.FALSE; }
89 public override bool is_prepared
91 get { return this._is_prepared; }
97 public override bool is_quiescent
99 get { return this._is_quiescent; }
105 public override string[] always_writeable_properties
107 get { return Ofono.PersonaStore._always_writeable_properties; }
113 public override Map<string, Persona> personas
115 get { return this._personas_ro; }
119 * Create a new PersonaStore.
121 * Create a new persona store to expose the {@link Persona}s provided by the
122 * modem with the given address.
124 * @param path the D-Bus object path of this modem
125 * @param alias the name this modem should display to users
129 public PersonaStore (ObjectPath path, string alias)
132 display_name: alias);
134 this.trust_level = PersonaStoreTrust.FULL;
135 this._personas = new HashMap<string, Persona> ();
136 this._personas_ro = this._personas.read_only_view;
140 private void _property_changed (string property, Variant value)
142 if (property == "Present" && value.get_boolean () == false)
144 this._remove_self ();
148 private void _remove_self ()
150 /* Marshal the personas from a Collection to a Set. */
151 var removed_personas = new HashSet<Persona> ();
152 var iter = this._personas.map_iterator ();
154 while (iter.next () == true)
156 removed_personas.add (iter.get_value ());
159 this._emit_personas_changed (null, removed_personas);
163 private string[] _split_all_vcards (string all_vcards)
165 /* Ofono vcards are in vcard 3.0 format and can include the following:
166 * FN, CATEGORIES, EMAIL and IMPP fields. */
167 string[] lines = all_vcards.split ("\n");
168 string[] vcards = {};
171 foreach (string line in lines)
176 if (line.strip () == "END:VCARD")
189 public override async void prepare () throws IOError, DBusError
191 Internal.profiling_start ("preparing Ofono.PersonaStore (ID: %s)",
194 if (this._is_prepared || this._prepare_pending)
201 this._prepare_pending = true;
202 this._ofono_phonebook = yield Bus.get_proxy (BusType.SYSTEM,
206 org.ofono.SimManager sim_manager = yield Bus.get_proxy (BusType.SYSTEM,
209 sim_manager.PropertyChanged.connect (this._property_changed);
211 string all_vcards = this._ofono_phonebook.Import ();
213 string[] vcards = this._split_all_vcards (all_vcards);
215 HashSet<Persona> added_personas = new HashSet<Persona> ();
217 foreach (string vcard in vcards)
219 Persona persona = new Persona (vcard, this);
220 this._personas.set (persona.iid, persona);
221 added_personas.add (persona);
224 if (this._personas.size > 0)
226 this._emit_personas_changed (added_personas, null);
229 catch (GLib.DBusError e)
231 warning ("DBus Error has occurred when fetching ofono phonebook, %s", e.message);
232 this._remove_self ();
234 catch (GLib.IOError e)
236 warning ("IO Error has occurred when fetching ofono phonebook, %s", e.message);
237 this._remove_self ();
241 this._is_prepared = true;
242 this.notify_property ("is-prepared");
244 /* We've finished loading all the personas we know about */
245 this._is_quiescent = true;
246 this.notify_property ("is-quiescent");
248 this._prepare_pending = false;
251 Internal.profiling_end ("preparing Ofono.PersonaStore (ID: %s)", this.id);
255 * Remove a {@link Persona} from the PersonaStore.
257 * See {@link Folks.PersonaStore.remove_persona}.
259 * @throws Folks.PersonaStoreError.READ_ONLY every time since the
260 * Ofono backend is read-only.
262 * @param persona the {@link Persona} to remove.
266 public override async void remove_persona (Folks.Persona persona)
267 throws Folks.PersonaStoreError
269 throw new PersonaStoreError.READ_ONLY (
270 "Personas cannot be removed from this store.");
274 * Add a new {@link Persona} to the PersonaStore.
276 * See {@link Folks.PersonaStore.add_persona_from_details}.
278 * @throws Folks.PersonaStoreError.READ_ONLY every time since the
279 * Ofono backend is read-only.
281 * @param details the details of the {@link Persona} to add.
285 public override async Folks.Persona? add_persona_from_details (
286 HashTable<string, Value?> details) throws Folks.PersonaStoreError
288 throw new PersonaStoreError.READ_ONLY (
289 "Personas cannot be added to this store.");