[empathy: 3/4] chat-manager: take an EmpathyChat instead of an EmpathyContact



commit d8dd568c2c1fed4cb328c2a9afc148186fda12aa
Author: Jonny Lamb <jonnylamb gnome org>
Date:   Sat Mar 6 10:58:11 2010 +0000

    chat-manager: take an EmpathyChat instead of an EmpathyContact
    
    This way, we can support both 1-to-1 chats, *and* MUCs.
    
    Signed-off-by: Jonny Lamb <jonnylamb gnome org>

 src/empathy-chat-manager.c |  113 ++++++++++++++++++++++++++++++++++++++-----
 src/empathy-chat-manager.h |    4 +-
 src/empathy-chat-window.c  |    8 ++--
 3 files changed, 105 insertions(+), 20 deletions(-)
---
diff --git a/src/empathy-chat-manager.c b/src/empathy-chat-manager.c
index 087077c..01506f5 100644
--- a/src/empathy-chat-manager.c
+++ b/src/empathy-chat-manager.c
@@ -47,6 +47,45 @@ struct _EmpathyChatManagerPriv
 
 static EmpathyChatManager *chat_manager_singleton = NULL;
 
+typedef struct
+{
+  TpAccount *account;
+  gchar *id;
+  gboolean room;
+} ChatData;
+
+static ChatData *
+chat_data_new (EmpathyChat *chat)
+{
+  ChatData *data = NULL;
+
+  data = g_slice_new0 (ChatData);
+
+  data->account = g_object_ref (empathy_chat_get_account (chat));
+  data->id = g_strdup (empathy_chat_get_id (chat));
+  data->room = empathy_chat_is_room (chat);
+
+  return data;
+}
+
+static void
+chat_data_free (ChatData *data)
+{
+  if (data->account != NULL)
+    {
+      g_object_unref (data->account);
+      data->account = NULL;
+    }
+
+  if (data->id != NULL)
+    {
+      g_free (data->id);
+      data->id = NULL;
+    }
+
+  g_slice_free (ChatData, data);
+}
+
 static void
 empathy_chat_manager_init (EmpathyChatManager *self)
 {
@@ -63,7 +102,7 @@ empathy_chat_manager_finalize (GObject *object)
 
   if (priv->queue != NULL)
     {
-      g_queue_foreach (priv->queue, (GFunc) g_object_unref, NULL);
+      g_queue_foreach (priv->queue, (GFunc) chat_data_free, NULL);
       g_queue_free (priv->queue);
       priv->queue = NULL;
     }
@@ -125,38 +164,84 @@ empathy_chat_manager_dup_singleton (void)
 
 void
 empathy_chat_manager_closed_chat (EmpathyChatManager *self,
-    EmpathyContact *contact)
+    EmpathyChat *chat)
 {
   EmpathyChatManagerPriv *priv = GET_PRIV (self);
+  ChatData *data;
 
-  DEBUG ("Adding contact to queue: %s", empathy_contact_get_id (contact));
+  data = chat_data_new (chat);
 
-  g_queue_push_tail (priv->queue, g_object_ref (contact));
+  DEBUG ("Adding %s to queue: %s", data->room ? "room" : "contact", data->id);
+
+  g_queue_push_tail (priv->queue, data);
 
   g_signal_emit (self, signals[CHATS_CHANGED], 0,
       g_queue_get_length (priv->queue));
 }
 
+static void
+connection_ready_cb (TpConnection *connection,
+    const GError *error,
+    gpointer user_data)
+{
+  ChatData *data = user_data;
+  EmpathyChatManager *self = chat_manager_singleton;
+  EmpathyChatManagerPriv *priv;
+
+  /* Extremely unlikely to happen, but I don't really want to keep refs to the
+   * chat manager in the ChatData structs as it'll then prevent the manager
+   * from being finalized. */
+  if (G_UNLIKELY (self == NULL))
+    goto out;
+
+  priv = GET_PRIV (self);
+
+  if (error == NULL)
+    {
+      if (data->room)
+        empathy_dispatcher_join_muc (connection, data->id, NULL, NULL);
+      else
+        empathy_dispatcher_chat_with_contact_id (connection, data->id,
+            NULL, NULL);
+
+      g_signal_emit (self, signals[CHATS_CHANGED], 0,
+          g_queue_get_length (priv->queue));
+    }
+  else
+    {
+      DEBUG ("Error readying connection, no chat: %s", error->message);
+    }
+
+out:
+  chat_data_free (data);
+}
+
 void
 empathy_chat_manager_undo_closed_chat (EmpathyChatManager *self)
 {
   EmpathyChatManagerPriv *priv = GET_PRIV (self);
-  EmpathyContact *contact;
+  ChatData *data;
+  TpConnection *connection;
 
-  contact = g_queue_pop_tail (priv->queue);
+  data = g_queue_pop_tail (priv->queue);
 
-  if (contact == NULL)
+  if (data == NULL)
     return;
 
-  DEBUG ("Removing contact from queue and starting a chat with them: %s",
-      empathy_contact_get_id (contact));
-
-  empathy_dispatcher_chat_with_contact (contact, NULL, NULL);
+  DEBUG ("Removing %s from queue and starting a chat with: %s",
+      data->room ? "room" : "contact", data->id);
 
-  g_object_unref (contact);
+  connection = tp_account_get_connection (data->account);
 
-  g_signal_emit (self, signals[CHATS_CHANGED], 0,
-      g_queue_get_length (priv->queue));
+  if (connection != NULL)
+    {
+      tp_connection_call_when_ready (connection, connection_ready_cb, data);
+    }
+  else
+    {
+      DEBUG ("No connection, no chat.");
+      chat_data_free (data);
+    }
 }
 
 guint
diff --git a/src/empathy-chat-manager.h b/src/empathy-chat-manager.h
index 1dc121c..3a20ab8 100644
--- a/src/empathy-chat-manager.h
+++ b/src/empathy-chat-manager.h
@@ -22,7 +22,7 @@
 
 #include <glib-object.h>
 
-#include <libempathy/empathy-contact.h>
+#include <libempathy-gtk/empathy-chat.h>
 
 G_BEGIN_DECLS
 
@@ -61,7 +61,7 @@ GType empathy_chat_manager_get_type (void);
 EmpathyChatManager *empathy_chat_manager_dup_singleton (void);
 
 void empathy_chat_manager_closed_chat (EmpathyChatManager *self,
-    EmpathyContact *contact);
+    EmpathyChat *chat);
 void empathy_chat_manager_undo_closed_chat (EmpathyChatManager *self);
 guint empathy_chat_manager_get_num_chats (EmpathyChatManager *self);
 
diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c
index 1df42f1..9748b61 100644
--- a/src/empathy-chat-window.c
+++ b/src/empathy-chat-window.c
@@ -2158,12 +2158,12 @@ empathy_chat_window_remove_chat (EmpathyChatWindow *window,
 		g_signal_handlers_disconnect_by_func (remote_contact,
 						      chat_window_update_chat_tab,
 						      chat);
-
-		chat_manager = empathy_chat_manager_dup_singleton ();
-		empathy_chat_manager_closed_chat (chat_manager, remote_contact);
-		g_object_unref (chat_manager);
 	}
 
+	chat_manager = empathy_chat_manager_dup_singleton ();
+	empathy_chat_manager_closed_chat (chat_manager, chat);
+	g_object_unref (chat_manager);
+
 	position = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook),
 					  GTK_WIDGET (chat));
 	gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), position);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]