1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * GData Client
4  * Copyright (C) Philip Withnall 2009, 2010, 2017 <philip@tecnocode.co.uk>
5  *
6  * GData Client is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * GData Client is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 /**
21  * SECTION:gdata-calendar-query
22  * @short_description: GData Calendar query object
23  * @stability: Stable
24  * @include: gdata/services/calendar/gdata-calendar-query.h
25  *
26  * #GDataCalendarQuery represents a collection of query parameters specific to the Google Calendar service, which go above and beyond
27  * those catered for by #GDataQuery.
28  *
29  * For more information on the custom GData query parameters supported by #GDataCalendarQuery, see the <ulink type="http"
30  * url="https://developers.google.com/google-apps/calendar/v3/reference/events/list">online
31  * documentation</ulink>.
32  *
33  * <example>
34  * 	<title>Querying for Events</title>
35  * 	<programlisting>
36  *	GDataCalendarService *service;
37  *	GDataCalendarCalendar *calendar;
38  *	GDataCalendarQuery *query;
39  *	GDataFeed *feed;
40  *	GTimeVal current_time;
41  *	GList *i;
42  *	GError *error = NULL;
43  *
44  *	/<!-- -->* Create a service and find a calendar to query in *<!-- -->/
45  *	service = create_calendar_service ();
46  *	calendar = get_calendar (service);
47  *
48  *	/<!-- -->* Create the query to use. We're going to query for events within the next week which match the search term "party",
49  *	 * ordered by last modification time (descending). *<!-- -->/
50  *	g_get_current_time (&current_time);
51  *	query = gdata_calendar_query_new_with_limits ("party", current_time.tv_sec, current_time.tv_sec + 7 * 24 * 60 * 60);
52  *	gdata_calendar_query_set_order_by (query, "lastmodified");
53  *
54  *	/<!-- -->* Execute the query *<!-- -->/
55  *	feed = gdata_calendar_service_query_events (service, calendar, query, NULL, NULL, NULL, &error);
56  *
57  *	g_object_unref (query);
58  *	g_object_unref (calendar);
59  *	g_object_unref (service);
60  *
61  *	if (error != NULL) {
62  *		g_error ("Error querying for events: %s", error->message);
63  *		g_error_free (error);
64  *		return;
65  *	}
66  *
67  *	/<!-- -->* Iterate through the returned events and do something with them *<!-- -->/
68  *	for (i = gdata_feed_get_entries (feed); i != NULL; i = i->next) {
69  *		GDataCalendarEvent *event = GDATA_CALENDAR_EVENT (i->data);
70  *
71  *		/<!-- -->* Do something with the event here, such as insert it into a UI *<!-- -->/
72  *	}
73  *
74  *	g_object_unref (feed);
75  * 	</programlisting>
76  * </example>
77  */
78 
79 #include <config.h>
80 #include <glib.h>
81 #include <glib/gi18n-lib.h>
82 #include <string.h>
83 
84 #include "gdata-calendar-query.h"
85 #include "gdata-query.h"
86 #include "gdata-parser.h"
87 #include "gdata-private.h"
88 
89 static void gdata_calendar_query_finalize (GObject *object);
90 static void gdata_calendar_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
91 static void gdata_calendar_query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
92 static void get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started);
93 
94 struct _GDataCalendarQueryPrivate {
95 	gboolean future_events;
96 	gchar *order_by; /* TODO: #defined values */
97 	gint64 recurrence_expansion_start;
98 	gint64 recurrence_expansion_end;
99 	gboolean single_events;
100 	gchar *sort_order; /* TODO: #defined values */
101 	gint64 start_min;  /* UNIX timestamp, seconds */
102 	gint64 start_max;  /* UNIX timestamp, seconds */
103 	gchar *timezone;
104 	guint max_attendees;
105 	gboolean show_deleted;
106 };
107 
108 enum {
109 	PROP_FUTURE_EVENTS = 1,
110 	PROP_ORDER_BY,
111 	PROP_RECURRENCE_EXPANSION_START,
112 	PROP_RECURRENCE_EXPANSION_END,
113 	PROP_SINGLE_EVENTS,
114 	PROP_SORT_ORDER,
115 	PROP_START_MIN,
116 	PROP_START_MAX,
117 	PROP_TIMEZONE,
118 	PROP_MAX_ATTENDEES,
119 	PROP_SHOW_DELETED,
120 };
121 
G_DEFINE_TYPE(GDataCalendarQuery,gdata_calendar_query,GDATA_TYPE_QUERY)122 G_DEFINE_TYPE (GDataCalendarQuery, gdata_calendar_query, GDATA_TYPE_QUERY)
123 
124 static void
125 gdata_calendar_query_class_init (GDataCalendarQueryClass *klass)
126 {
127 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
128 	GDataQueryClass *query_class = GDATA_QUERY_CLASS (klass);
129 
130 	g_type_class_add_private (klass, sizeof (GDataCalendarQueryPrivate));
131 
132 	gobject_class->set_property = gdata_calendar_query_set_property;
133 	gobject_class->get_property = gdata_calendar_query_get_property;
134 	gobject_class->finalize = gdata_calendar_query_finalize;
135 
136 	query_class->get_query_uri = get_query_uri;
137 
138 	/**
139 	 * GDataCalendarQuery:future-events:
140 	 *
141 	 * A shortcut to request all events scheduled for the future. Overrides the
142 	 * #GDataCalendarQuery:recurrence-expansion-start, #GDataCalendarQuery:recurrence-expansion-end,
143 	 * #GDataCalendarQuery:start-min and #GDataCalendarQuery:start-max properties.
144 	 */
145 	g_object_class_install_property (gobject_class, PROP_FUTURE_EVENTS,
146 	                                 g_param_spec_boolean ("future-events",
147 	                                                       "Future events?", "A shortcut to request all events scheduled for the future.",
148 	                                                       FALSE,
149 	                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
150 
151 	/**
152 	 * GDataCalendarQuery:order-by:
153 	 *
154 	 * Specifies order of entries in a feed. Supported values are <literal>lastmodified</literal> and
155 	 * <literal>starttime</literal>.
156 	 */
157 	g_object_class_install_property (gobject_class, PROP_ORDER_BY,
158 	                                 g_param_spec_string ("order-by",
159 	                                                      "Order by", "Specifies order of entries in a feed.",
160 	                                                      NULL,
161 	                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
162 
163 	/**
164 	 * GDataCalendarQuery:recurrence-expansion-start:
165 	 *
166 	 * Specifies the beginning of the time period to expand recurring events for, inclusive.
167 	 *
168 	 * Deprecated: 0.17.7: Use #GDataCalendarQuery:single-events instead, as this is no longer supported on the server.
169 	 */
170 	g_object_class_install_property (gobject_class, PROP_RECURRENCE_EXPANSION_START,
171 	                                 g_param_spec_int64 ("recurrence-expansion-start",
172 	                                                     "Recurrence expansion start", "Specifies start of period to expand recurrences for.",
173 	                                                     -1, G_MAXINT64, -1,
174 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
175 
176 	/**
177 	 * GDataCalendarQuery:recurrence-expansion-end:
178 	 *
179 	 * Specifies the end of the time period to expand recurring events for, exclusive.
180 	 *
181 	 * Deprecated: 0.17.7: Use #GDataCalendarQuery:single-events instead, as this is no longer supported on the server.
182 	 */
183 	g_object_class_install_property (gobject_class, PROP_RECURRENCE_EXPANSION_END,
184 	                                 g_param_spec_int64 ("recurrence-expansion-end",
185 	                                                     "Recurrence expansion end", "Specifies end of period to expand recurrences for.",
186 	                                                     -1, G_MAXINT64, -1,
187 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
188 
189 	/**
190 	 * GDataCalendarQuery:single-events:
191 	 *
192 	 * Indicates whether recurring events should be expanded or represented as a single event.
193 	 */
194 	g_object_class_install_property (gobject_class, PROP_SINGLE_EVENTS,
195 	                                 g_param_spec_boolean ("single-events",
196 	                                                       "Single events?", "Indicates whether recurring events should be expanded.",
197 	                                                       FALSE,
198 	                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
199 
200 	/**
201 	 * GDataCalendarQuery:sort-order:
202 	 *
203 	 * Specifies direction of sorting. Supported values are <literal>ascending</literal> and
204 	 * <literal>descending</literal>.
205 	 *
206 	 * By default, results are returned in ascending order.
207 	 *
208 	 * Deprecated: 0.17.7: Manually sort the results after retrieving them, as this is no longer supported on the server.
209 	 */
210 	g_object_class_install_property (gobject_class, PROP_SORT_ORDER,
211 	                                 g_param_spec_string ("sort-order",
212 	                                                      "Sort order", "Specifies direction of sorting.",
213 	                                                      NULL,
214 	                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
215 
216 	/**
217 	 * GDataCalendarQuery:start-min:
218 	 *
219 	 * Together with #GDataCalendarQuery:start-max, creates a timespan such that only events within the timespan are returned.
220 	 *
221 	 * #GDataCalendarQuery:start-min is inclusive, while #GDataCalendarQuery:start-max is exclusive. Events that overlap the range are
222 	 * included. Both are specified in seconds since the UNIX epoch.
223 	 *
224 	 * If not specified, the default #GDataCalendarQuery:start-min is <literal>1970-01-01</literal>.
225 	 */
226 	g_object_class_install_property (gobject_class, PROP_START_MIN,
227 	                                 g_param_spec_int64 ("start-min",
228 	                                                     "Start min", "A timespan such that only events within the timespan are returned.",
229 	                                                     -1, G_MAXINT64, -1,
230 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
231 
232 	/**
233 	 * GDataCalendarQuery:start-max:
234 	 *
235 	 * Together with #GDataCalendarQuery:start-min, creates a timespan such that only events within the timespan are returned
236 	 *
237 	 * #GDataCalendarQuery:start-min is inclusive, while #GDataCalendarQuery:start-max is exclusive. Events that overlap the range are
238 	 * included. Both are specified in seconds since the UNIX epoch.
239 	 *
240 	 * If not specified, the default #GDataCalendarQuery:start-max is <literal>2031-01-01</literal>.
241 	 */
242 	g_object_class_install_property (gobject_class, PROP_START_MAX,
243 	                                 g_param_spec_int64 ("start-max",
244 	                                                     "Start max", "A timespan such that only events within the timespan are returned.",
245 	                                                     -1, G_MAXINT64, -1,
246 	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
247 
248 	/**
249 	 * GDataCalendarQuery:timezone:
250 	 *
251 	 * The current timezone. If this is not specified, all times are returned in UTC.
252 	 *
253 	 * Since: 0.2.0
254 	 */
255 	g_object_class_install_property (gobject_class, PROP_TIMEZONE,
256 	                                 g_param_spec_string ("timezone",
257 	                                                      "Timezone", "The current timezone.",
258 	                                                      NULL,
259 	                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
260 
261 	/**
262 	 * GDataCalendarQuery:max-attendees:
263 	 *
264 	 * Specifies the maximum number of attendees to list for an event. If the actual number of attendees for an event is greater than this value,
265 	 * only the current user and the event organiser are listed.
266 	 *
267 	 * Since: 0.9.1
268 	 */
269 	g_object_class_install_property (gobject_class, PROP_MAX_ATTENDEES,
270 	                                 g_param_spec_uint ("max-attendees",
271 	                                                    "Max attendee count", "Specifies the maximum number of attendees to list for an event.",
272 	                                                    0, G_MAXUINT, 0,
273 	                                                    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
274 
275 	/**
276 	 * GDataCalendarQuery:show-deleted:
277 	 *
278 	 * Whether to include deleted/cancelled events in the query feed. Deleted events have their #GDataCalendarEvent:status property set to
279 	 * %GDATA_GD_EVENT_STATUS_CANCELED. They do not normally appear in query results.
280 	 *
281 	 * Since: 0.9.1
282 	 */
283 	g_object_class_install_property (gobject_class, PROP_SHOW_DELETED,
284 	                                 g_param_spec_boolean ("show-deleted",
285 	                                                       "Show deleted?", "Whether to include deleted/cancelled events in the query feed.",
286 	                                                       FALSE,
287 	                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
288 }
289 
290 static void
gdata_calendar_query_init(GDataCalendarQuery * self)291 gdata_calendar_query_init (GDataCalendarQuery *self)
292 {
293 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_CALENDAR_QUERY, GDataCalendarQueryPrivate);
294 	self->priv->recurrence_expansion_start = -1;
295 	self->priv->recurrence_expansion_end = -1;
296 	self->priv->start_min = -1;
297 	self->priv->start_max = -1;
298 
299 	_gdata_query_set_pagination_type (GDATA_QUERY (self),
300 	                                  GDATA_QUERY_PAGINATION_TOKENS);
301 }
302 
303 static void
gdata_calendar_query_finalize(GObject * object)304 gdata_calendar_query_finalize (GObject *object)
305 {
306 	GDataCalendarQueryPrivate *priv = GDATA_CALENDAR_QUERY (object)->priv;
307 
308 	g_free (priv->order_by);
309 	g_free (priv->sort_order);
310 	g_free (priv->timezone);
311 
312 	/* Chain up to the parent class */
313 	G_OBJECT_CLASS (gdata_calendar_query_parent_class)->finalize (object);
314 }
315 
316 static void
gdata_calendar_query_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)317 gdata_calendar_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
318 {
319 	GDataCalendarQueryPrivate *priv = GDATA_CALENDAR_QUERY (object)->priv;
320 
321 	switch (property_id) {
322 		case PROP_FUTURE_EVENTS:
323 			g_value_set_boolean (value, priv->future_events);
324 			break;
325 		case PROP_ORDER_BY:
326 			g_value_set_string (value, priv->order_by);
327 			break;
328 		case PROP_RECURRENCE_EXPANSION_START:
329 			g_value_set_int64 (value, priv->recurrence_expansion_start);
330 			break;
331 		case PROP_RECURRENCE_EXPANSION_END:
332 			g_value_set_int64 (value, priv->recurrence_expansion_end);
333 			break;
334 		case PROP_SINGLE_EVENTS:
335 			g_value_set_boolean (value, priv->single_events);
336 			break;
337 		case PROP_SORT_ORDER:
338 			g_value_set_string (value, priv->sort_order);
339 			break;
340 		case PROP_START_MIN:
341 			g_value_set_int64 (value, priv->start_min);
342 			break;
343 		case PROP_START_MAX:
344 			g_value_set_int64 (value, priv->start_max);
345 			break;
346 		case PROP_TIMEZONE:
347 			g_value_set_string (value, priv->timezone);
348 			break;
349 		case PROP_MAX_ATTENDEES:
350 			g_value_set_uint (value, priv->max_attendees);
351 			break;
352 		case PROP_SHOW_DELETED:
353 			g_value_set_boolean (value, priv->show_deleted);
354 			break;
355 		default:
356 			/* We don't have any other property... */
357 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
358 			break;
359 	}
360 }
361 
362 static void
gdata_calendar_query_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)363 gdata_calendar_query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
364 {
365 	GDataCalendarQuery *self = GDATA_CALENDAR_QUERY (object);
366 
367 	switch (property_id) {
368 		case PROP_FUTURE_EVENTS:
369 			gdata_calendar_query_set_future_events (self, g_value_get_boolean (value));
370 			break;
371 		case PROP_ORDER_BY:
372 			gdata_calendar_query_set_order_by (self, g_value_get_string (value));
373 			break;
374 		case PROP_RECURRENCE_EXPANSION_START:
375 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
376 			gdata_calendar_query_set_recurrence_expansion_start (self, g_value_get_int64 (value));
377 G_GNUC_END_IGNORE_DEPRECATIONS
378 			break;
379 		case PROP_RECURRENCE_EXPANSION_END:
380 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
381 			gdata_calendar_query_set_recurrence_expansion_end (self, g_value_get_int64 (value));
382 G_GNUC_END_IGNORE_DEPRECATIONS
383 			break;
384 		case PROP_SINGLE_EVENTS:
385 			gdata_calendar_query_set_single_events (self, g_value_get_boolean (value));
386 			break;
387 		case PROP_SORT_ORDER:
388 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
389 			gdata_calendar_query_set_sort_order (self, g_value_get_string (value));
390 G_GNUC_END_IGNORE_DEPRECATIONS
391 			break;
392 		case PROP_START_MIN:
393 			gdata_calendar_query_set_start_min (self, g_value_get_int64 (value));
394 			break;
395 		case PROP_START_MAX:
396 			gdata_calendar_query_set_start_max (self, g_value_get_int64 (value));
397 			break;
398 		case PROP_TIMEZONE:
399 			gdata_calendar_query_set_timezone (self, g_value_get_string (value));
400 			break;
401 		case PROP_MAX_ATTENDEES:
402 			gdata_calendar_query_set_max_attendees (self, g_value_get_uint (value));
403 			break;
404 		case PROP_SHOW_DELETED:
405 			gdata_calendar_query_set_show_deleted (self, g_value_get_boolean (value));
406 			break;
407 		default:
408 			/* We don't have any other property... */
409 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
410 			break;
411 	}
412 }
413 
414 /* Convert the v2 order-by values to the v3 orderBy values:
415  *  - https://developers.google.com/google-apps/calendar/v3/reference/events/list#orderBy
416  *  - There is no reference for v2 any more.
417  */
418 static const gchar *
order_by_to_v3(const gchar * order_by)419 order_by_to_v3 (const gchar *order_by)
420 {
421 	if (g_strcmp0 (order_by, "lastmodified") == 0)
422 		return "updated";
423 	else if (g_strcmp0 (order_by, "starttime") == 0)
424 		return "startTime";
425 	else
426 		return order_by;
427 }
428 
429 static void
get_query_uri(GDataQuery * self,const gchar * feed_uri,GString * query_uri,gboolean * params_started)430 get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started)
431 {
432 	GDataCalendarQueryPrivate *priv = GDATA_CALENDAR_QUERY (self)->priv;
433 
434 	#define APPEND_SEP g_string_append_c (query_uri, (*params_started == FALSE) ? '?' : '&'); *params_started = TRUE;
435 
436 	/* Chain up to the parent class */
437 	GDATA_QUERY_CLASS (gdata_calendar_query_parent_class)->get_query_uri (self, feed_uri, query_uri, params_started);
438 
439 	if (gdata_query_get_max_results (GDATA_QUERY (self)) != 0) {
440 		APPEND_SEP
441 		g_string_append_printf (query_uri, "maxResults=%u",
442 		                        gdata_query_get_max_results (GDATA_QUERY (self)));
443 	}
444 
445 	if (priv->order_by != NULL) {
446 		APPEND_SEP
447 		g_string_append (query_uri, "orderBy=");
448 		g_string_append_uri_escaped (query_uri,
449 		                             order_by_to_v3 (priv->order_by), NULL, FALSE);
450 	}
451 
452 	/* Convert the deprecated recurrence-expansion-* properties into single-events. */
453 	APPEND_SEP
454 	if (priv->single_events == TRUE ||
455 	    priv->recurrence_expansion_start >= 0 ||
456 	    priv->recurrence_expansion_end >= 0)
457 		g_string_append (query_uri, "singleEvents=true");
458 	else
459 		g_string_append (query_uri, "singleEvents=false");
460 
461 	if (priv->start_min != -1) {
462 		gchar *start_min;
463 		gint64 start_min_time;
464 
465 		if (priv->future_events)
466 			start_min_time = g_get_real_time () / G_USEC_PER_SEC;
467 		else
468 			start_min_time = priv->start_min;
469 
470 		APPEND_SEP
471 		g_string_append (query_uri, "timeMin=");
472 		start_min = gdata_parser_int64_to_iso8601 (start_min_time);
473 		g_string_append (query_uri, start_min);
474 		g_free (start_min);
475 	}
476 
477 	if (priv->start_max != -1 && !priv->future_events) {
478 		gchar *start_max;
479 
480 		APPEND_SEP
481 		g_string_append (query_uri, "timeMax=");
482 		start_max = gdata_parser_int64_to_iso8601 (priv->start_max);
483 		g_string_append (query_uri, start_max);
484 		g_free (start_max);
485 	}
486 
487 	if (priv->timezone != NULL) {
488 		APPEND_SEP
489 		g_string_append (query_uri, "timeZone=");
490 		g_string_append_uri_escaped (query_uri, priv->timezone, NULL, FALSE);
491 	}
492 
493 	if (priv->max_attendees > 0) {
494 		APPEND_SEP
495 		g_string_append_printf (query_uri, "maxAttendees=%u", priv->max_attendees);
496 	}
497 
498 	APPEND_SEP
499 	if (priv->show_deleted == TRUE) {
500 		g_string_append (query_uri, "showDeleted=true");
501 	} else {
502 		g_string_append (query_uri, "showDeleted=false");
503 	}
504 }
505 
506 /**
507  * gdata_calendar_query_new:
508  * @q: (allow-none): a query string, or %NULL
509  *
510  * Creates a new #GDataCalendarQuery with its #GDataQuery:q property set to @q.
511  *
512  * Return value: a new #GDataCalendarQuery
513  */
514 GDataCalendarQuery *
gdata_calendar_query_new(const gchar * q)515 gdata_calendar_query_new (const gchar *q)
516 {
517 	return g_object_new (GDATA_TYPE_CALENDAR_QUERY, "q", q, NULL);
518 }
519 
520 /**
521  * gdata_calendar_query_new_with_limits:
522  * @q: (allow-none): a query string, or %NULL
523  * @start_min: a starting time for the event period, or -1
524  * @start_max: an ending time for the event period, or -1
525  *
526  * Creates a new #GDataCalendarQuery with its #GDataQuery:q property set to @q, and the time limits @start_min and @start_max
527  * applied (both in seconds since the UNIX epoch).
528  *
529  * Return value: a new #GDataCalendarQuery
530  */
531 GDataCalendarQuery *
gdata_calendar_query_new_with_limits(const gchar * q,gint64 start_min,gint64 start_max)532 gdata_calendar_query_new_with_limits (const gchar *q, gint64 start_min, gint64 start_max)
533 {
534 	return g_object_new (GDATA_TYPE_CALENDAR_QUERY,
535 	                     "q", q,
536 	                     "start-min", start_min,
537 	                     "start-max", start_max,
538 	                     NULL);
539 }
540 
541 /**
542  * gdata_calendar_query_get_future_events:
543  * @self: a #GDataCalendarQuery
544  *
545  * Gets the #GDataCalendarQuery:future-events property.
546  *
547  * Return value: the future events property
548  */
549 gboolean
gdata_calendar_query_get_future_events(GDataCalendarQuery * self)550 gdata_calendar_query_get_future_events (GDataCalendarQuery *self)
551 {
552 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), FALSE);
553 	return self->priv->future_events;
554 }
555 
556 /**
557  * gdata_calendar_query_set_future_events:
558  * @self: a #GDataCalendarQuery
559  * @future_events: %TRUE to unconditionally show future events, %FALSE otherwise
560  *
561  * Sets the #GDataCalendarQuery:future-events property of the #GDataCalendarQuery to @future_events.
562  */
563 void
gdata_calendar_query_set_future_events(GDataCalendarQuery * self,gboolean future_events)564 gdata_calendar_query_set_future_events (GDataCalendarQuery *self, gboolean future_events)
565 {
566 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
567 	self->priv->future_events = future_events;
568 	g_object_notify (G_OBJECT (self), "future-events");
569 
570 	/* Our current ETag will no longer be relevant */
571 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
572 }
573 
574 /**
575  * gdata_calendar_query_get_order_by:
576  * @self: a #GDataCalendarQuery
577  *
578  * Gets the #GDataCalendarQuery:order-by property.
579  *
580  * Return value: the order by property, or %NULL if it is unset
581  */
582 const gchar *
gdata_calendar_query_get_order_by(GDataCalendarQuery * self)583 gdata_calendar_query_get_order_by (GDataCalendarQuery *self)
584 {
585 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), NULL);
586 	return self->priv->order_by;
587 }
588 
589 /**
590  * gdata_calendar_query_set_order_by:
591  * @self: a #GDataCalendarQuery
592  * @order_by: (allow-none): a new order by string, or %NULL
593  *
594  * Sets the #GDataCalendarQuery:order-by property of the #GDataCalendarQuery to the new order by string, @order_by.
595  *
596  * Set @order_by to %NULL to unset the property in the query URI.
597  */
598 void
gdata_calendar_query_set_order_by(GDataCalendarQuery * self,const gchar * order_by)599 gdata_calendar_query_set_order_by (GDataCalendarQuery *self, const gchar *order_by)
600 {
601 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
602 
603 	g_free (self->priv->order_by);
604 	self->priv->order_by = g_strdup (order_by);
605 	g_object_notify (G_OBJECT (self), "order-by");
606 
607 	/* Our current ETag will no longer be relevant */
608 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
609 }
610 
611 /**
612  * gdata_calendar_query_get_recurrence_expansion_start:
613  * @self: a #GDataCalendarQuery
614  *
615  * Gets the #GDataCalendarQuery:recurrence-expansion-start property. If the property is unset, <code class="literal">-1</code> will be returned.
616  *
617  * Return value: the UNIX timestamp for the recurrence-expansion-start property, or <code class="literal">-1</code>
618  * Deprecated: 0.17.7: Use #GDataCalendarQuery:single-events instead, as this is no longer supported on the server.
619  */
620 gint64
gdata_calendar_query_get_recurrence_expansion_start(GDataCalendarQuery * self)621 gdata_calendar_query_get_recurrence_expansion_start (GDataCalendarQuery *self)
622 {
623 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), -1);
624 	return self->priv->recurrence_expansion_start;
625 }
626 
627 /**
628  * gdata_calendar_query_set_recurrence_expansion_start:
629  * @self: a #GDataCalendarQuery
630  * @start: a new start time, or <code class="literal">-1</code>
631  *
632  * Sets the #GDataCalendarQuery:recurrence-expansion-start property of the #GDataCalendarQuery
633  * to the new time/date, @start.
634  *
635  * Set @start to <code class="literal">-1</code> to unset the property in the query URI.
636  *
637  * Deprecated: 0.17.7: Use #GDataCalendarQuery:single-events instead, as this is no longer supported on the server.
638  */
639 void
gdata_calendar_query_set_recurrence_expansion_start(GDataCalendarQuery * self,gint64 start)640 gdata_calendar_query_set_recurrence_expansion_start (GDataCalendarQuery *self, gint64 start)
641 {
642 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
643 	g_return_if_fail (start >= -1);
644 
645 	self->priv->recurrence_expansion_start = start;
646 	g_object_notify (G_OBJECT (self), "recurrence-expansion-start");
647 
648 	/* Our current ETag will no longer be relevant */
649 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
650 }
651 
652 /**
653  * gdata_calendar_query_get_recurrence_expansion_end:
654  * @self: a #GDataCalendarQuery
655  *
656  * Gets the #GDataCalendarQuery:recurrence-expansion-end property. If the property is unset, <code class="literal">-1</code> will be returned.
657  *
658  * Return value: the UNIX timestamp for the recurrence-expansion-end property, or <code class="literal">-1</code>
659  *
660  * Deprecated: 0.17.7: Use #GDataCalendarQuery:single-events instead, as this is no longer supported on the server.
661  */
662 gint64
gdata_calendar_query_get_recurrence_expansion_end(GDataCalendarQuery * self)663 gdata_calendar_query_get_recurrence_expansion_end (GDataCalendarQuery *self)
664 {
665 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), -1	);
666 	return self->priv->recurrence_expansion_end;
667 }
668 
669 /**
670  * gdata_calendar_query_set_recurrence_expansion_end:
671  * @self: a #GDataCalendarQuery
672  * @end: a new end time, or <code class="literal">-1</code>
673  *
674  * Sets the #GDataCalendarQuery:recurrence-expansion-end property of the #GDataCalendarQuery
675  * to the new time/date, @end.
676  *
677  * Set @end to <code class="literal">-1</code> to unset the property in the query URI.
678  *
679  * Deprecated: 0.17.7: Use #GDataCalendarQuery:single-events instead, as this is no longer supported on the server.
680  */
681 void
gdata_calendar_query_set_recurrence_expansion_end(GDataCalendarQuery * self,gint64 end)682 gdata_calendar_query_set_recurrence_expansion_end (GDataCalendarQuery *self, gint64 end)
683 {
684 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
685 	g_return_if_fail (end >= -1);
686 
687 	self->priv->recurrence_expansion_end = end;
688 	g_object_notify (G_OBJECT (self), "recurrence-expansion-end");
689 
690 	/* Our current ETag will no longer be relevant */
691 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
692 }
693 
694 /**
695  * gdata_calendar_query_get_single_events:
696  * @self: a #GDataCalendarQuery
697  *
698  * Gets the #GDataCalendarQuery:single-events property.
699  *
700  * Return value: the single events property
701  */
702 gboolean
gdata_calendar_query_get_single_events(GDataCalendarQuery * self)703 gdata_calendar_query_get_single_events (GDataCalendarQuery *self)
704 {
705 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), FALSE);
706 	return self->priv->single_events;
707 }
708 
709 /**
710  * gdata_calendar_query_set_single_events:
711  * @self: a #GDataCalendarQuery
712  * @single_events: %TRUE to show recurring events as single events, %FALSE otherwise
713  *
714  * Sets the #GDataCalendarQuery:single-events property of the #GDataCalendarQuery to @single_events.
715  */
716 void
gdata_calendar_query_set_single_events(GDataCalendarQuery * self,gboolean single_events)717 gdata_calendar_query_set_single_events (GDataCalendarQuery *self, gboolean single_events)
718 {
719 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
720 	self->priv->single_events = single_events;
721 	g_object_notify (G_OBJECT (self), "single-events");
722 
723 	/* Our current ETag will no longer be relevant */
724 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
725 }
726 
727 /**
728  * gdata_calendar_query_get_sort_order:
729  * @self: a #GDataCalendarQuery
730  *
731  * Gets the #GDataCalendarQuery:sort-order property.
732  *
733  * Return value: the sort order property, or %NULL if it is unset
734  * Deprecated: 0.17.7: Manually sort the results after retrieving them, as this is no longer supported on the server.
735  */
736 const gchar *
gdata_calendar_query_get_sort_order(GDataCalendarQuery * self)737 gdata_calendar_query_get_sort_order (GDataCalendarQuery *self)
738 {
739 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), NULL);
740 	return self->priv->sort_order;
741 }
742 
743 /**
744  * gdata_calendar_query_set_sort_order:
745  * @self: a #GDataCalendarQuery
746  * @sort_order: (allow-none): a new sort order string, or %NULL
747  *
748  * Sets the #GDataCalendarQuery:sort-order property of the #GDataCalendarQuery to the new sort order string, @sort_order.
749  *
750  * Set @sort_order to %NULL to unset the property in the query URI.
751  *
752  * Deprecated: 0.17.7: Manually sort the results after retrieving them, as this is no longer supported on the server.
753  */
754 void
gdata_calendar_query_set_sort_order(GDataCalendarQuery * self,const gchar * sort_order)755 gdata_calendar_query_set_sort_order (GDataCalendarQuery *self, const gchar *sort_order)
756 {
757 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
758 
759 	g_free (self->priv->sort_order);
760 	self->priv->sort_order = g_strdup (sort_order);
761 	g_object_notify (G_OBJECT (self), "sort-order");
762 
763 	/* Our current ETag will no longer be relevant */
764 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
765 }
766 
767 /**
768  * gdata_calendar_query_get_start_min:
769  * @self: a #GDataCalendarQuery
770  *
771  * Gets the #GDataCalendarQuery:start-min property. If the property is unset, <code class="literal">-1</code> will be returned.
772  *
773  * Return value: the UNIX timestamp (in seconds) for the start-min property, or <code class="literal">-1</code>
774  */
775 gint64
gdata_calendar_query_get_start_min(GDataCalendarQuery * self)776 gdata_calendar_query_get_start_min (GDataCalendarQuery *self)
777 {
778 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), -1);
779 	return self->priv->start_min;
780 }
781 
782 /**
783  * gdata_calendar_query_set_start_min:
784  * @self: a #GDataCalendarQuery
785  * @start_min: a new minimum start time (in seconds since the UNIX epoch), or <code class="literal">-1</code>
786  *
787  * Sets the #GDataCalendarQuery:start-min property of the #GDataCalendarQuery
788  * to the new time/date, @start_min.
789  *
790  * Set @start_min to <code class="literal">-1</code> to unset the property in the query URI.
791  */
792 void
gdata_calendar_query_set_start_min(GDataCalendarQuery * self,gint64 start_min)793 gdata_calendar_query_set_start_min (GDataCalendarQuery *self, gint64 start_min)
794 {
795 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
796 	g_return_if_fail (start_min >= -1);
797 
798 	self->priv->start_min = start_min;
799 	g_object_notify (G_OBJECT (self), "start-min");
800 
801 	/* Our current ETag will no longer be relevant */
802 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
803 }
804 
805 /**
806  * gdata_calendar_query_get_start_max:
807  * @self: a #GDataCalendarQuery
808  *
809  * Gets the #GDataCalendarQuery:start-max property. If the property is unset, <code class="literal">-1</code> will be returned.
810  *
811  * Return value: the UNIX timestamp (in seconds) for the start-max property, or <code class="literal">-1</code>
812  */
813 gint64
gdata_calendar_query_get_start_max(GDataCalendarQuery * self)814 gdata_calendar_query_get_start_max (GDataCalendarQuery *self)
815 {
816 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), -1);
817 	return self->priv->start_max;
818 }
819 
820 /**
821  * gdata_calendar_query_set_start_max:
822  * @self: a #GDataCalendarQuery
823  * @start_max: a new maximum start time (in seconds since the UNIX epoch), or <code class="literal">-1</code>
824  *
825  * Sets the #GDataCalendarQuery:start-max property of the #GDataCalendarQuery
826  * to the new time/date, @start_max.
827  *
828  * Set @start_max to <code class="literal">-1</code> to unset the property in the query URI.
829  */
830 void
gdata_calendar_query_set_start_max(GDataCalendarQuery * self,gint64 start_max)831 gdata_calendar_query_set_start_max (GDataCalendarQuery *self, gint64 start_max)
832 {
833 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
834 	g_return_if_fail (start_max >= -1);
835 
836 	self->priv->start_max = start_max;
837 	g_object_notify (G_OBJECT (self), "start-max");
838 
839 	/* Our current ETag will no longer be relevant */
840 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
841 }
842 
843 /**
844  * gdata_calendar_query_get_timezone:
845  * @self: a #GDataCalendarQuery
846  *
847  * Gets the #GDataCalendarQuery:timezone property.
848  *
849  * Return value: the timezone property, or %NULL if it is unset
850  *
851  * Since: 0.2.0
852  */
853 const gchar *
gdata_calendar_query_get_timezone(GDataCalendarQuery * self)854 gdata_calendar_query_get_timezone (GDataCalendarQuery *self)
855 {
856 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), NULL);
857 	return self->priv->timezone;
858 }
859 
860 /**
861  * gdata_calendar_query_set_timezone:
862  * @self: a #GDataCalendarQuery
863  * @_timezone: (allow-none): a new timezone string, or %NULL
864  *
865  * Sets the #GDataCalendarQuery:timezone property of the #GDataCalendarQuery to the new timezone string, @timezone.
866  *
867  * Set @timezone to %NULL to unset the property in the query URI.
868  *
869  * Since: 0.2.0
870  */
871 void
gdata_calendar_query_set_timezone(GDataCalendarQuery * self,const gchar * _timezone)872 gdata_calendar_query_set_timezone (GDataCalendarQuery *self, const gchar *_timezone)
873 {
874 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
875 
876 	g_free (self->priv->timezone);
877 
878 	/* Replace all spaces with underscores */
879 	if (_timezone != NULL) {
880 		gchar *zone, *i;
881 
882 		zone = g_strdup (_timezone);
883 		for (i = zone; *i != '\0'; i++) {
884 			if (*i == ' ')
885 				*i = '_';
886 		}
887 		self->priv->timezone = zone;
888 	} else {
889 		self->priv->timezone = NULL;
890 	}
891 
892 	g_object_notify (G_OBJECT (self), "timezone");
893 
894 	/* Our current ETag will no longer be relevant */
895 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
896 }
897 
898 /**
899  * gdata_calendar_query_get_max_attendees:
900  * @self: a #GDataCalendarQuery
901  *
902  * Gets the #GDataCalendarQuery:max-attendees property. If the property is unset, <code class="literal">0</code> will be returned.
903  *
904  * Return value: the maximum number of attendees, or <code class="literal">0</code>
905  *
906  * Since: 0.9.1
907  */
908 guint
gdata_calendar_query_get_max_attendees(GDataCalendarQuery * self)909 gdata_calendar_query_get_max_attendees (GDataCalendarQuery *self)
910 {
911 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), 0);
912 	return self->priv->max_attendees;
913 }
914 
915 /**
916  * gdata_calendar_query_set_max_attendees:
917  * @self: a #GDataCalendarQuery
918  * @max_attendees: a new maximum attendee count, or <code class="literal">0</code>
919  *
920  * Sets the #GDataCalendarQuery:max-attendees property of the #GDataCalendarQuery to the new value, @max_attendees.
921  *
922  * Set @max_attendees to <code class="literal">0</code> to unset the property in the query URI.
923  *
924  * Since: 0.9.1
925  */
926 void
gdata_calendar_query_set_max_attendees(GDataCalendarQuery * self,guint max_attendees)927 gdata_calendar_query_set_max_attendees (GDataCalendarQuery *self, guint max_attendees)
928 {
929 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
930 
931 	self->priv->max_attendees = max_attendees;
932 	g_object_notify (G_OBJECT (self), "max-attendees");
933 
934 	/* Our current ETag will no longer be relevant */
935 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
936 }
937 
938 /**
939  * gdata_calendar_query_show_deleted:
940  * @self: a #GDataCalendarQuery
941  *
942  * Gets the #GDataCalendarQuery:show-deleted property.
943  *
944  * Return value: %TRUE if deleted/cancelled events should be shown, %FALSE otherwise
945  *
946  * Since: 0.9.1
947  */
948 gboolean
gdata_calendar_query_show_deleted(GDataCalendarQuery * self)949 gdata_calendar_query_show_deleted (GDataCalendarQuery *self)
950 {
951 	g_return_val_if_fail (GDATA_IS_CALENDAR_QUERY (self), FALSE);
952 	return self->priv->show_deleted;
953 }
954 
955 /**
956  * gdata_calendar_query_set_show_deleted:
957  * @self: a #GDataCalendarQuery
958  * @show_deleted: %TRUE to show deleted events, %FALSE otherwise
959  *
960  * Sets the #GDataCalendarQuery:show-deleted property of the #GDataCalendarQuery.
961  *
962  * Since: 0.9.1
963  */
964 void
gdata_calendar_query_set_show_deleted(GDataCalendarQuery * self,gboolean show_deleted)965 gdata_calendar_query_set_show_deleted (GDataCalendarQuery *self, gboolean show_deleted)
966 {
967 	g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
968 
969 	self->priv->show_deleted = show_deleted;
970 	g_object_notify (G_OBJECT (self), "show-deleted");
971 
972 	/* Our current ETag will no longer be relevant */
973 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
974 }
975