]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-group-chat.c
Move modules that make no sense to be used in other applicaton from libempathy-gtk...
[empathy.git] / libempathy-gtk / empathy-group-chat.c
index 6861dd5cd1c6cd2650aa46bc5ebffb00e2dd241b..909e2316258665f79054a59dc99e088fc9c3c46e 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2002-2007 Imendio AB
- * Copyright (C) 2007 Collabora Ltd.
+ * Copyright (C) 2007-2008 Collabora Ltd.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
 
 #include <string.h>
 
+#include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
 #include <glade/glade.h>
 #include <glib/gi18n.h>
 
+#include <telepathy-glib/util.h>
+
 #include <libempathy/empathy-tp-chat.h>
 #include <libempathy/empathy-tp-chatroom.h>
 #include <libempathy/empathy-contact.h>
@@ -47,6 +50,7 @@
 //#include "empathy-sound.h"
 #include "empathy-images.h"
 #include "empathy-ui-utils.h"
+#include "empathy-conf.h"
 
 #define DEBUG_DOMAIN "GroupChat"
 
@@ -78,16 +82,12 @@ static void          group_chat_finalize                 (GObject           *obj
 static void          group_chat_create_ui                (EmpathyGroupChat  *chat);
 static void          group_chat_widget_destroy_cb        (GtkWidget         *widget,
                                                          EmpathyGroupChat  *chat);
-static void          group_chat_contact_added_cb         (EmpathyTpChatroom *tp_chat,
-                                                         EmpathyContact    *contact,
-                                                         EmpathyGroupChat  *chat);
-static void          group_chat_contact_removed_cb       (EmpathyTpChatroom *tp_chat,
+static void          group_chat_members_changed_cb       (EmpathyTpChatroom *tp_chat,
                                                          EmpathyContact    *contact,
-                                                         EmpathyGroupChat  *chat);
-static void          group_chat_topic_entry_activate_cb  (GtkWidget         *entry,
-                                                         GtkDialog         *dialog);
-static void          group_chat_topic_response_cb        (GtkWidget         *dialog,
-                                                         gint               response,                        
+                                                         EmpathyContact    *actor,
+                                                         guint              reason,
+                                                         gchar             *message,
+                                                         gboolean           is_member,
                                                          EmpathyGroupChat  *chat);
 static const gchar * group_chat_get_name                 (EmpathyChat       *chat);
 static gchar *       group_chat_get_tooltip              (EmpathyChat       *chat);
@@ -96,15 +96,8 @@ static GtkWidget *   group_chat_get_widget               (EmpathyChat       *cha
 static gboolean      group_chat_is_group_chat            (EmpathyChat       *chat);
 static void          group_chat_set_tp_chat              (EmpathyChat       *chat,
                                                          EmpathyTpChat     *tp_chat);
-static void          group_chat_subject_notify_cb        (EmpathyTpChat     *tp_chat,
-                                                         GParamSpec        *param,
-                                                         EmpathyGroupChat  *chat);
-static void          group_chat_name_notify_cb           (EmpathyTpChat     *tp_chat,
-                                                         GParamSpec        *param,
-                                                         EmpathyGroupChat  *chat);
-/*static gboolean      group_chat_key_press_event          (GtkWidget         *widget,
-                                                         GdkEventKey       *event,
-                                                         EmpathyGroupChat  *chat);*/
+static gboolean      group_chat_key_press_event          (EmpathyChat       *chat,
+                                                         GdkEventKey       *event);
 static gint          group_chat_contacts_completion_func (const gchar       *s1,
                                                          const gchar       *s2,
                                                          gsize              n);
@@ -128,6 +121,7 @@ empathy_group_chat_class_init (EmpathyGroupChatClass *klass)
        chat_class->get_widget           = group_chat_get_widget;
        chat_class->is_group_chat        = group_chat_is_group_chat;
        chat_class->set_tp_chat          = group_chat_set_tp_chat;
+       chat_class->key_press_event      = group_chat_key_press_event;
 
        g_type_class_add_private (object_class, sizeof (EmpathyGroupChatPriv));
 }
@@ -161,30 +155,27 @@ group_chat_finalize (GObject *object)
        
        g_free (priv->name);
        g_free (priv->topic);
-       g_object_unref (priv->store);
-       g_object_unref (priv->tp_chat); 
+       if (priv->store) {
+               g_object_unref (priv->store);
+       }
+       if (priv->tp_chat) {
+               g_object_unref (priv->tp_chat); 
+       }
        g_completion_free (priv->completion);
 
        G_OBJECT_CLASS (empathy_group_chat_parent_class)->finalize (object);
 }
 
 EmpathyGroupChat *
-empathy_group_chat_new (McAccount *account,
-                       TpChan    *tp_chan)
+empathy_group_chat_new (EmpathyTpChatroom *tp_chat)
 {
-       EmpathyGroupChat     *chat;
-       EmpathyGroupChatPriv *priv;
-
-       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-       g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL);
+       EmpathyGroupChat *chat;
 
-       chat = g_object_new (EMPATHY_TYPE_GROUP_CHAT, NULL);
-
-       priv = GET_PRIV (chat);
+       g_return_val_if_fail (EMPATHY_IS_TP_CHAT (tp_chat), NULL);
 
-       EMPATHY_CHAT (chat)->account = g_object_ref (account);
-       priv->tp_chat = empathy_tp_chatroom_new (account, tp_chan);
-       empathy_chat_set_tp_chat (EMPATHY_CHAT (chat), EMPATHY_TP_CHAT (priv->tp_chat));
+       chat = g_object_new (EMPATHY_TYPE_GROUP_CHAT,
+                            "tp-chat", tp_chat,
+                            NULL);
 
        return chat;
 }
