]> git.0d.be Git - empathy.git/commitdiff
Remove vtable and add info as properties. Reorder empathy-chat.c to not declare func...
authorXavier Claessens <xclaesse@src.gnome.org>
Wed, 2 Apr 2008 09:41:36 +0000 (09:41 +0000)
committerXavier Claessens <xclaesse@src.gnome.org>
Wed, 2 Apr 2008 09:41:36 +0000 (09:41 +0000)
svn path=/trunk/; revision=835

libempathy-gtk/empathy-chat.c
libempathy-gtk/empathy-chat.h

index 0d632faf75c17c7911c22c8b589a7de49577497b..9c6b61d272c6a89c93dfed73d586b7bc6b8387e0 100644 (file)
@@ -81,6 +81,10 @@ struct _EmpathyChatPriv {
        GList                 *backlog_messages;
        gboolean               is_first_char;
        guint                  block_events_timeout_id;
+       TpHandleType           handle_type;
+       gchar                 *name;
+       gchar                 *tooltip;
+       const gchar           *icon_name;
        /* Used to automatically shrink a window that has temporarily
         * grown due to long input. 
         */
@@ -90,80 +94,22 @@ struct _EmpathyChatPriv {
        gboolean               vscroll_visible;
 };
 
-typedef struct {
-       EmpathyChat  *chat;
-       gchar       *word;
-
-       GtkTextIter  start;
-       GtkTextIter  end;
-} EmpathyChatSpell;
-
-static void             empathy_chat_class_init           (EmpathyChatClass       *klass);
-static void             empathy_chat_init                 (EmpathyChat            *chat);
-static void             chat_finalize                     (GObject                *object);
-static void             chat_destroy_cb                   (EmpathyTpChat          *tp_chat,
-                                                          EmpathyChat            *chat);
-static void             chat_send                         (EmpathyChat            *chat,
-                                                          const gchar            *msg);
-static void             chat_input_text_view_send         (EmpathyChat            *chat);
-static void             chat_message_received_cb          (EmpathyTpChat          *tp_chat,
-                                                          EmpathyMessage         *message,
-                                                          EmpathyChat            *chat);
-static void             chat_send_error_cb                (EmpathyTpChat          *tp_chat,
-                                                          EmpathyMessage         *message,
-                                                          TpChannelTextSendError  error_code,
-                                                          EmpathyChat            *chat);
-static void             chat_sent_message_add             (EmpathyChat            *chat,
-                                                          const gchar            *str);
-static const gchar *    chat_sent_message_get_next        (EmpathyChat            *chat);
-static const gchar *    chat_sent_message_get_last        (EmpathyChat            *chat);
-static gboolean         chat_input_key_press_event_cb     (GtkWidget              *widget,
-                                                          GdkEventKey            *event,
-                                                          EmpathyChat            *chat);
-static void             chat_input_text_buffer_changed_cb (GtkTextBuffer          *buffer,
-                                                          EmpathyChat            *chat);
-static gboolean         chat_text_view_focus_in_event_cb  (GtkWidget              *widget,
-                                                          GdkEvent               *event,
-                                                          EmpathyChat            *chat);
-static void             chat_text_view_scroll_hide_cb     (GtkWidget              *widget,
-                                                          EmpathyChat            *chat);
-static void             chat_text_view_size_allocate_cb   (GtkWidget              *widget,
-                                                          GtkAllocation          *allocation,
-                                                          EmpathyChat            *chat);
-static void             chat_text_view_realize_cb         (GtkWidget              *widget,
-                                                          EmpathyChat            *chat);
-static void             chat_text_populate_popup_cb       (GtkTextView            *view,
-                                                          GtkMenu                *menu,
-                                                          EmpathyChat            *chat);
-static void             chat_text_check_word_spelling_cb  (GtkMenuItem            *menuitem,
-                                                          EmpathyChatSpell       *chat_spell);
-static EmpathyChatSpell *chat_spell_new                   (EmpathyChat            *chat,
-                                                          const gchar            *word,
-                                                          GtkTextIter             start,
-                                                          GtkTextIter             end);
-static void             chat_spell_free                   (EmpathyChatSpell       *chat_spell);
-static void             chat_composing_start              (EmpathyChat            *chat);
-static void             chat_composing_stop               (EmpathyChat            *chat);
-static void             chat_composing_remove_timeout     (EmpathyChat            *chat);
-static gboolean         chat_composing_stop_timeout_cb    (EmpathyChat            *chat);
-static void             chat_state_changed_cb             (EmpathyTpChat          *tp_chat,
-                                                          EmpathyContact         *contact,
-                                                          TpChannelChatState      state,
-                                                          EmpathyChat            *chat);
-static void             chat_add_logs                     (EmpathyChat            *chat);
-static gboolean         chat_scroll_down_idle_func        (EmpathyChat            *chat);
+static void empathy_chat_class_init (EmpathyChatClass *klass);
+static void empathy_chat_init       (EmpathyChat      *chat);
 
 enum {
        COMPOSING,
        NEW_MESSAGE,
-       NAME_CHANGED,
-       STATUS_CHANGED,
        LAST_SIGNAL
 };
 
 enum {
        PROP_0,
-       PROP_TP_CHAT
+       PROP_TP_CHAT,
+       PROP_NAME,
+       PROP_TOOLTIP,
+       PROP_ICON_NAME,
+       PROP_WIDGET
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -182,6 +128,18 @@ chat_get_property (GObject    *object,
        case PROP_TP_CHAT:
                g_value_set_object (value, priv->tp_chat);
                break;
+       case PROP_NAME:
+               g_value_set_string (value, priv->name);
+               break;
+       case PROP_TOOLTIP:
+               g_value_set_string (value, priv->tooltip);
+               break;
+       case PROP_ICON_NAME:
+               g_value_set_string (value, priv->icon_name);
+               break;
+       case PROP_WIDGET:
+               g_value_set_object (value, priv->widget);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                break;
@@ -221,23 +179,15 @@ chat_status_changed_cb (MissionControl           *mc,
        account = mc_account_lookup (unique_name);
 
        if (status == TP_CONNECTION_STATUS_CONNECTED && !priv->tp_chat &&
-           empathy_account_equal (account, priv->account)) {
-               TpHandleType handle_type;
-
+           empathy_account_equal (account, priv->account) &&
+           priv->handle_type != 0) {
                empathy_debug (DEBUG_DOMAIN,
                               "Account reconnected, request a new Text channel");
-
-               if (empathy_chat_is_group_chat (chat)) {
-                       handle_type = TP_HANDLE_TYPE_ROOM;
-               } else {
-                       handle_type = TP_HANDLE_TYPE_CONTACT;
-               }
-
                mission_control_request_channel_with_string_handle (mc,
                                                                    priv->account,
                                                                    TP_IFACE_CHANNEL_TYPE_TEXT,
                                                                    priv->id,
-                                                                   handle_type,
+                                                                   priv->handle_type,
                                                                    NULL, NULL);
        }
 
@@ -245,136 +195,63 @@ chat_status_changed_cb (MissionControl           *mc,
 }
 
 static void
-empathy_chat_class_init (EmpathyChatClass *klass)
+chat_composing_remove_timeout (EmpathyChat *chat)
 {
-       GObjectClass *object_class;
-
-       object_class = G_OBJECT_CLASS (klass);
-
-       object_class->finalize = chat_finalize;
-       object_class->get_property = chat_get_property;
-       object_class->set_property = chat_set_property;
+       EmpathyChatPriv *priv;
 
-       g_object_class_install_property (object_class,
-                                        PROP_TP_CHAT,
-                                        g_param_spec_object ("tp-chat",
-                                                             "Empathy tp chat",
-                                                             "The tp chat object",
-                                                             EMPATHY_TYPE_TP_CHAT,
-                                                             G_PARAM_CONSTRUCT |
-                                                             G_PARAM_READWRITE));
+       priv = GET_PRIV (chat);
 
-       signals[COMPOSING] =
-               g_signal_new ("composing",
-                             G_OBJECT_CLASS_TYPE (object_class),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__BOOLEAN,
-                             G_TYPE_NONE,
-                             1, G_TYPE_BOOLEAN);
+       if (priv->composing_stop_timeout_id) {
+               g_source_remove (priv->composing_stop_timeout_id);
+               priv->composing_stop_timeout_id = 0;
+       }
+}
 
-       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_TYPE_NONE,
-                             2, EMPATHY_TYPE_MESSAGE, G_TYPE_BOOLEAN);
+static gboolean
+chat_composing_stop_timeout_cb (EmpathyChat *chat)
+{
+       EmpathyChatPriv *priv;
 
-       signals[NAME_CHANGED] =
-               g_signal_new ("name-changed",
-                             G_OBJECT_CLASS_TYPE (object_class),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__POINTER,
-                             G_TYPE_NONE,
-                             1, G_TYPE_POINTER);
+       priv = GET_PRIV (chat);
 
-       signals[STATUS_CHANGED] =
-               g_signal_new ("status-changed",
-                             G_OBJECT_CLASS_TYPE (object_class),
-                             G_SIGNAL_RUN_LAST,
-                             0,
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__VOID,
-                             G_TYPE_NONE,
-                             0);
+       priv->composing_stop_timeout_id = 0;
+       empathy_tp_chat_set_state (priv->tp_chat,
+                                  TP_CHANNEL_CHAT_STATE_PAUSED);
 
-       g_type_class_add_private (object_class, sizeof (EmpathyChatPriv));
+       return FALSE;
 }
 
 static void
-empathy_chat_init (EmpathyChat *chat)
+chat_composing_start (EmpathyChat *chat)
 {
-       EmpathyChatPriv *priv = GET_PRIV (chat);
-       GtkTextBuffer  *buffer;
-
-       chat->view = empathy_chat_view_new ();
-       chat->input_text_view = gtk_text_view_new ();
-
-       priv->is_first_char = TRUE;
-
-       g_object_set (chat->input_text_view,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     "pixels-inside-wrap", 1,
-                     "right-margin", 2,
-                     "left-margin", 2,
-                     "wrap-mode", GTK_WRAP_WORD_CHAR,
-                     NULL);
-
-       priv->log_manager = empathy_log_manager_new ();
-       priv->default_window_height = -1;
-       priv->vscroll_visible = FALSE;
-       priv->sensitive = TRUE;
-       priv->sent_messages = NULL;
-       priv->sent_messages_index = -1;
-       priv->first_tp_chat = TRUE;
-       priv->mc = empathy_mission_control_new ();
-
-       dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged",
-                                    G_CALLBACK (chat_status_changed_cb),
-                                    chat, NULL);
+       EmpathyChatPriv *priv;
 
-       g_signal_connect (chat->input_text_view,
-                         "key_press_event",
-                         G_CALLBACK (chat_input_key_press_event_cb),
-                         chat);
+       priv = GET_PRIV (chat);
 
-       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (chat->input_text_view));
-       g_signal_connect (buffer,
-                         "changed",
-                         G_CALLBACK (chat_input_text_buffer_changed_cb),
-                         chat);
-       g_signal_connect (chat->view,
-                         "focus_in_event",
-                         G_CALLBACK (chat_text_view_focus_in_event_cb),
-                         chat);
+       if (priv->composing_stop_timeout_id) {
+               /* Just restart the timeout */
+               chat_composing_remove_timeout (chat);
+       } else {
+               empathy_tp_chat_set_state (priv->tp_chat,
+                                          TP_CHANNEL_CHAT_STATE_COMPOSING);
+       }
 
-       g_signal_connect (chat->input_text_view,
-                         "size_allocate",
-                         G_CALLBACK (chat_text_view_size_allocate_cb),
-                         chat);
+       priv->composing_stop_timeout_id = g_timeout_add_seconds (
+               COMPOSING_STOP_TIMEOUT,
+               (GSourceFunc) chat_composing_stop_timeout_cb,
+               chat);
+}
 
-       g_signal_connect (chat->input_text_view,
-                         "realize",
-                         G_CALLBACK (chat_text_view_realize_cb),
-                         chat);
+static void
+chat_composing_stop (EmpathyChat *chat)
+{
+       EmpathyChatPriv *priv;
 
-       g_signal_connect (GTK_TEXT_VIEW (chat->input_text_view),
-                         "populate_popup",
-                         G_CALLBACK (chat_text_populate_popup_cb),
-                         chat);
+       priv = GET_PRIV (chat);
 
-       /* create misspelt words identification tag */
-       gtk_text_buffer_create_tag (buffer,
-                                   "misspelled",
-                                   "underline", PANGO_UNDERLINE_ERROR,
-                                   NULL);
+       chat_composing_remove_timeout (chat);
+       empathy_tp_chat_set_state (priv->tp_chat,
+                                  TP_CHANNEL_CHAT_STATE_ACTIVE);
 }
 
 static void
@@ -420,6 +297,8 @@ chat_finalize (GObject *object)
        }
 
        g_free (priv->id);
