]> git.0d.be Git - empathy.git/commitdiff
Merge branch 'highlight-regex'
authorWill Thompson <will@willthompson.co.uk>
Wed, 25 Jan 2012 16:01:32 +0000 (16:01 +0000)
committerWill Thompson <will@willthompson.co.uk>
Wed, 25 Jan 2012 16:01:32 +0000 (16:01 +0000)
1  2 
libempathy-gtk/empathy-chat.c

index be5d71ec74d68b91a3bae5a6771b18bfbea06895,d3c503206d9d37e4f0d1b850d2c4669146cd541e..81350220b0589691a5afe99ed36213c3e58d8474
@@@ -73,6 -73,7 +73,7 @@@ struct _EmpathyChatPriv 
        gchar             *id;
        gchar             *name;
        gchar             *subject;
+       EmpathyContact    *self_contact;
        EmpathyContact    *remote_contact;
        gboolean           show_contacts;
  
         * 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;
  };
  
  typedef struct {
@@@ -896,14 -901,12 +901,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);
@@@ -1383,6 -1386,86 +1386,86 @@@ chat_state_changed_cb (EmpathyTpCha
        }
  }
  
+ 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,
  
                empathy_chat_view_edit_message (chat->view, message);
        } else {
+               gboolean should_highlight = chat_should_highlight (chat, message);
                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
@@@ -1604,19 -1689,15 +1689,19 @@@ chat_subject_changed_cb (EmpathyChat *c
                        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 {
 +                      } 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);
 +                      }
                }
  }
  
@@@ -2495,13 -2576,15 +2580,15 @@@ got_filtered_messages_cb (GObject *mana
                                "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);
@@@ -2799,6 -2882,32 +2886,32 @@@ empathy_chat_set_show_contacts (Empathy
        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)
  {
@@@ -3153,6 -3262,8 +3266,8 @@@ chat_finalize (GObject *object
                        chat_state_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,
        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);
        }
        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);
  }
  
@@@ -3300,6 -3419,14 +3423,14 @@@ empathy_chat_class_init (EmpathyChatCla
                              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),
                              NULL, NULL,
                              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",
@@@ -3874,6 -4001,9 +4005,9 @@@ empathy_chat_set_tp_chat (EmpathyCha
        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);
  
        /* Get initial value of properties */
        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);