X-Git-Url: https://git.0d.be/?p=empathy.git;a=blobdiff_plain;f=libempathy-gtk%2Fempathy-chat.c;h=d273a3792536b161095434f2e5c31d7f4a052478;hp=4e5de6e7ea2aa0b45980510bbd9a566fab6fe693;hb=9b3306a89a8419217e9c2350d7c32c1a83704eca;hpb=6670167794afb834c87fa7bae7286567b7a84cb3 diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c index 4e5de6e7..d273a379 100644 --- a/libempathy-gtk/empathy-chat.c +++ b/libempathy-gtk/empathy-chat.c @@ -49,13 +49,12 @@ #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" -#include "empathy-gtk-marshal.h" +#include "empathy-individual-store-channel.h" +#include "empathy-individual-view.h" #include "empathy-input-text-view.h" #include "empathy-search-bar.h" #include "empathy-theme-manager.h" +#include "empathy-theme-adium.h" #include "empathy-smiley-manager.h" #include "empathy-ui-utils.h" #include "empathy-string-parser.h" @@ -74,6 +73,7 @@ struct _EmpathyChatPriv { gchar *id; gchar *name; gchar *subject; + EmpathyContact *self_contact; EmpathyContact *remote_contact; gboolean show_contacts; @@ -106,6 +106,8 @@ struct _EmpathyChatPriv { guint update_misspelled_words_id; /* Source func ID for save_paned_pos_timeout () */ guint save_paned_pos_id; + /* Source func ID for chat_contacts_visible_timeout_cb () */ + guint contacts_visible_id; GtkWidget *widget; GtkWidget *hpaned; @@ -154,6 +156,14 @@ struct _EmpathyChatPriv { * the keyboard or the mouse. We can't ask GTK for the most recent * event, because it will be a notify event. Instead we track it here */ GdkEventType most_recent_event_type; + + /* A regex matching our own current nickname in the room, or %NULL if + * !empathy_chat_is_room (). */ + GRegex *highlight_regex; + + /* TRUE if empathy_chat_is_room () and there are unread highlighted messages. + * Cleared by empathy_chat_messages_read (). */ + gboolean highlighted; }; typedef struct { @@ -275,11 +285,13 @@ account_reconnected (EmpathyChat *chat, if (priv->sms_channel) empathy_sms_contact_id ( account, priv->id, - TP_USER_ACTION_TIME_NOT_USER_ACTION); + TP_USER_ACTION_TIME_NOT_USER_ACTION, + NULL, NULL); else empathy_chat_with_contact_id ( account, priv->id, - TP_USER_ACTION_TIME_NOT_USER_ACTION); + TP_USER_ACTION_TIME_NOT_USER_ACTION, + NULL, NULL); break; case TP_HANDLE_TYPE_ROOM: empathy_join_muc (account, priv->id, @@ -365,11 +377,18 @@ static gboolean chat_composing_stop_timeout_cb (EmpathyChat *chat) { EmpathyChatPriv *priv; + gboolean send_chat_states; priv = GET_PRIV (chat); priv->composing_stop_timeout_id = 0; - set_chat_state (chat, TP_CHANNEL_CHAT_STATE_PAUSED); + send_chat_states = g_settings_get_boolean (priv->gsettings_chat, + EMPATHY_PREFS_CHAT_SEND_CHAT_STATES); + if (!send_chat_states) { + set_chat_state (chat, TP_CHANNEL_CHAT_STATE_ACTIVE); + } else { + set_chat_state (chat, TP_CHANNEL_CHAT_STATE_PAUSED); + } return FALSE; } @@ -378,9 +397,16 @@ static void chat_composing_start (EmpathyChat *chat) { EmpathyChatPriv *priv; + gboolean send_chat_states; priv = GET_PRIV (chat); + send_chat_states = g_settings_get_boolean (priv->gsettings_chat, + EMPATHY_PREFS_CHAT_SEND_CHAT_STATES); + if (!send_chat_states) { + return; + } + if (priv->composing_stop_timeout_id) { /* Just restart the timeout */ chat_composing_remove_timeout (chat); @@ -754,26 +780,20 @@ chat_command_topic (EmpathyChat *chat, GStrv strv) { EmpathyChatPriv *priv = GET_PRIV (chat); - EmpathyTpChatProperty *property; - GValue value = {0, }; - property = empathy_tp_chat_get_property (priv->tp_chat, "subject"); - if (property == NULL) { + if (!empathy_tp_chat_supports_subject (priv->tp_chat)) { empathy_chat_view_append_event (chat->view, _("Topic not supported on this conversation")); return; } - if (!(property->flags & TP_PROPERTY_FLAG_WRITE)) { + if (!empathy_tp_chat_can_set_subject (priv->tp_chat)) { empathy_chat_view_append_event (chat->view, _("You are not allowed to change the topic")); return; } - g_value_init (&value, G_TYPE_STRING); - g_value_set_string (&value, strv[1]); - empathy_tp_chat_set_property (priv->tp_chat, "subject", &value); - g_value_unset (&value); + empathy_tp_chat_set_subject (priv->tp_chat, strv[1]); } void @@ -899,14 +919,12 @@ chat_command_me (EmpathyChat *chat, if (!tp_text_channel_supports_message_type (channel, TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION)) { /* Action message are not supported, 'simulate' the action */ - EmpathyContact *self_contact; gchar *tmp; - self_contact = empathy_tp_chat_get_self_contact (priv->tp_chat); /* The TpChat can't be ready if it doesn't have the self contact */ - g_assert (self_contact != NULL); + g_assert (priv->self_contact != NULL); - tmp = g_strdup_printf ("%s %s", empathy_contact_get_alias (self_contact), + tmp = g_strdup_printf ("%s %s", empathy_contact_get_alias (priv->self_contact), strv[1]); message = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, tmp); @@ -1040,6 +1058,16 @@ chat_command_babywhale (EmpathyChat *chat, g_object_unref (message); } +static void +chat_command_inspector (EmpathyChat *chat, + GStrv strv) +{ + if (EMPATHY_IS_THEME_ADIUM (chat->view)) { + empathy_theme_adium_show_inspector ( + EMPATHY_THEME_ADIUM (chat->view)); + } +} + static void chat_command_help (EmpathyChat *chat, GStrv strv); typedef void (*ChatCommandFunc) (EmpathyChat *chat, GStrv strv); @@ -1095,6 +1123,8 @@ static ChatCommandItem commands[] = { N_("/help []: show all supported commands. " "If is defined, show its usage.")}, + {"inspector", 1, 1, chat_command_inspector, NULL, NULL}, + {"whale", 1, 1, chat_command_whale, NULL, NULL}, {"babywhale", 1, 1, chat_command_babywhale, NULL, NULL}, }; @@ -1374,6 +1404,86 @@ chat_state_changed_cb (EmpathyTpChat *tp_chat, } } +static GRegex * +get_highlight_regex_for (const gchar *name) +{ + GRegex *regex; + gchar *name_esc, *pattern; + GError *error = NULL; + + name_esc = g_regex_escape_string (name, -1); + pattern = g_strdup_printf ("\\b%s\\b", name_esc); + regex = g_regex_new (pattern, G_REGEX_CASELESS | G_REGEX_OPTIMIZE, 0, + &error); + + if (regex == NULL) { + DEBUG ("couldn't compile regex /%s/: %s", pattern, + error->message); + + g_error_free (error); + } + + g_free (pattern); + g_free (name_esc); + + return regex; +} + +/* Called when priv->self_contact changes, or priv->self_contact:alias changes. + * Only connected if empathy_chat_is_room() is TRUE, for obvious-ish reasons. + */ +static void +chat_self_contact_alias_changed_cb (EmpathyChat *chat) +{ + EmpathyChatPriv *priv = GET_PRIV (chat); + + tp_clear_pointer (&priv->highlight_regex, g_regex_unref); + + if (priv->self_contact != NULL) { + const gchar *alias = empathy_contact_get_alias (priv->self_contact); + + g_return_if_fail (alias != NULL); + priv->highlight_regex = get_highlight_regex_for (alias); + } +} + +static gboolean +chat_should_highlight (EmpathyChat *chat, + EmpathyMessage *message) +{ + EmpathyChatPriv *priv = GET_PRIV (chat); + const gchar *msg; + TpChannelTextMessageFlags flags; + + g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE); + + if (!empathy_chat_is_room (chat)) { + return FALSE; + } + + if (!empathy_message_is_incoming (message)) { + return FALSE; + } + + msg = empathy_message_get_body (message); + if (!msg) { + return FALSE; + } + + flags = empathy_message_get_flags (message); + if (flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_SCROLLBACK) { + /* FIXME: Ideally we shouldn't highlight scrollback messages only if they + * have already been received by the user before (and so are in the logs) */ + return FALSE; + } + + if (priv->highlight_regex == NULL) { + return FALSE; + } + + return g_regex_match (priv->highlight_regex, msg, 0, NULL); +} + static void chat_message_received (EmpathyChat *chat, EmpathyMessage *message, @@ -1391,19 +1501,26 @@ chat_message_received (EmpathyChat *chat, empathy_chat_view_edit_message (chat->view, message); } else { + gboolean should_highlight = chat_should_highlight (chat, message); + + if (should_highlight) { + priv->highlighted = TRUE; + } + DEBUG ("Appending new message '%s' from %s (%d)", empathy_message_get_token (message), empathy_contact_get_alias (sender), empathy_contact_get_handle (sender)); - empathy_chat_view_append_message (chat->view, message); + empathy_chat_view_append_message (chat->view, message, should_highlight); if (empathy_message_is_incoming (message)) { priv->unread_messages++; g_object_notify (G_OBJECT (chat), "nb-unread-messages"); } - g_signal_emit (chat, signals[NEW_MESSAGE], 0, message, pending); + g_signal_emit (chat, signals[NEW_MESSAGE], 0, message, pending, + should_highlight); } /* We received a message so the contact is no longer @@ -1437,6 +1554,51 @@ chat_message_acknowledged_cb (EmpathyTpChat *tp_chat, } } +static void +append_balance_error (EmpathyChat *chat, + const gchar *message_body) +{ + EmpathyChatPriv *priv = GET_PRIV (chat); + TpConnection *conn = tp_channel_borrow_connection (TP_CHANNEL (priv->tp_chat)); + const gchar *uri = tp_connection_get_balance_uri (conn); + const gchar *error = _("insufficient balance to send message"); + gchar *str, *str_markup = NULL; + + if (message_body != NULL) { + str = g_strdup_printf (_("Error sending message '%s': %s"), message_body, error); + } else { + str = g_strdup_printf (_("Error sending message: %s"), error); + } + + if (!tp_str_empty (uri)) { + /* translators: error used when user doesn't have enough credit on his + * account to send the message. */ + gchar *markup_error = g_strdup_printf (_("insufficient balance to send message." + " Top up."), uri); + + if (message_body != NULL) { + gchar *escaped_body = g_markup_escape_text (message_body, -1); + + str_markup = g_strdup_printf (_("Error sending message '%s': %s"), + escaped_body, markup_error); + + g_free (escaped_body); + } else { + str_markup = g_strdup_printf (_("Error sending message: %s"), markup_error); + } + + g_free (markup_error); + } + + if (str_markup != NULL) + empathy_chat_view_append_event_markup (chat->view, str_markup, str); + else + empathy_chat_view_append_event (chat->view, str); + + g_free (str); + g_free (str_markup); +} + static void chat_send_error_cb (EmpathyTpChat *tp_chat, const gchar *message_body, @@ -1448,9 +1610,8 @@ chat_send_error_cb (EmpathyTpChat *tp_chat, gchar *str; if (!tp_strdiff (dbus_error, TP_ERROR_STR_INSUFFICIENT_BALANCE)) { - /* translators: error used when user doesn't have enough credit on his - * account to send the message. */ - error = _("insufficient balance to send message"); + append_balance_error (chat, message_body); + return; } else if (!tp_strdiff (dbus_error, TP_ERROR_STR_NOT_CAPABLE)) { error = _("not capable"); } @@ -1526,16 +1687,12 @@ chat_topic_expander_activate_cb (GtkExpander *expander, } static void -chat_property_changed_cb (EmpathyTpChat *tp_chat, - const gchar *name, - GValue *value, - EmpathyChat *chat) +chat_subject_changed_cb (EmpathyChat *chat) { EmpathyChatPriv *priv = GET_PRIV (chat); - if (!tp_strdiff (name, "subject")) { g_free (priv->subject); - priv->subject = g_value_dup_string (value); + priv->subject = g_strdup (empathy_tp_chat_get_subject (priv->tp_chat)); g_object_notify (G_OBJECT (chat), "subject"); if (EMP_STR_EMPTY (priv->subject)) { @@ -1555,22 +1712,37 @@ chat_property_changed_cb (EmpathyTpChat *tp_chat, gtk_widget_show (priv->hbox_topic); } if (priv->block_events_timeout_id == 0) { - gchar *str; + gchar *str = NULL; if (!EMP_STR_EMPTY (priv->subject)) { - str = g_strdup_printf (_("Topic set to: %s"), priv->subject); - } else { + const gchar *actor = empathy_tp_chat_get_subject_actor (priv->tp_chat); + + if (tp_str_empty (actor)) { + str = g_strdup_printf (_("Topic set to: %s"), priv->subject); + } else { + str = g_strdup_printf (_("Topic set by %s to: %s"), + actor, priv->subject); + } + } else if (empathy_tp_chat_supports_subject (priv->tp_chat)) { + /* No need to display this 'event' is no topic can be defined anyway */ str = g_strdup (_("No topic defined")); } - empathy_chat_view_append_event (EMPATHY_CHAT (chat)->view, str); - g_free (str); + + if (str != NULL) { + empathy_chat_view_append_event (EMPATHY_CHAT (chat)->view, str); + g_free (str); + } } - } - else if (!tp_strdiff (name, "name")) { +} + +static void +chat_title_changed_cb (EmpathyChat *chat) +{ + EmpathyChatPriv *priv = GET_PRIV (chat); + g_free (priv->name); - priv->name = g_value_dup_string (value); + priv->name = g_strdup (empathy_tp_chat_get_title (priv->tp_chat)); g_object_notify (G_OBJECT (chat), "name"); - } } static gboolean @@ -2277,7 +2449,10 @@ chat_input_populate_popup_cb (GtkTextView *view, switch (priv->most_recent_event_type) { case GDK_BUTTON_PRESS: /* get the location from the pointer */ - gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y); + gdk_window_get_device_position (gtk_widget_get_window (GTK_WIDGET (view)), + gdk_device_manager_get_client_pointer (gdk_display_get_device_manager ( + gtk_widget_get_display (GTK_WIDGET (view)))), &x, &y, NULL); + gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view), GTK_TEXT_WINDOW_WIDGET, x, y, @@ -2435,13 +2610,15 @@ got_filtered_messages_cb (GObject *manager, "sender", empathy_message_get_sender (message), NULL); - empathy_chat_view_append_message (chat->view, syn_msg); + empathy_chat_view_append_message (chat->view, syn_msg, + chat_should_highlight (chat, syn_msg)); empathy_chat_view_edit_message (chat->view, message); g_object_unref (syn_msg); } else { /* append the latest message */ - empathy_chat_view_append_message (chat->view, message); + empathy_chat_view_append_message (chat->view, message, + chat_should_highlight (chat, message)); } g_object_unref (message); @@ -2636,9 +2813,22 @@ chat_member_renamed_cb (EmpathyTpChat *tp_chat, } static gboolean -chat_reset_size_request (gpointer widget) +chat_contacts_visible_timeout_cb (gpointer chat) { - gtk_widget_set_size_request (widget, -1, -1); + EmpathyChatPriv *priv = GET_PRIV (chat); + + /* Relax the size request */ + gtk_widget_set_size_request (priv->vbox_left, -1, -1); + + /* Set the position of the slider. This must be done here because + * GtkPaned need to know its size allocation and it will be settled only + * after the gtk_window_resize () tough effect. */ + if (priv->contacts_width > 0) { + gtk_paned_set_position (GTK_PANED (priv->hpaned), + priv->contacts_width); + } + + priv->contacts_visible_id = 0; return FALSE; } @@ -2648,7 +2838,6 @@ chat_update_contacts_visibility (EmpathyChat *chat, gboolean show) { EmpathyChatPriv *priv = GET_PRIV (chat); - GtkAllocation allocation; if (!priv->scrolled_window_contacts) { return; @@ -2659,8 +2848,9 @@ chat_update_contacts_visibility (EmpathyChat *chat, } if (show && priv->contact_list_view == NULL) { - EmpathyContactListStore *store; + EmpathyIndividualStore *store; gint min_width; + GtkAllocation allocation; /* We are adding the contact list to the chat, we don't want the * chat view to become too small. If the chat view is already @@ -2671,26 +2861,35 @@ chat_update_contacts_visibility (EmpathyChat *chat, gtk_widget_get_allocation (priv->vbox_left, &allocation); min_width = MIN (allocation.width, 250); gtk_widget_set_size_request (priv->vbox_left, min_width, -1); - g_idle_add (chat_reset_size_request, priv->vbox_left); - if (priv->contacts_width > 0) { - gtk_paned_set_position (GTK_PANED (priv->hpaned), - priv->contacts_width); - } + /* There is no way to know when the window resize will happen + * since it is WM's decision. Let's hope it won't be longer. */ + if (priv->contacts_visible_id != 0) + g_source_remove (priv->contacts_visible_id); + priv->contacts_visible_id = g_timeout_add (500, + chat_contacts_visible_timeout_cb, chat); + + store = EMPATHY_INDIVIDUAL_STORE ( + empathy_individual_store_channel_new ((TpChannel *) priv->tp_chat)); + + empathy_individual_store_set_show_groups (store, FALSE); + + priv->contact_list_view = GTK_WIDGET (empathy_individual_view_new (store, + EMPATHY_INDIVIDUAL_VIEW_FEATURE_INDIVIDUAL_TOOLTIP, + EMPATHY_INDIVIDUAL_FEATURE_ADD_CONTACT | + EMPATHY_INDIVIDUAL_FEATURE_CHAT | + EMPATHY_INDIVIDUAL_FEATURE_CALL | + EMPATHY_INDIVIDUAL_FEATURE_LOG | + EMPATHY_INDIVIDUAL_FEATURE_INFO)); + + empathy_individual_view_set_show_offline ( + EMPATHY_INDIVIDUAL_VIEW (priv->contact_list_view), TRUE); + empathy_individual_view_set_show_uninteresting ( + EMPATHY_INDIVIDUAL_VIEW (priv->contact_list_view), TRUE); - store = empathy_contact_list_store_new ( - EMPATHY_CONTACT_LIST (priv->tp_chat)); - empathy_contact_list_store_set_show_groups ( - EMPATHY_CONTACT_LIST_STORE (store), FALSE); - - priv->contact_list_view = GTK_WIDGET (empathy_contact_list_view_new (store, - EMPATHY_CONTACT_LIST_FEATURE_CONTACT_TOOLTIP, - EMPATHY_CONTACT_FEATURE_CHAT | - EMPATHY_CONTACT_FEATURE_CALL | - EMPATHY_CONTACT_FEATURE_LOG | - EMPATHY_CONTACT_FEATURE_INFO)); gtk_container_add (GTK_CONTAINER (priv->scrolled_window_contacts), priv->contact_list_view); + gtk_widget_show (priv->contact_list_view); gtk_widget_show (priv->scrolled_window_contacts); g_object_unref (store); @@ -2717,6 +2916,32 @@ empathy_chat_set_show_contacts (EmpathyChat *chat, g_object_notify (G_OBJECT (chat), "show-contacts"); } +static void +chat_self_contact_changed_cb (EmpathyChat *chat) +{ + EmpathyChatPriv *priv = GET_PRIV (chat); + + if (priv->self_contact != NULL) { + g_signal_handlers_disconnect_by_func (priv->self_contact, + chat_self_contact_alias_changed_cb, + chat); + } + g_clear_object (&priv->self_contact); + + priv->self_contact = empathy_tp_chat_get_self_contact (priv->tp_chat); + if (priv->self_contact != NULL) { + g_object_ref (priv->self_contact); + + if (empathy_chat_is_room (chat)) { + g_signal_connect_swapped (priv->self_contact, "notify::alias", + G_CALLBACK (chat_self_contact_alias_changed_cb), + chat); + } + } + + chat_self_contact_alias_changed_cb (chat); +} + static void chat_remote_contact_changed_cb (EmpathyChat *chat) { @@ -2918,7 +3143,6 @@ chat_create_ui (EmpathyChat *chat) GList *list = NULL; gchar *filename; GtkTextBuffer *buffer; - gint paned_pos; EmpathyThemeManager *theme_mgr; filename = empathy_file_lookup ("empathy-chat.ui", @@ -3004,12 +3228,6 @@ chat_create_ui (EmpathyChat *chat) G_CALLBACK (chat_hpaned_pos_changed_cb), chat); - /* Load the paned position */ - paned_pos = g_settings_get_int (priv->gsettings_ui, - EMPATHY_PREFS_UI_CHAT_WINDOW_PANED_POS); - if (paned_pos != 0) - gtk_paned_set_position (GTK_PANED(priv->hpaned), paned_pos); - /* Set widget focus order */ list = g_list_append (NULL, priv->search_bar); list = g_list_append (list, priv->scrolled_window_input); @@ -3048,6 +3266,9 @@ chat_finalize (GObject *object) if (priv->save_paned_pos_id != 0) g_source_remove (priv->save_paned_pos_id); + if (priv->contacts_visible_id != 0) + g_source_remove (priv->contacts_visible_id); + g_object_unref (priv->gsettings_chat); g_object_unref (priv->gsettings_ui); @@ -3073,18 +3294,28 @@ chat_finalize (GObject *object) chat_send_error_cb, chat); g_signal_handlers_disconnect_by_func (priv->tp_chat, chat_state_changed_cb, chat); - g_signal_handlers_disconnect_by_func (priv->tp_chat, - chat_property_changed_cb, chat); g_signal_handlers_disconnect_by_func (priv->tp_chat, chat_members_changed_cb, chat); + g_signal_handlers_disconnect_by_func (priv->tp_chat, + chat_self_contact_changed_cb, chat); g_signal_handlers_disconnect_by_func (priv->tp_chat, chat_remote_contact_changed_cb, chat); + g_signal_handlers_disconnect_by_func (priv->tp_chat, + chat_title_changed_cb, chat); + g_signal_handlers_disconnect_by_func (priv->tp_chat, + chat_subject_changed_cb, chat); empathy_tp_chat_leave (priv->tp_chat, ""); g_object_unref (priv->tp_chat); } if (priv->account) { g_object_unref (priv->account); } + if (priv->self_contact) { + g_signal_handlers_disconnect_by_func (priv->self_contact, + chat_self_contact_alias_changed_cb, + chat); + g_object_unref (priv->self_contact); + } if (priv->remote_contact) { g_object_unref (priv->remote_contact); } @@ -3098,6 +3329,8 @@ chat_finalize (GObject *object) g_free (priv->subject); g_completion_free (priv->completion); + tp_clear_pointer (&priv->highlight_regex, g_regex_unref); + G_OBJECT_CLASS (empathy_chat_parent_class)->finalize (object); } @@ -3216,19 +3449,27 @@ empathy_chat_class_init (EmpathyChatClass *klass) G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + /** + * EmpathyChat::new-message: + * @self: the #EmpathyChat + * @message: the new message + * @pending: whether the message was in the pending queue when @self + * was created + * @should_highlight: %TRUE if the message mentions the local user + */ signals[NEW_MESSAGE] = g_signal_new ("new-message", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _empathy_gtk_marshal_VOID__OBJECT_BOOLEAN, + g_cclosure_marshal_generic, G_TYPE_NONE, - 2, EMPATHY_TYPE_MESSAGE, G_TYPE_BOOLEAN); + 3, EMPATHY_TYPE_MESSAGE, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); signals[PART_COMMAND_ENTERED] = g_signal_new ("part-command-entered", @@ -3236,7 +3477,7 @@ empathy_chat_class_init (EmpathyChatClass *klass) G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_STRV); @@ -3292,7 +3533,8 @@ empathy_chat_init (EmpathyChat *chat) priv->gsettings_chat = g_settings_new (EMPATHY_PREFS_CHAT_SCHEMA); priv->gsettings_ui = g_settings_new (EMPATHY_PREFS_UI_SCHEMA); - priv->contacts_width = -1; + priv->contacts_width = g_settings_get_int (priv->gsettings_ui, + EMPATHY_PREFS_UI_CHAT_WINDOW_PANED_POS); priv->input_history = NULL; priv->input_history_current = NULL; priv->account_manager = tp_account_manager_dup (); @@ -3403,7 +3645,7 @@ chat_prompt_to_save_password (EmpathyChat *self, gtk_info_bar_set_message_type (GTK_INFO_BAR (data->info_bar), GTK_MESSAGE_QUESTION); - hbox = gtk_hbox_new (FALSE, 5); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0); /* Add image */ @@ -3597,7 +3839,7 @@ display_password_info_bar (EmpathyChat *self) content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar)); - hbox = gtk_hbox_new (FALSE, 5); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0); /* Add image */ @@ -3757,7 +3999,6 @@ empathy_chat_set_tp_chat (EmpathyChat *chat, EmpathyTpChat *tp_chat) { EmpathyChatPriv *priv = GET_PRIV (chat); - GPtrArray *properties; g_return_if_fail (EMPATHY_IS_CHAT (chat)); g_return_if_fail (EMPATHY_IS_TP_CHAT (tp_chat)); @@ -3788,15 +4029,15 @@ empathy_chat_set_tp_chat (EmpathyChat *chat, g_signal_connect (tp_chat, "chat-state-changed-empathy", G_CALLBACK (chat_state_changed_cb), chat); - g_signal_connect (tp_chat, "property-changed", - G_CALLBACK (chat_property_changed_cb), - chat); g_signal_connect (tp_chat, "members-changed", G_CALLBACK (chat_members_changed_cb), chat); g_signal_connect (tp_chat, "member-renamed", G_CALLBACK (chat_member_renamed_cb), chat); + g_signal_connect_swapped (tp_chat, "notify::self-contact", + G_CALLBACK (chat_self_contact_changed_cb), + chat); g_signal_connect_swapped (tp_chat, "notify::remote-contact", G_CALLBACK (chat_remote_contact_changed_cb), chat); @@ -3809,28 +4050,19 @@ empathy_chat_set_tp_chat (EmpathyChat *chat, g_signal_connect_swapped (tp_chat, "notify::n-messages-sending", G_CALLBACK (chat_n_messages_sending_changed_cb), chat); + g_signal_connect_swapped (tp_chat, "notify::title", + G_CALLBACK (chat_title_changed_cb), + chat); + g_signal_connect_swapped (tp_chat, "notify::subject", + G_CALLBACK (chat_subject_changed_cb), + chat); /* Get initial value of properties */ - properties = empathy_tp_chat_get_properties (priv->tp_chat); - if (properties != NULL) { - guint i; - - for (i = 0; i < properties->len; i++) { - EmpathyTpChatProperty *property; - - property = g_ptr_array_index (properties, i); - if (property->value == NULL) - continue; - - chat_property_changed_cb (priv->tp_chat, - property->name, - property->value, - chat); - } - } - chat_sms_channel_changed_cb (chat); + chat_self_contact_changed_cb (chat); chat_remote_contact_changed_cb (chat); + chat_title_changed_cb (chat); + chat_subject_changed_cb (chat); if (chat->input_text_view) { gtk_widget_set_sensitive (chat->input_text_view, TRUE); @@ -3925,16 +4157,30 @@ empathy_chat_get_contact_menu (EmpathyChat *chat) { EmpathyChatPriv *priv = GET_PRIV (chat); GtkWidget *menu = NULL; + FolksIndividual *individual; + TpContact *contact; g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL); - if (priv->remote_contact) { - menu = empathy_contact_menu_new (priv->remote_contact, - EMPATHY_CONTACT_FEATURE_CALL | - EMPATHY_CONTACT_FEATURE_LOG | - EMPATHY_CONTACT_FEATURE_INFO | - EMPATHY_CONTACT_FEATURE_BLOCK); - } + if (priv->remote_contact == NULL) + return NULL; + + contact = empathy_contact_get_tp_contact (priv->remote_contact); + if (contact == NULL) + return NULL; + + individual = empathy_ensure_individual_from_tp_contact (contact); + + if (individual == NULL) + return NULL; + + menu = empathy_individual_menu_new (individual, + EMPATHY_INDIVIDUAL_FEATURE_CALL | + EMPATHY_INDIVIDUAL_FEATURE_LOG | + EMPATHY_INDIVIDUAL_FEATURE_INFO | + EMPATHY_INDIVIDUAL_FEATURE_BLOCK, NULL); + + g_object_unref (individual); return menu; } @@ -4086,6 +4332,16 @@ empathy_chat_is_room (EmpathyChat *chat) return (priv->handle_type == TP_HANDLE_TYPE_ROOM); } +gboolean +empathy_chat_is_highlighted (EmpathyChat *chat) +{ + EmpathyChatPriv *priv = GET_PRIV (chat); + + g_return_val_if_fail (EMPATHY_IS_CHAT (chat), FALSE); + + return priv->highlighted; +} + guint empathy_chat_get_nb_unread_messages (EmpathyChat *self) { @@ -4114,6 +4370,8 @@ empathy_chat_messages_read (EmpathyChat *self) TP_TEXT_CHANNEL (priv->tp_chat), NULL, NULL); } + priv->highlighted = FALSE; + if (priv->unread_messages_when_offline > 0) { /* We can't ack those as the connection has gone away so just consider * them as read. */