+       g_free (priv->name);
+       g_free (priv->tooltip);
 
        G_OBJECT_CLASS (empathy_chat_parent_class)->finalize (object);
 }
@@ -444,10 +323,97 @@ chat_destroy_cb (EmpathyTpChat *tp_chat,
        if (priv->block_events_timeout_id != 0) {
                g_source_remove (priv->block_events_timeout_id);
        }
+}
+
+static void 
+chat_sent_message_add (EmpathyChat  *chat,
+                      const gchar *str)
+{
+       EmpathyChatPriv *priv;
+       GSList         *list;
+       GSList         *item;
+
+       priv = GET_PRIV (chat);
+
+       /* Save the sent message in our repeat buffer */
+       list = priv->sent_messages;
+       
+       /* Remove any other occurances of this msg */
+       while ((item = g_slist_find_custom (list, str, (GCompareFunc) strcmp)) != NULL) {
+               list = g_slist_remove_link (list, item);
+               g_free (item->data);
+               g_slist_free1 (item);
+       }
+
+       /* Trim the list to the last 10 items */
+       while (g_slist_length (list) > 10) {
+               item = g_slist_last (list);
+               if (item) {
+                       list = g_slist_remove_link (list, item);
+                       g_free (item->data);
+                       g_slist_free1 (item);
+               }
+       }
+
+       /* Add new message */
+       list = g_slist_prepend (list, g_strdup (str));
+
+       /* Set list and reset the index */
+       priv->sent_messages = list;
+       priv->sent_messages_index = -1;
+}
+
+static const gchar *
+chat_sent_message_get_next (EmpathyChat *chat)
+{
+       EmpathyChatPriv *priv;
+       gint            max;
+       
+       priv = GET_PRIV (chat);
+
+       if (!priv->sent_messages) {
+               empathy_debug (DEBUG_DOMAIN, 
+                             "No sent messages, next message is NULL");
+               return NULL;
+       }
+
+       max = g_slist_length (priv->sent_messages) - 1;
 
-       if (EMPATHY_CHAT_GET_CLASS (chat)->set_tp_chat) {
-               EMPATHY_CHAT_GET_CLASS (chat)->set_tp_chat (chat, NULL);
+       if (priv->sent_messages_index < max) {
+               priv->sent_messages_index++;
        }
+       
+       empathy_debug (DEBUG_DOMAIN, 
+                     "Returning next message index:%d",
+                     priv->sent_messages_index);
+
+       return g_slist_nth_data (priv->sent_messages, priv->sent_messages_index);
+}
+
+static const gchar *
+chat_sent_message_get_last (EmpathyChat *chat)
+{
+       EmpathyChatPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL);
+
+       priv = GET_PRIV (chat);
+       
+       if (!priv->sent_messages) {
+               empathy_debug (DEBUG_DOMAIN, 
+                             "No sent messages, last message is NULL");
+               return NULL;
+       }
+
+       if (priv->sent_messages_index >= 0) {
+               priv->sent_messages_index--;
+       }
+
+       empathy_debug (DEBUG_DOMAIN, 
+                     "Returning last message index:%d",
+                     priv->sent_messages_index);
+
+       return g_slist_nth_data (priv->sent_messages, priv->sent_messages_index);
 }
 
 static void
