diff options
author | Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk> | 2010-11-17 22:29:01 +0800 |
---|---|---|
committer | Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk> | 2010-11-17 22:29:01 +0800 |
commit | 479275712b6f5984d58728d28d9bad99c94108cf (patch) | |
tree | 75c279e79e7d3c4f47a27e8176856bafb068df54 /libempathy-gtk | |
parent | a631e25e2ec0d4fdf0f526a38df6171a6a6b26bd (diff) | |
parent | de93254a7b91ea0620a4b6ae1c5cad2d922add91 (diff) | |
download | gsoc2013-empathy-479275712b6f5984d58728d28d9bad99c94108cf.tar gsoc2013-empathy-479275712b6f5984d58728d28d9bad99c94108cf.tar.gz gsoc2013-empathy-479275712b6f5984d58728d28d9bad99c94108cf.tar.bz2 gsoc2013-empathy-479275712b6f5984d58728d28d9bad99c94108cf.tar.lz gsoc2013-empathy-479275712b6f5984d58728d28d9bad99c94108cf.tar.xz gsoc2013-empathy-479275712b6f5984d58728d28d9bad99c94108cf.tar.zst gsoc2013-empathy-479275712b6f5984d58728d28d9bad99c94108cf.zip |
Merge branch 'bug-547658'
Diffstat (limited to 'libempathy-gtk')
-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 |
8 files changed, 230 insertions, 47 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> |