[libgdata] contacts: Add an async method for gdata_contacts_contact_set_photo()



commit 6fb9eb819b1122dca6128133484820ffcd5f421c
Author: Philip Withnall <philip tecnocode co uk>
Date:   Fri Dec 10 20:01:46 2010 +0000

    contacts: Add an async method for gdata_contacts_contact_set_photo()
    
    This includes new tests.
    
    The following API has been added:
     â?¢ gdata_contacts_contact_set_photo_async()
     â?¢ gdata_contacts_contact_set_photo_finish()
    
    Closes: bgo#633363

 docs/reference/gdata-sections.txt                |    2 +
 gdata/gdata.symbols                              |    2 +
 gdata/services/contacts/gdata-contacts-contact.c |  108 +++++++++++++++++++++-
 gdata/services/contacts/gdata-contacts-contact.h |    3 +
 gdata/tests/contacts.c                           |   76 +++++++++++++++
 5 files changed, 190 insertions(+), 1 deletions(-)
---
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index c24d879..911ee4c 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -429,6 +429,8 @@ gdata_contacts_contact_get_photo
 gdata_contacts_contact_get_photo_async
 gdata_contacts_contact_get_photo_finish
 gdata_contacts_contact_set_photo
+gdata_contacts_contact_set_photo_async
+gdata_contacts_contact_set_photo_finish
 <SUBSECTION Standard>
 gdata_contacts_contact_get_type
 GDATA_CONTACTS_CONTACT
diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols
index 6852ced..77a1070 100644
--- a/gdata/gdata.symbols
+++ b/gdata/gdata.symbols
@@ -858,3 +858,5 @@ gdata_calendar_service_query_events_async
 gdata_calendar_service_insert_event_async
 gdata_contacts_contact_get_photo_async
 gdata_contacts_contact_get_photo_finish