@@ -470,9 +436,6 @@ chat_send (EmpathyChat  *chat,
                return;
        }
 
-       /* FIXME: add here something to let group/privrate chat handle
-        *        some special messages */
-
        message = empathy_message_new (msg);
 
        empathy_tp_chat_send (priv->tp_chat, message);
@@ -505,6 +468,67 @@ chat_input_text_view_send (EmpathyChat *chat)
        priv->is_first_char = TRUE;
 }
 
+static void
+chat_state_changed_cb (EmpathyTpChat      *tp_chat,
+                      EmpathyContact     *contact,
+                      TpChannelChatState  state,
+                      EmpathyChat        *chat)
+{
+       EmpathyChatPriv *priv;
+       GList          *l;
+       gboolean        was_composing;
+
+       priv = GET_PRIV (chat);
+
+       if (empathy_contact_is_user (contact)) {
+               /* We don't care about our own chat state */
+               return;
+       }
+
+       was_composing = (priv->compositors != NULL);
+
+       /* Find the contact in the list. After that l is the list elem or NULL */
+       for (l = priv->compositors; l; l = l->next) {
+               if (contact == l->data) {
+                       break;
+               }
+       }
+
+       switch (state) {
+       case TP_CHANNEL_CHAT_STATE_GONE:
+       case TP_CHANNEL_CHAT_STATE_INACTIVE:
+       case TP_CHANNEL_CHAT_STATE_PAUSED:
+       case TP_CHANNEL_CHAT_STATE_ACTIVE:
+               /* Contact is not composing */
+               if (l) {
+                       priv->compositors = g_list_remove_link (priv->compositors, l);
+                       g_object_unref (l->data);
+                       g_list_free1 (l);
+               }
+               break;
+       case TP_CHANNEL_CHAT_STATE_COMPOSING:
+               /* Contact is composing */
+               if (!l) {
+                       priv->compositors = g_list_prepend (priv->compositors,
+                                                           g_object_ref (contact));
+               }
+               break;
+       default:
+               g_assert_not_reached ();
+       }
+
+       empathy_debug (DEBUG_DOMAIN, "Was composing: %s now composing: %s",
+                     was_composing ? "yes" : "no",
+                     priv->compositors ? "yes" : "no");
+
+       if ((was_composing && !priv->compositors) ||
+           (!was_composing && priv->compositors)) {
+               /* Composing state changed */
+               g_signal_emit (chat, signals[COMPOSING], 0,
+                              priv->compositors != NULL);
+       }
+}
+
 static void
 chat_message_received_cb (EmpathyTpChat  *tp_chat,
                          EmpathyMessage *message,
@@ -550,7 +574,7 @@ chat_message_received_cb (EmpathyTpChat  *tp_chat,
 
        empathy_log_manager_add_message (priv->log_manager,
                                         empathy_chat_get_id (chat),
-                                        empathy_chat_is_group_chat (chat),
+                                        FALSE,
                                         message);
 
        empathy_chat_view_append_message (chat->view, message);
@@ -586,212 +610,22 @@ chat_send_error_cb (EmpathyTpChat          *tp_chat,
        case TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED:
                error = _("permission denied");
                break;
-       case TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG:
-               error = _("too long message");
-               break;
-       case TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED:
-               error = _("not implemented");
-               break;
-       default:
-               error = _("unknown");
-               break;
-       }
-
-       str = g_strdup_printf (_("Error sending message '%s': %s"),
-                              empathy_message_get_body (message),
-                              error);
-       empathy_chat_view_append_event (chat->view, str);
-       g_free (str);
-}
-
-static void 
-chat_sent_message_add (EmpathyChat  *chat,
-                      const gchar *str)
-{
-       EmpathyChatPriv *priv;
-       GSList         *list;
-       GSList         *item;
-
-       priv = GET_PRIV (chat);
-
-       /* Save the sent message in our repeat buffer */
-       list = priv->sent_messages;
-       
-       /* Remove any other occurances of this msg */
-       while ((item = g_slist_find_custom (list, str, (GCompareFunc) strcmp)) != NULL) {
-               list = g_slist_remove_link (list, item);
-               g_free (item->data);
-               g_slist_free1 (item);
-       }
-
-       /* Trim the list to the last 10 items */
-       while (g_slist_length (list) > 10) {
-               item = g_slist_last (list);
-               if (item) {
-                       list = g_slist_remove_link (list, item);
-                       g_free (item->data);
-                       g_slist_free1 (item);
-               }
-       }
-
-       /* Add new message */
-       list = g_slist_prepend (list, g_strdup (str));
-
-       /* Set list and reset the index */
-       priv->sent_messages = list;
-       priv->sent_messages_index = -1;
-}
-
-static const gchar *
-chat_sent_message_get_next (EmpathyChat *chat)
-{
-       EmpathyChatPriv *priv;
-       gint            max;
-       
-       priv = GET_PRIV (chat);
-
-       if (!priv->sent_messages) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "No sent messages, next message is NULL");
-               return NULL;
-       }
-
-       max = g_slist_length (priv->sent_messages) - 1;
-
-       if (priv->sent_messages_index < max) {
-               priv->sent_messages_index++;
-       }
-       
-       empathy_debug (DEBUG_DOMAIN, 
-                     "Returning next message index:%d",
-                     priv->sent_messages_index);
-
-       return g_slist_nth_data (priv->sent_messages, priv->sent_messages_index);
-}
-
-static const gchar *
-chat_sent_message_get_last (EmpathyChat *chat)
-{
-       EmpathyChatPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL);
-
-       priv = GET_PRIV (chat);
-       
-       if (!priv->sent_messages) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "No sent messages, last message is NULL");
-               return NULL;
-       }
-
-       if (priv->sent_messages_index >= 0) {
-               priv->sent_messages_index--;
-       }
-
-       empathy_debug (DEBUG_DOMAIN, 
-                     "Returning last message index:%d",
-                     priv->sent_messages_index);
-
-       return g_slist_nth_data (priv->sent_messages, priv->sent_messages_index);
-}
-
-static gboolean
-chat_input_key_press_event_cb (GtkWidget   *widget,
-                              GdkEventKey *event,
-                              EmpathyChat *chat)
-{
-       EmpathyChatPriv *priv;
-       GtkAdjustment  *adj;
-       gdouble         val;
-       GtkWidget      *text_view_sw;
-
-       priv = GET_PRIV (chat);
-
-       /* Catch ctrl+up/down so we can traverse messages we sent */
-       if ((event->state & GDK_CONTROL_MASK) && 
-           (event->keyval == GDK_Up || 
-            event->keyval == GDK_Down)) {
-               GtkTextBuffer *buffer;
-               const gchar   *str;
-
-               buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (chat->input_text_view));
-
-               if (event->keyval == GDK_Up) {
-                       str = chat_sent_message_get_next (chat);
-               } else {
-                       str = chat_sent_message_get_last (chat);
-               }
-
-               g_signal_handlers_block_by_func (buffer, 
-                                                chat_input_text_buffer_changed_cb,
-                                                chat);
-               gtk_text_buffer_set_text (buffer, str ? str : "", -1);
-               g_signal_handlers_unblock_by_func (buffer, 
-                                                  chat_input_text_buffer_changed_cb,
-                                                  chat);
-
-               return TRUE;    
-       }
-
-       /* Catch enter but not ctrl/shift-enter */
-       if (IS_ENTER (event->keyval) &&
-           !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))) {
-               GtkTextView *view;
-
-               /* This is to make sure that kinput2 gets the enter. And if
-                * it's handled there we shouldn't send on it. This is because
-                * kinput2 uses Enter to commit letters. See:
-                * http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=104299
-                */
-
-               view = GTK_TEXT_VIEW (chat->input_text_view);
-               if (gtk_im_context_filter_keypress (view->im_context, event)) {
-                       GTK_TEXT_VIEW (chat->input_text_view)->need_im_reset = TRUE;
-                       return TRUE;
-               }
-
-               chat_input_text_view_send (chat);
-               return TRUE;
-       }
-
-       text_view_sw = gtk_widget_get_parent (GTK_WIDGET (chat->view));
-
-       if (IS_ENTER (event->keyval) &&
-           (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))) {
-               /* Newline for shift/control-enter. */
-               return FALSE;
-       }
-       else if (!(event->state & GDK_CONTROL_MASK) &&
-                event->keyval == GDK_Page_Up) {
-               adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (text_view_sw));
-               gtk_adjustment_set_value (adj, adj->value - adj->page_size);
-
-               return TRUE;
-       }
-       else if ((event->state & GDK_CONTROL_MASK) != GDK_CONTROL_MASK &&
-                event->keyval == GDK_Page_Down) {
-               adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (text_view_sw));
-               val = MIN (adj->value + adj->page_size, adj->upper - adj->page_size);
-               gtk_adjustment_set_value (adj, val);
-
-               return TRUE;
-       }
-
-       if (EMPATHY_CHAT_GET_CLASS (chat)->key_press_event) {
-               return EMPATHY_CHAT_GET_CLASS (chat)->key_press_event (chat, event);
+       case TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG:
+               error = _("too long message");
+               break;
+       case TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED:
+               error = _("not implemented");
+               break;
+       default:
+               error = _("unknown");
+               break;
        }
 
