|
Packit |
4b6dd7 |
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
|
Packit |
4b6dd7 |
/*
|
|
Packit |
4b6dd7 |
* GData Client
|
|
Packit |
4b6dd7 |
* Copyright (C) Philip Withnall 2010 <philip@tecnocode.co.uk>
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* GData Client is free software; you can redistribute it and/or
|
|
Packit |
4b6dd7 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
4b6dd7 |
* License as published by the Free Software Foundation; either
|
|
Packit |
4b6dd7 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* GData Client is distributed in the hope that it will be useful,
|
|
Packit |
4b6dd7 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
4b6dd7 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
4b6dd7 |
* Lesser General Public License for more details.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
4b6dd7 |
* License along with GData Client. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* SECTION:gdata-contacts-group
|
|
Packit |
4b6dd7 |
* @short_description: GData Contacts group object
|
|
Packit |
4b6dd7 |
* @stability: Stable
|
|
Packit |
4b6dd7 |
* @include: gdata/services/contacts/gdata-contacts-group.h
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* #GDataContactsGroup is a subclass of #GDataEntry to represent a group from a Google address book.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more details of Google Contacts' GData API, see the
|
|
Packit |
4b6dd7 |
* <ulink type="http" url="http://code.google.com/apis/contacts/docs/3.0/developers_guide_protocol.html#Groups">online documentation</ulink>.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* The user-set name of the group is stored in the #GDataEntry:title property, retrievable using gdata_entry_get_title(). Note that for system groups
|
|
Packit |
4b6dd7 |
* (see #GDataContactsGroup:system-group-id), this group name is provided by Google, and is not localised. Clients should provide their own localised
|
|
Packit |
4b6dd7 |
* group names for the system groups.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* In addition to all the standard properties available for a group, #GDataContactsGroup supports an additional kind of property: extended
|
|
Packit |
4b6dd7 |
* properties. Extended properties, set with gdata_contacts_group_set_extended_property() and retrieved with
|
|
Packit |
4b6dd7 |
* gdata_contacts_group_get_extended_property(), are provided as a method of storing client-specific data which shouldn't be seen or be editable
|
|
Packit |
4b6dd7 |
* by the user, such as IDs and cache times.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* <example>
|
|
Packit |
4b6dd7 |
* <title>Adding a New Group</title>
|
|
Packit |
4b6dd7 |
* <programlisting>
|
|
Packit |
4b6dd7 |
* GDataContactsService *service;
|
|
Packit |
4b6dd7 |
* GDataContactsGroup *group, *updated_group;
|
|
Packit |
4b6dd7 |
* GDataContactsContact *contact, *updated_contact;
|
|
Packit |
4b6dd7 |
* GError *error = NULL;
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Create a service and return a contact to add to the new group. */
|
|
Packit |
4b6dd7 |
* service = create_contacts_service ();
|
|
Packit |
4b6dd7 |
* contact = query_user_for_contact (service);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Create the new group */
|
|
Packit |
4b6dd7 |
* group = gdata_contacts_group_new (NULL);
|
|
Packit |
4b6dd7 |
* gdata_entry_set_title (GDATA_ENTRY (group), "Group Name");
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Insert the group on the server */
|
|
Packit |
4b6dd7 |
* updated_group = gdata_contacts_service_insert_group (service, group, NULL, &error);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* g_object_unref (group);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* if (error != NULL) {
|
|
Packit |
4b6dd7 |
* g_error ("Error adding a group: %s", error->message);
|
|
Packit |
4b6dd7 |
* g_error_free (error);
|
|
Packit |
4b6dd7 |
* g_object_unref (contact);
|
|
Packit |
4b6dd7 |
* g_object_unref (service);
|
|
Packit |
4b6dd7 |
* return;
|
|
Packit |
4b6dd7 |
* }
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Add the contact to the new group. */
|
|
Packit |
4b6dd7 |
* gdata_contacts_contact_add_group (contact, gdata_entry_get_id (GDATA_ENTRY (updated_group)));
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* g_object_unref (updated_group);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Update the contact on the server */
|
|
Packit |
4b6dd7 |
* updated_contact = GDATA_CONTACTS_CONTACT (gdata_service_update_entry (GDATA_SERVICE (service), GDATA_ENTRY (contact), NULL, &error));
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* g_object_unref (contact);
|
|
Packit |
4b6dd7 |
* g_object_unref (service);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* if (error != NULL) {
|
|
Packit |
4b6dd7 |
* g_error ("Error updating contact: %s", error->message);
|
|
Packit |
4b6dd7 |
* g_error_free (error);
|
|
Packit |
4b6dd7 |
* return;
|
|
Packit |
4b6dd7 |
* }
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Do something with the updated contact, such as update them in the UI, or store their ID for future use. */
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* g_object_unref (updated_contact);
|
|
Packit |
4b6dd7 |
* </programlisting>
|
|
Packit |
4b6dd7 |
* </example>
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
#include <config.h>
|
|
Packit |
4b6dd7 |
#include <glib.h>
|
|
Packit |
4b6dd7 |
#include <glib/gi18n-lib.h>
|
|
Packit |
4b6dd7 |
#include <libxml/parser.h>
|
|
Packit |
4b6dd7 |
#include <string.h>
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
#include "gdata-contacts-group.h"
|
|
Packit |
4b6dd7 |
#include "gdata-parser.h"
|
|
Packit |
4b6dd7 |
#include "gdata-types.h"
|
|
Packit |
4b6dd7 |
#include "gdata-private.h"
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* The maximum number of extended properties the server allows us. See
|
|
Packit |
4b6dd7 |
* http://code.google.com/apis/contacts/docs/3.0/reference.html#ProjectionsAndExtended.
|
|
Packit |
4b6dd7 |
* When updating this, make sure to update the API documentation for gdata_contacts_group_get_extended_property() and
|
|
Packit |
4b6dd7 |
* gdata_contacts_group_set_extended_property(). */
|
|
Packit |
4b6dd7 |
#define MAX_N_EXTENDED_PROPERTIES 10
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static GObject *gdata_contacts_group_constructor (GType type, guint n_construct_params, GObjectConstructParam *construct_params);
|
|
Packit |
4b6dd7 |
static void gdata_contacts_group_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
|
|
Packit |
4b6dd7 |
static void gdata_contacts_group_finalize (GObject *object);
|
|
Packit |
4b6dd7 |
static void get_xml (GDataParsable *parsable, GString *xml_string);
|
|
Packit |
4b6dd7 |
static gboolean parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error);
|
|
Packit |
4b6dd7 |
static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
|
|
Packit |
4b6dd7 |
static gchar *get_entry_uri (const gchar *id) G_GNUC_WARN_UNUSED_RESULT;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
struct _GDataContactsGroupPrivate {
|
|
Packit |
4b6dd7 |
gint64 edited;
|
|
Packit |
4b6dd7 |
GHashTable *extended_properties;
|
|
Packit |
4b6dd7 |
gboolean deleted;
|
|
Packit |
4b6dd7 |
gchar *system_group_id;
|
|
Packit |
4b6dd7 |
};
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
enum {
|
|
Packit |
4b6dd7 |
PROP_EDITED = 1,
|
|
Packit |
4b6dd7 |
PROP_DELETED,
|
|
Packit |
4b6dd7 |
PROP_SYSTEM_GROUP_ID
|
|
Packit |
4b6dd7 |
};
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
G_DEFINE_TYPE (GDataContactsGroup, gdata_contacts_group, GDATA_TYPE_ENTRY)
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
gdata_contacts_group_class_init (GDataContactsGroupClass *klass)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit |
4b6dd7 |
GDataParsableClass *parsable_class = GDATA_PARSABLE_CLASS (klass);
|
|
Packit |
4b6dd7 |
GDataEntryClass *entry_class = GDATA_ENTRY_CLASS (klass);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_type_class_add_private (klass, sizeof (GDataContactsGroupPrivate));
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
gobject_class->constructor = gdata_contacts_group_constructor;
|
|
Packit |
4b6dd7 |
gobject_class->get_property = gdata_contacts_group_get_property;
|
|
Packit |
4b6dd7 |
gobject_class->finalize = gdata_contacts_group_finalize;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
parsable_class->parse_xml = parse_xml;
|
|
Packit |
4b6dd7 |
parsable_class->get_xml = get_xml;
|
|
Packit |
4b6dd7 |
parsable_class->get_namespaces = get_namespaces;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
entry_class->get_entry_uri = get_entry_uri;
|
|
Packit |
4b6dd7 |
entry_class->kind_term = "http://schemas.google.com/contact/2008#group";
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* GDataContactsGroup:edited:
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* The last time the group was edited. If the group has not been edited yet, the content indicates the time it was created.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more information, see the <ulink type="http" url="http://www.atomenabled.org/developers/protocol/#appEdited">
|
|
Packit |
4b6dd7 |
* Atom Publishing Protocol specification</ulink>.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
g_object_class_install_property (gobject_class, PROP_EDITED,
|
|
Packit |
4b6dd7 |
g_param_spec_int64 ("edited",
|
|
Packit |
4b6dd7 |
"Edited", "The last time the group was edited.",
|
|
Packit |
4b6dd7 |
-1, G_MAXINT64, -1,
|
|
Packit |
4b6dd7 |
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* GDataContactsGroup:deleted:
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Whether the entry has been deleted.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
g_object_class_install_property (gobject_class, PROP_DELETED,
|
|
Packit |
4b6dd7 |
g_param_spec_boolean ("deleted",
|
|
Packit |
4b6dd7 |
"Deleted", "Whether the entry has been deleted.",
|
|
Packit |
4b6dd7 |
FALSE,
|
|
Packit |
4b6dd7 |
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* GDataContactsGroup:system-group-id:
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* The system group ID for this group, if it's a system group. If the group is not a system group, this is %NULL. Otherwise, it is one of the
|
|
Packit |
4b6dd7 |
* four system group IDs: %GDATA_CONTACTS_GROUP_CONTACTS, %GDATA_CONTACTS_GROUP_FRIENDS, %GDATA_CONTACTS_GROUP_FAMILY and
|
|
Packit |
4b6dd7 |
* %GDATA_CONTACTS_GROUP_COWORKERS.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* If this is non-%NULL, the group name stored in #GDataEntry:title will not be localised, so clients should provide localised group names of
|
|
Packit |
4b6dd7 |
* their own for each of the system groups. Whether a group is a system group should be detected solely on the basis of the value of this
|
|
Packit |
4b6dd7 |
* property, not by comparing the group name (#GDataEntry:title) or entry ID (#GDataEntry:id). The entry ID is not the same as the system
|
|
Packit |
4b6dd7 |
* group ID.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
g_object_class_install_property (gobject_class, PROP_SYSTEM_GROUP_ID,
|
|
Packit |
4b6dd7 |
g_param_spec_string ("system-group-id",
|
|
Packit |
4b6dd7 |
"System group ID", "The system group ID for this group, if it's a system group.",
|
|
Packit |
4b6dd7 |
NULL,
|
|
Packit |
4b6dd7 |
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void notify_content_cb (GObject *gobject, GParamSpec *pspec, GDataContactsGroup *self);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
notify_title_cb (GObject *gobject, GParamSpec *pspec, GDataContactsGroup *self)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
/* Update GDataEntry:content */
|
|
Packit |
4b6dd7 |
g_signal_handlers_block_by_func (self, notify_content_cb, self);
|
|
Packit |
4b6dd7 |
gdata_entry_set_content (GDATA_ENTRY (self), gdata_entry_get_title (GDATA_ENTRY (self)));
|
|
Packit |
4b6dd7 |
g_signal_handlers_unblock_by_func (self, notify_content_cb, self);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
notify_content_cb (GObject *gobject, GParamSpec *pspec, GDataContactsGroup *self)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
/* Update GDataEntry:title */
|
|
Packit |
4b6dd7 |
g_signal_handlers_block_by_func (self, notify_title_cb, self);
|
|
Packit |
4b6dd7 |
gdata_entry_set_title (GDATA_ENTRY (self), gdata_entry_get_content (GDATA_ENTRY (self)));
|
|
Packit |
4b6dd7 |
g_signal_handlers_unblock_by_func (self, notify_title_cb, self);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
gdata_contacts_group_init (GDataContactsGroup *self)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_CONTACTS_GROUP, GDataContactsGroupPrivate);
|
|
Packit |
4b6dd7 |
self->priv->extended_properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
|
Packit |
4b6dd7 |
self->priv->edited = -1;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Listen to change notifications for the entry's title and content, since they're linked */
|
|
Packit |
4b6dd7 |
g_signal_connect (self, "notify::title", (GCallback) notify_title_cb, self);
|
|
Packit |
4b6dd7 |
g_signal_connect (self, "notify::content", (GCallback) notify_content_cb, self);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static GObject *
|
|
Packit |
4b6dd7 |
gdata_contacts_group_constructor (GType type, guint n_construct_params, GObjectConstructParam *construct_params)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GObject *object;
|
|
Packit |
4b6dd7 |
guint i;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Find the "id" property and ensure it's sane */
|
|
Packit |
4b6dd7 |
for (i = 0; i < n_construct_params; i++) {
|
|
Packit |
4b6dd7 |
GParamSpec *pspec = construct_params[i].pspec;
|
|
Packit |
4b6dd7 |
GValue *value = construct_params[i].value;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
if (strcmp (g_param_spec_get_name (pspec), "id") == 0) {
|
|
Packit |
4b6dd7 |
gchar *base, *id;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
id = g_value_dup_string (value);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Fix the ID to refer to the full projection, rather than the base projection. */
|
|
Packit |
4b6dd7 |
if (id != NULL) {
|
|
Packit |
4b6dd7 |
base = strstr (id, "/base/");
|
|
Packit |
4b6dd7 |
if (base != NULL)
|
|
Packit |
4b6dd7 |
memcpy (base, "/full/", 6);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_value_take_string (value, id);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
break;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Chain up to the parent class */
|
|
Packit |
4b6dd7 |
object = G_OBJECT_CLASS (gdata_contacts_group_parent_class)->constructor (type, n_construct_params, construct_params);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
if (_gdata_parsable_is_constructed_from_xml (GDATA_PARSABLE (object)) == FALSE) {
|
|
Packit |
4b6dd7 |
GDataContactsGroupPrivate *priv = GDATA_CONTACTS_GROUP (object)->priv;
|
|
Packit |
4b6dd7 |
GTimeVal time_val;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause setting it from
|
|
Packit |
4b6dd7 |
* parse_xml() to fail (duplicate element). */
|
|
Packit |
4b6dd7 |
g_get_current_time (&time_val);
|
|
Packit |
4b6dd7 |
priv->edited = time_val.tv_sec;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return object;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
gdata_contacts_group_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GDataContactsGroupPrivate *priv = GDATA_CONTACTS_GROUP (object)->priv;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
switch (property_id) {
|
|
Packit |
4b6dd7 |
case PROP_EDITED:
|
|
Packit |
4b6dd7 |
g_value_set_int64 (value, priv->edited);
|
|
Packit |
4b6dd7 |
break;
|
|
Packit |
4b6dd7 |
case PROP_DELETED:
|
|
Packit |
4b6dd7 |
g_value_set_boolean (value, priv->deleted);
|
|
Packit |
4b6dd7 |
break;
|
|
Packit |
4b6dd7 |
case PROP_SYSTEM_GROUP_ID:
|
|
Packit |
4b6dd7 |
g_value_set_string (value, priv->system_group_id);
|
|
Packit |
4b6dd7 |
break;
|
|
Packit |
4b6dd7 |
default:
|
|
Packit |
4b6dd7 |
/* We don't have any other property... */
|
|
Packit |
4b6dd7 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
Packit |
4b6dd7 |
break;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
gdata_contacts_group_finalize (GObject *object)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GDataContactsGroupPrivate *priv = GDATA_CONTACTS_GROUP (object)->priv;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_hash_table_destroy (priv->extended_properties);
|
|
Packit |
4b6dd7 |
g_free (priv->system_group_id);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Chain up to the parent class */
|
|
Packit |
4b6dd7 |
G_OBJECT_CLASS (gdata_contacts_group_parent_class)->finalize (object);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static gboolean
|
|
Packit |
4b6dd7 |
parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
gboolean success;
|
|
Packit |
4b6dd7 |
GDataContactsGroup *self = GDATA_CONTACTS_GROUP (parsable);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app") == TRUE &&
|
|
Packit |
4b6dd7 |
gdata_parser_int64_time_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
|
|
Packit |
4b6dd7 |
return success;
|
|
Packit |
4b6dd7 |
} else if (gdata_parser_is_namespace (node, "http://www.w3.org/2005/Atom") == TRUE && xmlStrcmp (node->name, (xmlChar*) "id") == 0) {
|
|
Packit |
4b6dd7 |
/* We have to override <id> parsing to fix the projection. Modify it in-place so that the parser in GDataEntry will pick up the
|
|
Packit |
4b6dd7 |
* changes. This fixes bugs caused by referring to contacts by the base projection, rather than the full projection; such as
|
|
Packit |
4b6dd7 |
* http://code.google.com/p/gdata-issues/issues/detail?id=2129. */
|
|
Packit |
4b6dd7 |
gchar *base;
|
|
Packit |
4b6dd7 |
gchar *id = (gchar*) xmlNodeListGetString (doc, node->children, TRUE);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
if (id != NULL) {
|
|
Packit |
4b6dd7 |
base = strstr (id, "/base/");
|
|
Packit |
4b6dd7 |
if (base != NULL) {
|
|
Packit |
4b6dd7 |
memcpy (base, "/full/", 6);
|
|
Packit |
4b6dd7 |
xmlNodeSetContent (node, (xmlChar*) id);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
xmlFree (id);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return GDATA_PARSABLE_CLASS (gdata_contacts_group_parent_class)->parse_xml (parsable, doc, node, user_data, error);
|
|
Packit |
4b6dd7 |
} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005") == TRUE) {
|
|
Packit |
4b6dd7 |
if (xmlStrcmp (node->name, (xmlChar*) "extendedProperty") == 0) {
|
|
Packit |
4b6dd7 |
/* gd:extendedProperty */
|
|
Packit |
4b6dd7 |
xmlChar *name, *value;
|
|
Packit |
4b6dd7 |
xmlBuffer *buffer = NULL;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
name = xmlGetProp (node, (xmlChar*) "name");
|
|
Packit |
4b6dd7 |
if (name == NULL)
|
|
Packit |
4b6dd7 |
return gdata_parser_error_required_property_missing (node, "name", error);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Get either the value property, or the element's content */
|
|
Packit |
4b6dd7 |
value = xmlGetProp (node, (xmlChar*) "value");
|
|
Packit |
4b6dd7 |
if (value == NULL) {
|
|
Packit |
4b6dd7 |
xmlNode *child_node;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Use the element's content instead (arbitrary XML) */
|
|
Packit |
4b6dd7 |
buffer = xmlBufferCreate ();
|
|
Packit |
4b6dd7 |
for (child_node = node->children; child_node != NULL; child_node = child_node->next)
|
|
Packit |
4b6dd7 |
xmlNodeDump (buffer, doc, child_node, 0, 0);
|
|
Packit |
4b6dd7 |
value = (xmlChar*) xmlBufferContent (buffer);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
gdata_contacts_group_set_extended_property (self, (gchar*) name, (gchar*) value);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
xmlFree (name);
|
|
Packit |
4b6dd7 |
if (buffer != NULL)
|
|
Packit |
4b6dd7 |
xmlBufferFree (buffer);
|
|
Packit |
4b6dd7 |
else
|
|
Packit |
4b6dd7 |
xmlFree (value);
|
|
Packit |
4b6dd7 |
} else if (xmlStrcmp (node->name, (xmlChar*) "deleted") == 0) {
|
|
Packit |
4b6dd7 |
/* gd:deleted */
|
|
Packit |
4b6dd7 |
if (self->priv->deleted == TRUE)
|
|
Packit |
4b6dd7 |
return gdata_parser_error_duplicate_element (node, error);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
self->priv->deleted = TRUE;
|
|
Packit |
4b6dd7 |
} else {
|
|
Packit |
4b6dd7 |
return GDATA_PARSABLE_CLASS (gdata_contacts_group_parent_class)->parse_xml (parsable, doc, node, user_data, error);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/contact/2008") == TRUE) {
|
|
Packit |
4b6dd7 |
if (xmlStrcmp (node->name, (xmlChar*) "systemGroup") == 0) {
|
|
Packit |
4b6dd7 |
/* gContact:systemGroup */
|
|
Packit |
4b6dd7 |
xmlChar *value;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
if (self->priv->system_group_id != NULL)
|
|
Packit |
4b6dd7 |
return gdata_parser_error_duplicate_element (node, error);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
value = xmlGetProp (node, (xmlChar*) "id");
|
|
Packit |
4b6dd7 |
if (value == NULL || *value == '\0') {
|
|
Packit |
4b6dd7 |
xmlFree (value);
|
|
Packit |
4b6dd7 |
return gdata_parser_error_required_property_missing (node, "id", error);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
self->priv->system_group_id = (gchar*) value;
|
|
Packit |
4b6dd7 |
} else {
|
|
Packit |
4b6dd7 |
return GDATA_PARSABLE_CLASS (gdata_contacts_group_parent_class)->parse_xml (parsable, doc, node, user_data, error);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
} else {
|
|
Packit |
4b6dd7 |
return GDATA_PARSABLE_CLASS (gdata_contacts_group_parent_class)->parse_xml (parsable, doc, node, user_data, error);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return TRUE;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
get_extended_property_xml_cb (const gchar *name, const gchar *value, GString *xml_string)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
/* Note that the value *isn't* escaped (see http://code.google.com/apis/gdata/docs/2.0/elements.html#gdExtendedProperty) */
|
|
Packit |
4b6dd7 |
gdata_parser_string_append_escaped (xml_string, "<gd:extendedProperty name='", name, "'>");
|
|
Packit |
4b6dd7 |
g_string_append_printf (xml_string, "%s</gd:extendedProperty>", value);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
get_xml (GDataParsable *parsable, GString *xml_string)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GDataContactsGroupPrivate *priv = GDATA_CONTACTS_GROUP (parsable)->priv;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Chain up to the parent class */
|
|
Packit |
4b6dd7 |
GDATA_PARSABLE_CLASS (gdata_contacts_group_parent_class)->get_xml (parsable, xml_string);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Extended properties */
|
|
Packit |
4b6dd7 |
g_hash_table_foreach (priv->extended_properties, (GHFunc) get_extended_property_xml_cb, xml_string);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
/* Chain up to the parent class */
|
|
Packit |
4b6dd7 |
GDATA_PARSABLE_CLASS (gdata_contacts_group_parent_class)->get_namespaces (parsable, namespaces);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_hash_table_insert (namespaces, (gchar*) "gd", (gchar*) "http://schemas.google.com/g/2005");
|
|
Packit |
4b6dd7 |
g_hash_table_insert (namespaces, (gchar*) "gContact", (gchar*) "http://schemas.google.com/contact/2008");
|
|
Packit |
4b6dd7 |
g_hash_table_insert (namespaces, (gchar*) "app", (gchar*) "http://www.w3.org/2007/app");
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static gchar *
|
|
Packit |
4b6dd7 |
get_entry_uri (const gchar *id)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
const gchar *base_pos;
|
|
Packit |
4b6dd7 |
gchar *uri = g_strdup (id);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* The service API sometimes stubbornly insists on using the "base" view instead of the "full" view, which we have to fix, or our extended
|
|
Packit |
4b6dd7 |
* attributes are never visible */
|
|
Packit |
4b6dd7 |
base_pos = strstr (uri, "/base/");
|
|
Packit |
4b6dd7 |
if (base_pos != NULL)
|
|
Packit |
4b6dd7 |
memcpy ((char*) base_pos, "/full/", 6);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return uri;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_group_new:
|
|
Packit |
4b6dd7 |
* @id: (allow-none): the group's ID, or %NULL
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Creates a new #GDataContactsGroup with the given ID and default properties.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: a new #GDataContactsGroup; unref with g_object_unref()
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
GDataContactsGroup *
|
|
Packit |
4b6dd7 |
gdata_contacts_group_new (const gchar *id)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
return GDATA_CONTACTS_GROUP (g_object_new (GDATA_TYPE_CONTACTS_GROUP, "id", id, NULL));
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_group_get_edited:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsGroup
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Gets the #GDataContactsGroup:edited property. If the property is unset, -1 will be returned.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: the UNIX timestamp for the time the file was last edited, or -1
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
gint64
|
|
Packit |
4b6dd7 |
gdata_contacts_group_get_edited (GDataContactsGroup *self)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_GROUP (self), -1);
|
|
Packit |
4b6dd7 |
return self->priv->edited;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_group_get_system_group_id:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsGroup
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Gets the #GDataContactsGroup:system-group-id property. If the group is not a system group, %NULL will be returned.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: the group's system group ID, or %NULL
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
const gchar *
|
|
Packit |
4b6dd7 |
gdata_contacts_group_get_system_group_id (GDataContactsGroup *self)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_GROUP (self), NULL);
|
|
Packit |
4b6dd7 |
return self->priv->system_group_id;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_group_get_extended_property:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsGroup
|
|
Packit |
4b6dd7 |
* @name: the property name; an arbitrary, unique string
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Gets the value of an extended property of the group. Each group can have up to 10 client-set extended properties to store data of the client's
|
|
Packit |
4b6dd7 |
* choosing.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: the property's value, or %NULL
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
const gchar *
|
|
Packit |
4b6dd7 |
gdata_contacts_group_get_extended_property (GDataContactsGroup *self, const gchar *name)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_GROUP (self), NULL);
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (name != NULL && *name != '\0', NULL);
|
|
Packit |
4b6dd7 |
return g_hash_table_lookup (self->priv->extended_properties, name);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_group_get_extended_properties:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsGroup
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Gets the full list of extended properties of the group; a hash table mapping property name to value.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: (transfer none): a #GHashTable of extended properties
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
GHashTable *
|
|
Packit |
4b6dd7 |
gdata_contacts_group_get_extended_properties (GDataContactsGroup *self)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_GROUP (self), NULL);
|
|
Packit |
4b6dd7 |
return self->priv->extended_properties;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_group_set_extended_property:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsGroup
|
|
Packit |
4b6dd7 |
* @name: the property name; an arbitrary, unique string
|
|
Packit |
4b6dd7 |
* @value: (allow-none): the property value, or %NULL
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Sets the value of a group's extended property. Extended property names are unique (but of the client's choosing), and reusing the same property
|
|
Packit |
4b6dd7 |
* name will result in the old value of that property being overwritten.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* To unset a property, set @value to %NULL or an empty string.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* A group may have up to 10 extended properties, and each should be reasonably small (i.e. not a photo or ringtone). For more information, see the
|
|
Packit |
4b6dd7 |
* <ulink type="http" url="http://code.google.com/apis/contacts/docs/2.0/reference.html#ProjectionsAndExtended">online documentation</ulink>.
|
|
Packit |
4b6dd7 |
* %FALSE will be returned if you attempt to add more than 10 extended properties.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: %TRUE if the property was updated or deleted successfully, %FALSE otherwise
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
gboolean
|
|
Packit |
4b6dd7 |
gdata_contacts_group_set_extended_property (GDataContactsGroup *self, const gchar *name, const gchar *value)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GHashTable *extended_properties = self->priv->extended_properties;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_GROUP (self), FALSE);
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (name != NULL && *name != '\0', FALSE);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
if (value == NULL || *value == '\0') {
|
|
Packit |
4b6dd7 |
/* Removing a property */
|
|
Packit |
4b6dd7 |
g_hash_table_remove (extended_properties, name);
|
|
Packit |
4b6dd7 |
return TRUE;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* We can't add more than MAX_N_EXTENDED_PROPERTIES */
|
|
Packit |
4b6dd7 |
if (g_hash_table_lookup (extended_properties, name) == NULL && g_hash_table_size (extended_properties) >= MAX_N_EXTENDED_PROPERTIES)
|
|
Packit |
4b6dd7 |
return FALSE;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Updating an existing property or adding a new one */
|
|
Packit |
4b6dd7 |
g_hash_table_insert (extended_properties, g_strdup (name), g_strdup (value));
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return TRUE;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_group_is_deleted:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsGroup
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Returns whether the group has recently been deleted. This will always return %FALSE unless #GDataContactsQuery:show-deleted has been set to %TRUE
|
|
Packit |
4b6dd7 |
* for the query which returned the group; then this function will return %TRUE only if the group has been deleted.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* If a group has been deleted, no other information is available about it. This is designed to allow groups to be deleted from local address
|
|
Packit |
4b6dd7 |
* books using incremental updates from the server (e.g. with #GDataQuery:updated-min and #GDataContactsQuery:show-deleted).
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: %TRUE if the group has been deleted, %FALSE otherwise
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
gboolean
|
|
Packit |
4b6dd7 |
gdata_contacts_group_is_deleted (GDataContactsGroup *self)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_GROUP (self), FALSE);
|
|
Packit |
4b6dd7 |
return self->priv->deleted;
|
|
Packit |
4b6dd7 |
}
|