summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2016-12-08 14:51:00 +0000
committerPhilip Withnall <philip@tecnocode.co.uk>2017-02-24 23:42:22 +0000
commit38b934a9ef9dab89692d7253dcb332f4ce46f8f0 (patch)
tree51593b37322a1652619579d2f611683053571ff5
parentd9c1e590ac368354c0bf5225d22d3006bf1789da (diff)
downloadlibgdata-38b934a9ef9dab89692d7253dcb332f4ce46f8f0.tar.gz
core: Support pagination using page tokens from JSON
Based on a patch by Milan Crha <mcrha@redhat.com>. This reworks how pagination is implemented so that multiple pagination mechanisms are supported explicitly, making the code a lot clearer. A lot of the new services use pageToken parameters, which we did not previously support — so this fixes support for pagination in the Google Tasks service, for example. This also means that we can drop the hacky pagination support from GDataDocumentsService. https://bugzilla.gnome.org/show_bug.cgi?id=775813
-rw-r--r--docs/reference/gdata-sections.txt1
-rw-r--r--gdata/gdata-core.symbols1
-rw-r--r--gdata/gdata-feed.c47
-rw-r--r--gdata/gdata-feed.h1
-rw-r--r--gdata/gdata-private.h12
-rw-r--r--gdata/gdata-query.c201
-rw-r--r--gdata/gdata-service.c10
-rw-r--r--gdata/services/calendar/gdata-calendar-query.c4
-rw-r--r--gdata/services/contacts/gdata-contacts-query.c5
-rw-r--r--gdata/services/documents/gdata-documents-query.c4
-rw-r--r--gdata/services/documents/gdata-documents-service.c59
-rw-r--r--gdata/services/freebase/gdata-freebase-query.c5
-rw-r--r--gdata/services/picasaweb/gdata-picasaweb-query.c5
-rw-r--r--gdata/services/tasks/gdata-tasks-query.c4
-rw-r--r--gdata/services/youtube/gdata-youtube-query.c5
15 files changed, 245 insertions, 119 deletions
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index 441d67db..04b5e476 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -126,6 +126,7 @@ gdata_feed_get_rights
gdata_feed_get_start_index
gdata_feed_get_total_results
gdata_feed_get_items_per_page
+gdata_feed_get_next_page_token
<SUBSECTION Standard>
GDATA_FEED
GDATA_FEED_CLASS
diff --git a/gdata/gdata-core.symbols b/gdata/gdata-core.symbols
index 7f5da8a5..e8c43777 100644
--- a/gdata/gdata-core.symbols
+++ b/gdata/gdata-core.symbols
@@ -45,6 +45,7 @@ gdata_feed_get_rights
gdata_feed_get_items_per_page
gdata_feed_get_start_index
gdata_feed_get_total_results
+gdata_feed_get_next_page_token
gdata_service_get_type
gdata_service_error_quark
gdata_service_query
diff --git a/gdata/gdata-feed.c b/gdata/gdata-feed.c
index 14fe8a57..9085103c 100644
--- a/gdata/gdata-feed.c
+++ b/gdata/gdata-feed.c
@@ -78,6 +78,7 @@ struct _GDataFeedPrivate {
guint start_index;
guint total_results;
gchar *rights;
+ gchar *next_page_token;
};
enum {
@@ -92,7 +93,8 @@ enum {
PROP_ITEMS_PER_PAGE,
PROP_START_INDEX,
PROP_TOTAL_RESULTS,
- PROP_RIGHTS
+ PROP_RIGHTS,
+ PROP_NEXT_PAGE_TOKEN,
};
G_DEFINE_TYPE (GDataFeed, gdata_feed, GDATA_TYPE_PARSABLE)
@@ -296,6 +298,22 @@ gdata_feed_class_init (GDataFeedClass *klass)
"Total results", "The total number of results in the feed.",
0, 1000000, 0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GDataFeed:next-page-token:
+ *
+ * The next page token for feeds. Pass this to
+ * gdata_query_set_page_token() to advance to the next page when
+ * querying APIs which use page tokens rather than page numbers or
+ * offsets.
+ *
+ * Since: UNRELEASED
+ */
+ g_object_class_install_property (gobject_class, PROP_NEXT_PAGE_TOKEN,
+ g_param_spec_string ("next-page-token",
+ "Next page token", "The next page token for feeds.",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
}
static void
@@ -354,6 +372,7 @@ gdata_feed_finalize (GObject *object)
g_free (priv->logo);
g_free (priv->icon);
g_free (priv->rights);
+ g_free (priv->next_page_token);
/* Chain up to the parent class */
G_OBJECT_CLASS (gdata_feed_parent_class)->finalize (object);
@@ -401,6 +420,9 @@ gdata_feed_get_property (GObject *object, guint property_id, GValue *value, GPar
case PROP_TOTAL_RESULTS:
g_value_set_uint (value, priv->total_results);
break;
+ case PROP_NEXT_PAGE_TOKEN:
+ g_value_set_string (value, priv->next_page_token);
+ break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -643,6 +665,8 @@ parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data, GEr
/* Ignore. */
} else if (g_strcmp0 (json_reader_get_member_name (reader), "etag") == 0) {
GDATA_FEED (parsable)->priv->etag = g_strdup (json_reader_get_string_value (reader));
+ } else if (g_strcmp0 (json_reader_get_member_name (reader), "nextPageToken") == 0) {
+ GDATA_FEED (parsable)->priv->next_page_token = g_strdup (json_reader_get_string_value (reader));
} else {
return GDATA_PARSABLE_CLASS (gdata_feed_parent_class)->parse_json (parsable, reader, user_data, error);
}
@@ -1072,6 +1096,27 @@ gdata_feed_get_total_results (GDataFeed *self)
return self->priv->total_results;
}
+/**
+ * gdata_feed_get_next_page_token:
+ * @self: a #GDataFeed
+ *
+ * Returns the next page token for a query result, or %NULL if not set.
+ * This is #GDataFeed:next-page-token. The page token might not be set if there
+ * is no next page, or if this service does not use token based paging (for
+ * example, if it uses page number or offset based paging instead). Most more
+ * recent services use token based paging.
+ *
+ * Return value: (nullable): the next page token
+ *
+ * Since: UNRELEASED
+ */
+const gchar *
+gdata_feed_get_next_page_token (GDataFeed *self)
+{
+ g_return_val_if_fail (GDATA_IS_FEED (self), NULL);
+ return self->priv->next_page_token;
+}
+
void
_gdata_feed_add_entry (GDataFeed *self, GDataEntry *entry)
{
diff --git a/gdata/gdata-feed.h b/gdata/gdata-feed.h
index 6a1e050a..7bd510b3 100644
--- a/gdata/gdata-feed.h
+++ b/gdata/gdata-feed.h
@@ -90,6 +90,7 @@ guint gdata_feed_get_items_per_page (GDataFeed *self) G_GNUC_PURE;
guint gdata_feed_get_start_index (GDataFeed *self) G_GNUC_PURE;
guint gdata_feed_get_total_results (GDataFeed *self) G_GNUC_PURE;
const gchar *gdata_feed_get_icon (GDataFeed *self) G_GNUC_PURE;
+const gchar *gdata_feed_get_next_page_token (GDataFeed *self) G_GNUC_PURE;
G_END_DECLS
diff --git a/gdata/gdata-private.h b/gdata/gdata-private.h
index ecb4534e..4d65bdd7 100644
--- a/gdata/gdata-private.h
+++ b/gdata/gdata-private.h
@@ -71,13 +71,21 @@ G_GNUC_INTERNAL GDataSecureString _gdata_service_secure_strndup (const gchar *st
G_GNUC_INTERNAL void _gdata_service_secure_strfree (GDataSecureString str);
#include "gdata-query.h"
+typedef enum {
+ GDATA_QUERY_PAGINATION_INDEXED,
+ GDATA_QUERY_PAGINATION_URIS,
+ GDATA_QUERY_PAGINATION_TOKENS,
+} GDataQueryPaginationType;
+
G_GNUC_INTERNAL void _gdata_query_add_q_internal (GDataQuery *self, const gchar *q);
G_GNUC_INTERNAL void _gdata_query_clear_q_internal (GDataQuery *self);
+G_GNUC_INTERNAL void _gdata_query_clear_pagination (GDataQuery *self);
+G_GNUC_INTERNAL void _gdata_query_set_pagination_type (GDataQuery *self,
+ GDataQueryPaginationType type);
+G_GNUC_INTERNAL void _gdata_query_set_next_page_token (GDataQuery *self, const gchar *next_page_token);
G_GNUC_INTERNAL void _gdata_query_set_next_uri (GDataQuery *self, const gchar *next_uri);
-G_GNUC_INTERNAL void _gdata_query_set_next_uri_end (GDataQuery *self);
G_GNUC_INTERNAL gboolean _gdata_query_is_finished (GDataQuery *self);
G_GNUC_INTERNAL void _gdata_query_set_previous_uri (GDataQuery *self, const gchar *previous_uri);
-G_GNUC_INTERNAL void _gdata_query_set_previous_uri_end (GDataQuery *self);
#include "gdata-parsable.h"
G_GNUC_INTERNAL GDataParsable *_gdata_parsable_new_from_xml (GType parsable_type, const gchar *xml, gint length, gpointer user_data,
diff --git a/gdata/gdata-query.c b/gdata/gdata-query.c
index e1f54468..ebddeac2 100644
--- a/gdata/gdata-query.c
+++ b/gdata/gdata-query.c
@@ -68,22 +68,37 @@ struct _GDataQueryPrivate {
gboolean is_strict;
guint max_results;
- /* Pagination management. Supports three states:
- * 1. (next_uri == NULL && !use_next_uri):
- * Implement pagination by incrementing #GDataQuery:start-index
- * internally with each call to gdata_query_next_page(). Stop
- * when the returned #GDataFeed is empty.
- * 2a. (next_uri != NULL && use_next_uri):
- * Implement pagination with an explicit URI for the next page,
- * which will be used when gdata_query_next_page() is called.
- * 2b. (next_uri == NULL && use_next_uri):
- * End of pagination using known URIs; return an empty
- * #GDataFeed when gdata_query_next_page() is called.
+ /* Pagination management. The type of pagination is set as
+ * pagination_type, and should be set in the init() vfunc implementation
+ * of any class derived from GDataQuery. It defaults to
+ * %GDATA_QUERY_PAGINATION_INDEXED, which most subclasses will not want.
+ *
+ * The next_uri, previous_uri or next_page_token are set by
+ * #GDataService if a query returns a new #GDataFeed containing them. If
+ * the user then calls next_page() or previous_page(), use_next_page or
+ * use_previous_page are set as appopriate, and the next call to
+ * get_uri() will return a URI for the next or previous page. This might
+ * be next_uri, previous_uri, or a constructed URI which appends the
+ * next_page_token.
+ *
+ * Note that %GDATA_QUERY_PAGINATION_TOKENS does not support returning
+ * to the previous page.
+ *
+ * It is not invalid to have use_next_page set and to not have a
+ * next_uri for %GDATA_QUERY_PAGINATION_URIS; or to not have a
+ * next_page_token for %GDATA_QUERY_PAGINATION_TOKENS: this signifies
+ * that the current set of results are the last page. There are no
+ * further pages. Similarly for use_previous_page and a %NULL
+ * previous_page.
*/
+ GDataQueryPaginationType pagination_type;
+
gchar *next_uri;
gchar *previous_uri;
- gboolean use_next_uri;
- gboolean use_previous_uri;
+ gchar *next_page_token;
+
+ gboolean use_next_page;
+ gboolean use_previous_page;
gchar *etag;
};
@@ -295,6 +310,8 @@ gdata_query_init (GDataQuery *self)
self->priv->updated_max = -1;
self->priv->published_min = -1;
self->priv->published_max = -1;
+
+ _gdata_query_set_pagination_type (self, GDATA_QUERY_PAGINATION_INDEXED);
}
static void
@@ -309,6 +326,7 @@ gdata_query_finalize (GObject *object)
g_free (priv->next_uri);
g_free (priv->previous_uri);
g_free (priv->etag);
+ g_free (priv->next_page_token);
/* Chain up to the parent class */
G_OBJECT_CLASS (gdata_query_parent_class)->finalize (object);
@@ -490,6 +508,13 @@ get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboo
APPEND_SEP
g_string_append_printf (query_uri, "max-results=%u", priv->max_results);
}
+
+ if (priv->pagination_type == GDATA_QUERY_PAGINATION_TOKENS && priv->use_next_page &&
+ priv->next_page_token != NULL && *priv->next_page_token != '\0') {
+ APPEND_SEP
+ g_string_append (query_uri, "pageToken=");
+ g_string_append_uri_escaped (query_uri, priv->next_page_token, NULL, FALSE);
+ }
}
/**
@@ -550,10 +575,12 @@ gdata_query_get_query_uri (GDataQuery *self, const gchar *feed_uri)
g_return_val_if_fail (feed_uri != NULL, NULL);
/* Check to see if we're paginating first */
- if (self->priv->use_next_uri == TRUE)
- return g_strdup (self->priv->next_uri);
- if (self->priv->use_previous_uri == TRUE)
- return g_strdup (self->priv->previous_uri);
+ if (self->priv->pagination_type == GDATA_QUERY_PAGINATION_URIS) {
+ if (self->priv->use_next_page)
+ return g_strdup (self->priv->next_uri);
+ if (self->priv->use_previous_page)
+ return g_strdup (self->priv->previous_uri);
+ }
klass = GDATA_QUERY_GET_CLASS (self);
g_assert (klass->get_query_uri != NULL);
@@ -1014,24 +1041,60 @@ gdata_query_set_etag (GDataQuery *self, const gchar *etag)
}
void
-_gdata_query_set_next_uri (GDataQuery *self, const gchar *next_uri)
+_gdata_query_clear_pagination (GDataQuery *self)
{
g_return_if_fail (GDATA_IS_QUERY (self));
- g_free (self->priv->next_uri);
- self->priv->next_uri = g_strdup (next_uri);
- self->priv->use_next_uri = FALSE;
- self->priv->use_previous_uri = FALSE;
+
+ switch (self->priv->pagination_type) {
+ case GDATA_QUERY_PAGINATION_INDEXED:
+ /* Nothing to do here: indexes can always be incremented. */
+ break;
+ case GDATA_QUERY_PAGINATION_URIS:
+ g_clear_pointer (&self->priv->next_uri, g_free);
+ g_clear_pointer (&self->priv->previous_uri, g_free);
+ break;
+ case GDATA_QUERY_PAGINATION_TOKENS:
+ g_clear_pointer (&self->priv->next_page_token, g_free);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ self->priv->use_next_page = FALSE;
+ self->priv->use_previous_page = FALSE;
}
void
-_gdata_query_set_next_uri_end (GDataQuery *self)
+_gdata_query_set_pagination_type (GDataQuery *self,
+ GDataQueryPaginationType type)
+{
+ g_debug ("%s: Pagination type set to %u", G_STRFUNC, type);
+
+ _gdata_query_clear_pagination (self);
+ self->priv->pagination_type = type;
+}
+
+void
+_gdata_query_set_next_page_token (GDataQuery *self,
+ const gchar *next_page_token)
{
g_return_if_fail (GDATA_IS_QUERY (self));
+ g_return_if_fail (self->priv->pagination_type ==
+ GDATA_QUERY_PAGINATION_TOKENS);
+
+ g_free (self->priv->next_page_token);
+ self->priv->next_page_token = g_strdup (next_page_token);
+}
+
+void
+_gdata_query_set_next_uri (GDataQuery *self, const gchar *next_uri)
+{
+ g_return_if_fail (GDATA_IS_QUERY (self));
+ g_return_if_fail (self->priv->pagination_type ==
+ GDATA_QUERY_PAGINATION_URIS);
g_free (self->priv->next_uri);
- self->priv->next_uri = NULL;
- self->priv->use_next_uri = TRUE;
- self->priv->use_previous_uri = FALSE;
+ self->priv->next_uri = g_strdup (next_uri);
}
gboolean
@@ -1039,28 +1102,27 @@ _gdata_query_is_finished (GDataQuery *self)
{
g_return_val_if_fail (GDATA_IS_QUERY (self), FALSE);
- return (self->priv->next_uri == NULL && self->priv->use_next_uri);
+ switch (self->priv->pagination_type) {
+ case GDATA_QUERY_PAGINATION_INDEXED:
+ return FALSE;
+ case GDATA_QUERY_PAGINATION_URIS:
+ return (self->priv->next_uri == NULL && self->priv->use_next_page);
+ case GDATA_QUERY_PAGINATION_TOKENS:
+ return (self->priv->next_page_token == NULL && self->priv->use_next_page);
+ default:
+ g_assert_not_reached ();
+ }
}
void
_gdata_query_set_previous_uri (GDataQuery *self, const gchar *previous_uri)
{
g_return_if_fail (GDATA_IS_QUERY (self));
- g_free (self->priv->previous_uri);
- self->priv->previous_uri = g_strdup (previous_uri);
- self->priv->use_next_uri = FALSE;
- self->priv->use_previous_uri = FALSE;
-}
-
-void
-_gdata_query_set_previous_uri_end (GDataQuery *self)
-{
- g_return_if_fail (GDATA_IS_QUERY (self));
+ g_return_if_fail (self->priv->pagination_type ==
+ GDATA_QUERY_PAGINATION_URIS);
g_free (self->priv->previous_uri);
- self->priv->previous_uri = NULL;
- self->priv->use_next_uri = TRUE;
- self->priv->use_previous_uri = FALSE;
+ self->priv->previous_uri = g_strdup (previous_uri);
}
/**
@@ -1082,13 +1144,19 @@ gdata_query_next_page (GDataQuery *self)
g_return_if_fail (GDATA_IS_QUERY (self));
- if (priv->next_uri != NULL) {
- priv->use_next_uri = TRUE;
- priv->use_previous_uri = FALSE;
- } else {
+ switch (self->priv->pagination_type) {
+ case GDATA_QUERY_PAGINATION_INDEXED:
if (priv->start_index == 0)
priv->start_index++;
priv->start_index += priv->max_results;
+ break;
+ case GDATA_QUERY_PAGINATION_URIS:
+ case GDATA_QUERY_PAGINATION_TOKENS:
+ priv->use_next_page = TRUE;
+ priv->use_previous_page = FALSE;
+ break;
+ default:
+ g_assert_not_reached ();
}
/* Our current ETag will no longer be relevant */
@@ -1110,23 +1178,42 @@ gboolean
gdata_query_previous_page (GDataQuery *self)
{
GDataQueryPrivate *priv = self->priv;
+ gboolean retval;
g_return_val_if_fail (GDATA_IS_QUERY (self), FALSE);
- if (priv->previous_uri != NULL) {
- priv->use_previous_uri = TRUE;
- priv->use_next_uri = FALSE;
- } else if (priv->start_index <= priv->max_results ||
- (priv->previous_uri == NULL && priv->use_previous_uri)) {
- return FALSE;
- } else {
- priv->start_index -= priv->max_results;
- if (priv->start_index == 1)
- priv->start_index--;
+ switch (self->priv->pagination_type) {
+ case GDATA_QUERY_PAGINATION_INDEXED:
+ if (priv->start_index <= priv->max_results) {
+ retval = FALSE;
+ } else {
+ priv->start_index -= priv->max_results;
+ if (priv->start_index == 1)
+ priv->start_index--;
+ retval = TRUE;
+ }
+ break;
+ case GDATA_QUERY_PAGINATION_URIS:
+ if (priv->previous_uri != NULL) {
+ priv->use_next_page = FALSE;
+ priv->use_previous_page = TRUE;
+ retval = TRUE;
+ } else {
+ retval = FALSE;
+ }
+ break;
+ case GDATA_QUERY_PAGINATION_TOKENS:
+ /* There are no previous page tokens, unfortunately. */
+ retval = FALSE;
+ break;
+ default:
+ g_assert_not_reached ();
}
- /* Our current ETag will no longer be relevant */
- gdata_query_set_etag (self, NULL);
+ if (retval) {
+ /* Our current ETag will no longer be relevant */
+ gdata_query_set_etag (self, NULL);
+ }
- return TRUE;
+ return retval;
}
diff --git a/gdata/gdata-service.c b/gdata/gdata-service.c
index 1e6feebe..dfc46238 100644
--- a/gdata/gdata-service.c
+++ b/gdata/gdata-service.c
@@ -1035,13 +1035,23 @@ real_parse_feed (GDataService *self,
/* Update the query with the next and previous URIs from the feed */
if (query != NULL && feed != NULL) {
GDataLink *_link;
+ const gchar *token;
+ _gdata_query_clear_pagination (query);
+
+ /* Atom-style next and previous page links. */
_link = gdata_feed_look_up_link (feed, "http://www.iana.org/assignments/relation/next");
if (_link != NULL)
_gdata_query_set_next_uri (query, gdata_link_get_uri (_link));
_link = gdata_feed_look_up_link (feed, "http://www.iana.org/assignments/relation/previous");
if (_link != NULL)
_gdata_query_set_previous_uri (query, gdata_link_get_uri (_link));
+
+ /* JSON-style next page token. (There is no previous page
+ * token.) */
+ token = gdata_feed_get_next_page_token (feed);
+ if (token != NULL)
+ _gdata_query_set_next_page_token (query, token);
}
return feed;
diff --git a/gdata/services/calendar/gdata-calendar-query.c b/gdata/services/calendar/gdata-calendar-query.c
index 89597ae0..ea16dc8a 100644
--- a/gdata/services/calendar/gdata-calendar-query.c
+++ b/gdata/services/calendar/gdata-calendar-query.c
@@ -85,6 +85,7 @@
#include "gdata-calendar-query.h"
#include "gdata-query.h"
#include "gdata-parser.h"
+#include "gdata-private.h"
static void gdata_calendar_query_finalize (GObject *object);
static void gdata_calendar_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
@@ -287,6 +288,9 @@ gdata_calendar_query_init (GDataCalendarQuery *self)
self->priv->recurrence_expansion_end = -1;
self->priv->start_min = -1;
self->priv->start_max = -1;
+
+ _gdata_query_set_pagination_type (GDATA_QUERY (self),
+ GDATA_QUERY_PAGINATION_TOKENS);
}
static void
diff --git a/gdata/services/contacts/gdata-contacts-query.c b/gdata/services/contacts/gdata-contacts-query.c
index 23f40bbf..69c8b0b5 100644
--- a/gdata/services/contacts/gdata-contacts-query.c
+++ b/gdata/services/contacts/gdata-contacts-query.c
@@ -84,6 +84,7 @@
#include "gdata-contacts-query.h"
#include "gdata-query.h"
+#include "gdata-private.h"
static void gdata_contacts_query_finalize (GObject *object);
static void gdata_contacts_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
@@ -180,6 +181,10 @@ static void
gdata_contacts_query_init (GDataContactsQuery *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_CONTACTS_QUERY, GDataContactsQueryPrivate);
+
+ /* https://developers.google.com/google-apps/contacts/v3/reference#contacts-query-parameters-reference */
+ _gdata_query_set_pagination_type (GDATA_QUERY (self),
+ GDATA_QUERY_PAGINATION_INDEXED);
}
static void
diff --git a/gdata/services/documents/gdata-documents-query.c b/gdata/services/documents/gdata-documents-query.c
index 634e7a2e..6070c1b0 100644
--- a/gdata/services/documents/gdata-documents-query.c
+++ b/gdata/services/documents/gdata-documents-query.c
@@ -208,6 +208,10 @@ static void
gdata_documents_query_init (GDataDocumentsQuery *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_DOCUMENTS_QUERY, GDataDocumentsQueryPrivate);
+
+ /* https://developers.google.com/drive/v3/reference/files/list#q */
+ _gdata_query_set_pagination_type (GDATA_QUERY (self),
+ GDATA_QUERY_PAGINATION_TOKENS);
}
static void
diff --git a/gdata/services/documents/gdata-documents-service.c b/gdata/services/documents/gdata-documents-service.c
index 0de0aec6..07c4062c 100644
--- a/gdata/services/documents/gdata-documents-service.c
+++ b/gdata/services/documents/gdata-documents-service.c
@@ -270,17 +270,6 @@ gdata_documents_service_error_quark (void)
static void append_query_headers (GDataService *self, GDataAuthorizationDomain *domain, SoupMessage *message);
static GList *get_authorization_domains (void);
-static GDataFeed *
-parse_feed (GDataService *self,
- GDataAuthorizationDomain *domain,
- GDataQuery *query,
- GType entry_type,
- SoupMessage *message,
- GCancellable *cancellable,
- GDataQueryProgressCallback progress_callback,
- gpointer progress_user_data,
- GError **error);
-
static gchar *_get_upload_uri_for_query_and_folder (GDataDocumentsUploadQuery *query,
GDataDocumentsFolder *folder) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
@@ -296,7 +285,6 @@ gdata_documents_service_class_init (GDataDocumentsServiceClass *klass)
service_class->append_query_headers = append_query_headers;
service_class->get_authorization_domains = get_authorization_domains;
- service_class->parse_feed = parse_feed;
service_class->api_version = "3";
}
@@ -361,53 +349,6 @@ get_authorization_domains (void)
return authorization_domains;
}
-static GDataFeed *
-parse_feed (GDataService *self,
- GDataAuthorizationDomain *domain,
- GDataQuery *query,
- GType entry_type,
- SoupMessage *message,
- GCancellable *cancellable,
- GDataQueryProgressCallback progress_callback,
- gpointer progress_user_data,
- GError **error)
-{
- GDataServiceClass *klass; /* unowned */
- GDataFeed *feed = NULL; /* owned */
-
- klass = GDATA_SERVICE_CLASS (gdata_documents_service_parent_class);
-
- /* Parse the feed. */
- feed = klass->parse_feed (self, domain, query, entry_type, message,
- cancellable, progress_callback,
- progress_user_data, error);
-
- /* Update the query with the next and previous URIs from the feed. If
- * they are not present, we are on the first or final page of the
- * feed. (This behaviour is specific to Google Docs.) */
- if (query != NULL && feed != NULL) {
- GDataLink *_link;
-
- _link = gdata_feed_look_up_link (feed, "http://www.iana.org/assignments/relation/next");
-
- if (_link != NULL) {
- _gdata_query_set_next_uri (query, gdata_link_get_uri (_link));
- } else {
- _gdata_query_set_next_uri_end (query);
- }
-
- _link = gdata_feed_look_up_link (feed, "http://www.iana.org/assignments/relation/previous");
-
- if (_link != NULL) {
- _gdata_query_set_previous_uri (query, gdata_link_get_uri (_link));
- } else {
- _gdata_query_set_previous_uri_end (query);
- }
- }
-
- return feed;
-}
-
/**
* gdata_documents_service_new:
* @authorizer: (allow-none): a #GDataAuthorizer to authorize the service's requests, or %NULL
diff --git a/gdata/services/freebase/gdata-freebase-query.c b/gdata/services/freebase/gdata-freebase-query.c
index 8e66de17..19f0b10b 100644
--- a/gdata/services/freebase/gdata-freebase-query.c
+++ b/gdata/services/freebase/gdata-freebase-query.c
@@ -42,6 +42,7 @@
#include "gdata-freebase-query.h"
#include "gdata-query.h"
#include "gdata-parser.h"
+#include "gdata-private.h"
static void gdata_freebase_query_finalize (GObject *self);
static void gdata_freebase_query_set_property (GObject *self, guint prop_id, const GValue *value, GParamSpec *pspec);
@@ -94,6 +95,10 @@ static void
gdata_freebase_query_init (GDataFreebaseQuery *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_FREEBASE_QUERY, GDataFreebaseQueryPrivate);
+
+ /* https://developers.google.com/freebase/v1/search#cursor */
+ _gdata_query_set_pagination_type (GDATA_QUERY (self),
+ GDATA_QUERY_PAGINATION_INDEXED);
}
static void
diff --git a/gdata/services/picasaweb/gdata-picasaweb-query.c b/gdata/services/picasaweb/gdata-picasaweb-query.c
index d459748f..57851575 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-query.c
+++ b/gdata/services/picasaweb/gdata-picasaweb-query.c
@@ -41,6 +41,7 @@
#include "gdata-picasaweb-query.h"
#include "gdata-query.h"
#include "gdata-picasaweb-enums.h"
+#include "gdata-private.h"
static void gdata_picasaweb_query_finalize (GObject *object);
static void gdata_picasaweb_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
@@ -166,6 +167,10 @@ static void
gdata_picasaweb_query_init (GDataPicasaWebQuery *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_PICASAWEB_QUERY, GDataPicasaWebQueryPrivate);
+
+ /* https://developers.google.com/picasa-web/docs/3.0/reference#Parameters */
+ _gdata_query_set_pagination_type (GDATA_QUERY (self),
+ GDATA_QUERY_PAGINATION_INDEXED);
}
static void
diff --git a/gdata/services/tasks/gdata-tasks-query.c b/gdata/services/tasks/gdata-tasks-query.c
index 9e6dbd95..f5666055 100644
--- a/gdata/services/tasks/gdata-tasks-query.c
+++ b/gdata/services/tasks/gdata-tasks-query.c
@@ -40,6 +40,7 @@
#include "gdata-tasks-query.h"
#include "gdata-query.h"
#include "gdata-parser.h"
+#include "gdata-private.h"
static void gdata_tasks_query_finalize (GObject *object);
static void gdata_tasks_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
@@ -185,6 +186,9 @@ gdata_tasks_query_init (GDataTasksQuery *self)
self->priv->completed_max = -1;
self->priv->due_min = -1;
self->priv->due_max = -1;
+
+ _gdata_query_set_pagination_type (GDATA_QUERY (self),
+ GDATA_QUERY_PAGINATION_TOKENS);
}
static void
diff --git a/gdata/services/youtube/gdata-youtube-query.c b/gdata/services/youtube/gdata-youtube-query.c
index b15d01eb..99ae9961 100644
--- a/gdata/services/youtube/gdata-youtube-query.c
+++ b/gdata/services/youtube/gdata-youtube-query.c
@@ -45,6 +45,7 @@
#include "gdata-youtube-query.h"
#include "gdata-query.h"
#include "gdata-youtube-content.h"
+#include "gdata-private.h"
static void gdata_youtube_query_finalize (GObject *object);
static void gdata_youtube_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
@@ -354,6 +355,10 @@ gdata_youtube_query_init (GDataYouTubeQuery *self)
self->priv->latitude = G_MAXDOUBLE;
self->priv->longitude = G_MAXDOUBLE;
+
+ /* https://developers.google.com/youtube/v3/docs/search/list#pageToken */
+ _gdata_query_set_pagination_type (GDATA_QUERY (self),
+ GDATA_QUERY_PAGINATION_TOKENS);
}
static void