diff options
-rw-r--r-- | libempathy-gtk/empathy-cell-renderer-text.c | 33 | ||||
-rw-r--r-- | libempathy-gtk/empathy-contact-list-store.h | 1 | ||||
-rw-r--r-- | libempathy-gtk/empathy-individual-store.c | 44 | ||||
-rw-r--r-- | libempathy-gtk/empathy-individual-store.h | 1 | ||||
-rw-r--r-- | libempathy-gtk/empathy-individual-view.c | 5 | ||||
-rw-r--r-- | libempathy-gtk/empathy-individual-widget.c | 163 | ||||
-rw-r--r-- | libempathy-gtk/empathy-individual-widget.h | 1 | ||||
-rw-r--r-- | libempathy-gtk/empathy-individual-widget.ui | 29 | ||||
-rw-r--r-- | libempathy/empathy-contact.c | 52 | ||||
-rw-r--r-- | libempathy/empathy-contact.h | 1 | ||||
-rw-r--r-- | libempathy/empathy-tp-contact-factory.c | 1 |
11 files changed, 283 insertions, 48 deletions
diff --git a/libempathy-gtk/empathy-cell-renderer-text.c b/libempathy-gtk/empathy-cell-renderer-text.c index f64ee6b0c..22c0e05b3 100644 --- a/libempathy-gtk/empathy-cell-renderer-text.c +++ b/libempathy-gtk/empathy-cell-renderer-text.c @@ -38,6 +38,8 @@ typedef struct { gboolean is_valid; gboolean is_selected; + gchar **types; + gboolean compact; } EmpathyCellRendererTextPriv; @@ -67,7 +69,8 @@ enum { PROP_PRESENCE_TYPE, PROP_STATUS, PROP_IS_GROUP, - PROP_COMPACT + PROP_COMPACT, + PROP_CLIENT_TYPES }; G_DEFINE_TYPE (EmpathyCellRendererText, empathy_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT); @@ -137,6 +140,11 @@ empathy_cell_renderer_text_class_init (EmpathyCellRendererTextClass *klass) FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_COMPACT, spec); + spec = g_param_spec_boxed ("client-types", "Contact client types", + "Client types of the contact", + G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_CLIENT_TYPES, spec); + g_type_class_add_private (object_class, sizeof (EmpathyCellRendererTextPriv)); } @@ -167,6 +175,7 @@ cell_renderer_text_finalize (GObject *object) g_free (priv->name); g_free (priv->status); + g_strfreev (priv->types); (G_OBJECT_CLASS (empathy_cell_renderer_text_parent_class)->finalize) (object); } @@ -199,6 +208,9 @@ cell_renderer_text_get_property (GObject *object, case PROP_COMPACT: g_value_set_boolean (value, priv->compact); break; + case PROP_CLIENT_TYPES: + g_value_set_boxed (value, priv->types); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -245,6 +257,10 @@ cell_renderer_text_set_property (GObject *object, priv->compact = g_value_get_boolean (value); priv->is_valid = FALSE; break; + case PROP_CLIENT_TYPES: + priv->types = g_value_dup_boxed (value); + priv->is_valid = FALSE; + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -282,7 +298,7 @@ cell_renderer_text_update_text (EmpathyCellRendererText *cell, { EmpathyCellRendererTextPriv *priv; PangoAttrList *attr_list; - PangoAttribute *attr_color, *attr_size; + PangoAttribute *attr_color = NULL, *attr_size; GtkStyle *style; gchar *str; @@ -335,15 +351,26 @@ cell_renderer_text_update_text (EmpathyCellRendererText *cell, } } else { const gchar *status = priv->status; + gboolean on_a_phone = FALSE; if (EMP_STR_EMPTY (priv->status)) { status = empathy_presence_get_default_message (priv->presence_type); } + if (!priv->is_group && priv->types != NULL && g_strv_length (priv->types) > 0 + && !tp_strdiff (priv->types[0], "phone")) { + on_a_phone = TRUE; + /* We want the phone black. */ + if (attr_color) + attr_color->start_index += 3; + } + if (status == NULL) str = g_strdup (priv->name); else - str = g_strdup_printf ("%s\n%s", priv->name, status); + str = g_strdup_printf ("%s\n%s%s", priv->name, + on_a_phone ? "☎ " : "", + status); } g_object_set (cell, diff --git a/libempathy-gtk/empathy-contact-list-store.h b/libempathy-gtk/empathy-contact-list-store.h index 1760a0066..b68a274d6 100644 --- a/libempathy-gtk/empathy-contact-list-store.h +++ b/libempathy-gtk/empathy-contact-list-store.h @@ -65,6 +65,7 @@ typedef enum { EMPATHY_CONTACT_LIST_STORE_COL_CAN_VIDEO_CALL, EMPATHY_CONTACT_LIST_STORE_COL_FLAGS, EMPATHY_CONTACT_LIST_STORE_COL_IS_FAKE_GROUP, + EMPATHY_CONTACT_LIST_STORE_COL_CLIENT_TYPES, EMPATHY_CONTACT_LIST_STORE_COL_COUNT, } EmpathyContactListStoreCol; diff --git a/libempathy-gtk/empathy-individual-store.c b/libempathy-gtk/empathy-individual-store.c index 807afb2a2..ce2eacf82 100644 --- a/libempathy-gtk/empathy-individual-store.c +++ b/libempathy-gtk/empathy-individual-store.c @@ -154,6 +154,39 @@ individual_can_audio_video_call (FolksIndividual *individual, *can_video_call = can_video; } +static const gchar * const * +individual_get_client_types (FolksIndividual *individual) +{ + GList *personas, *l; + const gchar * const *types = NULL; + FolksPresenceType presence_type = FOLKS_PRESENCE_TYPE_UNSET; + + personas = folks_individual_get_personas (individual); + for (l = personas; l != NULL; l = l->next) + { + FolksPresence *presence; + + /* We only want personas which implement FolksPresence */ + if (!FOLKS_IS_PRESENCE (l->data)) + continue; + + presence = FOLKS_PRESENCE (l->data); + + if (folks_presence_typecmp (folks_presence_get_presence_type (presence), + presence_type) > 0) + { + TpContact *tp_contact; + + presence_type = folks_presence_get_presence_type (presence); + + tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data)); + types = tp_contact_get_client_types (tp_contact); + } + } + + return types; +} + static void add_individual_to_store (GtkTreeStore *self, GtkTreeIter *iter, @@ -161,10 +194,13 @@ add_individual_to_store (GtkTreeStore *self, FolksIndividual *individual) { gboolean can_audio_call, can_video_call; + const gchar * const *types; individual_can_audio_video_call (individual, &can_audio_call, &can_video_call); + types = individual_get_client_types (individual); + gtk_tree_store_insert_with_values (self, iter, parent, 0, EMPATHY_INDIVIDUAL_STORE_COL_NAME, folks_aliasable_get_alias (FOLKS_ALIASABLE (individual)), @@ -173,6 +209,7 @@ add_individual_to_store (GtkTreeStore *self, EMPATHY_INDIVIDUAL_STORE_COL_IS_SEPARATOR, FALSE, EMPATHY_INDIVIDUAL_STORE_COL_CAN_AUDIO_CALL, can_audio_call, EMPATHY_INDIVIDUAL_STORE_COL_CAN_VIDEO_CALL, can_video_call, + EMPATHY_INDIVIDUAL_STORE_COL_CLIENT_TYPES, types, -1); } @@ -738,10 +775,13 @@ individual_store_contact_update (EmpathyIndividualStore *self, for (l = iters; l && set_model; l = l->next) { gboolean can_audio_call, can_video_call; + const gchar * const *types; individual_can_audio_video_call (individual, &can_audio_call, &can_video_call); + types = individual_get_client_types (individual); + gtk_tree_store_set (GTK_TREE_STORE (self), l->data, EMPATHY_INDIVIDUAL_STORE_COL_ICON_STATUS, pixbuf_status, EMPATHY_INDIVIDUAL_STORE_COL_PIXBUF_AVATAR_VISIBLE, show_avatar, @@ -757,6 +797,7 @@ individual_store_contact_update (EmpathyIndividualStore *self, EMPATHY_INDIVIDUAL_STORE_COL_IS_SEPARATOR, FALSE, EMPATHY_INDIVIDUAL_STORE_COL_CAN_AUDIO_CALL, can_audio_call, EMPATHY_INDIVIDUAL_STORE_COL_CAN_VIDEO_CALL, can_video_call, + EMPATHY_INDIVIDUAL_STORE_COL_CLIENT_TYPES, types, -1); } @@ -859,6 +900,8 @@ individual_personas_changed_cb (FolksIndividual *individual, g_object_set_data (G_OBJECT (contact), "individual", individual); g_signal_connect (contact, "notify::capabilities", (GCallback) individual_store_contact_updated_cb, self); + g_signal_connect (contact, "notify::client-types", + (GCallback) individual_store_contact_updated_cb, self); g_object_unref (contact); } @@ -1494,6 +1537,7 @@ individual_store_setup (EmpathyIndividualStore *self) G_TYPE_BOOLEAN, /* Can make audio calls */ G_TYPE_BOOLEAN, /* Can make video calls */ G_TYPE_BOOLEAN, /* Is a fake group */ + G_TYPE_STRV, /* Client types */ }; priv = GET_PRIV (self); diff --git a/libempathy-gtk/empathy-individual-store.h b/libempathy-gtk/empathy-individual-store.h index debb218ad..246c73b91 100644 --- a/libempathy-gtk/empathy-individual-store.h +++ b/libempathy-gtk/empathy-individual-store.h @@ -64,6 +64,7 @@ typedef enum EMPATHY_INDIVIDUAL_STORE_COL_CAN_AUDIO_CALL, EMPATHY_INDIVIDUAL_STORE_COL_CAN_VIDEO_CALL, EMPATHY_INDIVIDUAL_STORE_COL_IS_FAKE_GROUP, + EMPATHY_INDIVIDUAL_STORE_COL_CLIENT_TYPES, EMPATHY_INDIVIDUAL_STORE_COL_COUNT, } EmpathyIndividualStoreCol; diff --git a/libempathy-gtk/empathy-individual-view.c b/libempathy-gtk/empathy-individual-view.c index 6eb301d34..a04682569 100644 --- a/libempathy-gtk/empathy-individual-view.c +++ b/libempathy-gtk/empathy-individual-view.c @@ -214,7 +214,8 @@ individual_view_query_tooltip_cb (EmpathyIndividualView *view, { priv->tooltip_widget = empathy_individual_widget_new (individual, EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP | - EMPATHY_INDIVIDUAL_WIDGET_SHOW_LOCATION); + EMPATHY_INDIVIDUAL_WIDGET_SHOW_LOCATION | + EMPATHY_INDIVIDUAL_WIDGET_SHOW_CLIENT_TYPES); gtk_container_set_border_width (GTK_CONTAINER (priv->tooltip_widget), 8); g_object_ref (priv->tooltip_widget); g_signal_connect (priv->tooltip_widget, "destroy", @@ -1832,6 +1833,8 @@ individual_view_constructed (GObject *object) "is_group", EMPATHY_INDIVIDUAL_STORE_COL_IS_GROUP); gtk_tree_view_column_add_attribute (col, cell, "compact", EMPATHY_INDIVIDUAL_STORE_COL_COMPACT); + gtk_tree_view_column_add_attribute (col, cell, + "client-types", EMPATHY_INDIVIDUAL_STORE_COL_CLIENT_TYPES); /* Audio Call Icon */ cell = empathy_cell_renderer_activatable_new (); diff --git a/libempathy-gtk/empathy-individual-widget.c b/libempathy-gtk/empathy-individual-widget.c index 5f180c0dc..863ce021e 100644 --- a/libempathy-gtk/empathy-individual-widget.c +++ b/libempathy-gtk/empathy-individual-widget.c @@ -78,7 +78,7 @@ typedef struct { EmpathyIndividualWidgetFlags flags; /* weak pointer to the contact whose contact details we're displaying */ - TpContact *contact_info_contact; + TpContact *contact; /* unowned Persona (borrowed from priv->individual) -> GtkTable child */ GHashTable *persona_tables; @@ -106,6 +106,9 @@ typedef struct { /* Groups */ GtkWidget *groups_widget; + /* Client types */ + GtkWidget *hbox_client_types; + /* Details */ GtkWidget *vbox_details; GtkWidget *table_details; @@ -122,6 +125,9 @@ enum { PROP_FLAGS }; +static void client_types_update (EmpathyIndividualWidget *self); +static void remove_weak_contact (EmpathyIndividualWidget *self); + static void details_set_up (EmpathyIndividualWidget *self) { @@ -193,6 +199,53 @@ contact_info_field_cmp (TpContactInfoField *field1, return contact_info_field_name_cmp (field1->field_name, field2->field_name); } +static void +update_weak_contact (EmpathyIndividualWidget *self) +{ + EmpathyIndividualWidgetPriv *priv = GET_PRIV (self); + TpContact *tp_contact = NULL; + + remove_weak_contact (self); + + if (priv->individual != NULL) + { + /* FIXME: We take the most available TpContact we find and only + * use its details. It would be a lot better if we would get the + * details for every TpContact in the Individual and merge them + * all, but that requires vCard support in libfolks for it to + * not be hideously complex. (bgo#627399) */ + GList *personas, *l; + FolksPresenceType presence_type = FOLKS_PRESENCE_TYPE_UNSET; + + personas = folks_individual_get_personas (priv->individual); + for (l = personas; l != NULL; l = l->next) + { + FolksPresence *presence; + + /* We only want personas which implement FolksPresence */ + if (!FOLKS_IS_PRESENCE (l->data)) + continue; + + presence = FOLKS_PRESENCE (l->data); + + if (folks_presence_typecmp (folks_presence_get_presence_type (presence), + presence_type) > 0 + && TPF_IS_PERSONA (presence)) + { + presence_type = folks_presence_get_presence_type (presence); + tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data)); + } + } + } + + if (tp_contact != NULL) + { + priv->contact = tp_contact; + g_object_add_weak_pointer (G_OBJECT (tp_contact), + (gpointer *) &priv->contact); + } +} + typedef struct { EmpathyIndividualWidget *widget; /* weak */ TpContact *contact; /* owned */ @@ -324,18 +377,6 @@ details_request_cb (TpContact *contact, tp_clear_object (&priv->details_cancellable); - /* We need a (weak) pointer to the contact so that we can disconnect the - * signal handler on deconstruction. */ - if (priv->contact_info_contact != NULL) - { - g_object_remove_weak_pointer (G_OBJECT (priv->contact_info_contact), - (gpointer *) &priv->contact_info_contact); - } - - priv->contact_info_contact = contact; - g_object_add_weak_pointer (G_OBJECT (contact), - (gpointer *) &priv->contact_info_contact); - g_signal_connect (contact, "notify::contact-info", (GCallback) details_notify_cb, self); } @@ -387,28 +428,10 @@ details_update (EmpathyIndividualWidget *self) gtk_widget_hide (priv->vbox_details); - if (priv->individual != NULL) - { - /* FIXME: We take the first TpContact we find and only use its details. - * It would be a lot better if we would get the details for every - * TpContact in the Individual and merge them all, but that requires - * vCard support in libfolks for it to not be hideously complex. - * (bgo#627399) */ - GList *personas, *l; + if (priv->contact == NULL) + update_weak_contact (self); - personas = folks_individual_get_personas (priv->individual); - for (l = personas; l != NULL; l = l->next) - { - if (TPF_IS_PERSONA (l->data)) - { - tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data)); - if (tp_contact != NULL) - break; - } - } - } - - if (tp_contact != NULL) + if (priv->contact != NULL) { GQuark features[] = { TP_CONNECTION_FEATURE_CONTACT_INFO, 0 }; TpConnection *connection; @@ -417,7 +440,7 @@ details_update (EmpathyIndividualWidget *self) data = g_slice_new (DetailsData); data->widget = self; g_object_add_weak_pointer (G_OBJECT (self), (gpointer *) &data->widget); - data->contact = g_object_ref (tp_contact); + data->contact = g_object_ref (priv->contact); /* First, make sure the CONTACT_INFO feature is ready on the connection */ connection = tp_contact_get_connection (tp_contact); @@ -785,6 +808,64 @@ location_update (EmpathyIndividualWidget *self) gtk_widget_show (priv->vbox_location); } +static void +client_types_notify_cb (TpContact *contact, + GParamSpec *pspec, + EmpathyIndividualWidget *self) +{ + client_types_update (self); +} + +static void +client_types_update (EmpathyIndividualWidget *self) +{ + EmpathyIndividualWidgetPriv *priv = GET_PRIV (self); + const gchar * const *types; + + if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_CLIENT_TYPES) || + priv->individual == NULL) + { + gtk_widget_hide (priv->hbox_client_types); + return; + } + + if (priv->contact == NULL) + update_weak_contact (self); + + /* let's try that again... */ + if (priv->contact == NULL) + return; + + types = tp_contact_get_client_types (priv->contact); + + if (types != NULL + && g_strv_length ((gchar **) types) > 0 + && !tp_strdiff (types[0], "phone")) + { + gtk_widget_show (priv->hbox_client_types); + } + else + { + gtk_widget_hide (priv->hbox_client_types); + } + + g_signal_connect (priv->contact, "notify::client-types", + (GCallback) client_types_notify_cb, self); +} + +static void +remove_weak_contact (EmpathyIndividualWidget *self) +{ + EmpathyIndividualWidgetPriv *priv = GET_PRIV (self); + + if (priv->contact == NULL) + return; + + g_object_remove_weak_pointer (G_OBJECT (priv->contact), + (gpointer *) &priv->contact); + priv->contact = NULL; +} + static EmpathyAvatar * persona_dup_avatar (FolksPersona *persona) { @@ -1741,14 +1822,8 @@ remove_individual (EmpathyIndividualWidget *self) remove_persona (self, FOLKS_PERSONA (l->data)); individual_table_destroy (self); - if (priv->contact_info_contact != NULL) - { - g_signal_handlers_disconnect_by_func (priv->contact_info_contact, - details_notify_cb, self); - g_object_remove_weak_pointer (G_OBJECT (priv->contact_info_contact), - (gpointer *) &priv->contact_info_contact); - priv->contact_info_contact = NULL; - } + if (priv->contact != NULL) + remove_weak_contact (self); tp_clear_object (&priv->individual); } @@ -1847,6 +1922,7 @@ empathy_individual_widget_init (EmpathyIndividualWidget *self) "vbox_details", &priv->vbox_details, "table_details", &priv->table_details, "hbox_details_requested", &priv->hbox_details_requested, + "hbox_client_types", &priv->hbox_client_types, NULL); g_free (filename); @@ -2080,4 +2156,5 @@ empathy_individual_widget_set_individual (EmpathyIndividualWidget *self, groups_update (self); details_update (self); location_update (self); + client_types_update (self); } diff --git a/libempathy-gtk/empathy-individual-widget.h b/libempathy-gtk/empathy-individual-widget.h index a968d14f3..24a7f3dc3 100644 --- a/libempathy-gtk/empathy-individual-widget.h +++ b/libempathy-gtk/empathy-individual-widget.h @@ -63,6 +63,7 @@ typedef enum EMPATHY_INDIVIDUAL_WIDGET_SHOW_LOCATION = 1 << 4, EMPATHY_INDIVIDUAL_WIDGET_SHOW_DETAILS = 1 << 5, EMPATHY_INDIVIDUAL_WIDGET_SHOW_PERSONAS = 1 << 6, + EMPATHY_INDIVIDUAL_WIDGET_SHOW_CLIENT_TYPES = 1 << 7, } EmpathyIndividualWidgetFlags; #define EMPATHY_TYPE_INDIVIDUAL_WIDGET (empathy_individual_widget_get_type ()) diff --git a/libempathy-gtk/empathy-individual-widget.ui b/libempathy-gtk/empathy-individual-widget.ui index 5fb382363..dcfc83a47 100644 --- a/libempathy-gtk/empathy-individual-widget.ui +++ b/libempathy-gtk/empathy-individual-widget.ui @@ -88,6 +88,35 @@ </packing> </child> <child> + <object class="GtkHBox" id="hbox_client_types"> + <property name="spacing">6</property> + <child> + <object class="GtkImage" id="image_phone"> + <property name="visible">True</property> + <property name="icon_name">phone</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Online from a phone or mobile device</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> <object class="EmpathyGroupsWidget" id="groups_widget"/> <packing> <property name="position">2</property> diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c index 4db37f693..5383187c1 100644 --- a/libempathy/empathy-contact.c +++ b/libempathy/empathy-contact.c @@ -70,6 +70,7 @@ typedef struct { */ GHashTable *location; GHashTable *groups; + gchar **client_types; } EmpathyContactPriv; static void contact_finalize (GObject *object); @@ -85,6 +86,9 @@ static void update_geocode (EmpathyContact *contact); static void empathy_contact_set_location (EmpathyContact *contact, GHashTable *location); +static void contact_set_client_types (EmpathyContact *contact, + const gchar * const *types); + static void set_capabilities_from_tp_caps (EmpathyContact *self, TpCapabilities *caps); @@ -110,7 +114,8 @@ enum PROP_HANDLE, PROP_CAPABILITIES, PROP_IS_USER, - PROP_LOCATION + PROP_LOCATION, + PROP_CLIENT_TYPES }; enum { @@ -163,6 +168,11 @@ tp_contact_notify_cb (TpContact *tp_contact, { contact_set_avatar_from_tp_contact (EMPATHY_CONTACT (contact)); } + else if (!tp_strdiff (param->name, "client-types")) + { + contact_set_client_types (EMPATHY_CONTACT (contact), + tp_contact_get_client_types (tp_contact)); + } } static void @@ -223,6 +233,7 @@ contact_constructed (GObject *object) GHashTable *location; TpHandle self_handle; TpHandle handle; + const gchar * const *client_types; if (priv->tp_contact == NULL) return; @@ -233,6 +244,10 @@ contact_constructed (GObject *object) if (location != NULL) empathy_contact_set_location (contact, location); + client_types = tp_contact_get_client_types (priv->tp_contact); + if (client_types != NULL) + contact_set_client_types (contact, client_types); + set_capabilities_from_tp_caps (contact, tp_contact_get_capabilities (priv->tp_contact)); @@ -365,6 +380,14 @@ empathy_contact_class_init (EmpathyContactClass *class) G_TYPE_HASH_TABLE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_CLIENT_TYPES, + g_param_spec_boxed ("client-types", + "Contact client types", + "Client types of the contact", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + signals[PRESENCE_CHANGED] = g_signal_new ("presence-changed", G_TYPE_FROM_CLASS (class), @@ -388,6 +411,7 @@ empathy_contact_init (EmpathyContact *contact) contact->priv = priv; priv->location = NULL; + priv->client_types = NULL; priv->groups = NULL; } @@ -404,6 +428,7 @@ contact_finalize (GObject *object) g_hash_table_destroy (priv->groups); g_free (priv->alias); g_free (priv->id); + g_strfreev (priv->client_types); G_OBJECT_CLASS (empathy_contact_parent_class)->finalize (object); } @@ -1396,6 +1421,31 @@ empathy_contact_set_location (EmpathyContact *contact, g_object_notify (G_OBJECT (contact), "location"); } +const gchar * const * +empathy_contact_get_client_types (EmpathyContact *contact) +{ + EmpathyContactPriv *priv; + + g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL); + + priv = GET_PRIV (contact); + + return (const gchar * const *) priv->client_types; +} + +static void +contact_set_client_types (EmpathyContact *contact, + const gchar * const *client_types) +{ + EmpathyContactPriv *priv = GET_PRIV (contact); + + if (priv->client_types != NULL) + g_strfreev (priv->client_types); + + priv->client_types = g_strdupv ((gchar **) client_types); + g_object_notify (G_OBJECT (contact), "client-types"); +} + /** * empathy_contact_equal: * @contact1: an #EmpathyContact diff --git a/libempathy/empathy-contact.h b/libempathy/empathy-contact.h index 005cf1e7a..f9217c108 100644 --- a/libempathy/empathy-contact.h +++ b/libempathy/empathy-contact.h @@ -125,6 +125,7 @@ gboolean empathy_avatar_save_to_file (EmpathyAvatar *avatar, const gchar *filename, GError **error); GHashTable * empathy_contact_get_location (EmpathyContact *contact); +const gchar * const * empathy_contact_get_client_types (EmpathyContact *contact); gboolean empathy_contact_equal (gconstpointer contact1, gconstpointer contact2); diff --git a/libempathy/empathy-tp-contact-factory.c b/libempathy/empathy-tp-contact-factory.c index ff572cc43..87c65385e 100644 --- a/libempathy/empathy-tp-contact-factory.c +++ b/libempathy/empathy-tp-contact-factory.c @@ -31,6 +31,7 @@ static TpContactFeature contact_features[] = { TP_CONTACT_FEATURE_PRESENCE, TP_CONTACT_FEATURE_LOCATION, TP_CONTACT_FEATURE_CAPABILITIES, + TP_CONTACT_FEATURE_CLIENT_TYPES, }; typedef union { |