-       return FALSE;
-}
-
-static gboolean
-chat_text_view_focus_in_event_cb (GtkWidget  *widget,
-                                 GdkEvent   *event,
-                                 EmpathyChat *chat)
-{
-       gtk_widget_grab_focus (chat->input_text_view);
-
-       return TRUE;
+       str = g_strdup_printf (_("Error sending message '%s': %s"),
+                              empathy_message_get_body (message),
+                              error);
+       empathy_chat_view_append_event (chat->view, str);
+       g_free (str);
 }
 
 static void
@@ -894,6 +728,101 @@ chat_input_text_buffer_changed_cb (GtkTextBuffer *buffer,
        }
 }
 
+static gboolean
+chat_input_key_press_event_cb (GtkWidget   *widget,
+                              GdkEventKey *event,
+                              EmpathyChat *chat)
+{
+       EmpathyChatPriv *priv;
+       GtkAdjustment  *adj;
+       gdouble         val;
+       GtkWidget      *text_view_sw;
+
+       priv = GET_PRIV (chat);
+
+       /* Catch ctrl+up/down so we can traverse messages we sent */
+       if ((event->state & GDK_CONTROL_MASK) && 
+           (event->keyval == GDK_Up || 
+            event->keyval == GDK_Down)) {
+               GtkTextBuffer *buffer;
+               const gchar   *str;
+
+               buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (chat->input_text_view));
+
+               if (event->keyval == GDK_Up) {
+                       str = chat_sent_message_get_next (chat);
+               } else {
+                       str = chat_sent_message_get_last (chat);
+               }
+
+               g_signal_handlers_block_by_func (buffer, 
+                                                chat_input_text_buffer_changed_cb,
+                                                chat);
+               gtk_text_buffer_set_text (buffer, str ? str : "", -1);
+               g_signal_handlers_unblock_by_func (buffer, 
+                                                  chat_input_text_buffer_changed_cb,
+                                                  chat);
+
+               return TRUE;    
+       }
+
+       /* Catch enter but not ctrl/shift-enter */
+       if (IS_ENTER (event->keyval) &&
+           !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))) {
+               GtkTextView *view;
+
+               /* This is to make sure that kinput2 gets the enter. And if
+                * it's handled there we shouldn't send on it. This is because
+                * kinput2 uses Enter to commit letters. See:
+                * http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=104299
+                */
+
+               view = GTK_TEXT_VIEW (chat->input_text_view);
+               if (gtk_im_context_filter_keypress (view->im_context, event)) {
+                       GTK_TEXT_VIEW (chat->input_text_view)->need_im_reset = TRUE;
+                       return TRUE;
+               }
+
+               chat_input_text_view_send (chat);
+               return TRUE;
+       }
+
+       text_view_sw = gtk_widget_get_parent (GTK_WIDGET (chat->view));
+
+       if (IS_ENTER (event->keyval) &&
+           (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))) {
+               /* Newline for shift/control-enter. */
+               return FALSE;
+       }
+       else if (!(event->state & GDK_CONTROL_MASK) &&
+                event->keyval == GDK_Page_Up) {
+               adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (text_view_sw));
+               gtk_adjustment_set_value (adj, adj->value - adj->page_size);
+
+               return TRUE;
+       }
+       else if ((event->state & GDK_CONTROL_MASK) != GDK_CONTROL_MASK &&
+                event->keyval == GDK_Page_Down) {
+               adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (text_view_sw));
+               val = MIN (adj->value + adj->page_size, adj->upper - adj->page_size);
+               gtk_adjustment_set_value (adj, val);
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static gboolean
+chat_text_view_focus_in_event_cb (GtkWidget  *widget,
+                                 GdkEvent   *event,
+                                 EmpathyChat *chat)
+{
+       gtk_widget_grab_focus (chat->input_text_view);
+
+       return TRUE;
+}
+
 typedef struct {
        GtkWindow *window;
        gint       width;
@@ -1029,6 +958,50 @@ chat_insert_smiley_activate_cb (GtkWidget   *menuitem,
        gtk_text_buffer_insert (buffer, &iter, " ", -1);
 }
 
+typedef struct {
+       EmpathyChat  *chat;
+       gchar       *word;
+
+       GtkTextIter  start;
+       GtkTextIter  end;
+} EmpathyChatSpell;
+
+static EmpathyChatSpell *
+chat_spell_new (EmpathyChat  *chat,
+               const gchar *word,
+               GtkTextIter  start,
+               GtkTextIter  end)
+{
+       EmpathyChatSpell *chat_spell;
+
+       chat_spell = g_slice_new0 (EmpathyChatSpell);
+
+       chat_spell->chat = g_object_ref (chat);
+       chat_spell->word = g_strdup (word);
+       chat_spell->start = start;
+       chat_spell->end = end;
+
+       return chat_spell;
+}
+
+static void
+chat_spell_free (EmpathyChatSpell *chat_spell)
+{
+       g_object_unref (chat_spell->chat);
+       g_free (chat_spell->word);
+       g_slice_free (EmpathyChatSpell, chat_spell);
+}
+
+static void
+chat_text_check_word_spelling_cb (GtkMenuItem     *menuitem,
+                                 EmpathyChatSpell *chat_spell)
+{
+       empathy_spell_dialog_show (chat_spell->chat,
+                                 chat_spell->start,
+                                 chat_spell->end,
+                                 chat_spell->word);
+}
+
 static void
 chat_text_populate_popup_cb (GtkTextView *view,
                             GtkMenu     *menu,
@@ -1069,200 +1042,58 @@ chat_text_populate_popup_cb (GtkTextView *view,
 
        gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
 
-       gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view),
-                                              GTK_TEXT_WINDOW_WIDGET,
-                                              x, y,
-                                              &x, &y);
-
-       gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter, x, y);
-
-       start = end = iter;
-
-       if (gtk_text_iter_backward_to_tag_toggle (&start, tag) &&
-           gtk_text_iter_forward_to_tag_toggle (&end, tag)) {
-
-               str = gtk_text_buffer_get_text (buffer,
-                                               &start, &end, FALSE);
-       }
-
-       if (G_STR_EMPTY (str)) {
-               return;
-       }
-
-       chat_spell = chat_spell_new (chat, str, start, end);
-
-       g_object_set_data_full (G_OBJECT (menu),
-                               "chat_spell", chat_spell,
-                               (GDestroyNotify) chat_spell_free);
-
-       item = gtk_separator_menu_item_new ();
-       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
-       gtk_widget_show (item);
-
-       item = gtk_menu_item_new_with_mnemonic (_("_Check Word Spelling..."));
-       g_signal_connect (item,
-                         "activate",
-                         G_CALLBACK (chat_text_check_word_spelling_cb),
-                         chat_spell);
-       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
-       gtk_widget_show (item);
-}
-
-static void
-chat_text_check_word_spelling_cb (GtkMenuItem     *menuitem,
-                                 EmpathyChatSpell *chat_spell)
-{
-       empathy_spell_dialog_show (chat_spell->chat,
-                                 chat_spell->start,
-                                 chat_spell->end,
-                                 chat_spell->word);
-}
-
-static EmpathyChatSpell *
-chat_spell_new (EmpathyChat  *chat,
-               const gchar *word,
-               GtkTextIter  start,
-               GtkTextIter  end)
-{
-       EmpathyChatSpell *chat_spell;
-
-       chat_spell = g_new0 (EmpathyChatSpell, 1);
-
-       chat_spell->chat = g_object_ref (chat);
-       chat_spell->word = g_strdup (word);
-       chat_spell->start = start;
-       chat_spell->end = end;
-
-       return chat_spell;
-}
-
-static void
-chat_spell_free (EmpathyChatSpell *chat_spell)
-{
-       g_object_unref (chat_spell->chat);
-       g_free (chat_spell->word);
-       g_free (chat_spell);
-}
-
-static void
-chat_composing_start (EmpathyChat *chat)
-{
-       EmpathyChatPriv *priv;
-
-       priv = GET_PRIV (chat);
-
-       if (priv->composing_stop_timeout_id) {
-               /* Just restart the timeout */
-               chat_composing_remove_timeout (chat);
-       } else {
-               empathy_tp_chat_set_state (priv->tp_chat,
-                                          TP_CHANNEL_CHAT_STATE_COMPOSING);
-       }
-
-       priv->composing_stop_timeout_id = g_timeout_add_seconds (
-               COMPOSING_STOP_TIMEOUT,
-               (GSourceFunc) chat_composing_stop_timeout_cb,
-               chat);
-}
-
-static void
-chat_composing_stop (EmpathyChat *chat)
-{
-       EmpathyChatPriv *priv;
+       gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view),
+                                              GTK_TEXT_WINDOW_WIDGET,
+                                              x, y,
+                                              &x, &y);
 