@@ -227,25 +218,58 @@ empathy_group_chat_set_show_contacts (EmpathyGroupChat *chat,
        }
 }
 
+static void
+group_chat_topic_response_cb (GtkWidget        *dialog,
+                             gint              response,
+                             EmpathyGroupChat *chat)
+{
+       if (response == GTK_RESPONSE_OK) {
+               GtkWidget   *entry;
+               const gchar *topic;
+
+               entry = g_object_get_data (G_OBJECT (dialog), "entry");
+               topic = gtk_entry_get_text (GTK_ENTRY (entry));
+               
+               if (!G_STR_EMPTY (topic)) {
+                       EmpathyGroupChatPriv *priv;
+                       GValue                value = {0, };
+
+                       priv = GET_PRIV (chat);
+
+                       g_value_init (&value, G_TYPE_STRING);
+                       g_value_set_string (&value, topic);
+                       empathy_tp_chat_set_property (EMPATHY_TP_CHAT (priv->tp_chat),
+                                                     "subject", &value);
+                       g_value_unset (&value);
+               }
+       }
+
+       gtk_widget_destroy (dialog);
+}
+
+static void
+group_chat_topic_entry_activate_cb (GtkWidget *entry,
+                                   GtkDialog *dialog)
+{
+       gtk_dialog_response (dialog, GTK_RESPONSE_OK);
+}
+
 void
 empathy_group_chat_set_topic (EmpathyGroupChat *chat)
 {
        EmpathyGroupChatPriv *priv;
-       EmpathyChatWindow    *chat_window;
-       GtkWidget           *chat_dialog;
-       GtkWidget           *dialog;
-       GtkWidget           *entry;
-       GtkWidget           *hbox;
-       const gchar         *topic;
-
-       g_return_if_fail (EMPATHY_IS_GROUP_CHAT (chat));
+       GtkWindow            *parent;
+       GtkWidget            *dialog;
+       GtkWidget            *entry;
+       GtkWidget            *hbox;
+       const gchar          *topic;
 
        priv = GET_PRIV (chat);
 
-       chat_window = empathy_chat_get_window (EMPATHY_CHAT (chat));
-       chat_dialog = empathy_chat_window_get_dialog (chat_window);
+       g_return_if_fail (EMPATHY_IS_GROUP_CHAT (chat));
 
-       dialog = gtk_message_dialog_new (GTK_WINDOW (chat_dialog),
+       parent = empathy_get_toplevel_window (empathy_chat_get_widget (EMPATHY_CHAT (chat)));
+       dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
                                         0,
                                         GTK_MESSAGE_QUESTION,
                                         GTK_BUTTONS_OK_CANCEL,
@@ -318,7 +342,7 @@ group_chat_create_ui (EmpathyGroupChat *chat)
        gtk_widget_show (EMPATHY_CHAT (chat)->input_text_view);
 
        /* Add nick name completion */
-       priv->completion = g_completion_new (NULL);
+       priv->completion = g_completion_new ((GCompletionFunc) empathy_contact_get_name);
        g_completion_set_compare (priv->completion,
                                  group_chat_contacts_completion_func);
 
@@ -348,66 +372,26 @@ group_chat_widget_destroy_cb (GtkWidget       *widget,
 }
 
 static void
-group_chat_contact_added_cb (EmpathyTpChatroom *tp_chat,
-                            EmpathyContact     *contact,
-                            EmpathyGroupChat   *chat)
-{
-       EmpathyGroupChatPriv *priv;
-       gchar               *str;
-
-       priv = GET_PRIV (chat);
-
-       str = g_strdup_printf (_("%s has joined the room"),
-                              empathy_contact_get_name (contact));
-       empathy_chat_view_append_event (EMPATHY_CHAT (chat)->view, str);
-       g_free (str);
-}
-
-static void
-group_chat_contact_removed_cb (EmpathyTpChatroom *tp_chat,
+group_chat_members_changed_cb (EmpathyTpChatroom *tp_chat,
                               EmpathyContact     *contact,
+                              EmpathyContact     *actor,
+                              guint               reason,
+                              gchar              *message,
+                              gboolean            is_member,
                               EmpathyGroupChat   *chat)
 {
-       EmpathyGroupChatPriv *priv;
-       gchar               *str;
-
-       priv = GET_PRIV (chat);
-
-       str = g_strdup_printf (_("%s has left the room"),
-                              empathy_contact_get_name (contact));
-       empathy_chat_view_append_event (EMPATHY_CHAT (chat)->view, str);
-       g_free (str);
-}
-
-static void
-group_chat_topic_entry_activate_cb (GtkWidget *entry,
-                                   GtkDialog *dialog)
-{
-       gtk_dialog_response (dialog, GTK_RESPONSE_OK);
-}
-
-static void
-group_chat_topic_response_cb (GtkWidget       *dialog,
-                             gint             response,                              
-                             EmpathyGroupChat *chat)
-{
-       if (response == GTK_RESPONSE_OK) {
-               GtkWidget   *entry;
-               const gchar *topic;
-
-               entry = g_object_get_data (G_OBJECT (dialog), "entry");
-               topic = gtk_entry_get_text (GTK_ENTRY (entry));
-               
-               if (!G_STR_EMPTY (topic)) {
-                       EmpathyGroupChatPriv *priv;
-
-                       priv = GET_PRIV (chat);
-
-                       empathy_tp_chatroom_set_topic (priv->tp_chat, topic);
+       if (!EMPATHY_CHAT (chat)->block_events) {
+               gchar *str;
+               if (is_member) {
+                       str = g_strdup_printf (_("%s has joined the room"),
+                                              empathy_contact_get_name (contact));
+               } else {
+                       str = g_strdup_printf (_("%s has left the room"),
+                                              empathy_contact_get_name (contact));
                }
+               empathy_chat_view_append_event (EMPATHY_CHAT (chat)->view, str);
+               g_free (str);
        }
-
-       gtk_widget_destroy (dialog);
 }
 
 static const gchar *
@@ -490,6 +474,52 @@ group_chat_is_group_chat (EmpathyChat *chat)
        return TRUE;
 }
 
+static void
+group_chat_property_changed_cb (EmpathyTpChat    *tp_chat,
+                               gchar            *name,
+                               GValue           *value,
+                               EmpathyGroupChat *chat)
+{
+       EmpathyGroupChatPriv *priv;
+       const gchar          *str = NULL;
+
+       priv = GET_PRIV (chat);
+
+       /* FIXME: this is ugly, should use properties on EmpathyChat obj */
+
+       if (!tp_strdiff (name, "name")) {
+               str = g_value_get_string (value);
+               g_free (priv->name);
+               priv->name = g_strdup (str);
+               return;
+       }
+
+       if (tp_strdiff (name, "subject")) {
+               return;
+       }
+
+       str = g_value_get_string (value);
+       if (!tp_strdiff (priv->topic, str)) {
+               return;
+       }
+
+       g_free (priv->topic);
+       priv->topic = g_strdup (str);
+       gtk_label_set_text (GTK_LABEL (priv->label_topic), priv->topic);
+
+       if (!EMPATHY_CHAT (chat)->block_events) {
+               gchar *string;
+
+               if (!G_STR_EMPTY (priv->topic)) {
+                       string = g_strdup_printf (_("Topic set to: %s"), priv->topic);
+               } else {
+                       string = g_strdup (_("No topic defined"));
+               }
+               empathy_chat_view_append_event (EMPATHY_CHAT (chat)->view, string);
+               g_free (string);
+       }
+}
+
 static void
 group_chat_set_tp_chat (EmpathyChat    *chat,
                        EmpathyTpChat *tp_chat)
@@ -529,85 +559,47 @@ group_chat_set_tp_chat (EmpathyChat    *chat,
 
        priv->tp_chat = g_object_ref (tp_chat);
 
-       /* FIXME: Ask the user before accepting */
-       empathy_tp_chatroom_accept_invitation (priv->tp_chat);
+       if (empathy_tp_chatroom_get_invitation (priv->tp_chat, NULL, NULL)) {
+               empathy_tp_chatroom_accept_invitation (priv->tp_chat);
+       }
 
        /* Create contact list */
        priv->store = empathy_contact_list_store_new (EMPATHY_CONTACT_LIST (priv->tp_chat));
-       priv->view = empathy_contact_list_view_new (priv->store);
+       priv->view = empathy_contact_list_view_new (priv->store,
+                                                   EMPATHY_CONTACT_LIST_FEATURE_CONTACT_CHAT |
+                                                   EMPATHY_CONTACT_LIST_FEATURE_CONTACT_CALL |
+                                                   EMPATHY_CONTACT_LIST_FEATURE_CONTACT_LOG |
+                                                   EMPATHY_CONTACT_LIST_FEATURE_CONTACT_FT |
+                                                   EMPATHY_CONTACT_LIST_FEATURE_CONTACT_INVITE |
+                                                   EMPATHY_CONTACT_LIST_FEATURE_CONTACT_INFO);
+
        gtk_container_add (GTK_CONTAINER (priv->scrolled_window_contacts),
                           GTK_WIDGET (priv->view));
        gtk_widget_show (GTK_WIDGET (priv->view));
 
        /* Connect signals */
-       g_signal_connect (priv->tp_chat, "contact-added",
-                         G_CALLBACK (group_chat_contact_added_cb),
-                         chat);
-       g_signal_connect (priv->tp_chat, "contact-removed",
-                         G_CALLBACK (group_chat_contact_removed_cb),
+       g_signal_connect (priv->tp_chat, "members-changed",
+                         G_CALLBACK (group_chat_members_changed_cb),
                          chat);
-       g_signal_connect (priv->tp_chat, "notify::subject",
-                         G_CALLBACK (group_chat_subject_notify_cb),
-                         chat);
-       g_signal_connect (priv->tp_chat, "notify::name",
-                         G_CALLBACK (group_chat_name_notify_cb),
+       g_signal_connect (priv->tp_chat, "property-changed",
+                         G_CALLBACK (group_chat_property_changed_cb),
                          chat);
 }
 
-static void
-group_chat_subject_notify_cb (EmpathyTpChat   *tp_chat,
-                             GParamSpec      *param,
-                             EmpathyGroupChat *chat)
-{
-       EmpathyGroupChatPriv *priv;
-       gchar               *str;
-
-       priv = GET_PRIV (chat);
-
-       g_free (priv->topic);
-
-       g_object_get (priv->tp_chat, "subject", &priv->topic, NULL);
-       gtk_label_set_text (GTK_LABEL (priv->label_topic), priv->topic);
-
-       str = g_strdup_printf (_("Topic set to: %s"), priv->topic);
-       empathy_chat_view_append_event (EMPATHY_CHAT (chat)->view, str);
-       g_free (str);
-}
-
-static void
-group_chat_name_notify_cb (EmpathyTpChat   *tp_chat,
-                          GParamSpec      *param,
-                          EmpathyGroupChat *chat)
-{
-       EmpathyGroupChatPriv *priv;
-
-       priv = GET_PRIV (chat);
-
-       g_free (priv->name);
-       g_object_get (priv->tp_chat, "name", &priv->name, NULL);
-}
-
-#if 0
 static gboolean
-group_chat_key_press_event (GtkWidget       *widget,
-                           GdkEventKey     *event,
-                           EmpathyGroupChat *chat)
+group_chat_key_press_event (EmpathyChat *chat,
+                           GdkEventKey *event)
 {
-       EmpathyGroupChatPriv *priv;
-       GtkAdjustment       *adj;
-       gdouble              val;
-       GtkTextBuffer       *buffer;
-       GtkTextIter          start, current;
-       gchar               *nick, *completed;
-       gint                 len;
-       GList               *list, *l, *completed_list;
-       gboolean             is_start_of_buffer;
+       EmpathyGroupChatPriv *priv = GET_PRIV (chat);
 
-       priv = GET_PRIV (chat);
-
-       if ((event->state & GDK_CONTROL_MASK) != GDK_CONTROL_MASK &&
-           (event->state & GDK_SHIFT_MASK) != GDK_SHIFT_MASK &&
+       if (!(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) &&
            event->keyval == GDK_Tab) {
+               GtkTextBuffer *buffer;
+               GtkTextIter    start, current;
+               gchar         *nick, *completed;
+               GList         *list, *completed_list;
+               gboolean       is_start_of_buffer;
+
                buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (EMPATHY_CHAT (chat)->input_text_view));
                gtk_text_buffer_get_iter_at_mark (buffer, &current, gtk_text_buffer_get_insert (buffer));
 
@@ -616,16 +608,10 @@ group_chat_key_press_event (GtkWidget       *widget,
                gtk_text_iter_backward_word_start (&start);
                is_start_of_buffer = gtk_text_iter_is_start (&start);
 
-               nick = gtk_text_buffer_get_text (buffer, &start, &current, FALSE);
-
-               g_completion_clear_items (priv->completion);
-
-               len = strlen (nick);
-
-               list = group_chat_get_nick_list (chat);
-
+               list = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (priv->tp_chat));
                g_completion_add_items (priv->completion, list);
 
+               nick = gtk_text_buffer_get_text (buffer, &start, &current, FALSE);
                completed_list = g_completion_complete (priv->completion,
                                                        nick,
                                                        &completed);
@@ -633,8 +619,9 @@ group_chat_key_press_event (GtkWidget       *widget,
                g_free (nick);
 
                if (completed) {
-                       int       len;
-                       gchar    *text;
+                       guint        len;
+                       const gchar *text;
+                       gchar       *complete_char = NULL;
 
                        gtk_text_buffer_delete (buffer, &start, &current);
 
@@ -647,17 +634,23 @@ group_chat_key_press_event (GtkWidget       *widget,
                                 * which might be cased all wrong.
                                 * Fixes #120876
                                 * */
-                               text = (gchar *) completed_list->data;
+                               text = empathy_contact_get_name (completed_list->data);
                        } else {
                                text = completed;
                        }
 
                        gtk_text_buffer_insert_at_cursor (buffer, text, strlen (text));
 
-                       if (len == 1) {
-                               if (is_start_of_buffer) {
-                                       gtk_text_buffer_insert_at_cursor (buffer, ", ", 2);
-                               }
+                       if (len == 1 && is_start_of_buffer &&
+                           empathy_conf_get_string (empathy_conf_get (),
+                                                    EMPATHY_PREFS_CHAT_NICK_COMPLETION_CHAR,
+                                                    &complete_char) &&
+                           complete_char != NULL) {
+                               gtk_text_buffer_insert_at_cursor (buffer,
+                                                                 complete_char,
+                                                                 strlen (complete_char));
+                               gtk_text_buffer_insert_at_cursor (buffer, " ", 1);
+                               g_free (complete_char);
                        }
 
                        g_free (completed);
@@ -665,10 +658,7 @@ group_chat_key_press_event (GtkWidget       *widget,
 
                g_completion_clear_items (priv->completion);
 
-               for (l = list; l; l = l->next) {
-                       g_free (l->data);
-               }
-
+               g_list_foreach (list, (GFunc) g_object_unref, NULL);
                g_list_free (list);
 
                return TRUE;
@@ -676,7 +666,6 @@ group_chat_key_press_event (GtkWidget       *widget,
 
        return FALSE;
 }
-#endif
 
 static gint
 group_chat_contacts_completion_func (const gchar *s1,