Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-contact-store"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <libvalent-core.h>
9 : :
10 : : #include "valent-contact-store.h"
11 : : #include "valent-eds.h"
12 : :
13 : :
14 : : /**
15 : : * ValentContactStore:
16 : : *
17 : : * An abstract base class for address books.
18 : : *
19 : : * #ValentContactStore is a base class to provide an interface to an address
20 : : * book. This usually means adding, removing and querying contacts.
21 : : *
22 : : * Since: 1.0
23 : : */
24 : :
25 : : typedef struct
26 : : {
27 : : ESource *source;
28 : : } ValentContactStorePrivate;
29 : :
30 [ + + + - ]: 532 : G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ValentContactStore, valent_contact_store, VALENT_TYPE_OBJECT)
31 : :
32 : : /**
33 : : * ValentContactStoreClass:
34 : : * @add_contacts: the virtual function pointer for valent_contact_store_add_contacts()
35 : : * @get_contact: the virtual function pointer for valent_contact_store_get_contact()
36 : : * @remove_contact: the virtual function pointer for valent_contact_store_remove_contact()
37 : : * @query: the virtual function pointer for valent_contact_store_query()
38 : : * @contact_added: the class closure for #ValentContactStore::contact-added
39 : : * @contact_removed: the class closure for #ValentContactStore::contact-removed
40 : : *
41 : : * The virtual function table for #ValentContactStore.
42 : : */
43 : :
44 : :
45 : : enum {
46 : : PROP_0,
47 : : PROP_NAME,
48 : : PROP_SOURCE,
49 : : PROP_UID,
50 : : N_PROPERTIES
51 : : };
52 : :
53 : : static GParamSpec *properties[N_PROPERTIES] = { NULL, };
54 : :
55 : : enum {
56 : : CONTACT_ADDED,
57 : : CONTACT_REMOVED,
58 : : N_SIGNALS
59 : : };
60 : :
61 : : static guint signals[N_SIGNALS] = { 0, };
62 : :
63 : :
64 : : /*
65 : : * Signal Emission Helpers
66 : : */
67 : : typedef struct
68 : : {
69 : : GRecMutex mutex;
70 : : GWeakRef store;
71 : : char *uid;
72 : : EContact *contact;
73 : : } SignalEmission;
74 : :
75 : : static gboolean
76 : 21 : valent_contact_store_contact_added_main (gpointer data)
77 : : {
78 : 21 : SignalEmission *emission = data;
79 : 42 : g_autoptr (ValentContactStore) store = NULL;
80 : :
81 [ + - ]: 21 : g_assert (VALENT_IS_MAIN_THREAD ());
82 : :
83 : 21 : g_rec_mutex_lock (&emission->mutex);
84 [ + - ]: 21 : if ((store = g_weak_ref_get (&emission->store)) != NULL)
85 : 21 : g_signal_emit (G_OBJECT (store),
86 : : signals [CONTACT_ADDED], 0,
87 : : emission->contact);
88 : :
89 : 21 : g_weak_ref_clear (&emission->store);
90 [ + - ]: 21 : g_clear_object (&emission->contact);
91 : 21 : g_rec_mutex_unlock (&emission->mutex);
92 : 21 : g_rec_mutex_clear (&emission->mutex);
93 : 21 : g_clear_pointer (&emission, g_free);
94 : :
95 [ + - ]: 21 : return G_SOURCE_REMOVE;
96 : : }
97 : :
98 : : static gboolean
99 : 1 : valent_contact_store_contact_removed_main (gpointer data)
100 : : {
101 : 1 : SignalEmission *emission = data;
102 : 2 : g_autoptr (ValentContactStore) store = NULL;
103 : :
104 [ + - ]: 1 : g_assert (VALENT_IS_MAIN_THREAD ());
105 : :
106 : 1 : g_rec_mutex_lock (&emission->mutex);
107 [ + - ]: 1 : if ((store = g_weak_ref_get (&emission->store)) != NULL)
108 : 1 : g_signal_emit (G_OBJECT (store),
109 : : signals [CONTACT_REMOVED], 0,
110 : : emission->uid);
111 : :
112 : 1 : g_weak_ref_clear (&emission->store);
113 [ + - ]: 1 : g_clear_pointer (&emission->uid, g_free);
114 : 1 : g_rec_mutex_unlock (&emission->mutex);
115 : 1 : g_rec_mutex_clear (&emission->mutex);
116 : 1 : g_clear_pointer (&emission, g_free);
117 : :
118 [ + - ]: 1 : return G_SOURCE_REMOVE;
119 : : }
120 : :
121 : : /* LCOV_EXCL_START */
122 : : static void
123 : : valent_contact_store_real_add_contacts (ValentContactStore *store,
124 : : GSList *contacts,
125 : : GCancellable *cancellable,
126 : : GAsyncReadyCallback callback,
127 : : gpointer user_data)
128 : : {
129 : : g_assert (VALENT_IS_CONTACT_STORE (store));
130 : : g_assert (contacts != NULL);
131 : : g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
132 : :
133 : : g_task_report_new_error (store, callback, user_data,
134 : : valent_contact_store_real_add_contacts,
135 : : G_IO_ERROR,
136 : : G_IO_ERROR_NOT_SUPPORTED,
137 : : "%s does not implement add_contacts()",
138 : : G_OBJECT_TYPE_NAME (store));
139 : : }
140 : :
141 : : static void
142 : : valent_contact_store_real_remove_contacts (ValentContactStore *store,
143 : : GSList *uids,
144 : : GCancellable *cancellable,
145 : : GAsyncReadyCallback callback,
146 : : gpointer user_data)
147 : : {
148 : : g_assert (VALENT_IS_CONTACT_STORE (store));
149 : : g_assert (uids != NULL);
150 : : g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
151 : :
152 : : g_task_report_new_error (store, callback, user_data,
153 : : valent_contact_store_real_remove_contacts,
154 : : G_IO_ERROR,
155 : : G_IO_ERROR_NOT_SUPPORTED,
156 : : "%s does not implement remove_contacts()",
157 : : G_OBJECT_TYPE_NAME (store));
158 : : }
159 : :
160 : : static void
161 : : valent_contact_store_real_get_contact (ValentContactStore *store,
162 : : const char *uid,
163 : : GCancellable *cancellable,
164 : : GAsyncReadyCallback callback,
165 : : gpointer user_data)
166 : : {
167 : : g_assert (VALENT_IS_CONTACT_STORE (store));
168 : : g_assert (uid != NULL);
169 : : g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
170 : :
171 : : g_task_report_new_error (store, callback, user_data,
172 : : valent_contact_store_real_get_contact,
173 : : G_IO_ERROR,
174 : : G_IO_ERROR_NOT_SUPPORTED,
175 : : "%s does not implement get_contact()",
176 : : G_OBJECT_TYPE_NAME (store));
177 : : }
178 : :
179 : : static void
180 : : valent_contact_store_real_query (ValentContactStore *store,
181 : : const char *query,
182 : : GCancellable *cancellable,
183 : : GAsyncReadyCallback callback,
184 : : gpointer user_data)
185 : : {
186 : : g_assert (VALENT_IS_CONTACT_STORE (store));
187 : : g_assert (query != NULL);
188 : : g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
189 : :
190 : : g_task_report_new_error (store, callback, user_data,
191 : : valent_contact_store_real_query,
192 : : G_IO_ERROR,
193 : : G_IO_ERROR_NOT_SUPPORTED,
194 : : "%s does not implement query()",
195 : : G_OBJECT_TYPE_NAME (store));
196 : : }
197 : : /* LCOV_EXCL_STOP */
198 : :
199 : : /*
200 : : * GObject
201 : : */
202 : : static void
203 : 8 : valent_contact_store_finalize (GObject *object)
204 : : {
205 : 8 : ValentContactStore *self = VALENT_CONTACT_STORE (object);
206 : 8 : ValentContactStorePrivate *priv = valent_contact_store_get_instance_private (self);
207 : :
208 [ + - ]: 8 : g_clear_object (&priv->source);
209 : :
210 : 8 : G_OBJECT_CLASS (valent_contact_store_parent_class)->finalize (object);
211 : 8 : }
212 : :
213 : : static void
214 : 4 : valent_contact_store_get_property (GObject *object,
215 : : guint prop_id,
216 : : GValue *value,
217 : : GParamSpec *pspec)
218 : : {
219 : 4 : ValentContactStore *self = VALENT_CONTACT_STORE (object);
220 : 4 : ValentContactStorePrivate *priv = valent_contact_store_get_instance_private (self);
221 : :
222 [ + + + - ]: 4 : switch (prop_id)
223 : : {
224 : 2 : case PROP_NAME:
225 : 2 : g_value_set_string (value, valent_contact_store_get_name (self));
226 : 2 : break;
227 : :
228 : 1 : case PROP_SOURCE:
229 : 1 : g_value_set_object (value, priv->source);
230 : 1 : break;
231 : :
232 : 1 : case PROP_UID:
233 : 1 : g_value_set_string (value, valent_contact_store_get_uid (self));
234 : 1 : break;
235 : :
236 : 0 : default:
237 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
238 : : }
239 : 4 : }
240 : :
241 : : static void
242 : 20 : valent_contact_store_set_property (GObject *object,
243 : : guint prop_id,
244 : : const GValue *value,
245 : : GParamSpec *pspec)
246 : : {
247 : 20 : ValentContactStore *self = VALENT_CONTACT_STORE (object);
248 : 20 : ValentContactStorePrivate *priv = valent_contact_store_get_instance_private (self);
249 : :
250 [ + + - ]: 20 : switch (prop_id)
251 : : {
252 : 3 : case PROP_NAME:
253 : 3 : valent_contact_store_set_name (self, g_value_get_string (value));
254 : 3 : break;
255 : :
256 : 17 : case PROP_SOURCE:
257 : 17 : priv->source = g_value_dup_object (value);
258 : 17 : break;
259 : :
260 : 0 : default:
261 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
262 : : }
263 : 20 : }
264 : :
265 : : static void
266 : 8 : valent_contact_store_class_init (ValentContactStoreClass *klass)
267 : : {
268 : 8 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
269 : :
270 : 8 : object_class->finalize = valent_contact_store_finalize;
271 : 8 : object_class->get_property = valent_contact_store_get_property;
272 : 8 : object_class->set_property = valent_contact_store_set_property;
273 : :
274 : 8 : klass->add_contacts = valent_contact_store_real_add_contacts;
275 : 8 : klass->remove_contacts = valent_contact_store_real_remove_contacts;
276 : 8 : klass->query = valent_contact_store_real_query;
277 : 8 : klass->get_contact = valent_contact_store_real_get_contact;
278 : :
279 : : /**
280 : : * ValentContactStore:name: (getter get_name) (setter set_name)
281 : : *
282 : : * The display name.
283 : : *
284 : : * Since: 1.0
285 : : */
286 : 16 : properties [PROP_NAME] =
287 : 8 : g_param_spec_string ("name", NULL, NULL,
288 : : NULL,
289 : : (G_PARAM_READWRITE |
290 : : G_PARAM_EXPLICIT_NOTIFY |
291 : : G_PARAM_STATIC_STRINGS));
292 : :
293 : : /**
294 : : * ValentContactStore:source: (getter get_source)
295 : : *
296 : : * The store [class@EDataServer.Source].
297 : : *
298 : : * Since: 1.0
299 : : */
300 : 16 : properties [PROP_SOURCE] =
301 : 8 : g_param_spec_object ("source", NULL, NULL,
302 : : E_TYPE_SOURCE,
303 : : (G_PARAM_READWRITE |
304 : : G_PARAM_CONSTRUCT_ONLY |
305 : : G_PARAM_EXPLICIT_NOTIFY |
306 : : G_PARAM_STATIC_STRINGS));
307 : :
308 : : /**
309 : : * ValentContactStore:uid: (getter get_uid)
310 : : *
311 : : * The unique identifier.
312 : : *
313 : : * Since: 1.0
314 : : */
315 : 16 : properties [PROP_UID] =
316 : 8 : g_param_spec_string ("uid", NULL, NULL,
317 : : NULL,
318 : : (G_PARAM_READABLE |
319 : : G_PARAM_EXPLICIT_NOTIFY |
320 : : G_PARAM_STATIC_STRINGS));
321 : :
322 : 8 : g_object_class_install_properties (object_class, N_PROPERTIES, properties);
323 : :
324 : : /**
325 : : * ValentContactStore::contact-added:
326 : : * @store: a #ValentContactStore
327 : : * @contact: a #EContact
328 : : *
329 : : * Emitted when an [class@EBookContacts.Contact] is added to @store.
330 : : *
331 : : * Since: 1.0
332 : : */
333 : 16 : signals [CONTACT_ADDED] =
334 : 8 : g_signal_new ("contact-added",
335 : : G_TYPE_FROM_CLASS (klass),
336 : : G_SIGNAL_RUN_LAST,
337 : : G_STRUCT_OFFSET (ValentContactStoreClass, contact_added),
338 : : NULL, NULL,
339 : : g_cclosure_marshal_VOID__OBJECT,
340 : : G_TYPE_NONE,
341 : : 1,
342 : : E_TYPE_CONTACT);
343 : 8 : g_signal_set_va_marshaller (signals [CONTACT_ADDED],
344 : : G_TYPE_FROM_CLASS (klass),
345 : : g_cclosure_marshal_VOID__OBJECTv);
346 : :
347 : : /**
348 : : * ValentContactStore::contact-removed:
349 : : * @store: a #ValentContactStore
350 : : * @uid: the UID of the removed contact
351 : : *
352 : : * Emitted when an [class@EBookContacts.Contact] is removed from @store.
353 : : *
354 : : * Since: 1.0
355 : : */
356 : 16 : signals [CONTACT_REMOVED] =
357 : 8 : g_signal_new ("contact-removed",
358 : : G_TYPE_FROM_CLASS (klass),
359 : : G_SIGNAL_RUN_LAST,
360 : : G_STRUCT_OFFSET (ValentContactStoreClass, contact_removed),
361 : : NULL, NULL,
362 : : g_cclosure_marshal_VOID__STRING,
363 : : G_TYPE_NONE,
364 : : 1,
365 : : G_TYPE_STRING);
366 : 8 : g_signal_set_va_marshaller (signals [CONTACT_REMOVED],
367 : : G_TYPE_FROM_CLASS (klass),
368 : : g_cclosure_marshal_VOID__STRINGv);
369 : 8 : }
370 : :
371 : : static void
372 : 17 : valent_contact_store_init (ValentContactStore *store)
373 : : {
374 : 17 : }
375 : :
376 : : /**
377 : : * valent_contact_store_contact_added:
378 : : * @store: a #ValentContactStore
379 : : * @contact: the #EContact
380 : : *
381 : : * Emits [signal@Valent.ContactStore::contact-added] signal on @store.
382 : : *
383 : : * This method should only be called by implementations of
384 : : * [class@Valent.ContactStore]. Signal handlers may query the state, so it must
385 : : * emitted after the internal representation has been updated.
386 : : *
387 : : * Since: 1.0
388 : : */
389 : : void
390 : 21 : valent_contact_store_contact_added (ValentContactStore *store,
391 : : EContact *contact)
392 : : {
393 : 21 : SignalEmission *emission;
394 : :
395 [ + - ]: 21 : g_return_if_fail (VALENT_IS_CONTACT_STORE (store));
396 : :
397 [ + - ]: 21 : if G_LIKELY (VALENT_IS_MAIN_THREAD ())
398 : : {
399 : 0 : g_signal_emit (G_OBJECT (store), signals [CONTACT_ADDED], 0, contact);
400 : 0 : return;
401 : : }
402 : :
403 : 21 : emission = g_new0 (SignalEmission, 1);
404 : 21 : g_rec_mutex_init (&emission->mutex);
405 : 21 : g_rec_mutex_lock (&emission->mutex);
406 : 21 : g_weak_ref_init (&emission->store, store);
407 : 21 : emission->contact = g_object_ref (contact);
408 : 21 : g_rec_mutex_unlock (&emission->mutex);
409 : :
410 : 21 : g_timeout_add (0, valent_contact_store_contact_added_main, emission);
411 : : }
412 : :
413 : : /**
414 : : * valent_contact_store_contact_removed:
415 : : * @store: a #ValentContactStore
416 : : * @uid: the UID of @contact
417 : : *
418 : : * Emits [signal@Valent.ContactStore::contact-removed] on @store.
419 : : *
420 : : * This method should only be called by implementations of
421 : : * [class@Valent.ContactStore]. Signal handlers may query the state, so it must
422 : : * emitted after the internal representation has been updated.
423 : : *
424 : : * Since: 1.0
425 : : */
426 : : void
427 : 1 : valent_contact_store_contact_removed (ValentContactStore *store,
428 : : const char *uid)
429 : : {
430 : 1 : SignalEmission *emission;
431 : :
432 [ + - ]: 1 : g_return_if_fail (VALENT_IS_CONTACT_STORE (store));
433 : :
434 [ + - ]: 1 : if G_LIKELY (VALENT_IS_MAIN_THREAD ())
435 : : {
436 : 0 : g_signal_emit (G_OBJECT (store), signals [CONTACT_REMOVED], 0, uid);
437 : 0 : return;
438 : : }
439 : :
440 : 1 : emission = g_new0 (SignalEmission, 1);
441 : 1 : g_rec_mutex_init (&emission->mutex);
442 : 1 : g_rec_mutex_lock (&emission->mutex);
443 : 1 : g_weak_ref_init (&emission->store, store);
444 [ - + ]: 1 : emission->uid = g_strdup (uid);
445 : 1 : g_rec_mutex_unlock (&emission->mutex);
446 : :
447 : 1 : g_timeout_add (0, valent_contact_store_contact_removed_main, emission);
448 : : }
449 : :
450 : : /**
451 : : * valent_contact_store_get_name: (get-property name)
452 : : * @store: a #ValentContactStore
453 : : *
454 : : * Get the display name of @store.
455 : : *
456 : : * Returns: (transfer none): a display name
457 : : *
458 : : * Since: 1.0
459 : : */
460 : : const char *
461 : 3 : valent_contact_store_get_name (ValentContactStore *store)
462 : : {
463 : 3 : ValentContactStorePrivate *priv = valent_contact_store_get_instance_private (store);
464 : :
465 [ + - ]: 3 : g_return_val_if_fail (VALENT_IS_CONTACT_STORE (store), NULL);
466 : :
467 : 3 : return e_source_get_display_name (priv->source);
468 : : }
469 : :
470 : : /**
471 : : * valent_contact_store_set_name: (set-property name)
472 : : * @store: a #ValentContactStore
473 : : * @name: a display name
474 : : *
475 : : * Set the display name of @store to @name.
476 : : *
477 : : * Since: 1.0
478 : : */
479 : : void
480 : 3 : valent_contact_store_set_name (ValentContactStore *store,
481 : : const char *name)
482 : : {
483 : 3 : ValentContactStorePrivate *priv = valent_contact_store_get_instance_private (store);
484 : :
485 [ + - ]: 3 : g_return_if_fail (VALENT_IS_CONTACT_STORE (store));
486 [ - + ]: 3 : g_return_if_fail (name != NULL);
487 : :
488 [ + - ]: 3 : if (priv->source != NULL)
489 : 3 : e_source_set_display_name (priv->source, name);
490 : : }
491 : :
492 : : /**
493 : : * valent_contact_store_get_source: (get-property source)
494 : : * @store: a #ValentContactStore
495 : : *
496 : : * Get the #ESource backing @store.
497 : : *
498 : : * Returns: (transfer none) (not nullable): an #ESource
499 : : *
500 : : * Since: 1.0
501 : : */
502 : : ESource *
503 : 18 : valent_contact_store_get_source (ValentContactStore *store)
504 : : {
505 : 18 : ValentContactStorePrivate *priv = valent_contact_store_get_instance_private (store);
506 : :
507 [ + - ]: 18 : g_return_val_if_fail (VALENT_IS_CONTACT_STORE (store), NULL);
508 : :
509 : 18 : return priv->source;
510 : : }
511 : :
512 : : /**
513 : : * valent_contact_store_get_uid: (get-property uid)
514 : : * @store: a #ValentContactStore
515 : : *
516 : : * Get the UID of @store.
517 : : *
518 : : * Returns: (transfer none): a UID
519 : : *
520 : : * Since: 1.0
521 : : */
522 : : const char *
523 : 17 : valent_contact_store_get_uid (ValentContactStore *store)
524 : : {
525 : 17 : ValentContactStorePrivate *priv = valent_contact_store_get_instance_private (store);
526 : :
527 [ + - ]: 17 : g_return_val_if_fail (VALENT_IS_CONTACT_STORE (store), NULL);
528 : :
529 : 17 : return e_source_get_uid (priv->source);
530 : : }
531 : :
532 : : /**
533 : : * valent_contact_store_add_contact:
534 : : * @store: a #ValentContactStore
535 : : * @contact: a #EContact
536 : : * @cancellable: (nullable): #GCancellable
537 : : * @callback: (scope async): a #GAsyncReadyCallback
538 : : * @user_data: (closure): user supplied data
539 : : *
540 : : * A convenience wrapper around [method@Valent.ContactStore.add_contacts] for
541 : : * adding a single contact.
542 : : *
543 : : * Call [method@Valent.ContactStore.add_contacts_finish] to get the result.
544 : : *
545 : : * Since: 1.0
546 : : */
547 : : void
548 : 10 : valent_contact_store_add_contact (ValentContactStore *store,
549 : : EContact *contact,
550 : : GCancellable *cancellable,
551 : : GAsyncReadyCallback callback,
552 : : gpointer user_data)
553 : : {
554 : 20 : g_autoptr (GSList) contacts = NULL;
555 : :
556 : 10 : VALENT_ENTRY;
557 : :
558 [ + - ]: 10 : g_return_if_fail (VALENT_IS_CONTACT_STORE (store));
559 [ + - + - : 10 : g_return_if_fail (E_IS_CONTACT (contact));
- + - - ]
560 [ + + + - : 10 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- + - - ]
561 : :
562 : 10 : contacts = g_slist_append (contacts, contact);
563 : 10 : valent_contact_store_add_contacts (store,
564 : : contacts,
565 : : cancellable,
566 : : callback,
567 : : user_data);
568 : :
569 [ + - ]: 10 : VALENT_EXIT;
570 : : }
571 : :
572 : : /**
573 : : * valent_contact_store_add_contacts: (virtual add_contacts)
574 : : * @store: a #ValentContactStore
575 : : * @contacts: (element-type EContact): a #GSList
576 : : * @cancellable: (nullable): #GCancellable
577 : : * @callback: (scope async): a #GAsyncReadyCallback
578 : : * @user_data: (closure): user supplied data
579 : : *
580 : : * Add @contacts to @store.
581 : : *
582 : : * Call [method@Valent.ContactStore.add_contacts_finish] to get the result.
583 : : *
584 : : * Since: 1.0
585 : : */
586 : : void
587 : 14 : valent_contact_store_add_contacts (ValentContactStore *store,
588 : : GSList *contacts,
589 : : GCancellable *cancellable,
590 : : GAsyncReadyCallback callback,
591 : : gpointer user_data)
592 : : {
593 : 14 : VALENT_ENTRY;
594 : :
595 [ + - ]: 14 : g_return_if_fail (VALENT_IS_CONTACT_STORE (store));
596 [ - + ]: 14 : g_return_if_fail (contacts != NULL);
597 [ + + + - : 14 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- + - - ]
598 : :
599 : 14 : VALENT_CONTACT_STORE_GET_CLASS (store)->add_contacts (store,
600 : : contacts,
601 : : cancellable,
602 : : callback,
603 : : user_data);
604 : :
605 : 14 : VALENT_EXIT;
606 : : }
607 : :
608 : : /**
609 : : * valent_contact_store_add_contacts_finish:
610 : : * @store: a #ValentContactStore
611 : : * @result: a #GAsyncResult
612 : : * @error: (nullable): a #GError
613 : : *
614 : : * Finish an operation started by [method@Valent.ContactStore.add_contact] or
615 : : * [method@Valent.ContactStore.add_contacts].
616 : : *
617 : : * Returns: %TRUE if successful, or %FALSE with @error set
618 : : *
619 : : * Since: 1.0
620 : : */
621 : : gboolean
622 : 14 : valent_contact_store_add_contacts_finish (ValentContactStore *store,
623 : : GAsyncResult *result,
624 : : GError **error)
625 : : {
626 : 14 : gboolean ret;
627 : :
628 : 14 : VALENT_ENTRY;
629 : :
630 [ + - ]: 14 : g_return_val_if_fail (VALENT_IS_CONTACT_STORE (store), FALSE);
631 [ - + ]: 14 : g_return_val_if_fail (g_task_is_valid (result, store), FALSE);
632 [ + - - + ]: 14 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
633 : :
634 : 14 : ret = g_task_propagate_boolean (G_TASK (result), error);
635 : :
636 : 14 : VALENT_RETURN (ret);
637 : : }
638 : :
639 : : /**
640 : : * valent_contact_store_remove_contact:
641 : : * @store: a #ValentContactStore
642 : : * @uid: a contact UID
643 : : * @cancellable: (nullable): #GCancellable
644 : : * @callback: (scope async): a #GAsyncReadyCallback
645 : : * @user_data: (closure): user supplied data
646 : : *
647 : : * Remove contact @uid from @store.
648 : : *
649 : : * A convenience wrapper around [method@Valent.ContactStore.remove_contacts] for
650 : : * removing a single contact.
651 : : *
652 : : * Call [method@Valent.ContactStore.remove_contacts_finish] to get the result.
653 : : *
654 : : * Since: 1.0
655 : : */
656 : : void
657 : 1 : valent_contact_store_remove_contact (ValentContactStore *store,
658 : : const char *uid,
659 : : GCancellable *cancellable,
660 : : GAsyncReadyCallback callback,
661 : : gpointer user_data)
662 : : {
663 : 2 : g_autoptr (GSList) contacts = NULL;
664 : :
665 : 1 : VALENT_ENTRY;
666 : :
667 [ + - ]: 1 : g_return_if_fail (VALENT_IS_CONTACT_STORE (store));
668 [ - + ]: 1 : g_return_if_fail (uid != NULL);
669 [ - + - - : 1 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - ]
670 : :
671 : 1 : contacts = g_slist_append (contacts, (char *)uid);
672 : 1 : valent_contact_store_remove_contacts (store,
673 : : contacts,
674 : : cancellable,
675 : : callback,
676 : : user_data);
677 : :
678 [ + - ]: 1 : VALENT_EXIT;
679 : : }
680 : :
681 : : /**
682 : : * valent_contact_store_remove_contacts: (virtual remove_contacts)
683 : : * @store: a #ValentContactStore
684 : : * @uids: (element-type utf8): a #GSList of contact UIDs
685 : : * @cancellable: (nullable): #GCancellable
686 : : * @callback: (scope async): a #GAsyncReadyCallback
687 : : * @user_data: (closure): user supplied data
688 : : *
689 : : * Remove contact @uid from @store.
690 : : *
691 : : * Call [method@Valent.ContactStore.remove_contacts_finish] to get the result.
692 : : *
693 : : * Since: 1.0
694 : : */
695 : : void
696 : 1 : valent_contact_store_remove_contacts (ValentContactStore *store,
697 : : GSList *uids,
698 : : GCancellable *cancellable,
699 : : GAsyncReadyCallback callback,
700 : : gpointer user_data)
701 : : {
702 : 1 : VALENT_ENTRY;
703 : :
704 [ + - ]: 1 : g_return_if_fail (VALENT_IS_CONTACT_STORE (store));
705 [ - + ]: 1 : g_return_if_fail (uids != NULL);
706 [ - + - - : 1 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - ]
707 : :
708 : 1 : VALENT_CONTACT_STORE_GET_CLASS (store)->remove_contacts (store,
709 : : uids,
710 : : cancellable,
711 : : callback,
712 : : user_data);
713 : :
714 : 1 : VALENT_EXIT;
715 : : }
716 : :
717 : : /**
718 : : * valent_contact_store_remove_contacts_finish:
719 : : * @store: a #ValentContactStore
720 : : * @result: a #GAsyncResult
721 : : * @error: (nullable): a #GError
722 : : *
723 : : * Finish an operation started by [method@Valent.ContactStore.remove_contact] or
724 : : * [method@Valent.ContactStore.remove_contacts].
725 : : *
726 : : * Returns: %TRUE if successful, or %FALSE with @error set
727 : : *
728 : : * Since: 1.0
729 : : */
730 : : gboolean
731 : 1 : valent_contact_store_remove_contacts_finish (ValentContactStore *store,
732 : : GAsyncResult *result,
733 : : GError **error)
734 : : {
735 : 1 : gboolean ret;
736 : :
737 : 1 : VALENT_ENTRY;
738 : :
739 [ + - ]: 1 : g_return_val_if_fail (VALENT_IS_CONTACT_STORE (store), FALSE);
740 [ - + ]: 1 : g_return_val_if_fail (g_task_is_valid (result, store), FALSE);
741 [ + - - + ]: 1 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
742 : :
743 : 1 : ret = g_task_propagate_boolean (G_TASK (result), error);
744 : :
745 : 1 : VALENT_RETURN (ret);
746 : : }
747 : :
748 : : /**
749 : : * valent_contact_store_query: (virtual query)
750 : : * @store: a #ValentContactStore
751 : : * @query: a search expression
752 : : * @cancellable: (nullable): #GCancellable
753 : : * @callback: (scope async): a #GAsyncReadyCallback
754 : : * @user_data: (closure): user supplied data
755 : : *
756 : : * Query @store for contacts matching @query.
757 : : *
758 : : * Call [method@Valent.ContactStore.query_finish] to get the result.
759 : : *
760 : : * Since: 1.0
761 : : */
762 : : void
763 : 12 : valent_contact_store_query (ValentContactStore *store,
764 : : const char *query,
765 : : GCancellable *cancellable,
766 : : GAsyncReadyCallback callback,
767 : : gpointer user_data)
768 : : {
769 : 12 : VALENT_ENTRY;
770 : :
771 [ + - ]: 12 : g_return_if_fail (VALENT_IS_CONTACT_STORE (store));
772 [ - + ]: 12 : g_return_if_fail (query != NULL);
773 [ + + + - : 12 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- + - - ]
774 : :
775 : 12 : VALENT_CONTACT_STORE_GET_CLASS (store)->query (store,
776 : : query,
777 : : cancellable,
778 : : callback,
779 : : user_data);
780 : :
781 : 12 : VALENT_EXIT;
782 : : }
783 : :
784 : : /**
785 : : * valent_contact_store_query_finish:
786 : : * @store: a #ValentContactStore
787 : : * @result: a #GAsyncResult
788 : : * @error: (nullable): a #GError
789 : : *
790 : : * Finish an operation started by [method@Valent.ContactStore.query].
791 : : *
792 : : * Returns: (transfer full) (element-type EContact): a #GSList
793 : : *
794 : : * Since: 1.0
795 : : */
796 : : GSList *
797 : 11 : valent_contact_store_query_finish (ValentContactStore *store,
798 : : GAsyncResult *result,
799 : : GError **error)
800 : : {
801 : 11 : GSList *ret;
802 : :
803 : 11 : VALENT_ENTRY;
804 : :
805 [ + - ]: 11 : g_return_val_if_fail (VALENT_IS_CONTACT_STORE (store), NULL);
806 [ - + ]: 11 : g_return_val_if_fail (g_task_is_valid (result, store), NULL);
807 [ + - - + ]: 11 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
808 : :
809 : 11 : ret = g_task_propagate_pointer (G_TASK (result), error);
810 : :
811 : 11 : VALENT_RETURN (ret);
812 : : }
813 : :
814 : : /**
815 : : * valent_contact_store_get_contact: (virtual get_contact)
816 : : * @store: a #ValentContactStore
817 : : * @uid: a contact UID
818 : : * @cancellable: (nullable): #GCancellable
819 : : * @callback: (scope async): a #GAsyncReadyCallback
820 : : * @user_data: (closure): user supplied data
821 : : *
822 : : * Get a contact by UID.
823 : : *
824 : : * Call [method@Valent.ContactStore.get_contact_finish] to get the result.
825 : : *
826 : : * Since: 1.0
827 : : */
828 : : void
829 : 2 : valent_contact_store_get_contact (ValentContactStore *store,
830 : : const char *uid,
831 : : GCancellable *cancellable,
832 : : GAsyncReadyCallback callback,
833 : : gpointer user_data)
834 : : {
835 : 2 : VALENT_ENTRY;
836 : :
837 [ + - ]: 2 : g_return_if_fail (VALENT_IS_CONTACT_STORE (store));
838 [ - + ]: 2 : g_return_if_fail (uid != NULL);
839 [ - + - - : 2 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - ]
840 : :
841 : 2 : VALENT_CONTACT_STORE_GET_CLASS (store)->get_contact (store,
842 : : uid,
843 : : cancellable,
844 : : callback,
845 : : user_data);
846 : :
847 : 2 : VALENT_EXIT;
848 : : }
849 : :
850 : : /**
851 : : * valent_contact_store_get_contact_finish:
852 : : * @store: a #ValentContactStore
853 : : * @result: a #GAsyncResult
854 : : * @error: (nullable): a #GError
855 : : *
856 : : * Finish an operation started by valent_contact_store_get_contact().
857 : : *
858 : : * Returns: (transfer full) (nullable): a #EContact
859 : : *
860 : : * Since: 1.0
861 : : */
862 : : EContact *
863 : 2 : valent_contact_store_get_contact_finish (ValentContactStore *store,
864 : : GAsyncResult *result,
865 : : GError **error)
866 : : {
867 : 2 : EContact *ret;
868 : :
869 : 2 : VALENT_ENTRY;
870 : :
871 [ + - ]: 2 : g_return_val_if_fail (VALENT_IS_CONTACT_STORE (store), NULL);
872 [ - + ]: 2 : g_return_val_if_fail (g_task_is_valid (result, store), NULL);
873 [ + - - + ]: 2 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
874 : :
875 : 2 : ret = g_task_propagate_pointer (G_TASK (result), error);
876 : :
877 : 2 : VALENT_RETURN (ret);
878 : : }
879 : :
880 : : /**
881 : : * valent_contact_store_get_contacts:
882 : : * @store: a #ValentContactStore
883 : : * @uids: a list of UIDs
884 : : * @cancellable: (nullable): #GCancellable
885 : : * @callback: (scope async): a #GAsyncReadyCallback
886 : : * @user_data: (closure): user supplied data
887 : : *
888 : : * A convenience wrapper around [method@Valent.ContactStore.query] for searching
889 : : * contacts by UID.
890 : : *
891 : : * Call [method@Valent.ContactStore.query_finish] to get the result.
892 : : *
893 : : * Since: 1.0
894 : : */
895 : : void
896 : 1 : valent_contact_store_get_contacts (ValentContactStore *store,
897 : : char **uids,
898 : : GCancellable *cancellable,
899 : : GAsyncReadyCallback callback,
900 : : gpointer user_data)
901 : : {
902 : 2 : g_autofree char *sexp = NULL;
903 : 1 : g_autofree EBookQuery **queries = NULL;
904 : 1 : g_autoptr (EBookQuery) query = NULL;
905 : 1 : unsigned int n;
906 : :
907 : 1 : VALENT_ENTRY;
908 : :
909 [ + - ]: 1 : g_return_if_fail (VALENT_IS_CONTACT_STORE (store));
910 [ - + - - : 1 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - ]
911 : :
912 : 1 : n = g_strv_length (uids);
913 [ - + ]: 1 : queries = g_new0 (EBookQuery *, n);
914 : :
915 [ + + ]: 2 : for (unsigned int i = 0; i < n; i++)
916 : 1 : queries[i] = e_book_query_field_test (E_CONTACT_UID, E_BOOK_QUERY_IS, uids[i]);
917 : :
918 : 1 : query = e_book_query_or (n, queries, TRUE);
919 : 1 : sexp = e_book_query_to_string (query);
920 : :
921 : 1 : valent_contact_store_query (store, sexp, cancellable, callback, user_data);
922 : :
923 [ + - ]: 2 : VALENT_EXIT;
924 : : }
925 : :
|