/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/*
* GData Client
* Copyright (C) Richard Schwarting 2009 <aquarichy@gmail.com>
* Copyright (C) Philip Withnall 2009–2010 <philip@tecnocode.co.uk>
*
* GData Client is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GData Client is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GData Client. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:gdata-picasaweb-query
* @short_description: GData PicasaWeb query object
* @stability: Stable
* @include: gdata/services/picasaweb/gdata-picasaweb-query.h
*
* #GDataPicasaWebQuery represents a collection of query parameters specific to the Google PicasaWeb service, which go above and beyond
* those catered for by #GDataQuery.
*
* For more information on the custom GData query parameters supported by #GDataPicasaWebQuery, see the <ulink type="http"
* url="http://code.google.com/apis/picasaweb/reference.html#Parameters">online documentation</ulink>.
*
* Since: 0.4.0
*/
#include <config.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <string.h>
#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);
static void gdata_picasaweb_query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
static void get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started);
struct _GDataPicasaWebQueryPrivate {
GDataPicasaWebVisibility visibility;
gchar *thumbnail_size;
gchar *image_size;
gchar *tag;
gchar *location;
struct {
gdouble north;
gdouble east;
gdouble south;
gdouble west;
} bounding_box;
};
enum {
PROP_VISIBILITY = 1,
PROP_THUMBNAIL_SIZE,
PROP_IMAGE_SIZE,
PROP_TAG,
PROP_LOCATION
};
G_DEFINE_TYPE (GDataPicasaWebQuery, gdata_picasaweb_query, GDATA_TYPE_QUERY)
static void
gdata_picasaweb_query_class_init (GDataPicasaWebQueryClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GDataQueryClass *query_class = GDATA_QUERY_CLASS (klass);
g_type_class_add_private (klass, sizeof (GDataPicasaWebQueryPrivate));
gobject_class->get_property = gdata_picasaweb_query_get_property;
gobject_class->set_property = gdata_picasaweb_query_set_property;
gobject_class->finalize = gdata_picasaweb_query_finalize;
query_class->get_query_uri = get_query_uri;
/**
* GDataPicasaWebQuery:visibility:
*
* Specifies which albums should be listed, in terms of their visibility (#GDataPicasaWebAlbum:visibility).
*
* Set the property to <code class="literal">0</code> to list all albums, regardless of their visibility. Otherwise, use values
* from #GDataPicasaWebVisibility.
*
* For more information, see the <ulink type="http" url="http://code.google.com/apis/picasaweb/reference.html#Visibility">
* online documentation</ulink>.
*
* Since: 0.4.0
*/
g_object_class_install_property (gobject_class, PROP_VISIBILITY,
g_param_spec_int ("visibility",
"Visibility", "Specifies which albums should be listed, in terms of their visibility.",
0, GDATA_PICASAWEB_PRIVATE, 0,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GDataPicasaWebQuery:thumbnail-size:
*
* A comma-separated list of thumbnail widths (in pixels) to return. Only certain sizes are allowed, and whether the thumbnail should be
* cropped or scaled can be specified; for more information, see the
* <ulink type="http" url="http://code.google.com/apis/picasaweb/reference.html#Parameters">online documentation</ulink>.
*
* Since: 0.4.0
*/
g_object_class_install_property (gobject_class, PROP_THUMBNAIL_SIZE,
g_param_spec_string ("thumbnail-size",
"Thumbnail size", "A comma-separated list of thumbnail width (in pixels) to return.",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GDataPicasaWebQuery:image-size:
*
* A comma-separated list of image sizes (width in pixels) to return. Only certain sizes are allowed, and whether the image should be
* cropped or scaled can be specified; for more information, see the
* <ulink type="http" url="http://code.google.com/apis/picasaweb/reference.html#Parameters">online documentation</ulink>.
*
* Since: 0.4.0
*/
g_object_class_install_property (gobject_class, PROP_IMAGE_SIZE,
g_param_spec_string ("image-size",
"Image size", "A comma-separated list of image sizes (width in pixels) to return.",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GDataPicasaWebQuery:tag:
*
* A tag which returned results must contain.
*
* Since: 0.4.0
*/
g_object_class_install_property (gobject_class, PROP_TAG,
g_param_spec_string ("tag",
"Tag", "A tag which returned results must contain.",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GDataPicasaWebQuery:location:
*
* A location to search for photos, e.g. "London".
*
* Since: 0.4.0
*/
g_object_class_install_property (gobject_class, PROP_LOCATION,
g_param_spec_string ("location",
"Location", "A location to search for photos, e.g. \"London\".",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
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
gdata_picasaweb_query_finalize (GObject *object)
{
GDataPicasaWebQueryPrivate *priv = GDATA_PICASAWEB_QUERY (object)->priv;
g_free (priv->thumbnail_size);
g_free (priv->image_size);
g_free (priv->tag);
g_free (priv->location);
/* Chain up to the parent class */
G_OBJECT_CLASS (gdata_picasaweb_query_parent_class)->finalize (object);
}
static void
gdata_picasaweb_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
GDataPicasaWebQueryPrivate *priv = GDATA_PICASAWEB_QUERY (object)->priv;
switch (property_id) {
case PROP_VISIBILITY:
g_value_set_int (value, priv->visibility);
break;
case PROP_THUMBNAIL_SIZE:
g_value_set_string (value, priv->thumbnail_size);
break;
case PROP_IMAGE_SIZE:
g_value_set_string (value, priv->image_size);
break;
case PROP_TAG:
g_value_set_string (value, priv->tag);
break;
case PROP_LOCATION:
g_value_set_string (value, priv->location);
break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gdata_picasaweb_query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
GDataPicasaWebQuery *self = GDATA_PICASAWEB_QUERY (object);
switch (property_id) {
case PROP_VISIBILITY:
gdata_picasaweb_query_set_visibility (self, g_value_get_int (value));
break;
case PROP_THUMBNAIL_SIZE:
gdata_picasaweb_query_set_thumbnail_size (self, g_value_get_string (value));
break;
case PROP_IMAGE_SIZE:
gdata_picasaweb_query_set_image_size (self, g_value_get_string (value));
break;
case PROP_TAG:
gdata_picasaweb_query_set_tag (self, g_value_get_string (value));
break;
case PROP_LOCATION:
gdata_picasaweb_query_set_location (self, g_value_get_string (value));
break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started)
{
GDataPicasaWebQueryPrivate *priv = GDATA_PICASAWEB_QUERY (self)->priv;
#define APPEND_SEP g_string_append_c (query_uri, (*params_started == FALSE) ? '?' : '&'); *params_started = TRUE;
/* Chain up to the parent class */
GDATA_QUERY_CLASS (gdata_picasaweb_query_parent_class)->get_query_uri (self, feed_uri, query_uri, params_started);
APPEND_SEP
if (priv->visibility == 0)
; // Appending nothing to retrieve all for authenticated users and just public albums for unauthenticated
else if (priv->visibility == GDATA_PICASAWEB_PUBLIC)
g_string_append (query_uri, "access=public");
else if (priv->visibility == GDATA_PICASAWEB_PRIVATE)
g_string_append (query_uri, "access=private");
else
g_assert_not_reached ();
if (priv->thumbnail_size != NULL) {
APPEND_SEP
g_string_append (query_uri, "thumbsize=");
g_string_append_uri_escaped (query_uri, priv->thumbnail_size, NULL, FALSE);
}
if (priv->image_size != NULL) {
APPEND_SEP
g_string_append (query_uri, "imgmax=");
g_string_append_uri_escaped (query_uri, priv->image_size, NULL, FALSE);
}
if (priv->tag != NULL) {
APPEND_SEP
g_string_append (query_uri, "tag=");
g_string_append_uri_escaped (query_uri, priv->tag, NULL, FALSE);
}
if (priv->bounding_box.north != priv->bounding_box.south && priv->bounding_box.east != priv->bounding_box.west) {
gchar west[G_ASCII_DTOSTR_BUF_SIZE], south[G_ASCII_DTOSTR_BUF_SIZE], east[G_ASCII_DTOSTR_BUF_SIZE], north[G_ASCII_DTOSTR_BUF_SIZE];
APPEND_SEP
g_string_append_printf (query_uri, "bbox=%s,%s,%s,%s",
g_ascii_dtostr (west, sizeof (west), priv->bounding_box.west),
g_ascii_dtostr (south, sizeof (south), priv->bounding_box.south),
g_ascii_dtostr (east, sizeof (east), priv->bounding_box.east),
g_ascii_dtostr (north, sizeof (north), priv->bounding_box.north));
}
if (priv->location != NULL) {
APPEND_SEP
g_string_append (query_uri, "l=");
g_string_append_uri_escaped (query_uri, priv->location, NULL, FALSE);
}
}
/**
* gdata_picasaweb_query_new:
* @q: (allow-none): a query string, or %NULL
*
* Creates a new #GDataPicasaWebQuery with its #GDataQuery:q property set to @q.
*
* Note that when querying for albums with gdata_picasaweb_service_query_all_albums(), the @q parameter cannot be used.
*
* Return value: a new #GDataPicasaWebQuery
*
* Since: 0.4.0
*/
GDataPicasaWebQuery *
gdata_picasaweb_query_new (const gchar *q)
{
return g_object_new (GDATA_TYPE_PICASAWEB_QUERY, "q", q, NULL);
}
/**
* gdata_picasaweb_query_new_with_limits:
* @q: (allow-none): a query string, or %NULL
* @start_index: the index of the first result to include, or <code class="literal">0</code>
* @max_results: the maximum number of results to include, or <code class="literal">0</code>
*
* Creates a #GDataPicasaWebQuery with its #GDataQuery:q property set to @q, returning @max_results starting from the @start_index<!-- -->th result.
*
* Note that when querying for albums with gdata_picasaweb_service_query_all_albums(), the @q parameter cannot be used.
*
* This is useful for paging through results, but the result set between separate queries may change. So, if you use this to
* request the next ten results after a previous query, it may include some of the previously returned results if their order changed, or
* omit ones that would have otherwise been found in a earlier but larger query.
*
* Return value: a new #GDataPicasaWebQuery
*
* Since: 0.6.0
*/
GDataPicasaWebQuery *
gdata_picasaweb_query_new_with_limits (const gchar *q, guint start_index, guint max_results)
{
return g_object_new (GDATA_TYPE_PICASAWEB_QUERY,
"q", q,
"start-index", start_index,
"max-results", max_results,
NULL);
}
/**
* gdata_picasaweb_query_get_visibility:
* @self: a #GDataPicasaWebQuery
*
* Gets the #GDataPicasaWebQuery:visibility property.
*
* Return value: the visibility of the objects to retrieve, or <code class="literal">0</code> to retrieve all objects
*
* Since: 0.4.0
*/
GDataPicasaWebVisibility
gdata_picasaweb_query_get_visibility (GDataPicasaWebQuery *self)
{
g_return_val_if_fail (GDATA_IS_PICASAWEB_QUERY (self), 0);
return self->priv->visibility;
}
/**
* gdata_picasaweb_query_set_visibility:
* @self: a #GDataPicasaWebQuery
* @visibility: the visibility of the objects to retrieve, or <code class="literal">0</code> to retrieve all objects
*
* Sets the #GDataPicasaWebQuery:visibility property to @visibility.
*
* Since: 0.4.0
*/
void
gdata_picasaweb_query_set_visibility (GDataPicasaWebQuery *self, GDataPicasaWebVisibility visibility)
{
g_return_if_fail (GDATA_IS_PICASAWEB_QUERY (self));
self->priv->visibility = visibility;
g_object_notify (G_OBJECT (self), "visibility");
/* Our current ETag will no longer be relevant */
gdata_query_set_etag (GDATA_QUERY (self), NULL);
}
/**
* gdata_picasaweb_query_get_thumbnail_size:
* @self: a #GDataPicasaWebQuery
*
* Gets the #GDataPicasaWebQuery:thumbnail-size property.
*
* Return value: a comma-separated list of thumbnail sizes to retrieve, or %NULL
*
* Since: 0.4.0
*/
const gchar *
gdata_picasaweb_query_get_thumbnail_size (GDataPicasaWebQuery *self)
{
g_return_val_if_fail (GDATA_IS_PICASAWEB_QUERY (self), NULL);
return self->priv->thumbnail_size;
}
/**
* gdata_picasaweb_query_set_thumbnail_size:
* @self: a #GDataPicasaWebQuery
* @thumbnail_size: (allow-none): a comma-separated list of thumbnail sizes to retrieve, or %NULL
*
* Sets the #GDataPicasaWebQuery:thumbnail-size property to @thumbnail_size.
*
* Set @thumbnail_size to %NULL to unset the property.
*
* Since: 0.4.0
*/
void
gdata_picasaweb_query_set_thumbnail_size (GDataPicasaWebQuery *self, const gchar *thumbnail_size)
{
g_return_if_fail (GDATA_IS_PICASAWEB_QUERY (self));
g_free (self->priv->thumbnail_size);
self->priv->thumbnail_size = g_strdup (thumbnail_size);
g_object_notify (G_OBJECT (self), "thumbnail-size");
/* Our current ETag will no longer be relevant */
gdata_query_set_etag (GDATA_QUERY (self), NULL);
}
/**
* gdata_picasaweb_query_get_image_size:
* @self: a #GDataPicasaWebQuery
*
* Gets the #GDataPicasaWebQuery:image-size property.
*
* Return value: the currently set desired image size for retrieval, or %NULL
*
* Since: 0.4.0
*/
const gchar *
gdata_picasaweb_query_get_image_size (GDataPicasaWebQuery *self)
{
g_return_val_if_fail (GDATA_IS_PICASAWEB_QUERY (self), NULL);
return self->priv->image_size;
}
/**
* gdata_picasaweb_query_set_image_size:
* @self: a #GDataPicasaWebQuery
* @image_size: (allow-none): the desired size of the image to be retrieved, or %NULL
*
* Sets the #GDataPicasaWebQuery:image-size property to @image_size.
* Valid sizes are described in the
* <ulink type="http" url="http://code.google.com/apis/picasaweb/docs/2.0/reference.html#Parameters">online documentation</ulink>.
*
* Set @image_size to %NULL to unset the property.
*
* Since: 0.4.0
*/
void
gdata_picasaweb_query_set_image_size (GDataPicasaWebQuery *self, const gchar *image_size)
{
g_return_if_fail (GDATA_IS_PICASAWEB_QUERY (self));
g_free (self->priv->image_size);
self->priv->image_size = g_strdup (image_size);
g_object_notify (G_OBJECT (self), "image-size");
/* Our current ETag will no longer be relevant */
gdata_query_set_etag (GDATA_QUERY (self), NULL);
}
/**
* gdata_picasaweb_query_get_tag:
* @self: a #GDataPicasaWebQuery
*
* Gets the #GDataPicasaWebQuery:tag property.
*
* Return value: a tag which retrieved objects must have, or %NULL
*
* Since: 0.4.0
*/
const gchar *
gdata_picasaweb_query_get_tag (GDataPicasaWebQuery *self)
{
g_return_val_if_fail (GDATA_IS_PICASAWEB_QUERY (self), NULL);
return self->priv->tag;
}
/**
* gdata_picasaweb_query_set_tag:
* @self: a #GDataPicasaWebQuery
* @tag: (allow-none): a tag which retrieved objects must have, or %NULL
*
* Sets the #GDataPicasaWebQuery:tag property to @tag.
*
* Set @tag to %NULL to unset the property.
*
* Since: 0.4.0
*/
void
gdata_picasaweb_query_set_tag (GDataPicasaWebQuery *self, const gchar *tag)
{
g_return_if_fail (GDATA_IS_PICASAWEB_QUERY (self));
g_free (self->priv->tag);
self->priv->tag = g_strdup (tag);
g_object_notify (G_OBJECT (self), "tag");
/* Our current ETag will no longer be relevant */
gdata_query_set_etag (GDATA_QUERY (self), NULL);
}
/**
* gdata_picasaweb_query_get_bounding_box:
* @self: a #GDataPicasaWebQuery
* @north: (out caller-allocates) (allow-none): return location for the latitude of the top of the box, or %NULL
* @east: (out caller-allocates) (allow-none): return location for the longitude of the right of the box, or %NULL
* @south: (out caller-allocates) (allow-none): return location for the latitude of the south of the box, or %NULL
* @west: (out caller-allocates) (allow-none): return location for the longitude of the left of the box, or %NULL
*
* Gets the latitudes and longitudes of a bounding box, inside which all the results must lie.
*
* Since: 0.4.0
*/
void
gdata_picasaweb_query_get_bounding_box (GDataPicasaWebQuery *self, gdouble *north, gdouble *east, gdouble *south, gdouble *west)
{
g_return_if_fail (GDATA_IS_PICASAWEB_QUERY (self));
if (north != NULL)
*north = self->priv->bounding_box.north;
if (east != NULL)
*east = self->priv->bounding_box.east;
if (south != NULL)
*south = self->priv->bounding_box.south;
if (west != NULL)
*west = self->priv->bounding_box.west;
}
/**
* gdata_picasaweb_query_set_bounding_box:
* @self: a #GDataPicasaWebQuery
* @north: latitude of the top of the box
* @east: longitude of the right of the box
* @south: latitude of the bottom of the box
* @west: longitude of the left of the box
*
* Sets a bounding box, inside which all the returned results must lie.
*
* Set @north, @east, @south and @west to <code class="literal">0</code> to unset the property.
*
* Since: 0.4.0
*/
void
gdata_picasaweb_query_set_bounding_box (GDataPicasaWebQuery *self, gdouble north, gdouble east, gdouble south, gdouble west)
{
g_return_if_fail (GDATA_IS_PICASAWEB_QUERY (self));
g_return_if_fail (north >= -90.0 && north <= 90.0);
g_return_if_fail (south >= -90.0 && south <= 90.0);
g_return_if_fail (east >= -180.0 && east <= 180.0);
g_return_if_fail (west >= -180.0 && west <= 180.0);
self->priv->bounding_box.north = north;
self->priv->bounding_box.east = east;
self->priv->bounding_box.south = south;
self->priv->bounding_box.west = west;
/* Our current ETag will no longer be relevant */
gdata_query_set_etag (GDATA_QUERY (self), NULL);
}
/**
* gdata_picasaweb_query_get_location:
* @self: a #GDataPicasaWebQuery
*
* Gets the #GDataPicasaWebQuery:location property.
*
* Return value: a location which returned objects must be near, or %NULL
*
* Since: 0.4.0
*/
const gchar *
gdata_picasaweb_query_get_location (GDataPicasaWebQuery *self)
{
g_return_val_if_fail (GDATA_IS_PICASAWEB_QUERY (self), NULL);
return self->priv->location;
}
/**
* gdata_picasaweb_query_set_location:
* @self: a #GDataPicasaWebQuery
* @location: (allow-none): a location which returned objects must be near, or %NULL
*
* Sets the #GDataPicasaWebQuery:location property to @location.
*
* Set @location to %NULL to unset the property.
*
* Since: 0.4.0
*/
void
gdata_picasaweb_query_set_location (GDataPicasaWebQuery *self, const gchar *location)
{
g_return_if_fail (GDATA_IS_PICASAWEB_QUERY (self));
g_free (self->priv->location);
self->priv->location = g_strdup (location);
g_object_notify (G_OBJECT (self), "location");
/* Our current ETag will no longer be relevant */
gdata_query_set_etag (GDATA_QUERY (self), NULL);
}