-       priv = GET_PRIV (chat);
+       gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter, x, y);
 
-       chat_composing_remove_timeout (chat);
-       empathy_tp_chat_set_state (priv->tp_chat,
-                                  TP_CHANNEL_CHAT_STATE_ACTIVE);
-}
+       start = end = iter;
 
-static void
-chat_composing_remove_timeout (EmpathyChat *chat)
-{
-       EmpathyChatPriv *priv;
+       if (gtk_text_iter_backward_to_tag_toggle (&start, tag) &&
+           gtk_text_iter_forward_to_tag_toggle (&end, tag)) {
 
-       priv = GET_PRIV (chat);
+               str = gtk_text_buffer_get_text (buffer,
+                                               &start, &end, FALSE);
+       }
 
-       if (priv->composing_stop_timeout_id) {
-               g_source_remove (priv->composing_stop_timeout_id);
-               priv->composing_stop_timeout_id = 0;
+       if (G_STR_EMPTY (str)) {
+               return;
        }
-}
 
-static gboolean
-chat_composing_stop_timeout_cb (EmpathyChat *chat)
-{
-       EmpathyChatPriv *priv;
+       chat_spell = chat_spell_new (chat, str, start, end);
 
-       priv = GET_PRIV (chat);
+       g_object_set_data_full (G_OBJECT (menu),
+                               "chat_spell", chat_spell,
+                               (GDestroyNotify) chat_spell_free);
 
-       priv->composing_stop_timeout_id = 0;
-       empathy_tp_chat_set_state (priv->tp_chat,
-                                  TP_CHANNEL_CHAT_STATE_PAUSED);
+       item = gtk_separator_menu_item_new ();
+       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show (item);
 
-       return FALSE;
+       item = gtk_menu_item_new_with_mnemonic (_("_Check Word Spelling..."));
+       g_signal_connect (item,
+                         "activate",
+                         G_CALLBACK (chat_text_check_word_spelling_cb),
+                         chat_spell);
+       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show (item);
 }
 
-static void
-chat_state_changed_cb (EmpathyTpChat      *tp_chat,
-                      EmpathyContact     *contact,
-                      TpChannelChatState  state,
-                      EmpathyChat        *chat)
+static gboolean
+chat_scroll_down_idle_func (EmpathyChat *chat)
 {
        EmpathyChatPriv *priv;
-       GList          *l;
-       gboolean        was_composing;
 
        priv = GET_PRIV (chat);
 
-       if (empathy_contact_is_user (contact)) {
-               /* We don't care about our own chat state */
-               return;
-       }
-
-       was_composing = (priv->compositors != NULL);
-
-       /* Find the contact in the list. After that l is the list elem or NULL */
-       for (l = priv->compositors; l; l = l->next) {
-               if (contact == l->data) {
-                       break;
-               }
-       }
-
-       switch (state) {
-       case TP_CHANNEL_CHAT_STATE_GONE:
-       case TP_CHANNEL_CHAT_STATE_INACTIVE:
-       case TP_CHANNEL_CHAT_STATE_PAUSED:
-       case TP_CHANNEL_CHAT_STATE_ACTIVE:
-               /* Contact is not composing */
-               if (l) {
-                       priv->compositors = g_list_remove_link (priv->compositors, l);
-                       g_object_unref (l->data);
-                       g_list_free1 (l);
-               }
-               break;
-       case TP_CHANNEL_CHAT_STATE_COMPOSING:
-               /* Contact is composing */
-               if (!l) {
-                       priv->compositors = g_list_prepend (priv->compositors,
-                                                           g_object_ref (contact));
-               }
-               break;
-       default:
-               g_assert_not_reached ();
-       }
+       empathy_chat_scroll_down (chat);
+       g_object_unref (chat);
 
-       empathy_debug (DEBUG_DOMAIN, "Was composing: %s now composing: %s",
-                     was_composing ? "yes" : "no",
-                     priv->compositors ? "yes" : "no");
+       priv->scroll_idle_id = 0;
 
-       if ((was_composing && !priv->compositors) ||
-           (!was_composing && priv->compositors)) {
-               /* Composing state changed */
-               g_signal_emit (chat, signals[COMPOSING], 0,
-                              priv->compositors != NULL);
-       }
+       return FALSE;
 }
 
 static void
@@ -1282,7 +1113,7 @@ chat_add_logs (EmpathyChat *chat)
        messages = empathy_log_manager_get_last_messages (priv->log_manager,
                                                          priv->account,
                                                          empathy_chat_get_id (chat),
-                                                         empathy_chat_is_group_chat (chat));
+                                                         FALSE);
        num_messages  = g_list_length (messages);
 
        /* Only keep the 10 last messages */
