EContact: Added boxed type E_CONTACT_TYPE_ATTR_LIST and e_contact_field_type()
authorTristan Van Berkom <tristanvb@openismus.com>
Fri, 5 Oct 2012 09:35:05 +0000 (18:35 +0900)
committerTristan Van Berkom <tristanvb@openismus.com>
Tue, 20 Nov 2012 06:52:12 +0000 (15:52 +0900)
This boxed type is used in place of pointer types for properties
installed on EContact which are returned lists of strings.

This does not effect the behavior of e_contact_set()/e_contact_get(),
only it allows e_contact_field_type() to return a distinct type
for those fields, allowing automated code to introspect those useful
contact field types.

The e_contact_field_type() convenience function is used to fetch the GType
for a given field when used with EContact (this allows more automated
routines to be written for EContactFields).

addressbook/libebook/e-contact.c
addressbook/libebook/e-contact.h

index 0f90212..349dae2 100644 (file)
@@ -390,6 +390,13 @@ e_contact_class_init (EContactClass *class)
                                (field_info[i].read_only ? G_PARAM_READABLE : G_PARAM_READWRITE) |
                                G_PARAM_STATIC_NICK |
                                G_PARAM_STATIC_BLURB);
+               else if (field_info[i].t & E_CONTACT_FIELD_TYPE_MULTI)
+                       pspec = g_param_spec_boxed (field_info[i].field_name,
+                                                   _(field_info[i].pretty_name),
+                                                   field_info[i].pretty_name,
+                                                   E_TYPE_CONTACT_ATTR_LIST,
+                                                   (field_info[i].read_only ? G_PARAM_READABLE : G_PARAM_READWRITE)
+                                                   | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
                else
                        pspec = g_param_spec_pointer (
                                field_info[i].field_name,
@@ -857,7 +864,7 @@ e_contact_set_property (GObject *object,
        info = &field_info[prop_id];
 
        if (info->t & E_CONTACT_FIELD_TYPE_MULTI) {
-               GList *new_values = g_value_get_pointer (value);
+               GList *new_values = g_value_get_boxed (value);
                GList *l;
 
                /* first we remove all attributes of the type we're
@@ -1308,7 +1315,9 @@ e_contact_get_property (GObject *object,
        info = &field_info[prop_id];
        data = e_contact_get (E_CONTACT (object), prop_id);
 
-       if (info->t & E_CONTACT_FIELD_TYPE_BOOLEAN) {
+       if (info->t & E_CONTACT_FIELD_TYPE_MULTI) {
+               g_value_take_boxed (value, data);
+       } else if (info->t & E_CONTACT_FIELD_TYPE_BOOLEAN) {
                g_value_set_boolean (value, data != NULL);
        } else if (info->t & E_CONTACT_FIELD_TYPE_LIST) {
                g_value_set_pointer (value, data);
@@ -1410,6 +1419,39 @@ e_contact_duplicate (EContact *contact)
 }
 
 /**
+ * e_contact_field_type:
+ * @field_id: an #EContactField
+ *
+ * Gets the #GType used for this contact field, this indicates
+ * what kind of value can be passed to e_contact_set().
+ *
+ * Returns: The #GType used for @field_id, or %G_TYPE_INVALID if it doesn't exist.
+ *
+ * Since: 3.8
+ **/
+GType
+e_contact_field_type (EContactField field_id)
+{
+       GTypeClass  *class;
+       GParamSpec  *pspec;
+       const gchar *field_name;
+       GType       type = G_TYPE_INVALID;
+
+       g_return_val_if_fail (field_id >= 1 && field_id < E_CONTACT_FIELD_LAST, G_TYPE_INVALID);
+
+       field_name = e_contact_field_name (field_id);
+       class      = g_type_class_ref (E_TYPE_CONTACT);
+       pspec      = g_object_class_find_property (G_OBJECT_CLASS (class), field_name);
+
+       if (pspec)
+               type = G_PARAM_SPEC_VALUE_TYPE (pspec);
+
+       g_type_class_unref (class);
+
+       return type;
+}
+
+/**
  * e_contact_field_name:
  * @field_id: an #EContactField
  *
@@ -2548,3 +2590,50 @@ e_contact_cert_copy (EContactCert *cert)
 }
 
 E_CONTACT_DEFINE_BOXED_TYPE (e_contact_cert, "EContactCert")
+
+
+/**
+ * e_contact_attr_list_copy:
+ * @list: A #GList of strings
+ *
+ * Copies a list of allocated strings, specifically
+ * for the #EContactAttrList boxed type used for multi valued
+ * contact fields.
+ *
+ * Returns: (transfer full): A copy of @list
+ *
+ * Since: 3.8
+ */
+GList *
+e_contact_attr_list_copy (GList *list)
+{
+       GList *dup_list = NULL, *l;
+
+       for (l = list; l; l = l->next) {
+               gchar *str = g_strdup ((gchar *)l->data);
+
+               dup_list = g_list_prepend (dup_list, str);
+       }
+
+       return g_list_reverse (dup_list);
+}
+
+/**
+ * e_contact_attr_list_free:
+ * @list: A #GList of strings
+ *
+ * Frees a list of allocated strings, specifically
+ * for the #EContactAttrList boxed type used for multi valued
+ * contact fields.
+ *
+ * Since: 3.8
+ */
+void
+e_contact_attr_list_free (GList *list)
+{
+       g_list_foreach (list, (GFunc)g_free, NULL);
+       g_list_free (list);
+}
+
+typedef GList EContactAttrList;
+G_DEFINE_BOXED_TYPE (EContactAttrList, e_contact_attr_list, e_contact_attr_list_copy, e_contact_attr_list_free);
index 2ee2858..d0ce271 100644 (file)
@@ -31,6 +31,7 @@ G_BEGIN_DECLS
 #define E_TYPE_CONTACT_PHOTO      (e_contact_photo_get_type ())
 #define E_TYPE_CONTACT_CERT       (e_contact_cert_get_type ())
 #define E_TYPE_CONTACT_ADDRESS    (e_contact_address_get_type ())
+#define E_TYPE_CONTACT_ATTR_LIST  (e_contact_attr_list_get_type ())
 
 typedef struct _EContact EContact;
 typedef struct _EContactClass EContactClass;
@@ -368,6 +369,11 @@ EContactAddress *        e_contact_address_new      (void);
 GType                   e_contact_address_get_type (void);
 void                    e_contact_address_free     (EContactAddress *address);
 
+GList                  *e_contact_attr_list_copy     (GList *list);
+void                    e_contact_attr_list_free     (GList *list);
+GType                   e_contact_attr_list_get_type (void);
+
+GType                     e_contact_field_type       (EContactField field_id);
 const gchar *             e_contact_field_name       (EContactField field_id);
 const gchar *             e_contact_pretty_name      (EContactField field_id);
 const gchar *             e_contact_vcard_attribute  (EContactField field_id);