45
45
#include "empathy-groups-widget.h"
46
46
#include "empathy-gtk-enum-types.h"
47
47
#include "empathy-individual-widget.h"
48
#include "empathy-kludge-label.h"
49
48
#include "empathy-string-parser.h"
50
49
#include "empathy-ui-utils.h"
79
78
EmpathyIndividualWidgetFlags flags;
81
80
/* weak pointer to the contact whose contact details we're displaying */
82
TpContact *contact_info_contact;
84
83
/* unowned Persona (borrowed from priv->individual) -> GtkTable child */
85
84
GHashTable *persona_tables;
194
199
return contact_info_field_name_cmp (field1->field_name, field2->field_name);
203
client_types_notify_cb (TpContact *contact,
205
EmpathyIndividualWidget *self)
207
client_types_update (self);
211
update_weak_contact (EmpathyIndividualWidget *self)
213
EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
214
TpContact *tp_contact = NULL;
216
remove_weak_contact (self);
218
if (priv->individual != NULL)
220
/* FIXME: We take the most available TpContact we find and only
221
* use its details. It would be a lot better if we would get the
222
* details for every TpContact in the Individual and merge them
223
* all, but that requires vCard support in libfolks for it to
224
* not be hideously complex. (bgo#627399) */
226
FolksPresenceType presence_type = FOLKS_PRESENCE_TYPE_UNSET;
228
personas = folks_individual_get_personas (priv->individual);
229
for (l = personas; l != NULL; l = l->next)
231
FolksPresenceDetails *presence;
233
/* We only want personas which implement FolksPresence */
234
if (!FOLKS_IS_PRESENCE_DETAILS (l->data))
237
presence = FOLKS_PRESENCE_DETAILS (l->data);
239
if (folks_presence_details_typecmp (
240
folks_presence_details_get_presence_type (presence),
241
presence_type) > 0 &&
242
empathy_folks_persona_is_interesting (FOLKS_PERSONA (presence)))
244
presence_type = folks_presence_details_get_presence_type (
246
tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data));
251
if (tp_contact != NULL)
253
priv->contact = tp_contact;
254
g_object_add_weak_pointer (G_OBJECT (tp_contact),
255
(gpointer *) &priv->contact);
257
g_signal_connect (priv->contact, "notify::client-types",
258
(GCallback) client_types_notify_cb, self);
198
263
EmpathyIndividualWidget *widget; /* weak */
199
264
TpContact *contact; /* owned */
326
391
tp_clear_object (&priv->details_cancellable);
328
/* We need a (weak) pointer to the contact so that we can disconnect the
329
* signal handler on deconstruction. */
330
if (priv->contact_info_contact != NULL)
332
g_object_remove_weak_pointer (G_OBJECT (priv->contact_info_contact),
333
(gpointer *) &priv->contact_info_contact);
336
priv->contact_info_contact = contact;
337
g_object_add_weak_pointer (G_OBJECT (contact),
338
(gpointer *) &priv->contact_info_contact);
340
393
g_signal_connect (contact, "notify::contact-info",
341
394
(GCallback) details_notify_cb, self);
381
434
details_update (EmpathyIndividualWidget *self)
383
436
EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
384
TpContact *tp_contact = NULL;
386
438
if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_DETAILS))
389
441
gtk_widget_hide (priv->vbox_details);
391
if (priv->individual != NULL)
393
/* FIXME: We take the first TpContact we find and only use its details.
394
* It would be a lot better if we would get the details for every
395
* TpContact in the Individual and merge them all, but that requires
396
* vCard support in libfolks for it to not be hideously complex.
400
personas = folks_individual_get_personas (priv->individual);
401
for (l = personas; l != NULL; l = l->next)
403
if (empathy_folks_persona_is_interesting (FOLKS_PERSONA (l->data)))
405
tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data));
406
if (tp_contact != NULL)
412
if (tp_contact != NULL)
443
if (priv->contact == NULL)
444
update_weak_contact (self);
446
if (priv->contact != NULL)
414
448
GQuark features[] = { TP_CONNECTION_FEATURE_CONTACT_INFO, 0 };
415
449
TpConnection *connection;
418
452
data = g_slice_new (DetailsData);
419
453
data->widget = self;
420
454
g_object_add_weak_pointer (G_OBJECT (self), (gpointer *) &data->widget);
421
data->contact = g_object_ref (tp_contact);
455
data->contact = g_object_ref (priv->contact);
423
457
/* First, make sure the CONTACT_INFO feature is ready on the connection */
424
connection = tp_contact_get_connection (tp_contact);
458
connection = tp_contact_get_connection (priv->contact);
425
459
tp_proxy_prepare_async (connection, features,
426
460
(GAsyncReadyCallback) details_feature_prepared_cb, data);
588
622
gchar *user_date;
594
627
stamp = g_value_get_int64 (value);
597
user_date = empathy_time_to_string_relative (time_);
629
user_date = empathy_time_to_string_relative (stamp);
599
631
tmp = g_strdup_printf ("<b>%s</b>", _("Location"));
600
632
/* translators: format is "Location, $date" */
705
736
gtk_container_add (GTK_CONTAINER (priv->viewport_map),
706
737
priv->map_view_embed);
707
738
g_object_set (G_OBJECT (priv->map_view),
708
"show-license", TRUE,
709
"scroll-mode", CHAMPLAIN_SCROLL_MODE_KINETIC,
739
"kinetic-mode", TRUE,
710
740
"zoom-level", 10,
713
layer = champlain_layer_new ();
714
champlain_view_add_layer (priv->map_view, layer);
715
markers = g_ptr_array_new ();
743
layer = champlain_marker_layer_new ();
744
champlain_view_add_layer (priv->map_view, CHAMPLAIN_LAYER (layer));
717
746
/* FIXME: For now, we have to do this manually. Once libfolks grows a
718
747
* location interface, we can use that. (bgo#627400) */
760
789
lon = g_value_get_double (value);
762
791
/* Add a marker to the map */
763
marker = champlain_marker_new_with_text (
792
marker = champlain_label_new_with_text (
764
793
folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (persona)),
765
794
NULL, NULL, NULL);
766
champlain_base_marker_set_position (
767
CHAMPLAIN_BASE_MARKER (marker), lat, lon);
768
clutter_container_add (CLUTTER_CONTAINER (layer), marker, NULL);
770
g_ptr_array_add (markers, marker);
795
champlain_location_set_location (CHAMPLAIN_LOCATION (marker),
797
champlain_marker_layer_add_marker (layer,
798
CHAMPLAIN_MARKER (marker));
772
800
g_object_unref (contact);
776
804
/* Zoom to show all of the markers */
777
g_ptr_array_add (markers, NULL); /* NULL-terminate the array */
778
champlain_view_ensure_markers_visible (priv->map_view,
779
(ChamplainBaseMarker **) markers->pdata, FALSE);
780
g_ptr_array_free (markers, TRUE);
805
champlain_view_ensure_layers_visible (priv->map_view, FALSE);
782
807
gtk_widget_show_all (priv->viewport_map);
786
811
gtk_widget_show (priv->vbox_location);
815
client_types_update (EmpathyIndividualWidget *self)
817
EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
818
const gchar * const *types;
820
if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_CLIENT_TYPES) ||
821
priv->individual == NULL)
823
gtk_widget_hide (priv->hbox_client_types);
827
if (priv->contact == NULL)
828
update_weak_contact (self);
830
/* let's try that again... */
831
if (priv->contact == NULL)
834
types = tp_contact_get_client_types (priv->contact);
837
&& g_strv_length ((gchar **) types) > 0
838
&& !tp_strdiff (types[0], "phone"))
840
gtk_widget_show (priv->hbox_client_types);
844
gtk_widget_hide (priv->hbox_client_types);
850
remove_weak_contact (EmpathyIndividualWidget *self)
852
EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
854
if (priv->contact == NULL)
857
g_signal_handlers_disconnect_by_func (priv->contact, client_types_notify_cb,
860
g_object_remove_weak_pointer (G_OBJECT (priv->contact),
861
(gpointer *) &priv->contact);
862
priv->contact = NULL;
789
865
static EmpathyAvatar *
790
866
persona_dup_avatar (FolksPersona *persona)
935
1011
empathy_avatar_unref (avatar);
937
menu = gtk_menu_new ();
1013
menu = empathy_context_menu_new (parent);
939
1015
/* Add "Save as..." entry */
940
1016
item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, NULL);
955
1031
event_time = gtk_get_current_event_time ();
958
gtk_menu_attach_to_widget (GTK_MENU (menu), parent, NULL);
959
1034
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, button, event_time);
960
g_object_ref_sink (menu);
961
g_object_unref (menu);
1273
1346
gtk_widget_show (image);
1275
/* Set up status_label as a KludgeLabel */
1276
label = empathy_kludge_label_new ("");
1348
label = gtk_label_new ("");
1277
1349
gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
1278
1350
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1351
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1280
1353
gtk_label_set_selectable (GTK_LABEL (label),
1281
1354
(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP) ? FALSE : TRUE);
1571
1644
num_personas++;
1574
message = g_strdup_printf (ngettext ("Meta-contact containing %u contact",
1575
"Meta-contact containing %u contacts", num_personas), num_personas);
1647
/* Translators: the plurality applies to both instances of the word
1649
message = g_strdup_printf (
1650
ngettext ("Linked contact containing %u contact",
1651
"Linked contacts containing %u contacts", num_personas),
1576
1653
label = gtk_label_new (message);
1577
1654
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1578
1655
g_free (message);
1747
1824
remove_persona (self, FOLKS_PERSONA (l->data));
1748
1825
individual_table_destroy (self);
1750
if (priv->contact_info_contact != NULL)
1752
g_signal_handlers_disconnect_by_func (priv->contact_info_contact,
1753
details_notify_cb, self);
1754
g_object_remove_weak_pointer (G_OBJECT (priv->contact_info_contact),
1755
(gpointer *) &priv->contact_info_contact);
1756
priv->contact_info_contact = NULL;
1827
if (priv->contact != NULL)
1828
remove_weak_contact (self);
1759
1830
tp_clear_object (&priv->individual);
1853
1924
"vbox_details", &priv->vbox_details,
1854
1925
"table_details", &priv->table_details,
1855
1926
"hbox_details_requested", &priv->hbox_details_requested,
1927
"hbox_client_types", &priv->hbox_client_types,
1857
1929
g_free (filename);