@@ -1309,20 +1140,145 @@ chat_add_logs (EmpathyChat *chat)
                                           g_object_ref (chat));
 }
 
-/* Scroll down after the back-log has been received. */
-static gboolean
-chat_scroll_down_idle_func (EmpathyChat *chat)
+static void
+empathy_chat_class_init (EmpathyChatClass *klass)
 {
-       EmpathyChatPriv *priv;
+       GObjectClass *object_class;
 
-       priv = GET_PRIV (chat);
+       object_class = G_OBJECT_CLASS (klass);
 
-       empathy_chat_scroll_down (chat);
-       g_object_unref (chat);
+       object_class->finalize = chat_finalize;
+       object_class->get_property = chat_get_property;
+       object_class->set_property = chat_set_property;
 
-       priv->scroll_idle_id = 0;
+       g_object_class_install_property (object_class,
+                                        PROP_TP_CHAT,
+                                        g_param_spec_object ("tp-chat",
+                                                             "Empathy tp chat",
+                                                             "The tp chat object",
+                                                             EMPATHY_TYPE_TP_CHAT,
+                                                             G_PARAM_CONSTRUCT |
+                                                             G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_NAME,
+                                        g_param_spec_string ("name",
+                                                             "Chat's name",
+                                                             "The name of the chat",
+                                                             NULL,
+                                                             G_PARAM_READABLE));
+       g_object_class_install_property (object_class,
+                                        PROP_TOOLTIP,
+                                        g_param_spec_string ("tooltip",
+                                                             "Chat's tooltip",
+                                                             "The tooltip of the chat",
+                                                             NULL,
+                                                             G_PARAM_READABLE));
+       g_object_class_install_property (object_class,
+                                        PROP_ICON_NAME,
+                                        g_param_spec_string ("icon-name",
+                                                             "Chat's icon name",
+                                                             "The icon name of the chat",
+                                                             NULL,
+                                                             G_PARAM_READABLE));
+       g_object_class_install_property (object_class,
+                                        PROP_WIDGET,
+                                        g_param_spec_object ("widget",
+                                                             "Chat's widget",
+                                                             "The widget of the chat",
+                                                             GTK_TYPE_WIDGET,
+                                                             G_PARAM_READABLE));
 
-       return FALSE;
+       signals[COMPOSING] =
+               g_signal_new ("composing",
+                             G_OBJECT_CLASS_TYPE (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             0,
+                             NULL, NULL,
+                             g_cclosure_marshal_VOID__BOOLEAN,
+                             G_TYPE_NONE,
+                             1, G_TYPE_BOOLEAN);
+
+       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_TYPE_NONE,
+                             2, EMPATHY_TYPE_MESSAGE, G_TYPE_BOOLEAN);
+
+       g_type_class_add_private (object_class, sizeof (EmpathyChatPriv));
+}
+
+static void
+empathy_chat_init (EmpathyChat *chat)
+{
+       EmpathyChatPriv *priv = GET_PRIV (chat);
+       GtkTextBuffer  *buffer;
+
+       chat->view = empathy_chat_view_new ();
+       chat->input_text_view = gtk_text_view_new ();
+
+       priv->is_first_char = TRUE;
+
+       g_object_set (chat->input_text_view,
+                     "pixels-above-lines", 2,
+                     "pixels-below-lines", 2,
+                     "pixels-inside-wrap", 1,
+                     "right-margin", 2,
+                     "left-margin", 2,
+                     "wrap-mode", GTK_WRAP_WORD_CHAR,
+                     NULL);
+
+       priv->log_manager = empathy_log_manager_new ();
+       priv->default_window_height = -1;
+       priv->vscroll_visible = FALSE;
+       priv->sensitive = TRUE;
+       priv->sent_messages = NULL;
+       priv->sent_messages_index = -1;
+       priv->first_tp_chat = TRUE;
+       priv->mc = empathy_mission_control_new ();
+
+       dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged",
+                                    G_CALLBACK (chat_status_changed_cb),
+                                    chat, NULL);
+
+       g_signal_connect (chat->input_text_view,
+                         "key_press_event",
+                         G_CALLBACK (chat_input_key_press_event_cb),
+                         chat);
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (chat->input_text_view));
+       g_signal_connect (buffer,
+                         "changed",
+                         G_CALLBACK (chat_input_text_buffer_changed_cb),
+                         chat);
+       g_signal_connect (chat->view,
+                         "focus_in_event",
+                         G_CALLBACK (chat_text_view_focus_in_event_cb),
+                         chat);
+
+       g_signal_connect (chat->input_text_view,
+                         "size_allocate",
+                         G_CALLBACK (chat_text_view_size_allocate_cb),
+                         chat);
+
+       g_signal_connect (chat->input_text_view,
+                         "realize",
+                         G_CALLBACK (chat_text_view_realize_cb),
+                         chat);
+
+       g_signal_connect (GTK_TEXT_VIEW (chat->input_text_view),
+                         "populate_popup",
+                         G_CALLBACK (chat_text_populate_popup_cb),
+                         chat);
+
+       /* create misspelt words identification tag */
+       gtk_text_buffer_create_tag (buffer,
+                                   "misspelled",
+                                   "underline", PANGO_UNDERLINE_ERROR,
+                                   NULL);
 }
 
 gboolean
