[folks] eds: expose Google system groups in the public API
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks] eds: expose Google system groups in the public API
- Date: Tue, 6 Nov 2012 18:33:24 +0000 (UTC)
commit 49760b614f3dd0202146717765cc67a707cbd473
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Sat Oct 20 16:34:04 2012 +0200
eds: expose Google system groups in the public API
This will allow gnome-contacts to change it directly (to switch a contact
from My Contacts to Other and back)
https://bugzilla.gnome.org/show_bug.cgi?id=687050
backends/eds/lib/edsf-persona-store.vala | 35 ++++++
backends/eds/lib/edsf-persona.vala | 194 +++++++++++++++++++++++++-----
2 files changed, 200 insertions(+), 29 deletions(-)
---
diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala
index 5d96015..68dc6c7 100644
--- a/backends/eds/lib/edsf-persona-store.vala
+++ b/backends/eds/lib/edsf-persona-store.vala
@@ -2046,6 +2046,18 @@ public class Edsf.PersonaStore : Folks.PersonaStore
yield this._commit_modified_property (persona, "groups");
}
+ internal async void _set_system_groups (Edsf.Persona persona,
+ Set<string> system_groups) throws PropertyError
+ {
+ if (!this._is_google_contacts_address_book ())
+ {
+ throw new PropertyError.NOT_WRITEABLE (_("My Contacts is only available for Google Contacts"));
+ }
+
+ this._set_contact_system_groups (persona.contact, system_groups);
+ yield this._commit_modified_property (persona, "system-groups");
+ }
+
private void _set_contact_groups (E.Contact contact, Set<string> groups,
bool is_favourite)
{
@@ -2077,6 +2089,29 @@ public class Edsf.PersonaStore : Folks.PersonaStore
contact.set (ContactField.CATEGORY_LIST, categories);
}
+ private void _set_contact_system_groups (E.Contact contact, Set<string> system_groups)
+ {
+ var vcard = (E.VCard) contact;
+ unowned E.VCardAttribute? prev_attr =
+ vcard.get_attribute ("X-GOOGLE-SYSTEM-GROUP-IDS");
+
+ if (prev_attr != null)
+ contact.remove_attribute (prev_attr);
+
+ E.VCardAttribute new_attr = new E.VCardAttribute ("", "X-GOOGLE-SYSTEM-GROUP-IDS");
+ foreach (var group in system_groups)
+ {
+ if (group == null || group == "")
+ {
+ continue;
+ }
+
+ new_attr.add_value (group);
+ }
+
+ vcard.add_attribute (new_attr);
+ }
+
internal async void _set_gender (Edsf.Persona persona,
Gender gender) throws PropertyError
{
diff --git a/backends/eds/lib/edsf-persona.vala b/backends/eds/lib/edsf-persona.vala
index 64069ed..69fbd95 100644
--- a/backends/eds/lib/edsf-persona.vala
+++ b/backends/eds/lib/edsf-persona.vala
@@ -618,6 +618,80 @@ public class Edsf.Persona : Folks.Persona,
}
/**
+ * Change the contact's system groups.
+ *
+ * The system groups are a property exposed by Google Contacts address books,
+ * and can include any combination of the following identifier:
+ * - "Contacts"
+ * - "Family"
+ * - "Friends"
+ * - "Coworkers"
+ *
+ * Setting the system groups will also change the group membership to include
+ * the localized version of those groups, and may change the value of { link
+ * EdsfPersona.in_google_personal_group}
+ *
+ * Attempting to call this method on a persona beloging to a PersonaStore which
+ * is not Google will throw a PropertyError.
+ *
+ * It's preferred to call this rather than setting { link Persona.system_groups}
+ * directly, as this method gives error notification and will only return once
+ * the groups have been written to the relevant backing store (or the
+ * operation's failed).
+ *
+ * @param system_groups the complete set of system group ids the contact should be a member of
+ * @throws PropertyError if setting the groups failed
+ * @since UNRELEASED
+ */
+ public async void change_system_groups (Set<string> system_groups) throws PropertyError
+ {
+ yield ((Edsf.PersonaStore) this.store)._set_system_groups (this, system_groups);
+ }
+
+ private static const string GOOGLE_PERSONAL_GROUP_NAME = "Contacts";
+
+ /**
+ * Change whether this contact belongs to the personal group or not.
+ *
+ * The personal contact group is a concept that exists only in Google
+ * address books. Other backends will throw a PropertyError.
+ *
+ * It's preferred to call this rather than setting { link Persona.in_google_personal_group}
+ * directly, as this method gives error notification and will only return once
+ * the membership has been written to the relevant backing store (or the
+ * operation's failed).
+ *
+ * @param in_personal Whether to add or remove the personal group membership
+ * @throws PropertyError if the address book is not Google, or if setting the property failed
+ * @since UNRELEASED
+ */
+ public async void change_in_google_personal_group (bool in_personal) throws PropertyError
+ {
+ if (in_personal == this._in_google_personal_group)
+ {
+ return;
+ }
+
+ HashSet<string> new_system_groups = new HashSet<string> ();
+ foreach (var sg in this._system_groups)
+ {
+ if (sg == GOOGLE_PERSONAL_GROUP_NAME && !in_personal)
+ {
+ continue;
+ }
+
+ new_system_groups.add (sg);
+ }
+
+ if (in_personal)
+ {
+ new_system_groups.add (GOOGLE_PERSONAL_GROUP_NAME);
+ }
+
+ yield ((Edsf.PersonaStore) this.store)._set_system_groups (this, new_system_groups);
+ }
+
+ /**
* { inheritDoc}
*
* e-d-s has no equivalent field, so this is unsupported.
@@ -750,9 +824,29 @@ public class Edsf.Persona : Folks.Persona,
yield ((Edsf.PersonaStore) this.store)._set_anti_links (this, anti_links);
}
+ private HashSet<string>? _system_groups = null;
+ private Set<string>? _system_groups_ro = null;
private bool _in_google_personal_group;
/**
+ * The complete set of system group identifiers the contact belongs to.
+ * See { link Persona.change_system_groups} for details.
+ *
+ * @since UNRELEASED
+ */
+ [CCode (notify = false)]
+ public Set<string>? system_groups
+ {
+ get
+ {
+ this._update_groups (true);
+ return this._system_groups_ro;
+ }
+
+ set { this.change_system_groups.begin (value); }
+ }
+
+ /**
* Whether this contact is in the âMy Contactsâ section of the userâs address
* book, rather than the âOtherâ section.
*
@@ -766,6 +860,8 @@ public class Edsf.Persona : Folks.Persona,
this._update_groups (true); /* also checks for the personal group */
return this._in_google_personal_group;
}
+
+ set { this.change_in_google_personal_group.begin (value); }
}
/**
@@ -1603,16 +1699,11 @@ public class Edsf.Persona : Folks.Persona,
}
return;
}
- else if (this._groups == null)
- {
- this._groups = new HashSet<string> ();
- this._groups_ro = this._groups.read_only_view;
- }
var category_names =
this._contact.get<GLib.List<string>> (E.ContactField.CATEGORY_LIST);
var new_categories = new HashSet<string> ();
- var added_categories = new LinkedList<string> ();
+ bool any_added_categories = false;
foreach (var category_name in category_names)
{
@@ -1627,34 +1718,41 @@ public class Edsf.Persona : Folks.Persona,
new_categories.add (category_name);
/* Is this a new category? */
- if (!this._groups.contains (category_name))
+ if (this._groups == null || !this._groups.contains (category_name))
{
- added_categories.add (category_name);
+ any_added_categories = true;
}
}
- /* Work out which categories have been removed. */
- var removed_categories = new LinkedList<string> ();
+ /* Work out if categories have been removed. */
+ bool any_removed_categories = false;
- foreach (var category_name in this._groups)
+ if (this._groups != null)
{
- /* Skip the âStarred in Androidâ group for Google personas; we handle
- * it later. */
- if (((Edsf.PersonaStore) store)._is_google_contacts_address_book () &&
- category_name == Edsf.PersonaStore.android_favourite_group_name)
+ foreach (var category_name in this._groups)
{
- continue;
- }
+ /* Skip the âStarred in Androidâ group for Google personas; we handle
+ * it later. */
+ if (((Edsf.PersonaStore) store)._is_google_contacts_address_book () &&
+ category_name == Edsf.PersonaStore.android_favourite_group_name)
+ {
+ continue;
+ }
- if (!new_categories.contains (category_name))
- {
- removed_categories.add (category_name);
+ if (!new_categories.contains (category_name))
+ {
+ any_removed_categories = true;
+ }
}
}
+ this._groups = new_categories;
+ this._groups_ro = this._groups.read_only_view;
+
/* Check our new set of system groups if this is a Google address book. */
var store = (Edsf.PersonaStore) this.store;
var in_google_personal_group = false;
+ var should_notify_sysgroups = false;
if (store._is_google_contacts_address_book ())
{
@@ -1663,19 +1761,53 @@ public class Edsf.Persona : Folks.Persona,
vcard.get_attribute ("X-GOOGLE-SYSTEM-GROUP-IDS");
if (attr != null)
{
- unowned GLib.List<string> vals = attr.get_values ();
+ unowned GLib.List<string> system_group_ids = attr.get_values();
+ var new_sysgroups = new HashSet<string> ();
+ bool any_added_sysgroups = false;
+
+ foreach (var system_group_id in system_group_ids)
+ {
+ new_sysgroups.add (system_group_id);
+
+ if (this._system_groups == null ||
+ !this._system_groups.contains (system_group_id))
+ {
+ any_added_sysgroups = true;
+ }
+ }
+
+ /* Work out if categories have been removed. */
+ bool any_removed_sysgroups = false;
+
+ if (this._system_groups != null)
+ {
+ foreach (var system_group_id in this._system_groups)
+ {
+ if (!new_sysgroups.contains (system_group_id))
+ {
+ any_removed_sysgroups = true;
+ }
+ }
+ }
/* If we're in the GDATA_CONTACTS_GROUP_CONTACTS group, then
* we're in the user's "My Contacts" address book, as opposed
* to their "Other" address book. */
- foreach (var system_group_id in vals)
+ if (new_sysgroups.contains (GOOGLE_PERSONAL_GROUP_NAME))
{
- if (system_group_id == "Contacts")
- {
- in_google_personal_group = true;
- break;
- }
+ in_google_personal_group = true;
}
+
+ this._system_groups = new_sysgroups;
+ this._system_groups_ro = new_sysgroups.read_only_view;
+
+ if (any_added_sysgroups || any_removed_sysgroups)
+ should_notify_sysgroups = true;
+ }
+ else
+ {
+ this._system_groups = new HashSet<string>();
+ this._system_groups_ro = this._system_groups.read_only_view;
}
}
@@ -1701,11 +1833,15 @@ public class Edsf.Persona : Folks.Persona,
/* Notify if anything's changed. */
this.freeze_notify ();
- if ((added_categories.size != 0 || removed_categories.size != 0) &&
- emit_notification)
+ if ((any_added_categories || any_removed_categories) &&
+ emit_notification)
{
this.notify_property ("groups");
}
+ if (should_notify_sysgroups && emit_notification)
+ {
+ this.notify_property ("system-groups");
+ }
if (this._is_favourite != old_is_favourite && emit_notification)
{
this.notify_property ("is-favourite");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]