+gdata_contacts_contact_set_photo_async
+gdata_contacts_contact_set_photo_finish
diff --git a/gdata/services/contacts/gdata-contacts-contact.c b/gdata/services/contacts/gdata-contacts-contact.c
index 05a5520..3fa8f4f 100644
--- a/gdata/services/contacts/gdata-contacts-contact.c
+++ b/gdata/services/contacts/gdata-contacts-contact.c
@@ -2999,6 +2999,7 @@ gdata_contacts_contact_get_photo (GDataContactsContact *self, GDataContactsServi
 }
 
 typedef struct {
+	GDataContactsService *service;
 	guint8 *data;
 	gsize length;
 	gchar *content_type;
@@ -3007,6 +3008,8 @@ typedef struct {
 static void
 photo_data_free (PhotoData *data)
 {
+	if (data->service != NULL)
+		g_object_unref (data->service);
 	g_free (data->data);
 	g_free (data->content_type);
 	g_slice_free (PhotoData, data);
@@ -3152,7 +3155,6 @@ gdata_contacts_contact_set_photo (GDataContactsContact *self, GDataContactsServi
 	guint status;
 	gboolean adding_photo = FALSE, deleting_photo = FALSE;
 
-	/* TODO: async version */
 	g_return_val_if_fail (GDATA_IS_CONTACTS_CONTACT (self), FALSE);
 	g_return_val_if_fail (GDATA_IS_CONTACTS_SERVICE (service), FALSE);
 	g_return_val_if_fail (data == NULL || content_type != NULL, FALSE);
@@ -3201,3 +3203,107 @@ gdata_contacts_contact_set_photo (GDataContactsContact *self, GDataContactsServi
 
 	return TRUE;
 }
+
+static void
+set_photo_thread (GSimpleAsyncResult *result, GDataContactsContact *contact, GCancellable *cancellable)
+{
+	PhotoData *data;
+	gboolean success;
+	GError *error = NULL;
+
+	/* Input photo data */
+	data = g_simple_async_result_get_op_res_gpointer (result);
+
+	/* Set the photo */
+	success = gdata_contacts_contact_set_photo (contact, data->service, data->data, data->length, data->content_type, cancellable, &error);
+	if (error != NULL) {
+		g_simple_async_result_set_from_error (result, error);
+		g_error_free (error);
+		return;
+	}
+
+	/* Replace the photo data with the success value */
+	g_simple_async_result_set_op_res_gboolean (result, success);
+}
+
+/**
+ * gdata_contacts_contact_set_photo_async:
+ * @self: a #GDataContactsContact
+ * @service: a #GDataContactsService
+ * @data: (allow-none): the image data, or %NULL
+ * @length: the image length, in bytes
+ * @content_type: (allow-none): the content type of the image, or %NULL
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the photo has been set, or %NULL
+ * @user_data: (closure): data to pass to the @callback function
+ *
+ * Sets the contact's photo to @data or, if @data is %NULL, deletes the contact's photo. @content_type must be specified if @data is non-%NULL. @self,
+ * @service, @data and @content_type are all reffed and copied when this function is called, so can safely be unreffed after this function returns.
+ *
+ * When the operation is finished, @callback will be called. You can then call gdata_contacts_contact_set_photo_finish() to get the results of the
+ * operation.
+ *
+ * For more details, see gdata_contacts_contact_set_photo(), which is the synchronous version of this function.
+ *
+ * If @cancellable is not %NULL, then the operation can be cancelled by triggering the @cancellable object from another thread.
+ * If the operation was cancelled, the error %G_IO_ERROR_CANCELLED will be returned by gdata_contacts_contact_set_photo_finish().
+ *
+ * If there is an error setting the photo, a %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error will be returned by gdata_contacts_contact_set_photo_finish().
+ *
+ * Since: 0.8.0
+ **/
+void
+gdata_contacts_contact_set_photo_async (GDataContactsContact *self, GDataContactsService *service, const guint8 *data, gsize length,
+                                        const gchar *content_type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+	GSimpleAsyncResult *result;
+	PhotoData *photo_data;
+
+	g_return_if_fail (GDATA_IS_CONTACTS_CONTACT (self));
+	g_return_if_fail (GDATA_IS_CONTACTS_SERVICE (service));
+	g_return_if_fail (data == NULL || content_type != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	/* Prepare the data to be passed to the thread */
+	photo_data = g_slice_new (PhotoData);
+	photo_data->service = g_object_ref (service);
+	photo_data->data = g_memdup (data, length);
+	photo_data->length = length;
+	photo_data->content_type = g_strdup (content_type);
+
+	result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gdata_contacts_contact_set_photo_async);
+	g_simple_async_result_set_op_res_gpointer (result, photo_data, (GDestroyNotify) photo_data_free);
+	g_simple_async_result_run_in_thread (result, (GSimpleAsyncThreadFunc) set_photo_thread, G_PRIORITY_DEFAULT, cancellable);
+	g_object_unref (result);
+}
+
+/**
+ * gdata_contacts_contact_set_photo_finish:
+ * @self: a #GDataContactsContact
+ * @async_result: a #GAsyncResult
+ * @error: a #GError, or %NULL
+ *
+ * Finishes an asynchronous contact photo setting operation started with gdata_contacts_contact_set_photo_async().
+ *
+ * If there is an error setting the photo, a %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error will be returned.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise
+ *
+ * Since: 0.8.0
+ **/
+gboolean
+gdata_contacts_contact_set_photo_finish (GDataContactsContact *self, GAsyncResult *async_result, GError **error)
+{
+	GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (async_result);
+
+	g_return_val_if_fail (GDATA_IS_CONTACTS_CONTACT (self), FALSE);
+	g_return_val_if_fail (G_IS_ASYNC_RESULT (async_result), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	g_warn_if_fail (g_simple_async_result_get_source_tag (result) == gdata_contacts_contact_set_photo_async);
+
+	if (g_simple_async_result_propagate_error (result, error) == TRUE)
+		return FALSE;
+
+	return g_simple_async_result_get_op_res_gboolean (result);
+}
diff --git a/gdata/services/contacts/gdata-contacts-contact.h b/gdata/services/contacts/gdata-contacts-contact.h
index 1e565b7..5b6b3a7 100644
--- a/gdata/services/contacts/gdata-contacts-contact.h
+++ b/gdata/services/contacts/gdata-contacts-contact.h
@@ -288,6 +288,9 @@ guint8 *gdata_contacts_contact_get_photo_finish (GDataContactsContact *self, GAs
 
 gboolean gdata_contacts_contact_set_photo (GDataContactsContact *self, GDataContactsService *service, const guint8 *data, gsize length,
                                            const gchar *content_type, GCancellable *cancellable, GError **error);
+void gdata_contacts_contact_set_photo_async (GDataContactsContact *self, GDataContactsService *service, const guint8 *data, gsize length,
+                                             const gchar *content_type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean gdata_contacts_contact_set_photo_finish (GDataContactsContact *self, GAsyncResult *async_result, GError **error);
 
 G_END_DECLS
 
diff --git a/gdata/tests/contacts.c b/gdata/tests/contacts.c
index 0e383b9..dc25cf7 100644
--- a/gdata/tests/contacts.c
+++ b/gdata/tests/contacts.c
@@ -1589,6 +1589,45 @@ test_photo_add (gconstpointer service)
 }
 
 static void
+test_photo_add_async_cb (GDataContactsContact *contact, GAsyncResult *result, GMainLoop *main_loop)
+{
+	gboolean success;
+	GError *error = NULL;
+
+	success = gdata_contacts_contact_set_photo_finish (contact, result, &error);
+	g_assert_no_error (error);
+	g_assert (success == TRUE);
+
+	g_assert (gdata_contacts_contact_has_photo (contact) == TRUE);
+
+	g_main_loop_quit (main_loop);
+}
+
+static void
+test_photo_add_async (gconstpointer service)
+{
+	GDataContactsContact *contact;
+	guint8 *data;
+	gsize length;
+	GMainLoop *main_loop;
+
+	/* Get the photo */
+	g_assert (g_file_get_contents (TEST_FILE_DIR "photo.jpg", (gchar**) &data, &length, NULL) == TRUE);
+
+	contact = get_contact (service);
+	main_loop = g_main_loop_new (NULL, TRUE);
+
+	/* Add it to the contact asynchronously */
+	gdata_contacts_contact_set_photo_async (contact, GDATA_CONTACTS_SERVICE (service), data, length, "image/jpeg", NULL,
+	                                        (GAsyncReadyCallback) test_photo_add_async_cb, main_loop);
+	g_main_loop_run (main_loop);
+
+	g_main_loop_unref (main_loop);
+	g_object_unref (contact);
+	g_free (data);
+}
+
+static void
 test_photo_get (gconstpointer service)
 {
 	GDataContactsContact *contact;
@@ -1678,6 +1717,41 @@ test_photo_delete (gconstpointer service)
 }
 
 static void
+test_photo_delete_async_cb (GDataContactsContact *contact, GAsyncResult *result, GMainLoop *main_loop)
+{
+	gboolean success;
+	GError *error = NULL;
+
+	success = gdata_contacts_contact_set_photo_finish (contact, result, &error);
+	g_assert_no_error (error);
+	g_assert (success == TRUE);
+
+	g_assert (gdata_contacts_contact_has_photo (contact) == FALSE);
+
+	g_main_loop_quit (main_loop);
+}
+
+static void
+test_photo_delete_async (gconstpointer service)
+{
+	GDataContactsContact *contact;
+	GMainLoop *main_loop;
+
+	contact = get_contact (service);
+	main_loop = g_main_loop_new (NULL, TRUE);
+
+	g_assert (gdata_contacts_contact_has_photo (contact) == TRUE);
+
+	/* Delete it from the contact asynchronously */
+	gdata_contacts_contact_set_photo_async (contact, GDATA_CONTACTS_SERVICE (service), NULL, 0, NULL, NULL,
+	                                        (GAsyncReadyCallback) test_photo_delete_async_cb, main_loop);
+	g_main_loop_run (main_loop);
+
+	g_main_loop_unref (main_loop);
+	g_object_unref (contact);
+}
+
+static void
 test_batch (gconstpointer service)
 {
 	GDataBatchOperation *operation;
@@ -1955,6 +2029,8 @@ main (int argc, char *argv[])
 		g_test_add_data_func ("/contacts/photo/get", service, test_photo_get);
 		g_test_add_data_func ("/contacts/photo/get/async", service, test_photo_get_async);
 		g_test_add_data_func ("/contacts/photo/delete", service, test_photo_delete);
+		g_test_add_data_func ("/contacts/photo/add/async", service, test_photo_add_async);
+		g_test_add_data_func ("/contacts/photo/delete/async", service, test_photo_delete_async);
 
 		g_test_add_data_func ("/contacts/batch", service, test_batch);
 		g_test_add ("/contacts/batch/async", BatchAsyncData, service, setup_batch_async, test_batch_async, teardown_batch_async);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]