@@ -1369,37 +1325,31 @@ empathy_chat_correct_word (EmpathyChat  *chat,
 const gchar *
 empathy_chat_get_name (EmpathyChat *chat)
 {
-       g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL);
+       EmpathyChatPriv *priv = GET_PRIV (chat);
 
-       if (EMPATHY_CHAT_GET_CLASS (chat)->get_name) {
-               return EMPATHY_CHAT_GET_CLASS (chat)->get_name (chat);
-       }
+       g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL);
 
-       return NULL;
+       return priv->name;
 }
 
-gchar *
+const gchar *
 empathy_chat_get_tooltip (EmpathyChat *chat)
 {
-       g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL);
+       EmpathyChatPriv *priv = GET_PRIV (chat);
 
-       if (EMPATHY_CHAT_GET_CLASS (chat)->get_tooltip) {
-               return EMPATHY_CHAT_GET_CLASS (chat)->get_tooltip (chat);
-       }
+       g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL);
 
-       return NULL;
+       return priv->tooltip;
 }
 
 const gchar *
 empathy_chat_get_status_icon_name (EmpathyChat *chat)
 {
-       g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL);
+       EmpathyChatPriv *priv = GET_PRIV (chat);
 
-       if (EMPATHY_CHAT_GET_CLASS (chat)->get_status_icon_name) {
-               return EMPATHY_CHAT_GET_CLASS (chat)->get_status_icon_name (chat);
-       }
+       g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL);
 
