diff options
-rw-r--r-- | libempathy-gtk/empathy-chat.c | 82 | ||||
-rw-r--r-- | libempathy-gtk/empathy-contact-widget.c | 159 | ||||
-rw-r--r-- | libempathy/empathy-time.c | 64 | ||||
-rw-r--r-- | libempathy/empathy-time.h | 1 |
4 files changed, 267 insertions, 39 deletions
diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c index 183b49bf9..034cd9ea7 100644 --- a/libempathy-gtk/empathy-chat.c +++ b/libempathy-gtk/empathy-chat.c @@ -47,6 +47,7 @@ #include "empathy-chat.h" #include "empathy-spell.h" +#include "empathy-contact-dialogs.h" #include "empathy-contact-list-store.h" #include "empathy-contact-list-view.h" #include "empathy-contact-menu.h" @@ -905,6 +906,84 @@ chat_command_say (EmpathyChat *chat, g_object_unref (message); } +static void +whois_got_contact_cb (TpConnection *connection, + guint n_contacts, + TpContact * const *contacts, + const gchar * const *requested_ids, + GHashTable *failed_id_errors, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyChat *chat = EMPATHY_CHAT (weak_object); + + g_return_if_fail (n_contacts <= 1); + + if (n_contacts == 0) { + GHashTableIter iter; + gpointer key = NULL, value = NULL; + gchar *id; + GError *id_error; + + /* tp-glib guarantees that the contacts you requested will be + * in failed_id_errors regardless of whether the individual + * contact was invalid or the whole operation failed. + */ + g_hash_table_iter_init (&iter, failed_id_errors); + g_hash_table_iter_next (&iter, &key, &value); + id = key; + id_error = value; + + DEBUG ("Error getting TpContact for '%s': %s %u %s", + id, g_quark_to_string (id_error->domain), + id_error->code, id_error->message); + + if (error == NULL) { + /* The specific ID failed. */ + gchar *event = g_strdup_printf ( + _("“%s” is not a valid contact ID"), id); + empathy_chat_view_append_event (chat->view, event); + g_free (event); + } + /* Otherwise we're disconnected or something; so the window + * will already say ‘Disconnected’, so let's not show anything. + */ + } else { + EmpathyContact *empathy_contact; + GtkWidget *window; + + g_return_if_fail (contacts[0] != NULL); + empathy_contact = empathy_contact_dup_from_tp_contact ( + contacts[0]); + + window = gtk_widget_get_toplevel (GTK_WIDGET (chat)); + /* If we're alive and this command is running, we'd better be + * in a window. */ + g_return_if_fail (window != NULL); + g_return_if_fail (gtk_widget_is_toplevel (window)); + empathy_contact_information_dialog_show (empathy_contact, + GTK_WINDOW (window)); + g_object_unref (empathy_contact); + } +} + +static void +chat_command_whois (EmpathyChat *chat, + GStrv strv) +{ + EmpathyChatPriv *priv = GET_PRIV (chat); + TpConnection *conn; + + conn = empathy_tp_chat_get_connection (priv->tp_chat); + tp_connection_get_contacts_by_id (conn, + /* Element 0 of 'strv' is "whois"; element 1 is the contact ID + * entered by the user (including spaces, if any). */ + 1, (const gchar * const *) strv + 1, + 0, NULL, + whois_got_contact_cb, NULL, NULL, G_OBJECT (chat)); +} + static void chat_command_help (EmpathyChat *chat, GStrv strv); typedef void (*ChatCommandFunc) (EmpathyChat *chat, GStrv strv); @@ -953,6 +1032,9 @@ static ChatCommandItem commands[] = { "This is used to send a message starting with a '/'. For example: " "\"/say /join is used to join a new chat room\"")}, + {"whois", 2, 2, chat_command_whois, NULL, + N_("/whois <contact ID>: display information about a contact")}, + {"help", 1, 2, chat_command_help, NULL, N_("/help [<command>]: show all supported commands. " "If <command> is defined, show its usage.")}, diff --git a/libempathy-gtk/empathy-contact-widget.c b/libempathy-gtk/empathy-contact-widget.c index c4e3748b4..14042bf61 100644 --- a/libempathy-gtk/empathy-contact-widget.c +++ b/libempathy-gtk/empathy-contact-widget.c @@ -40,6 +40,7 @@ #include <libempathy/empathy-contact-manager.h> #include <libempathy/empathy-contact-list.h> #include <libempathy/empathy-location.h> +#include <libempathy/empathy-request-util.h> #include <libempathy/empathy-time.h> #include <libempathy/empathy-utils.h> @@ -283,20 +284,74 @@ contact_widget_bday_changed_cb (GtkCalendar *calendar, static void contact_widget_details_notify_cb (EmpathyContactWidget *information); +typedef gchar * (* FieldFormatFunc) (GStrv); + typedef struct { const gchar *field_name; const gchar *title; - gboolean linkify; + FieldFormatFunc format; } InfoFieldData; +static gchar * +linkify_first_value (GStrv values) +{ + return empathy_add_link_markup (values[0]); +} + +static gchar * +format_idle_time (GStrv values) +{ + const gchar *value = values[0]; + int duration = strtol (value, NULL, 10); + + if (duration <= 0) + return NULL; + + return empathy_duration_to_string (duration); +} + +static gchar * +format_server (GStrv values) +{ + g_assert (values[0] != NULL); + + if (values[1] == NULL) + return g_markup_escape_text (values[0], -1); + else + return g_markup_printf_escaped ("%s (%s)", values[0], values[1]); +} + +static gchar * +presence_hack (GStrv values) +{ + if (tp_str_empty (values[0])) + return NULL; + + return g_markup_escape_text (values[0], -1); +} + static InfoFieldData info_field_datas[] = { - { "fn", N_("Full name:"), FALSE }, - { "tel", N_("Phone number:"), FALSE }, - { "email", N_("E-mail address:"), TRUE }, - { "url", N_("Website:"), TRUE }, - { "bday", N_("Birthday:"), FALSE }, + { "fn", N_("Full name:"), NULL }, + { "tel", N_("Phone number:"), NULL }, + { "email", N_("E-mail address:"), linkify_first_value }, + { "url", N_("Website:"), linkify_first_value }, + { "bday", N_("Birthday:"), NULL }, + + /* Note to translators: this is the caption for a string of the form "5 + * minutes ago", and refers to the time since the contact last interacted + * with their IM client. + */ + { "x-idle-time", N_("Last seen:"), format_idle_time }, + { "x-irc-server", N_("Server:"), format_server }, + { "x-host", N_("Connected from:"), format_server }, + + /* FIXME: once Idle implements SimplePresence using this information, we can + * and should bin this. + */ + { "x-presence-status-message", N_("Away message:"), presence_hack }, + { NULL, NULL } }; @@ -526,12 +581,73 @@ contact_widget_details_update_edit (EmpathyContactWidget *information) return n_rows; } +static gboolean +channel_name_activated_cb ( + GtkLabel *label, + gchar *uri, + EmpathyContactWidget *information) +{ + TpAccount *account = empathy_contact_get_account (information->contact); + + empathy_join_muc (account, uri, empathy_get_current_action_time ()); + return TRUE; +} + +static void +add_channel_list ( + EmpathyContactWidget *information, + GPtrArray *channels, + guint row) +{ + GtkWidget *w; + GString *label_markup = g_string_new (""); + guint i; + + w = gtk_label_new (_("Channels:")); + gtk_table_attach (GTK_TABLE (information->table_details), + w, 0, 1, row, row + 1, GTK_FILL, 0, 0, 0); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); + gtk_widget_show (w); + + for (i = 0; i < channels->len; i++) + { + const gchar *channel_name = g_ptr_array_index (channels, i); + /* We abuse the URI of the link to hold the channel name. It seems to + * be okay to just use it essentially verbatim, rather than trying to + * ensure it's actually a valid URI. g_string_append_uri_escaped() + * escapes way more than we actually need to; so we're just using + * g_markup_escape_text directly. + */ + gchar *escaped = g_markup_escape_text (channel_name, -1); + + if (i > 0) + g_string_append (label_markup, ", "); + + g_string_append_printf (label_markup, "<a href='%s'>%s</a>", + escaped, channel_name); + g_free (escaped); + } + + w = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (w), label_markup->str); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + g_signal_connect (w, "activate-link", + (GCallback) channel_name_activated_cb, information); + gtk_table_attach_defaults (GTK_TABLE (information->table_details), + w, 1, 2, row, row + 1); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); + gtk_widget_show (w); + + g_string_free (label_markup, TRUE); +} + static guint contact_widget_details_update_show (EmpathyContactWidget *information) { TpContact *contact; GList *info, *l; guint n_rows = 0; + GPtrArray *channels = g_ptr_array_new (); contact = empathy_contact_get_tp_contact (information->contact); info = tp_contact_get_contact_info (contact); @@ -541,6 +657,7 @@ contact_widget_details_update_show (EmpathyContactWidget *information) TpContactInfoField *field = l->data; InfoFieldData *field_data; const gchar *value; + gchar *markup = NULL; GtkWidget *w; if (field->field_value == NULL || field->field_value[0] == NULL) @@ -548,6 +665,12 @@ contact_widget_details_update_show (EmpathyContactWidget *information) value = field->field_value[0]; + if (!tp_strdiff (field->field_name, "x-irc-channel")) + { + g_ptr_array_add (channels, (gpointer) field->field_value[0]); + continue; + } + field_data = find_info_field_data (field->field_name); if (field_data == NULL) { @@ -555,6 +678,18 @@ contact_widget_details_update_show (EmpathyContactWidget *information) continue; } + if (field_data->format != NULL) + { + markup = field_data->format (field->field_value); + + if (markup == NULL) + { + DEBUG ("Invalid value for field '%s' (first element was '%s')", + field->field_name, field->field_value[0]); + continue; + } + } + /* Add Title */ w = gtk_label_new (_(field_data->title)); gtk_table_attach (GTK_TABLE (information->table_details), @@ -564,11 +699,8 @@ contact_widget_details_update_show (EmpathyContactWidget *information) /* Add Value */ w = gtk_label_new (value); - if (field_data->linkify) + if (markup != NULL) { - gchar *markup; - - markup = empathy_add_link_markup (value); gtk_label_set_markup (GTK_LABEL (w), markup); g_free (markup); } @@ -585,6 +717,13 @@ contact_widget_details_update_show (EmpathyContactWidget *information) } g_list_free (info); + if (channels->len > 0) + { + add_channel_list (information, channels, n_rows); + n_rows++; + } + + g_ptr_array_unref (channels); return n_rows; } diff --git a/libempathy/empathy-time.c b/libempathy/empathy-time.c index f33152d97..5144fa4d8 100644 --- a/libempathy/empathy-time.c +++ b/libempathy/empathy-time.c @@ -81,6 +81,40 @@ empathy_time_to_string_local (gint64 t, return result; } +gchar * +empathy_duration_to_string (guint seconds) +{ + if (seconds < 60) { + return g_strdup_printf (ngettext ("%d second ago", + "%d seconds ago", seconds), seconds); + } + else if (seconds < (60 * 60)) { + seconds /= 60; + return g_strdup_printf (ngettext ("%d minute ago", + "%d minutes ago", seconds), seconds); + } + else if (seconds < (60 * 60 * 24)) { + seconds /= 60 * 60; + return g_strdup_printf (ngettext ("%d hour ago", + "%d hours ago", seconds), seconds); + } + else if (seconds < (60 * 60 * 24 * 7)) { + seconds /= 60 * 60 * 24; + return g_strdup_printf (ngettext ("%d day ago", + "%d days ago", seconds), seconds); + } + else if (seconds < (60 * 60 * 24 * 30)) { + seconds /= 60 * 60 * 24 * 7; + return g_strdup_printf (ngettext ("%d week ago", + "%d weeks ago", seconds), seconds); + } + else { + seconds /= 60 * 60 * 24 * 30; + return g_strdup_printf (ngettext ("%d month ago", + "%d months ago", seconds), seconds); + } +} + gchar * empathy_time_to_string_relative (gint64 t) { @@ -96,35 +130,7 @@ empathy_time_to_string_relative (gint64 t) seconds = delta / G_TIME_SPAN_SECOND; if (seconds > 0) { - if (seconds < 60) { - result = g_strdup_printf (ngettext ("%d second ago", - "%d seconds ago", seconds), seconds); - } - else if (seconds < (60 * 60)) { - seconds /= 60; - result = g_strdup_printf (ngettext ("%d minute ago", - "%d minutes ago", seconds), seconds); - } - else if (seconds < (60 * 60 * 24)) { - seconds /= 60 * 60; - result = g_strdup_printf (ngettext ("%d hour ago", - "%d hours ago", seconds), seconds); - } - else if (seconds < (60 * 60 * 24 * 7)) { - seconds /= 60 * 60 * 24; - result = g_strdup_printf (ngettext ("%d day ago", - "%d days ago", seconds), seconds); - } - else if (seconds < (60 * 60 * 24 * 30)) { - seconds /= 60 * 60 * 24 * 7; - result = g_strdup_printf (ngettext ("%d week ago", - "%d weeks ago", seconds), seconds); - } - else { - seconds /= 60 * 60 * 24 * 30; - result = g_strdup_printf (ngettext ("%d month ago", - "%d months ago", seconds), seconds); - } + result = empathy_duration_to_string (seconds); } else { result = g_strdup (_("in the future")); diff --git a/libempathy/empathy-time.h b/libempathy/empathy-time.h index 7fac48221..3a22adeee 100644 --- a/libempathy/empathy-time.h +++ b/libempathy/empathy-time.h @@ -45,6 +45,7 @@ gchar *empathy_time_to_string_utc (gint64 t, gchar *empathy_time_to_string_local (gint64 t, const gchar *format); gchar *empathy_time_to_string_relative (gint64 t); +gchar *empathy_duration_to_string (guint seconds); G_END_DECLS |