=?utf-8?q?=5Blibgdata=5D_Bug_607270_=E2=80=94_Support_copying_documents?=
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgdata] Bug 607270 â Support copying documents
- Date: Sun, 15 Jul 2012 10:02:27 +0000 (UTC)
commit 2bfde8ba318c991ec909c3f7d788c244b615d7b8
Author: Philip Withnall <philip tecnocode co uk>
Date: Sun Jul 15 11:00:50 2012 +0100
Bug 607270 â Support copying documents
Add support for copying uploaded Google Documents documents without having
to re-upload them.
New API:
â gdata_documents_service_copy_document()
â gdata_documents_service_copy_document_async()
â gdata_documents_service_copy_document_finish()
This includes a test case, but I havenât been able to run it because Googleâs
servers are still acting up re. metadata-only uploads.
Closes: https://bugzilla.gnome.org/show_bug.cgi?id=607270
docs/reference/gdata-sections.txt | 3 +
gdata/gdata.symbols | 3 +
gdata/services/documents/gdata-documents-service.c | 157 ++++++++++++++++++++
gdata/services/documents/gdata-documents-service.h | 7 +
gdata/tests/documents.c | 46 ++++++
5 files changed, 216 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index 3fb2da3..eb83965 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -1779,6 +1779,9 @@ gdata_documents_service_upload_document_resumable
gdata_documents_service_update_document
gdata_documents_service_update_document_resumable
gdata_documents_service_finish_upload
+gdata_documents_service_copy_document
+gdata_documents_service_copy_document_async
+gdata_documents_service_copy_document_finish
gdata_documents_service_add_entry_to_folder
gdata_documents_service_add_entry_to_folder_async
gdata_documents_service_add_entry_to_folder_finish
diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols
index 012df7c..103867e 100644
--- a/gdata/gdata.symbols
+++ b/gdata/gdata.symbols
@@ -952,3 +952,6 @@ gdata_documents_document_new
gdata_documents_upload_query_get_convert
gdata_documents_upload_query_set_convert
gdata_documents_entry_get_quota_used
+gdata_documents_service_copy_document
+gdata_documents_service_copy_document_async
+gdata_documents_service_copy_document_finish
diff --git a/gdata/services/documents/gdata-documents-service.c b/gdata/services/documents/gdata-documents-service.c
index c806ddd..81eb19c 100644
--- a/gdata/services/documents/gdata-documents-service.c
+++ b/gdata/services/documents/gdata-documents-service.c
@@ -891,6 +891,163 @@ done:
}
/**
+ * gdata_documents_service_copy_document:
+ * @self: an authenticated #GDataDocumentsService
+ * @document: the #GDataDocumentsDocument to copy
+ * @cancellable: (allow-none): optional #GCancellable object, or %NULL
+ * @error: a #GError, or %NULL
+ *
+ * Copy the given @document, producing a duplicate document in the same folder and returning its #GDataDocumentsDocument. Note that @document
+ * may only be a document, not an arbitrary file; i.e. @document must be an instance of a subclass of #GDataDocumentsDocument.
+ *
+ * Errors from #GDataServiceError can be returned for exceptional conditions, as determined by the server.
+ *
+ * Return value: (transfer full): the duplicate #GDataDocumentsDocument, or %NULL; unref with g_object_unref()
+ *
+ * Since: 0.13.1
+ */
+GDataDocumentsDocument *
+gdata_documents_service_copy_document (GDataDocumentsService *self, GDataDocumentsDocument *document, GCancellable *cancellable, GError **error)
+{
+ GDataDocumentsDocument *new_document;
+ gchar *upload_data;
+ SoupMessage *message;
+ guint status;
+
+ g_return_val_if_fail (GDATA_IS_DOCUMENTS_SERVICE (self), NULL);
+ g_return_val_if_fail (GDATA_IS_DOCUMENTS_DOCUMENT (document), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ if (gdata_authorizer_is_authorized_for_domain (gdata_service_get_authorizer (GDATA_SERVICE (self)),
+ get_documents_authorization_domain ()) == FALSE) {
+ g_set_error_literal (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED,
+ _("You must be authenticated to copy documents."));
+ return NULL;
+ }
+
+ message = _gdata_service_build_message (GDATA_SERVICE (self), get_documents_authorization_domain (), SOUP_METHOD_POST,
+ "https://docs.google.com/feeds/default/private/full", NULL, TRUE);
+
+ /* Append the data */
+ upload_data = gdata_parsable_get_xml (GDATA_PARSABLE (document));
+ soup_message_set_request (message, "application/atom+xml", SOUP_MEMORY_TAKE, upload_data, strlen (upload_data));
+
+ /* Send the message */
+ status = _gdata_service_send_message (GDATA_SERVICE (self), message, cancellable, error);
+
+ if (status == SOUP_STATUS_NONE || status == SOUP_STATUS_CANCELLED) {
+ /* Redirect error or cancelled */
+ g_object_unref (message);
+ return NULL;
+ } else if (status != SOUP_STATUS_CREATED) {
+ /* Error */
+ GDataServiceClass *klass = GDATA_SERVICE_GET_CLASS (self);
+ g_assert (klass->parse_error_response != NULL);
+ klass->parse_error_response (GDATA_SERVICE (self), GDATA_OPERATION_UPDATE, status, message->reason_phrase,
+ message->response_body->data, message->response_body->length, error);
+ g_object_unref (message);
+ return NULL;
+ }
+
+ /* Parse the XML; and update the entry */
+ g_assert (message->response_body->data != NULL);
+ new_document = GDATA_DOCUMENTS_DOCUMENT (gdata_parsable_new_from_xml (G_OBJECT_TYPE (document), message->response_body->data,
+ message->response_body->length, error));
+ g_object_unref (message);
+
+ return new_document;
+}
+
+static void
+copy_document_thread (GSimpleAsyncResult *result, GDataDocumentsService *service, GCancellable *cancellable)
+{
+ GDataDocumentsDocument *document, *new_document;
+ GError *error = NULL;
+
+ document = g_simple_async_result_get_op_res_gpointer (result);
+
+ /* Copy the document and return */
+ new_document = gdata_documents_service_copy_document (service, document, cancellable, &error);
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ return;
+ }
+
+ /* Return the document copy */
+ g_simple_async_result_set_op_res_gpointer (result, g_object_ref (new_document), (GDestroyNotify) g_object_unref);
+}
+
+/**
+ * gdata_documents_service_copy_document_async:
+ * @self: a #GDataDocumentsService
+ * @document: the #GDataDocumentsDocument to copy
+ * @cancellable: (allow-none): optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the operation is finished, or %NULL
+ * @user_data: (closure): data to pass to the @callback function
+ *
+ * Copy the given @document, producing a duplicate document in the same folder and returning its #GDataDocumentsDocument. @self and @document are
+ * both reffed when this function is called, so can safely be unreffed after this function returns.
+ *
+ * For more details, see gdata_documents_service_copy_document(), which is the synchronous version of this function.
+ *
+ * When the operation is finished, @callback will be called. You can then call gdata_documents_service_copy_document_finish() to get the results
+ * of the operation.
+ *
+ * Since: 0.13.1
+ */
+void
+gdata_documents_service_copy_document_async (GDataDocumentsService *self, GDataDocumentsDocument *document, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+
+ g_return_if_fail (GDATA_IS_DOCUMENTS_SERVICE (self));
+ g_return_if_fail (GDATA_IS_DOCUMENTS_DOCUMENT (document));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gdata_documents_service_copy_document_async);
+ g_simple_async_result_set_op_res_gpointer (result, g_object_ref (document), (GDestroyNotify) g_object_unref);
+ g_simple_async_result_run_in_thread (result, (GSimpleAsyncThreadFunc) copy_document_thread, G_PRIORITY_DEFAULT, cancellable);
+ g_object_unref (result);
+}
+
+/**
+ * gdata_documents_service_copy_document_finish:
+ * @self: a #GDataDocumentsService
+ * @async_result: a #GAsyncResult
+ * @error: a #GError, or %NULL
+ *
+ * Finish an asynchronous operation to copy a #GDataDocumentsDocument started with gdata_documents_service_copy_document_async().
+ *
+ * Return value: (transfer full): the duplicate #GDataDocumentsDocument, or %NULL; unref with g_object_unref()
+ *
+ * Since: 0.13.1
+ */
+GDataDocumentsDocument *
+gdata_documents_service_copy_document_finish (GDataDocumentsService *self, GAsyncResult *async_result, GError **error)
+{
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (async_result);
+ GDataDocumentsDocument *new_document;
+
+ g_return_val_if_fail (GDATA_IS_DOCUMENTS_SERVICE (self), NULL);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (async_result), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (result) == gdata_documents_service_copy_document_async);
+
+ if (g_simple_async_result_propagate_error (result, error) == TRUE) {
+ return NULL;
+ }
+
+ new_document = g_simple_async_result_get_op_res_gpointer (result);
+ g_assert (GDATA_IS_DOCUMENTS_DOCUMENT (new_document));
+
+ return new_document;
+}
+
+/**
* gdata_documents_service_add_entry_to_folder:
* @self: an authenticated #GDataDocumentsService
* @entry: the #GDataDocumentsEntry to move
diff --git a/gdata/services/documents/gdata-documents-service.h b/gdata/services/documents/gdata-documents-service.h
index df6e1a8..9f0b83c 100644
--- a/gdata/services/documents/gdata-documents-service.h
+++ b/gdata/services/documents/gdata-documents-service.h
@@ -115,6 +115,13 @@ GDataUploadStream *gdata_documents_service_update_document_resumable (GDataDocum
GDataDocumentsDocument *gdata_documents_service_finish_upload (GDataDocumentsService *self, GDataUploadStream *upload_stream,
GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+GDataDocumentsDocument *gdata_documents_service_copy_document (GDataDocumentsService *self, GDataDocumentsDocument *document,
+ GCancellable *cancellable, GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+void gdata_documents_service_copy_document_async (GDataDocumentsService *self, GDataDocumentsDocument *document, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data);
+GDataDocumentsDocument *gdata_documents_service_copy_document_finish (GDataDocumentsService *self, GAsyncResult *async_result,
+ GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+
GDataDocumentsEntry *gdata_documents_service_add_entry_to_folder (GDataDocumentsService *self, GDataDocumentsEntry *entry,
GDataDocumentsFolder *folder, GCancellable *cancellable,
GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
diff --git a/gdata/tests/documents.c b/gdata/tests/documents.c
index dabf1e2..46ed8a4 100644
--- a/gdata/tests/documents.c
+++ b/gdata/tests/documents.c
@@ -961,6 +961,46 @@ test_update (UpdateDocumentData *data, gconstpointer _test_params)
}
typedef struct {
+ TempDocumentData parent;
+ GDataDocumentsDocument *new_document;
+} TempCopyDocumentData;
+
+static void
+set_up_copy_document (TempCopyDocumentData *data, gconstpointer service)
+{
+ /* Create a temporary document. */
+ set_up_temp_document_spreadsheet ((TempDocumentData*) data, service);
+
+ data->new_document = NULL;
+}
+
+static void
+tear_down_copy_document (TempCopyDocumentData *data, gconstpointer service)
+{
+ /* Delete the copied document */
+ delete_entry (GDATA_DOCUMENTS_ENTRY (data->new_document), GDATA_SERVICE (service));
+ g_object_unref (data->new_document);
+
+ /* Delete the folder */
+ tear_down_temp_document ((TempDocumentData*) data, service);
+}
+
+static void
+test_copy_document (TempCopyDocumentData *data, gconstpointer service)
+{
+ GError *error = NULL;
+
+ /* Copy the document */
+ data->new_document = gdata_documents_service_copy_document (GDATA_DOCUMENTS_SERVICE (service), data->parent.document, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (GDATA_IS_DOCUMENTS_SPREADSHEET (data->new_document));
+
+ /* Check their IDs are different but that their other properties (e.g. title) are the same. */
+ g_assert_cmpstr (gdata_entry_get_id (GDATA_ENTRY (data->parent.document)), !=, gdata_entry_get_id (GDATA_ENTRY (data->new_document)));
+ g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (data->parent.document)), ==, gdata_entry_get_title (GDATA_ENTRY (data->new_document)));
+}
+
+typedef struct {
GDataDocumentsFolder *folder;
GDataDocumentsDocument *document;
} FoldersData;
@@ -1746,6 +1786,12 @@ main (int argc, char *argv[])
g_test_add ("/documents/query/all_documents/async/cancellation", GDataAsyncTestData, service, set_up_temp_documents_async,
test_query_all_documents_async_cancellation, tear_down_temp_documents_async);
+ g_test_add ("/documents/copy", TempCopyDocumentData, service, set_up_copy_document, test_copy_document, tear_down_copy_document);
+ /*g_test_add ("/documents/copy/async", GDataAsyncTestData, service, set_up_folders_add_to_folder_async,
+ test_folders_add_to_folder_async, tear_down_folders_add_to_folder_async);
+ g_test_add ("/documents/copy/async/cancellation", GDataAsyncTestData, service, set_up_folders_add_to_folder_async,
+ test_folders_add_to_folder_async_cancellation, tear_down_folders_add_to_folder_async);*/
+
g_test_add ("/documents/folders/add_to_folder", FoldersData, service, set_up_folders_add_to_folder,
test_folders_add_to_folder, tear_down_folders_add_to_folder);
g_test_add ("/documents/folders/add_to_folder/async", GDataAsyncTestData, service, set_up_folders_add_to_folder_async,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]