-       return NULL;
+       return priv->icon_name;
 }
 
 GtkWidget *
@@ -1409,25 +1359,9 @@ empathy_chat_get_widget (EmpathyChat *chat)
 
        g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL);
 
-       if (!priv->widget && EMPATHY_CHAT_GET_CLASS (chat)->get_widget) {
-               priv->widget = EMPATHY_CHAT_GET_CLASS (chat)->get_widget (chat);
-       }
-
        return priv->widget;
 }
 
-gboolean
-empathy_chat_is_group_chat (EmpathyChat *chat)
-{
-       g_return_val_if_fail (EMPATHY_IS_CHAT (chat), FALSE);
-
-       if (EMPATHY_CHAT_GET_CLASS (chat)->is_group_chat) {
-               return EMPATHY_CHAT_GET_CLASS (chat)->is_group_chat (chat);
-       }
-
-       return FALSE;
-}
-
 gboolean 
 empathy_chat_is_connected (EmpathyChat *chat)
 {
@@ -1493,6 +1427,7 @@ empathy_chat_set_tp_chat (EmpathyChat   *chat,
                          EmpathyTpChat *tp_chat)
 {
        EmpathyChatPriv *priv;
+       TpChan          *tp_chan;
 
        g_return_if_fail (EMPATHY_IS_CHAT (chat));
        g_return_if_fail (EMPATHY_IS_TP_CHAT (tp_chat));
@@ -1532,7 +1467,8 @@ empathy_chat_set_tp_chat (EmpathyChat   *chat,
        priv->tp_chat = g_object_ref (tp_chat);
        priv->id = g_strdup (empathy_tp_chat_get_id (tp_chat));
        priv->account = g_object_ref (empathy_tp_chat_get_account (tp_chat));
-       empathy_tp_chat_set_acknowledge (tp_chat, TRUE);
+       tp_chan = empathy_tp_chat_get_channel (tp_chat);
+       priv->handle_type = tp_chan->handle_type;
 
        if (priv->first_tp_chat) {
                chat_add_logs (chat);
@@ -1558,10 +1494,6 @@ empathy_chat_set_tp_chat (EmpathyChat   *chat,
                priv->sensitive = TRUE;
        }
 
-       if (EMPATHY_CHAT_GET_CLASS (chat)->set_tp_chat) {
-               EMPATHY_CHAT_GET_CLASS (chat)->set_tp_chat (chat, tp_chat);
-       }
-
        g_object_notify (G_OBJECT (chat), "tp-chat");
 }
 
index aa5c3f1b3e3aa23af3dc48d99f59554760e6999f..113c285e0c2fe1fb97b3d90acdd781daa3267472 100644 (file)
@@ -61,17 +61,6 @@ struct _EmpathyChat {
 
 struct _EmpathyChatClass {
        GObjectClass parent;
-
-       /* VTable */
-       const gchar *    (*get_name)            (EmpathyChat   *chat);
-       gchar *          (*get_tooltip)         (EmpathyChat   *chat);
-       const gchar *    (*get_status_icon_name)(EmpathyChat   *chat);
-       GtkWidget *      (*get_widget)          (EmpathyChat   *chat);
-       gboolean         (*is_group_chat)       (EmpathyChat   *chat);
-       void             (*set_tp_chat)         (EmpathyChat   *chat,
-                                                EmpathyTpChat *tp_chat);
-       gboolean         (*key_press_event)     (EmpathyChat   *chat,
-                                                GdkEventKey   *event);
 };
 
 GType              empathy_chat_get_type              (void);
@@ -83,10 +72,9 @@ void               empathy_chat_cut                   (EmpathyChat       *chat);
 void               empathy_chat_copy                  (EmpathyChat       *chat);
 void               empathy_chat_paste                 (EmpathyChat       *chat);
 const gchar *      empathy_chat_get_name              (EmpathyChat       *chat);
-gchar *            empathy_chat_get_tooltip           (EmpathyChat       *chat);
+const gchar *      empathy_chat_get_tooltip           (EmpathyChat       *chat);
 const gchar *      empathy_chat_get_status_icon_name  (EmpathyChat       *chat);
 GtkWidget *        empathy_chat_get_widget            (EmpathyChat       *chat);
-gboolean           empathy_chat_is_group_chat         (EmpathyChat       *chat);
 gboolean           empathy_chat_is_connected          (EmpathyChat       *chat);
 void               empathy_chat_save_geometry         (EmpathyChat       *chat,
                                                       gint               x,