aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk/gossip-chat-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy-gtk/gossip-chat-manager.c')
-rw-r--r--libempathy-gtk/gossip-chat-manager.c327
1 files changed, 327 insertions, 0 deletions
diff --git a/libempathy-gtk/gossip-chat-manager.c b/libempathy-gtk/gossip-chat-manager.c
new file mode 100644
index 000000000..86cd0ea3f
--- /dev/null
+++ b/libempathy-gtk/gossip-chat-manager.c
@@ -0,0 +1,327 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004-2007 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Martyn Russell <martyn@imendio.com>
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include <libgossip/gossip-account.h>
+#include <libgossip/gossip-event.h>
+#include <libgossip/gossip-session.h>
+#include <libgossip/gossip-message.h>
+#include <libgossip/gossip-debug.h>
+#include <libgossip/gossip-event-manager.h>
+
+#include "gossip-app.h"
+#include "gossip-chat.h"
+#include "gossip-chat-manager.h"
+
+#define DEBUG_DOMAIN "ChatManager"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CHAT_MANAGER, GossipChatManagerPriv))
+
+typedef struct _GossipChatManagerPriv GossipChatManagerPriv;
+
+struct _GossipChatManagerPriv {
+ GHashTable *chats;
+ GHashTable *events;
+};
+
+static void chat_manager_finalize (GObject *object);
+static void chat_manager_new_message_cb (GossipSession *session,
+ GossipMessage *msg,
+ GossipChatManager *manager);
+static void chat_manager_event_activated_cb (GossipEventManager *event_manager,
+ GossipEvent *event,
+ GObject *object);
+static void chat_manager_get_chats_foreach (GossipContact *contact,
+ GossipPrivateChat *chat,
+ GList **chats);
+static void chat_manager_chat_removed_cb (GossipChatManager *manager,
+ GossipChat *chat,
+ gboolean is_last_ref);
+
+G_DEFINE_TYPE (GossipChatManager, gossip_chat_manager, G_TYPE_OBJECT);
+
+static void
+gossip_chat_manager_class_init (GossipChatManagerClass *class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = chat_manager_finalize;
+
+ g_type_class_add_private (object_class, sizeof (GossipChatManagerPriv));
+}
+
+static void
+gossip_chat_manager_init (GossipChatManager *manager)
+{
+ GossipChatManagerPriv *priv;
+
+ priv = GET_PRIV (manager);
+
+ priv->chats = g_hash_table_new_full (gossip_contact_hash,
+ gossip_contact_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) g_object_unref);
+
+ priv->events = g_hash_table_new_full (gossip_contact_hash,
+ gossip_contact_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) g_object_unref);
+
+ /* Connect to signals on GossipSession to listen for new messages */
+ g_signal_connect (gossip_app_get_session (),
+ "new-message",
+ G_CALLBACK (chat_manager_new_message_cb),
+ manager);
+}
+
+static void
+chat_manager_finalize (GObject *object)
+{
+ GossipChatManagerPriv *priv;
+
+ priv = GET_PRIV (object);
+
+ g_hash_table_destroy (priv->chats);
+ g_hash_table_destroy (priv->events);
+
+ G_OBJECT_CLASS (gossip_chat_manager_parent_class)->finalize (object);
+}
+
+static void
+chat_manager_new_message_cb (GossipSession *session,
+ GossipMessage *message,
+ GossipChatManager *manager)
+{
+ GossipChatManagerPriv *priv;
+ GossipPrivateChat *chat;
+ GossipContact *sender;
+ GossipEvent *event = NULL;
+ GossipEvent *old_event;
+
+ priv = GET_PRIV (manager);
+
+ sender = gossip_message_get_sender (message);
+ chat = g_hash_table_lookup (priv->chats, sender);
+
+ old_event = g_hash_table_lookup (priv->events, sender);
+
+ /* Add event to event manager if one doesn't exist already. */
+ if (!chat) {
+ gossip_debug (DEBUG_DOMAIN, "New chat for: %s",
+ gossip_contact_get_id (sender));
+ chat = gossip_chat_manager_get_chat (manager, sender);
+
+ if (!old_event) {
+ event = gossip_event_new (GOSSIP_EVENT_NEW_MESSAGE);
+ }
+ } else {
+ GossipChatWindow *window;
+
+ window = gossip_chat_get_window (GOSSIP_CHAT (chat));
+
+ if (!window && !old_event) {
+ event = gossip_event_new (GOSSIP_EVENT_NEW_MESSAGE);
+ }
+ }
+
+ gossip_private_chat_append_message (chat, message);
+
+ if (event) {
+ gchar *str;
+
+ str = g_strdup_printf (_("New message from %s"),
+ gossip_contact_get_name (sender));
+ g_object_set (event,
+ "message", str,
+ "data", message,
+ NULL);
+ g_free (str);
+
+ gossip_event_manager_add (gossip_app_get_event_manager (),
+ event,
+ chat_manager_event_activated_cb,
+ G_OBJECT (manager));
+
+ g_hash_table_insert (priv->events,
+ g_object_ref (sender),
+ g_object_ref (event));
+ }
+}
+
+static void
+chat_manager_event_activated_cb (GossipEventManager *event_manager,
+ GossipEvent *event,
+ GObject *object)
+{
+ GossipMessage *message;
+ GossipContact *contact;
+
+ message = GOSSIP_MESSAGE (gossip_event_get_data (event));
+ contact = gossip_message_get_sender (message);
+
+ gossip_chat_manager_show_chat (GOSSIP_CHAT_MANAGER (object), contact);
+}
+
+static void
+chat_manager_get_chats_foreach (GossipContact *contact,
+ GossipPrivateChat *chat,
+ GList **chats)
+{
+ const gchar *contact_id;
+
+ contact_id = gossip_contact_get_id (contact);
+ *chats = g_list_prepend (*chats, g_strdup (contact_id));
+}
+
+GossipChatManager *
+gossip_chat_manager_new (void)
+{
+ return g_object_new (GOSSIP_TYPE_CHAT_MANAGER, NULL);
+}
+
+static void
+chat_manager_chat_removed_cb (GossipChatManager *manager,
+ GossipChat *chat,
+ gboolean is_last_ref)
+{
+ GossipChatManagerPriv *priv;
+ GossipContact *contact;
+
+ if (!is_last_ref) {
+ return;
+ }
+
+ priv = GET_PRIV (manager);
+
+ contact = gossip_chat_get_contact (chat);
+
+ gossip_debug (DEBUG_DOMAIN,
+ "Removing an old chat:'%s'",
+ gossip_contact_get_id (contact));
+
+ g_hash_table_remove (priv->chats, contact);
+}
+
+GossipPrivateChat *
+gossip_chat_manager_get_chat (GossipChatManager *manager,
+ GossipContact *contact)
+{
+ GossipChatManagerPriv *priv;
+ GossipPrivateChat *chat;
+
+ g_return_val_if_fail (GOSSIP_IS_CHAT_MANAGER (manager), NULL);
+ g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
+
+ priv = GET_PRIV (manager);
+
+ chat = g_hash_table_lookup (priv->chats, contact);
+
+ if (!chat) {
+ GossipSession *session;
+ GossipAccount *account;
+ GossipContact *own_contact;
+
+ session = gossip_app_get_session ();
+ account = gossip_contact_get_account (contact);
+ own_contact = gossip_session_get_own_contact (session, account);
+
+ chat = gossip_private_chat_new (own_contact, contact);
+ g_hash_table_insert (priv->chats,
+ g_object_ref (contact),
+ chat);
+ g_object_add_toggle_ref (G_OBJECT (chat),
+ (GToggleNotify) chat_manager_chat_removed_cb,
+ manager);
+
+ gossip_debug (DEBUG_DOMAIN,
+ "Creating a new chat:'%s'",
+ gossip_contact_get_id (contact));
+ }
+
+ return chat;
+}
+
+GList *
+gossip_chat_manager_get_chats (GossipChatManager *manager)
+{
+ GossipChatManagerPriv *priv;
+ GList *chats = NULL;
+
+ g_return_val_if_fail (GOSSIP_IS_CHAT_MANAGER (manager), NULL);
+
+ priv = GET_PRIV (manager);
+
+ g_hash_table_foreach (priv->chats,
+ (GHFunc) chat_manager_get_chats_foreach,
+ &chats);
+
+ chats = g_list_sort (chats, (GCompareFunc) strcmp);
+
+ return chats;
+}
+
+void
+gossip_chat_manager_remove_events (GossipChatManager *manager,
+ GossipContact *contact)
+{
+ GossipChatManagerPriv *priv;
+ GossipEvent *event;
+
+ g_return_if_fail (GOSSIP_IS_CHAT_MANAGER (manager));
+ g_return_if_fail (GOSSIP_IS_CONTACT (contact));
+
+ gossip_debug (DEBUG_DOMAIN,
+ "Removing events for contact:'%s'",
+ gossip_contact_get_id (contact));
+
+ priv = GET_PRIV (manager);
+
+ event = g_hash_table_lookup (priv->events, contact);
+ if (event) {
+ gossip_event_manager_remove (gossip_app_get_event_manager (),
+ event, G_OBJECT (manager));
+ g_hash_table_remove (priv->events, contact);
+ }
+}
+
+void
+gossip_chat_manager_show_chat (GossipChatManager *manager,
+ GossipContact *contact)
+{
+ GossipPrivateChat *chat;
+
+ g_return_if_fail (GOSSIP_IS_CHAT_MANAGER (manager));
+ g_return_if_fail (GOSSIP_IS_CONTACT (contact));
+
+ chat = gossip_chat_manager_get_chat (manager, contact);
+
+ gossip_chat_present (GOSSIP_CHAT (chat));
+
+ gossip_chat_manager_remove_events(manager, contact);
+}