empathy r967 - in trunk: docs/libempathy extensions libempathy src



Author: xclaesse
Date: Sat Apr 19 18:36:22 2008
New Revision: 967
URL: http://svn.gnome.org/viewvc/empathy?rev=967&view=rev

Log:
Drop Chandler and Filter, do not use MC for dispatching channels, do it ourself.


Added:
   trunk/src/empathy-filter.c
   trunk/src/empathy-filter.h
      - copied, changed from r966, /trunk/libempathy/empathy-filter.h
Removed:
   trunk/extensions/Chandler.xml
   trunk/extensions/Filter.xml
   trunk/libempathy/empathy-chandler.c
   trunk/libempathy/empathy-chandler.h
   trunk/libempathy/empathy-filter.c
   trunk/libempathy/empathy-filter.h
   trunk/src/empathy-call-chandler.c
   trunk/src/empathy-call.chandler
   trunk/src/empathy-chat.chandler
   trunk/src/org.gnome.Empathy.Call.service.in
   trunk/src/org.gnome.Empathy.Chat.service.in
Modified:
   trunk/docs/libempathy/libempathy-docs.sgml
   trunk/docs/libempathy/libempathy.types
   trunk/extensions/Makefile.am
   trunk/extensions/misc.xml
   trunk/libempathy/Makefile.am
   trunk/libempathy/empathy-utils.c
   trunk/src/Makefile.am
   trunk/src/empathy-status-icon.c
   trunk/src/empathy.c

Modified: trunk/docs/libempathy/libempathy-docs.sgml
==============================================================================
--- trunk/docs/libempathy/libempathy-docs.sgml	(original)
+++ trunk/docs/libempathy/libempathy-docs.sgml	Sat Apr 19 18:36:22 2008
@@ -26,7 +26,6 @@
       <xi:include href="xml/empathy-contact-manager.xml"/>
       <xi:include href="xml/empathy-contact.xml"/>
       <xi:include href="xml/empathy-enum-types.xml"/>
-      <xi:include href="xml/empathy-filter.xml"/>
       <xi:include href="xml/empathy-idle.xml"/>
       <xi:include href="xml/empathy-irc-server.xml"/>
       <xi:include href="xml/empathy-irc-network.xml"/>

Modified: trunk/docs/libempathy/libempathy.types
==============================================================================
--- trunk/docs/libempathy/libempathy.types	(original)
+++ trunk/docs/libempathy/libempathy.types	Sat Apr 19 18:36:22 2008
@@ -3,7 +3,6 @@
 empathy_reg_ex_type_get_type
 empathy_message_type_get_type
 empathy_capabilities_get_type
-empathy_filter_get_type
 empathy_idle_get_type
 empathy_log_manager_get_type
 empathy_message_get_gtype

Modified: trunk/extensions/Makefile.am
==============================================================================
--- trunk/extensions/Makefile.am	(original)
+++ trunk/extensions/Makefile.am	Sat Apr 19 18:36:22 2008
@@ -10,9 +10,7 @@
     all.xml \
     misc.xml \
     Channel_Handler.xml \
-    Stream_Engine.xml \
-    Chandler.xml \
-    Filter.xml
+    Stream_Engine.xml
 
 noinst_LTLIBRARIES = libemp-extensions.la
 

Modified: trunk/extensions/misc.xml
==============================================================================
--- trunk/extensions/misc.xml	(original)
+++ trunk/extensions/misc.xml	Sat Apr 19 18:36:22 2008
@@ -6,7 +6,5 @@
 
 <xi:include href="Stream_Engine.xml"/>
 <xi:include href="Channel_Handler.xml"/>
-<xi:include href="Chandler.xml"/>
-<xi:include href="Filter.xml"/>
 
 </tp:spec>

Modified: trunk/libempathy/Makefile.am
==============================================================================
--- trunk/libempathy/Makefile.am	(original)
+++ trunk/libempathy/Makefile.am	Sat Apr 19 18:36:22 2008
@@ -35,8 +35,6 @@
 	empathy-tp-chat.c				\
 	empathy-tp-roomlist.c				\
 	empathy-tp-call.c				\
-	empathy-chandler.c				\
-	empathy-filter.c				\
 	empathy-idle.c					\
 	empathy-log-manager.c				\
 	empathy-irc-network-manager.c			\
@@ -75,8 +73,6 @@
 	empathy-tp-chat.h			\
 	empathy-tp-roomlist.h			\
 	empathy-tp-call.h			\
-	empathy-chandler.h			\
-	empathy-filter.h			\
 	empathy-idle.h				\
 	empathy-log-manager.h			\
 	empathy-irc-network-manager.h		\

Modified: trunk/libempathy/empathy-utils.c
==============================================================================
--- trunk/libempathy/empathy-utils.c	(original)
+++ trunk/libempathy/empathy-utils.c	Sat Apr 19 18:36:22 2008
@@ -353,21 +353,19 @@
 
 	g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
-	/* StreamedMedia channels must have handle=0 and handle_type=none.
-	 * To call a contact we have to add him in the group interface of the
-	 * channel. MissionControl will detect the channel creation and 
-	 * dispatch it to the VoIP chandler automatically. */
-
 	mc = empathy_mission_control_new ();
 	account = empathy_contact_get_account (contact);
 	connection = mission_control_get_tpconnection (mc, account, NULL);
 	tp_connection_run_until_ready (connection, FALSE, NULL, NULL);
+	g_object_unref (mc);
 
+	/* We abuse of suppress_handler, TRUE means OUTGOING. The channel
+	 * will be catched in EmpathyFilter */
 	if (!tp_cli_connection_run_request_channel (connection, -1,
 						    TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
 						    TP_HANDLE_TYPE_NONE,
 						    0,
-						    FALSE,
+						    TRUE,
 						    &object_path,
 						    &error,
 						    NULL)) {
@@ -375,7 +373,6 @@
 			      "Couldn't request channel: %s",
 			      error ? error->message : "No error given");
 		g_clear_error (&error);
-		g_object_unref (mc);
 		g_object_unref (connection);
 		return;
 	}
@@ -399,7 +396,6 @@
 	g_object_unref (factory);
 	g_object_unref (self_contact);
 	g_object_unref (group);
-	g_object_unref (mc);
 	g_object_unref (connection);
 	g_object_unref (channel);
 	g_free (object_path);
@@ -427,31 +423,43 @@
 void
 empathy_chat_with_contact (EmpathyContact  *contact)
 {
-	MissionControl *mc;
+	MissionControl        *mc;
+	McAccount             *account;
+	TpConnection          *connection;
+
+	g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
 	mc = empathy_mission_control_new ();
-	mission_control_request_channel (mc,
-					 empathy_contact_get_account (contact),
-					 TP_IFACE_CHANNEL_TYPE_TEXT,
-					 empathy_contact_get_handle (contact),
-					 TP_HANDLE_TYPE_CONTACT,
-					 NULL, NULL);
+	account = empathy_contact_get_account (contact);
+	connection = mission_control_get_tpconnection (mc, account, NULL);
+	tp_connection_run_until_ready (connection, FALSE, NULL, NULL);
 	g_object_unref (mc);
+
+	/* We abuse of suppress_handler, TRUE means OUTGOING. The channel
+	 * will be catched in EmpathyFilter */
+	tp_cli_connection_call_request_channel (connection, -1,
+						TP_IFACE_CHANNEL_TYPE_TEXT,
+						TP_HANDLE_TYPE_CONTACT,
+						empathy_contact_get_handle (contact),
+						TRUE,
+						NULL, NULL, NULL, NULL);
+	g_object_unref (connection);
 }
 
 void
 empathy_chat_with_contact_id (McAccount *account, const gchar *contact_id)
 {
-	MissionControl *mc;
+	EmpathyContactFactory *factory;
+	EmpathyContact        *contact;
 
-	mc = empathy_mission_control_new ();
-	mission_control_request_channel_with_string_handle (mc,
-							    account,
-							    TP_IFACE_CHANNEL_TYPE_TEXT,
-							    contact_id,
-							    TP_HANDLE_TYPE_CONTACT,
-							    NULL, NULL);
-	g_object_unref (mc);
+	factory = empathy_contact_factory_new ();
+	contact = empathy_contact_factory_get_from_id (factory, account, contact_id);
+	empathy_contact_run_until_ready (contact, EMPATHY_CONTACT_READY_HANDLE, NULL);
+
+	empathy_chat_with_contact (contact);
+
+	g_object_unref (contact);
+	g_object_unref (factory);
 }
 
 const gchar *

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Sat Apr 19 18:36:22 2008
@@ -29,23 +29,13 @@
 	empathy-chatrooms-window.c empathy-chatrooms-window.h		\
 	empathy-main-window.c empathy-main-window.h			\
 	empathy-preferences.c empathy-preferences.h			\
+	empathy-call-window.c empathy-call-window.h			\
+	empathy-filter.c empathy-filter.h				\
 	ephy-spinner.c ephy-spinner.h
 
 empathy_accounts_SOURCES = empathy-accounts.c
 empathy_logs_SOURCES = empathy-logs.c
 
-# Dbus service files
-servicedir = $(datadir)/dbus-1/services
-service_DATA =							\
-	org.gnome.Empathy.Chat.service
-
-%.service: %.service.in Makefile
-	@sed -e "s|\ libexecdir\@|$(libexecdir)|" $< | sed -e "s|\ bindir\@|$(bindir)|" > $@
-
-chandlerdir = $(datadir)/telepathy/managers
-chandler_DATA =							\
-	empathy-chat.chandler
-
 gladedir = $(datadir)/empathy
 glade_DATA = 					\
 	empathy-call-window.glade		\
@@ -56,26 +46,9 @@
 	empathy-new-chatroom-dialog.glade	\
 	empathy-status-icon.glade
 
-BUILT_SOURCES =							\
-	$(service_DATA)
-
 EXTRA_DIST =							\
-	org.gnome.Empathy.Chat.service.in			\
-	org.gnome.Empathy.Call.service.in			\
 	$(autostart_DATA)					\
-	$(chandler_DATA)					\
 	$(glade_DATA)
 
 CLEANFILES = $(BUILT_SOURCES)
 
-if HAVE_VOIP
-libexec_PROGRAMS = empathy-call-chandler
-empathy_call_chandler_SOURCES =				\
-	empathy-call-chandler.c				\
-	empathy-call-window.c empathy-call-window.h
-service_DATA +=	org.gnome.Empathy.Call.service
-chandler_DATA += empathy-call.chandler
-else
-EXTRA_DIST += empathy-call.chandler
-endif
-

Added: trunk/src/empathy-filter.c
==============================================================================
--- (empty file)
+++ trunk/src/empathy-filter.c	Sat Apr 19 18:36:22 2008
@@ -0,0 +1,555 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007-2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Authors: Xavier Claessens <xclaesse gmail com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include <telepathy-glib/enums.h>
+#include <telepathy-glib/channel.h>
+#include <telepathy-glib/connection.h>
+#include <telepathy-glib/util.h>
+
+#include <libmissioncontrol/mission-control.h>
+#include <libmissioncontrol/mc-account.h>
+
+#include <libempathy/empathy-tp-chat.h>
+#include <libempathy/empathy-tp-call.h>
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-debug.h>
+
+#include <libempathy-gtk/empathy-chat.h>
+#include <libempathy-gtk/empathy-images.h>
+
+#include "empathy-filter.h"
+#include "empathy-chat-window.h"
+#include "empathy-call-window.h"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+		       EMPATHY_TYPE_FILTER, EmpathyFilterPriv))
+
+#define DEBUG_DOMAIN "Filter"
+
+struct _EmpathyFilterPriv {
+	GSList         *events;
+	GHashTable     *accounts;
+	gpointer        token;
+	MissionControl *mc;
+};
+
+static void empathy_filter_class_init (EmpathyFilterClass *klass);
+static void empathy_filter_init       (EmpathyFilter      *filter);
+
+G_DEFINE_TYPE (EmpathyFilter, empathy_filter, G_TYPE_OBJECT);
+
+enum {
+	PROP_0,
+	PROP_TOP_EVENT,
+};
+
+typedef void (*FilterFunc) (EmpathyFilter *filter,
+			    gpointer       user_data);
+
+typedef struct {
+	EmpathyFilterEvent public;
+	FilterFunc         func;
+	gpointer           user_data;
+} EmpathyFilterEventExt;
+
+static void
+filter_event_free (EmpathyFilterEventExt *event)
+{
+	g_free (event->public.icon_name);
+	g_free (event->public.message);
+	g_slice_free (EmpathyFilterEventExt, event);
+}
+
+static void
+filter_emit_event (EmpathyFilter *filter,
+		   const gchar   *icon_name,
+		   const gchar   *message,
+		   FilterFunc     func,
+		   gpointer       user_data)
+{
+	EmpathyFilterPriv     *priv = GET_PRIV (filter);
+	EmpathyFilterEventExt *event;
+
+	empathy_debug (DEBUG_DOMAIN, "Emit event, icon_name=%s message='%s'",
+		       icon_name, message);
+
+	event = g_slice_new0 (EmpathyFilterEventExt);
+	event->func = func;
+	event->user_data = user_data;
+	event->public.icon_name = g_strdup (icon_name);
+	event->public.message = g_strdup (message);
+
+	priv->events = g_slist_append (priv->events, event);
+	if (priv->events->data == event) {
+		g_object_notify (G_OBJECT (filter), "top-event");
+	}
+}
+
+void
+empathy_filter_activate_event (EmpathyFilter      *filter,
+			       EmpathyFilterEvent *event)
+{
+	EmpathyFilterPriv     *priv = GET_PRIV (filter);
+	EmpathyFilterEventExt *event_ext;
+	GSList                *l;
+	gboolean               is_top;
+
+	g_return_if_fail (EMPATHY_IS_FILTER (filter));
+	g_return_if_fail (event != NULL);
+
+	if (!(l = g_slist_find (priv->events, event))) {
+		return;
+	}
+
+	empathy_debug (DEBUG_DOMAIN, "Activating event");
+
+	event_ext = (EmpathyFilterEventExt*) event;
+	if (event_ext->func) {
+		event_ext->func (filter, event_ext->user_data);
+	}
+
+	is_top = (l == priv->events);
+	priv->events = g_slist_delete_link (priv->events, l);
+	if (is_top) {
+		g_object_notify (G_OBJECT (filter), "top-event");
+	}
+
+	filter_event_free (event_ext);
+}
+
+EmpathyFilterEvent *
+empathy_filter_get_top_event (EmpathyFilter *filter)
+{
+	EmpathyFilterPriv *priv = GET_PRIV (filter);
+
+	g_return_val_if_fail (EMPATHY_IS_FILTER (filter), NULL);
+
+	return priv->events ? priv->events->data : NULL;
+}
+
+static void
+filter_chat_dispatch (EmpathyFilter *filter,
+		      gpointer       user_data)
+{
+	EmpathyTpChat *tp_chat = EMPATHY_TP_CHAT (user_data);
+	McAccount     *account;
+	EmpathyChat   *chat;
+	const gchar   *id;
+
+	id = empathy_tp_chat_get_id (tp_chat);
+	account = empathy_tp_chat_get_account (tp_chat);
+	chat = empathy_chat_window_find_chat (account, id);
+
+	if (chat) {
+		empathy_chat_set_tp_chat (chat, tp_chat);
+	} else {
+		chat = empathy_chat_new (tp_chat);
+	}
+
+	empathy_chat_window_present_chat (chat);
+	g_object_unref (tp_chat);
+}
+
+static void
+filter_chat_message_received_cb (EmpathyTpChat   *tp_chat,
+				 EmpathyMessage  *message,
+				 EmpathyFilter   *filter)
+{
+	EmpathyContact  *sender;
+	gchar           *msg;
+
+	g_signal_handlers_disconnect_by_func (tp_chat,
+			  		      filter_chat_message_received_cb,
+			  		      filter);
+
+	sender = empathy_message_get_sender (message);
+	msg = g_strdup_printf (_("New message from %s:\n%s"),
+			       empathy_contact_get_name (sender),
+			       empathy_message_get_body (message));
+
+	filter_emit_event (filter, EMPATHY_IMAGE_NEW_MESSAGE, msg,
+			   filter_chat_dispatch, tp_chat);
+
+	g_free (msg);
+}
+
+static void
+filter_chat_handle_channel (EmpathyFilter *filter,
+			    TpChannel     *channel,
+			    gboolean       is_incoming)
+{
+	EmpathyTpChat *tp_chat;
+
+	empathy_debug (DEBUG_DOMAIN, "New text channel to be filtered: %p",
+		       channel);
+
+	tp_chat = empathy_tp_chat_new (channel, FALSE);
+	if (is_incoming) {
+		filter_chat_dispatch (filter, tp_chat);
+	} else {
+		g_signal_connect (tp_chat, "message-received",
+				  G_CALLBACK (filter_chat_message_received_cb),
+				  filter);
+	}
+}
+
+static void
+filter_call_dispatch (EmpathyFilter *filter,
+		      gpointer       user_data)
+{
+	EmpathyTpCall *call = EMPATHY_TP_CALL (user_data);
+
+	empathy_call_window_new (call);
+	g_object_unref (call);
+}
+
+static void
+filter_call_contact_notify_cb (EmpathyTpCall *call,
+			       gpointer       unused,
+			       EmpathyFilter *filter)
+{
+	EmpathyContact *contact;
+	gchar          *msg;
+
+	g_object_get (call, "contact", &contact, NULL);
+	if (!contact) {
+		return;
+	}
+
+	empathy_contact_run_until_ready (contact,
+					 EMPATHY_CONTACT_READY_NAME,
+					 NULL);
+
+	msg = g_strdup_printf (_("Incoming call from %s"),
+			       empathy_contact_get_name (contact));
+
+	filter_emit_event (filter, EMPATHY_IMAGE_VOIP, msg,
+			   filter_call_dispatch, call);
+
+	g_free (msg);
+	g_object_unref (contact);
+}
+
+static void
+filter_call_handle_channel (EmpathyFilter *filter,
+			    TpChannel     *channel,
+			    gboolean       is_incoming)
+{
+	EmpathyTpCall *call;
+
+	empathy_debug (DEBUG_DOMAIN, "New media channel to be filtered: %p",
+		       channel);
+
+	call = empathy_tp_call_new (channel);
+	if (is_incoming) {
+		filter_call_dispatch (filter, call);
+	} else {
+		g_signal_connect (call, "notify::contact",
+				  G_CALLBACK (filter_call_contact_notify_cb),
+				  filter);	
+	}
+}
+
+#if 0
+static void
+status_icon_pendings_changed_cb (EmpathyContactManager *manager,
+				 EmpathyContact        *contact,
+				 EmpathyContact        *actor,
+				 guint                  reason,
+				 gchar                 *message,
+				 gboolean               is_pending,
+				 EmpathyStatusIcon     *icon)
+{
+	EmpathyStatusIconPriv *priv;
+	StatusIconEvent       *event;
+	GString               *str;
+
+	priv = GET_PRIV (icon);
+
+	if (!is_pending) {
+		/* FIXME: We should remove the event */
+		return;
+	}
+
+	empathy_contact_run_until_ready (contact,
+					 EMPATHY_CONTACT_READY_NAME,
+					 NULL);
+
+	str = g_string_new (NULL);
+	g_string_printf (str, _("Subscription requested by %s"),
+			 empathy_contact_get_name (contact));	
+	if (!G_STR_EMPTY (message)) {
+		g_string_append_printf (str, _("\nMessage: %s"), message);
+	}
+
+	event = status_icon_event_new (icon, GTK_STOCK_DIALOG_QUESTION, str->str);
+	event->user_data = g_object_ref (contact);
+	event->func = status_icon_event_subscribe_cb;
+
+	g_string_free (str, TRUE);
+}
+
+static void
+status_icon_event_subscribe_cb (StatusIconEvent *event)
+{
+	EmpathyContact *contact;
+
+	contact = EMPATHY_CONTACT (event->user_data);
+
+	empathy_subscription_dialog_show (contact, NULL);
+
+	g_object_unref (contact);
+}
+	g_signal_connect (priv->manager, "pendings-changed",
+			  G_CALLBACK (status_icon_pendings_changed_cb),
+			  icon);
+
+	pendings = empathy_contact_list_get_pendings (EMPATHY_CONTACT_LIST (priv->manager));
+	for (l = pendings; l; l = l->next) {
+		EmpathyPendingInfo *info;
+
+		info = l->data;
+		status_icon_pendings_changed_cb (priv->manager,
+						 info->member,
+						 info->actor,
+						 0,
+						 info->message,
+						 TRUE,
+						 icon);
+		empathy_pending_info_free (info);
+	}
+	g_list_free (pendings);
+#endif
+
+static void
+filter_connection_invalidated_cb (TpConnection  *connection,
+				  guint          domain,
+				  gint           code,
+				  gchar         *message,
+				  EmpathyFilter *filter)
+{
+	EmpathyFilterPriv *priv = GET_PRIV (filter);
+	GHashTableIter     iter;
+	gpointer           key, value;
+
+	empathy_debug (DEBUG_DOMAIN, "connection invalidated: %s", message);
+
+	g_hash_table_iter_init (&iter, priv->accounts);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		if (value == connection) {
+			g_hash_table_remove (priv->accounts, key);
+			break;
+		}
+	}
+}
+
+typedef void (*HandleChannelFunc) (EmpathyFilter *filter,
+				   TpChannel     *channel,
+				   gboolean       is_incoming);
+
+static void
+filter_conection_new_channel_cb (TpConnection *connection,
+				 const gchar  *object_path,
+				 const gchar  *channel_type,
+				 guint         handle_type,
+				 guint         handle,
+				 gboolean      suppress_handler,
+				 gpointer      user_data,
+				 GObject      *filter)
+{
+	HandleChannelFunc  func = NULL;
+	TpChannel         *channel;
+	
+	if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT)) {
+		func = filter_chat_handle_channel;
+	}
+	else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA)) {
+		func = filter_call_handle_channel;
+	} else {
+		empathy_debug (DEBUG_DOMAIN, "Unknown channel type %s",
+			       channel_type);
+		return;
+	}
+
+	channel = tp_channel_new (connection, object_path, channel_type,
+				  handle_type, handle, NULL);
+	tp_channel_run_until_ready (channel, NULL, NULL);
+
+	/* We abuse of suppress_handler, TRUE means OUTGOING */
+	func (EMPATHY_FILTER (filter), channel, suppress_handler);
+
+	g_object_unref (channel);
+}
+
+static void
+filter_connection_ready_cb (TpConnection  *connection,
+			    gpointer       unused,
+			    EmpathyFilter *filter)
+{
+	empathy_debug (DEBUG_DOMAIN, "Connection ready, accepting new channels");
+	tp_cli_connection_connect_to_new_channel (connection,
+						  filter_conection_new_channel_cb,
+						  NULL, NULL,
+						  G_OBJECT (filter), NULL);
+}
+
+static void
+filter_update_account (EmpathyFilter *filter,
+		       McAccount     *account)
+{
+	EmpathyFilterPriv *priv = GET_PRIV (filter);
+	TpConnection      *connection;
+	gboolean           ready;
+
+	connection = g_hash_table_lookup (priv->accounts, account);
+	if (connection) {
+		return;
+	}
+
+	connection = mission_control_get_tpconnection (priv->mc, account, NULL);
+	if (!connection) {
+		return;
+	}
+
+	g_hash_table_insert (priv->accounts, g_object_ref (account), connection);
+	g_signal_connect (connection, "invalidated",
+			  G_CALLBACK (filter_connection_invalidated_cb),
+			  filter);
+
+	g_object_get (connection, "connection-ready", &ready, NULL);
+	if (ready) {
+		filter_connection_ready_cb (connection, NULL, filter);
+	} else {
+		g_signal_connect (connection, "notify::connection-ready",
+				  G_CALLBACK (filter_connection_ready_cb),
+				  filter);
+	}
+}
+
+static void
+filter_status_changed_cb (MissionControl           *mc,
+			  TpConnectionStatus        status,
+			  McPresence                presence,
+			  TpConnectionStatusReason  reason,
+			  const gchar              *unique_name,
+			  EmpathyFilter            *filter)
+{
+	McAccount *account;
+
+	account = mc_account_lookup (unique_name);
+	filter_update_account (filter, account);
+	g_object_unref (account);
+}
+
+static void
+filter_finalize (GObject *object)
+{
+	EmpathyFilterPriv *priv = GET_PRIV (object);
+
+	empathy_disconnect_account_status_changed (priv->token);
+	g_object_unref (priv->mc);
+
+	g_slist_foreach (priv->events, (GFunc) filter_event_free, NULL);
+	g_slist_free (priv->events);
+
+	g_hash_table_destroy (priv->accounts);
+}
+
+static void
+filter_get_property (GObject    *object,
+		     guint       param_id,
+		     GValue     *value,
+		     GParamSpec *pspec)
+{
+	EmpathyFilterPriv *priv = GET_PRIV (object);
+
+	switch (param_id) {
+	case PROP_TOP_EVENT:
+		g_value_set_pointer (value, priv->events ? priv->events->data : NULL);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+		break;
+	};
+}
+
+static void
+empathy_filter_class_init (EmpathyFilterClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = filter_finalize;
+	object_class->get_property = filter_get_property;
+
+	g_object_class_install_property (object_class,
+					 PROP_TOP_EVENT,
+					 g_param_spec_pointer ("top-event",
+							       "The top event",
+							       "The first event in the events list",
+							       G_PARAM_READABLE));
+
+	g_type_class_add_private (object_class, sizeof (EmpathyFilterPriv));
+}
+
+static void
+empathy_filter_init (EmpathyFilter *filter)
+{
+	EmpathyFilterPriv *priv = GET_PRIV (filter);
+	GList             *accounts, *l;
+
+	priv->mc = empathy_mission_control_new ();
+	priv->token = empathy_connect_to_account_status_changed (priv->mc,
+		G_CALLBACK (filter_status_changed_cb),
+		filter, NULL);
+
+	priv->accounts = g_hash_table_new_full (empathy_account_hash,
+						empathy_account_equal,
+						g_object_unref,
+						g_object_unref);
+	accounts = mc_accounts_list_by_enabled (TRUE);
+	for (l = accounts; l; l = l->next) {
+		filter_update_account (filter, l->data);
+		g_object_unref (l->data);
+	}
+	g_list_free (accounts);
+}
+
+EmpathyFilter *
+empathy_filter_new (void)
+{
+	static EmpathyFilter *filter = NULL;
+
+	if (!filter) {
+		filter = g_object_new (EMPATHY_TYPE_FILTER, NULL);
+		g_object_add_weak_pointer (G_OBJECT (filter), (gpointer) &filter);
+	} else {
+		g_object_ref (filter);
+	}
+
+	return filter;
+}
+

Copied: trunk/src/empathy-filter.h (from r966, /trunk/libempathy/empathy-filter.h)
==============================================================================
--- /trunk/libempathy/empathy-filter.h	(original)
+++ trunk/src/empathy-filter.h	Sat Apr 19 18:36:22 2008
@@ -24,13 +24,11 @@
 
 #include <glib.h>
 
-#include <telepathy-glib/channel.h>
-
 G_BEGIN_DECLS
 
 #define EMPATHY_TYPE_FILTER         (empathy_filter_get_type ())
 #define EMPATHY_FILTER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_FILTER, EmpathyFilter))
-#define EMPATHY_FILTER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_FILTER, EmpathyFilterClass))
+#define EMPATHY_FILTER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_FILTER, EmpathyFilterClass))
 #define EMPATHY_IS_FILTER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_FILTER))
 #define EMPATHY_IS_FILTER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_FILTER))
 #define EMPATHY_FILTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_FILTER, EmpathyFilterClass))
@@ -40,22 +38,23 @@
 typedef struct _EmpathyFilterPriv  EmpathyFilterPriv;
 
 struct _EmpathyFilter {
-	GObject parent;
+	GObject      parent;
 };
 
 struct _EmpathyFilterClass {
 	GObjectClass parent_class;
 };
 
-GType          empathy_filter_get_type (void) G_GNUC_CONST;
-EmpathyFilter *empathy_filter_new      (const gchar   *bus_name,
-					const gchar   *object_path,
-					const gchar   *channel_type,
-					guint          priority,
-					guint          flags);
-void           empathy_filter_process  (EmpathyFilter *filter,
-					TpChannel     *channel,
-					gboolean       process);
+typedef struct {
+	gchar *icon_name;
+	gchar *message;
+} EmpathyFilterEvent;
+
+GType               empathy_filter_get_type       (void) G_GNUC_CONST;
+EmpathyFilter *     empathy_filter_new            (void);
+void                empathy_filter_activate_event (EmpathyFilter      *filter,
+						   EmpathyFilterEvent *event);
+EmpathyFilterEvent *empathy_filter_get_top_event  (EmpathyFilter      *filter);
 
 G_END_DECLS
 

Modified: trunk/src/empathy-status-icon.c
==============================================================================
--- trunk/src/empathy-status-icon.c	(original)
+++ trunk/src/empathy-status-icon.c	Sat Apr 19 18:36:22 2008
@@ -27,18 +27,10 @@
 #include <glade/glade.h>
 #include <glib/gi18n.h>
 
-#include <libmissioncontrol/mission-control.h>
-
-#include <libempathy/empathy-contact-list.h>
-#include <libempathy/empathy-contact-manager.h>
-#include <libempathy/empathy-contact.h>
-#include <libempathy/empathy-tp-chat.h>
 #include <libempathy/empathy-debug.h>
 #include <libempathy/empathy-utils.h>
 #include <libempathy/empathy-idle.h>
-#include <libempathy/empathy-filter.h>
 
-#include <libempathy-gtk/empathy-contact-dialogs.h>
 #include <libempathy-gtk/empathy-presence-chooser.h>
 #include <libempathy-gtk/empathy-conf.h>
 #include <libempathy-gtk/empathy-ui-utils.h>
@@ -48,7 +40,7 @@
 
 #include "empathy-status-icon.h"
 #include "empathy-preferences.h"
-
+#include "empathy-filter.h"
 
 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
 		       EMPATHY_TYPE_STATUS_ICON, EmpathyStatusIconPriv))
@@ -61,88 +53,52 @@
 typedef struct _StatusIconEvent StatusIconEvent;
 
 struct _EmpathyStatusIconPriv {
-	GtkStatusIcon         *icon;
-	EmpathyContactManager *manager;
-	EmpathyFilter         *text_filter;
-	EmpathyFilter         *call_filter;
-	EmpathyIdle           *idle;
-	MissionControl        *mc;
-	GList                 *events;
-	gboolean               showing_event_icon;
-	StatusIconEvent       *flash_state_event;
-	guint                  blink_timeout;
-
-	GtkWindow             *window;
-	GtkWidget             *popup_menu;
-	GtkWidget             *show_window_item;
-	GtkWidget             *message_item;
-	GtkWidget             *status_item;
+	GtkStatusIcon      *icon;
+	EmpathyIdle        *idle;
+	EmpathyFilter      *filter;
+	EmpathyFilterEvent *event;
+	gboolean            showing_event_icon;
+	guint               blink_timeout;
+
+	GtkWindow          *window;
+	GtkWidget          *popup_menu;
+	GtkWidget          *show_window_item;
+	GtkWidget          *message_item;
+	GtkWidget          *status_item;
 };
 
-typedef void (*EventActivatedFunc) (StatusIconEvent *event);
+G_DEFINE_TYPE (EmpathyStatusIcon, empathy_status_icon, G_TYPE_OBJECT);
 
-struct _StatusIconEvent {
-	gchar              *icon_name;
-	gchar              *message;
-	EventActivatedFunc  func;
-	gpointer            user_data;
-};
+static void
+status_icon_set_visibility (EmpathyStatusIcon *icon,
+			    gboolean           visible,
+			    gboolean           store)
+{
+	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
 
+	if (store) {
+		empathy_conf_set_bool (empathy_conf_get (),
+				       EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN, !visible);
+	}
 
-static void       empathy_status_icon_class_init  (EmpathyStatusIconClass *klass);
-static void       empathy_status_icon_init        (EmpathyStatusIcon      *icon);
-static void       status_icon_finalize            (GObject                *object);
-static void       status_icon_text_filter_new_channel (EmpathyFilter      *filter,
-						   TpChannel              *channel,
-						   EmpathyStatusIcon      *icon);
-static void       status_icon_call_filter_new_channel (EmpathyFilter      *filter,
-						   TpChannel              *channel,
-						   EmpathyStatusIcon      *icon);
-static void       status_icon_message_received_cb (EmpathyTpChat          *tp_chat,
-						   EmpathyMessage         *message,
-						   EmpathyStatusIcon      *icon);
-static void       status_icon_idle_notify_cb      (EmpathyStatusIcon      *icon);
-static void       status_icon_update_tooltip      (EmpathyStatusIcon      *icon);
-static void       status_icon_set_from_state      (EmpathyStatusIcon      *icon);
-static void       status_icon_set_visibility      (EmpathyStatusIcon      *icon,
-						   gboolean                visible,
-						   gboolean                store);
-static void       status_icon_toggle_visibility   (EmpathyStatusIcon      *icon);
-static void       status_icon_activate_cb         (GtkStatusIcon          *status_icon,
-						   EmpathyStatusIcon      *icon);
-static gboolean   status_icon_delete_event_cb     (GtkWidget              *widget,
-						   GdkEvent               *event,
-						   EmpathyStatusIcon      *icon);
-static void       status_icon_popup_menu_cb       (GtkStatusIcon          *status_icon,
-						   guint                   button,
-						   guint                   activate_time,
-						   EmpathyStatusIcon      *icon);
-static void       status_icon_create_menu         (EmpathyStatusIcon      *icon);
-static void       status_icon_new_message_cb      (GtkWidget              *widget,
-						   EmpathyStatusIcon      *icon);
-static void       status_icon_quit_cb             (GtkWidget              *window,
-						   EmpathyStatusIcon      *icon);
-static void       status_icon_show_hide_window_cb (GtkWidget              *widget,
-						   EmpathyStatusIcon      *icon);
-static void       status_icon_pendings_changed_cb (EmpathyContactManager  *manager,
-						   EmpathyContact         *contact,
-						   EmpathyContact         *actor,
-						   guint                   reason,
-						   gchar                  *message,
-						   gboolean                is_pending,
-						   EmpathyStatusIcon      *icon);
-static void       status_icon_event_subscribe_cb  (StatusIconEvent        *event);
-static void       status_icon_event_flash_state_cb (StatusIconEvent       *event);
-static void       status_icon_event_msg_cb        (StatusIconEvent        *event);
-static StatusIconEvent * status_icon_event_new    (EmpathyStatusIcon      *icon,
-						   const gchar            *icon_name,
-						   const gchar            *message);
-static void       status_icon_event_remove        (EmpathyStatusIcon      *icon,
-						   StatusIconEvent        *event);
-static gboolean   status_icon_event_timeout_cb    (EmpathyStatusIcon      *icon);
-static void       status_icon_event_free          (StatusIconEvent        *event);
+	if (!visible) {
+		empathy_window_iconify (priv->window, priv->icon);
+	} else {
+		GList *accounts;
 
-G_DEFINE_TYPE (EmpathyStatusIcon, empathy_status_icon, G_TYPE_OBJECT);
+		empathy_window_present (GTK_WINDOW (priv->window), TRUE);
+	
+		/* Show the accounts dialog if there is no enabled accounts */
+		accounts = mc_accounts_list_by_enabled (TRUE);
+		if (accounts) {
+			mc_accounts_list_free (accounts);
+		} else {
+			empathy_debug (DEBUG_DOMAIN,
+				      "No enabled account, Showing account dialog");
+			empathy_accounts_dialog_show (GTK_WINDOW (priv->window));
+		}
+	}
+}
 
 static void
 status_icon_notify_visibility_cb (EmpathyConf *conf,
@@ -158,389 +114,112 @@
 }
 
 static void
-empathy_status_icon_class_init (EmpathyStatusIconClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-	object_class->finalize = status_icon_finalize;
-
-	g_type_class_add_private (object_class, sizeof (EmpathyStatusIconPriv));
-}
-
-static void
-empathy_status_icon_init (EmpathyStatusIcon *icon)
+status_icon_toggle_visibility (EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv;
-	GList                 *pendings, *l;
-
-	priv = GET_PRIV (icon);
-
-	priv->icon = gtk_status_icon_new ();
-	priv->manager = empathy_contact_manager_new ();
-	priv->mc = empathy_mission_control_new ();
-	priv->text_filter = empathy_filter_new ("org.gnome.Empathy.ChatFilter",
-						"/org/gnome/Empathy/ChatFilter",
-						TP_IFACE_CHANNEL_TYPE_TEXT,
-						MC_FILTER_PRIORITY_DIALOG,
-						MC_FILTER_FLAG_INCOMING);
-	priv->call_filter = empathy_filter_new ("org.gnome.Empathy.CallFilter",
-						"/org/gnome/Empathy/CallFilter",
-						TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
-						MC_FILTER_PRIORITY_DIALOG,
-						MC_FILTER_FLAG_INCOMING);
-
-	priv->idle = empathy_idle_new ();
-
-	/* make icon listen and respond to MAIN_WINDOW_HIDDEN changes */
-	empathy_conf_notify_add (empathy_conf_get (),
-				 EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN,
-				 status_icon_notify_visibility_cb,
-				 icon);
-
-	status_icon_create_menu (icon);
-	status_icon_idle_notify_cb (icon);
-
-	g_signal_connect (priv->text_filter, "new-channel",
-			  G_CALLBACK (status_icon_text_filter_new_channel),
-			  icon);
-	g_signal_connect (priv->call_filter, "new-channel",
-			  G_CALLBACK (status_icon_call_filter_new_channel),
-			  icon);
-	g_signal_connect_swapped (priv->idle, "notify",
-				  G_CALLBACK (status_icon_idle_notify_cb),
-				  icon);
-	g_signal_connect (priv->icon, "activate",
-			  G_CALLBACK (status_icon_activate_cb),
-			  icon);
-	g_signal_connect (priv->icon, "popup-menu",
-			  G_CALLBACK (status_icon_popup_menu_cb),
-			  icon);
-	g_signal_connect (priv->manager, "pendings-changed",
-			  G_CALLBACK (status_icon_pendings_changed_cb),
-			  icon);
+	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
+	gboolean               visible;
 
-	pendings = empathy_contact_list_get_pendings (EMPATHY_CONTACT_LIST (priv->manager));
-	for (l = pendings; l; l = l->next) {
-		EmpathyPendingInfo *info;
-
-		info = l->data;
-		status_icon_pendings_changed_cb (priv->manager,
-						 info->member,
-						 info->actor,
-						 0,
-						 info->message,
-						 TRUE,
-						 icon);
-		empathy_pending_info_free (info);
-	}
-	g_list_free (pendings);
+	visible = gtk_window_is_active (priv->window);
+	status_icon_set_visibility (icon, !visible, TRUE);
 }
 
 static void
-status_icon_finalize (GObject *object)
+status_icon_update_tooltip (EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv;
-
-	priv = GET_PRIV (object);
-
-	g_list_foreach (priv->events, (GFunc) status_icon_event_free, NULL);
-	g_list_free (priv->events);
+	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
+	const gchar           *tooltip = NULL;
 
-	if (priv->blink_timeout) {
-		g_source_remove (priv->blink_timeout);
+	if (priv->event) {
+		tooltip = priv->event->message;
 	}
 
-	g_object_unref (priv->icon);
-	g_object_unref (priv->window);
-	g_object_unref (priv->idle);
-	g_object_unref (priv->manager);
-	g_object_unref (priv->mc);
-	g_object_unref (priv->text_filter);
-	g_object_unref (priv->call_filter);
-}
-
-EmpathyStatusIcon *
-empathy_status_icon_new (GtkWindow *window)
-{
-	EmpathyStatusIconPriv *priv;
-	EmpathyStatusIcon     *icon;
-	gboolean               should_hide;
-
-	g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
-
-	icon = g_object_new (EMPATHY_TYPE_STATUS_ICON, NULL);
-	priv = GET_PRIV (icon);
-
-	priv->window = g_object_ref (window);
-
-	g_signal_connect (priv->window, "delete-event",
-			  G_CALLBACK (status_icon_delete_event_cb),
-			  icon);
-
-	empathy_conf_get_bool (empathy_conf_get (),
-			      EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN,
-			      &should_hide);
-
-	if (gtk_window_is_active (priv->window) == should_hide) {
-		status_icon_set_visibility (icon, !should_hide, FALSE);
+	if (!tooltip) {
+		tooltip = empathy_idle_get_status (priv->idle);
 	}
 
-	return icon;
-}
-
-static void
-status_icon_text_filter_new_channel (EmpathyFilter     *filter,
-				     TpChannel         *channel,
-				     EmpathyStatusIcon *icon)
-{
-	EmpathyTpChat *tp_chat;
-
-	empathy_debug (DEBUG_DOMAIN, "New text channel to be filtered for contact %p",
-		       channel);
-
-	tp_chat = empathy_tp_chat_new (channel, FALSE);
-	g_object_set_data (G_OBJECT (tp_chat), "filter", filter);
-	g_object_set_data (G_OBJECT (tp_chat), "channel", channel);
-
-	g_signal_connect (tp_chat, "message-received",
-			  G_CALLBACK (status_icon_message_received_cb),
-			  icon);
-}
-
-static void
-status_icon_message_received_cb (EmpathyTpChat     *tp_chat,
-				 EmpathyMessage    *message,
-				 EmpathyStatusIcon *icon)
-{
-	EmpathyContact  *sender;
-	gchar           *msg;
-	StatusIconEvent *event;
-
-	empathy_debug (DEBUG_DOMAIN, "Message received, add event");
-
-	g_signal_handlers_disconnect_by_func (tp_chat,
-			  		      status_icon_message_received_cb,
-			  		      icon);
-
-	sender = empathy_message_get_sender (message);
-	msg = g_strdup_printf (_("New message from %s:\n%s"),
-			       empathy_contact_get_name (sender),
-			       empathy_message_get_body (message));
-
-	event = status_icon_event_new (icon, EMPATHY_IMAGE_NEW_MESSAGE, msg);
-	event->func = status_icon_event_msg_cb;
-	event->user_data = tp_chat;
-	g_free (msg);
-}
-
-static void
-status_icon_event_call_cb (StatusIconEvent *event)
-{
-	EmpathyTpGroup *group;
-	EmpathyFilter  *filter;
-	TpChannel      *channel;
-
-	empathy_debug (DEBUG_DOMAIN, "Dispatching call channel");
-
-	group = event->user_data;
-	filter = g_object_get_data (G_OBJECT (group), "filter");
-	channel = g_object_get_data (G_OBJECT (group), "channel");
-	empathy_filter_process (filter, channel, TRUE);
-	g_object_unref (group);
+	gtk_status_icon_set_tooltip (priv->icon, tooltip);	
 }
 
 static void
-status_icon_call_filter_new_channel (EmpathyFilter     *filter,
-				     TpChannel         *channel,
-				     EmpathyStatusIcon *icon)
+status_icon_update_icon (EmpathyStatusIcon *icon)
 {
-	EmpathyTpGroup     *group;
-	EmpathyPendingInfo *invitation;
-	EmpathyContact     *contact = NULL;
-
-	empathy_debug (DEBUG_DOMAIN, "New media channel to be filtered");
-
-	/* FIXME: We have to check if the user is member or local-pending to
-	 * know if it's an incoming or outgoing call because of the way we
-	 * request media channels MC can't know if it's incoming or outgoing */
-	group = empathy_tp_group_new (channel);
-	empathy_run_until_ready (group);
+	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
+	const gchar           *icon_name;
 
-	invitation = empathy_tp_group_get_invitation (group, &contact);	
-	if (!invitation) {
-		empathy_debug (DEBUG_DOMAIN, "Process OUTGOING call channel");
-		empathy_filter_process (filter, channel, TRUE);
+	if (priv->event && priv->showing_event_icon) {
+		icon_name = priv->event->icon_name;
 	} else {
-		StatusIconEvent *event;
-		gchar           *msg;
+		McPresence state;
 
-		/* We are local pending, it's an incoming call, we need to ask
-		 * the user if he wants to accept the call. */
-		empathy_contact_run_until_ready (contact,
-						 EMPATHY_CONTACT_READY_NAME,
-						 NULL);
-
-		empathy_debug (DEBUG_DOMAIN, "INCOMING call, add event");
-
-		msg = g_strdup_printf (_("Incoming call from %s:\n%s"),
-				       empathy_contact_get_name (contact),
-				       invitation->message);
-
-		g_object_set_data (G_OBJECT (group), "filter", filter);
-		g_object_set_data (G_OBJECT (group), "channel", channel);
-		event = status_icon_event_new (icon, EMPATHY_IMAGE_VOIP, msg);
-		event->func = status_icon_event_call_cb;
-		event->user_data = group;
-		g_free (msg);
+		state = empathy_idle_get_state (priv->idle);
+		icon_name = empathy_icon_name_for_presence (state);
 	}
 
-	if (contact) {
-		g_object_unref (contact);
-	}
+	gtk_status_icon_set_from_icon_name (priv->icon, icon_name);
 }
 
 static void
 status_icon_idle_notify_cb (EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv;
-	McPresence             flash_state;
-
-	priv = GET_PRIV (icon);
-
-	flash_state = empathy_idle_get_flash_state (priv->idle);
-	if (flash_state != MC_PRESENCE_UNSET) {
-		const gchar *icon_name;
-
-		icon_name = empathy_icon_name_for_presence (flash_state);
-		if (!priv->flash_state_event) {
-			/* We are now flashing */
-			priv->flash_state_event = status_icon_event_new (icon, icon_name, NULL);
-			priv->flash_state_event->user_data = icon;
-			priv->flash_state_event->func = status_icon_event_flash_state_cb;
-		} else {
-			/* We are still flashing but with another state */
-			g_free (priv->flash_state_event->icon_name);
-			priv->flash_state_event->icon_name = g_strdup (icon_name);
-		}
-	}
-	else if (priv->flash_state_event) {
-		/* We are no more flashing */
-		status_icon_event_remove (icon, priv->flash_state_event);
-		priv->flash_state_event = NULL;
-	}
-
-	if (!priv->showing_event_icon) {
-		status_icon_set_from_state (icon);
-	}
-
+	status_icon_update_icon (icon);
 	status_icon_update_tooltip (icon);
 }
 
-static void
-status_icon_update_tooltip (EmpathyStatusIcon *icon)
-{
-	EmpathyStatusIconPriv *priv;
-	const gchar           *tooltip = NULL;
-
-	priv = GET_PRIV (icon);
-
-	if (priv->events) {
-		StatusIconEvent *event;
-
-		event = priv->events->data;
-		tooltip = event->message;
-	}
-
-	if (!tooltip) {
-		tooltip = empathy_idle_get_status (priv->idle);
-	}
-
-	gtk_status_icon_set_tooltip (priv->icon, tooltip);	
-}
-
-static void
-status_icon_set_from_state (EmpathyStatusIcon *icon)
+static gboolean
+status_icon_delete_event_cb (GtkWidget         *widget,
+			     GdkEvent          *event,
+			     EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv;
-	McPresence             state;
-	const gchar           *icon_name;
-
-	priv = GET_PRIV (icon);
-
-	state = empathy_idle_get_state (priv->idle);
-	icon_name = empathy_icon_name_for_presence (state);
-	gtk_status_icon_set_from_icon_name (priv->icon, icon_name);
+	status_icon_set_visibility (icon, FALSE, TRUE);
+	return TRUE;
 }
 
 static void
-status_icon_set_visibility (EmpathyStatusIcon *icon,
-			    gboolean           visible,
-			    gboolean           store)
+status_icon_activate_cb (GtkStatusIcon     *status_icon,
+			 EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv;
-
-	priv = GET_PRIV (icon);
+	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
 
-	if (store) {
-		empathy_conf_set_bool (empathy_conf_get (),
-				       EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN, !visible);
-	}
+	empathy_debug (DEBUG_DOMAIN, "Activated: %s",
+		       priv->event ? "event" : "toggle");
 
-	if (!visible) {
-		empathy_window_iconify (priv->window, priv->icon);
-	} else {
-		GList *accounts;
+	if (priv->event) {
+		empathy_filter_activate_event (priv->filter, priv->event);
+		priv->event = empathy_filter_get_top_event (priv->filter);
+		status_icon_update_tooltip (icon);
+		status_icon_update_icon (icon);
 
-		empathy_window_present (GTK_WINDOW (priv->window), TRUE);
-	
-		/* Show the accounts dialog if there is no enabled accounts */
-		accounts = mc_accounts_list_by_enabled (TRUE);
-		if (accounts) {
-			mc_accounts_list_free (accounts);
-		} else {
-			empathy_debug (DEBUG_DOMAIN,
-				      "No enabled account, Showing account dialog");
-			empathy_accounts_dialog_show (GTK_WINDOW (priv->window));
+		if (!priv->event && priv->blink_timeout) {
+			g_source_remove (priv->blink_timeout);
+			priv->blink_timeout = 0;
 		}
+	} else {
+		status_icon_toggle_visibility (icon);
 	}
 }
 
 static void
-status_icon_toggle_visibility (EmpathyStatusIcon *icon)
+status_icon_show_hide_window_cb (GtkWidget         *widget,
+				 EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
-	gboolean               visible;
+	gboolean visible;
 
-	visible = gtk_window_is_active (priv->window);
-	status_icon_set_visibility (icon, !visible, TRUE);
+	visible = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget));
+	status_icon_set_visibility (icon, visible, TRUE);
 }
 
 static void
-status_icon_activate_cb (GtkStatusIcon     *status_icon,
-			 EmpathyStatusIcon *icon)
+status_icon_new_message_cb (GtkWidget         *widget,
+			    EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv;
-
-	priv = GET_PRIV (icon);
-
-	empathy_debug (DEBUG_DOMAIN, "Activated: %s",
-		       priv->events ? "event" : "toggle");
-
-	if (priv->events) {
-		status_icon_event_remove (icon, priv->events->data);
-	} else {
-		status_icon_toggle_visibility (icon);
-	}
+	empathy_new_message_dialog_show (NULL);
 }
 
-static gboolean
-status_icon_delete_event_cb (GtkWidget         *widget,
-			     GdkEvent          *event,
-			     EmpathyStatusIcon *icon)
+static void
+status_icon_quit_cb (GtkWidget         *window,
+		     EmpathyStatusIcon *icon)
 {
-	status_icon_set_visibility (icon, FALSE, TRUE);
-
-	return TRUE;
+	gtk_main_quit ();
 }
 
 static void
@@ -549,12 +228,10 @@
 			   guint              activate_time,
 			   EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv;
+	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
 	GtkWidget             *submenu;
 	gboolean               show;
 
-	priv = GET_PRIV (icon);
-
 	show = empathy_window_get_is_visible (GTK_WINDOW (priv->window));
 
 	g_signal_handlers_block_by_func (priv->show_window_item,
@@ -581,12 +258,10 @@
 static void
 status_icon_create_menu (EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv;
+	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
 	GladeXML              *glade;
 	gchar                 *filename;
 
-	priv = GET_PRIV (icon);
-
 	filename = empathy_file_lookup ("empathy-status-icon.glade", "src");
 	glade = empathy_glade_get_file (filename,
 				       "tray_menu",
@@ -608,191 +283,116 @@
 	g_object_unref (glade);
 }
 
-static void
-status_icon_new_message_cb (GtkWidget         *widget,
-			    EmpathyStatusIcon *icon)
+static gboolean
+status_icon_blink_timeout_cb (EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv;
+	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
 
-	priv = GET_PRIV (icon);
+	priv->showing_event_icon = !priv->showing_event_icon;
+	status_icon_update_icon (icon);
 
-	empathy_new_message_dialog_show (NULL);
+	return TRUE;
 }
 
 static void
-status_icon_quit_cb (GtkWidget         *window,
-		     EmpathyStatusIcon *icon)
+status_icon_top_event_notify_cb (EmpathyStatusIcon *icon)
 {
-	gtk_main_quit ();
-}
+	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
 
-static void
-status_icon_show_hide_window_cb (GtkWidget         *widget,
-				 EmpathyStatusIcon *icon)
-{
-	gboolean visible;
+	priv->event = empathy_filter_get_top_event (priv->filter);
+	priv->showing_event_icon = priv->event != NULL;
+	status_icon_update_icon (icon);
+	status_icon_update_tooltip (icon);
 
-	visible = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget));
-	status_icon_set_visibility (icon, visible, TRUE);
+	if (!priv->blink_timeout) {
+		priv->blink_timeout = g_timeout_add (BLINK_TIMEOUT,
+						     (GSourceFunc) status_icon_blink_timeout_cb,
+						     icon);
+	}
 }
 
 static void
-status_icon_pendings_changed_cb (EmpathyContactManager *manager,
-				 EmpathyContact        *contact,
-				 EmpathyContact        *actor,
-				 guint                  reason,
-				 gchar                 *message,
-				 gboolean               is_pending,
-				 EmpathyStatusIcon     *icon)
+status_icon_finalize (GObject *object)
 {
-	EmpathyStatusIconPriv *priv;
-	StatusIconEvent       *event;
-	GString               *str;
-
-	priv = GET_PRIV (icon);
-
-	if (!is_pending) {
-		/* FIXME: We should remove the event */
-		return;
-	}
+	EmpathyStatusIconPriv *priv = GET_PRIV (object);
 
-	empathy_contact_run_until_ready (contact,
-					 EMPATHY_CONTACT_READY_NAME,
-					 NULL);
-
-	str = g_string_new (NULL);
-	g_string_printf (str, _("Subscription requested by %s"),
-			 empathy_contact_get_name (contact));	
-	if (!G_STR_EMPTY (message)) {
-		g_string_append_printf (str, _("\nMessage: %s"), message);
+	if (priv->blink_timeout) {
+		g_source_remove (priv->blink_timeout);
 	}
 
-	event = status_icon_event_new (icon, GTK_STOCK_DIALOG_QUESTION, str->str);
-	event->user_data = g_object_ref (contact);
-	event->func = status_icon_event_subscribe_cb;
-
-	g_string_free (str, TRUE);
+	g_object_unref (priv->icon);
+	g_object_unref (priv->idle);
+	g_object_unref (priv->filter);
 }
 
 static void
-status_icon_event_subscribe_cb (StatusIconEvent *event)
+empathy_status_icon_class_init (EmpathyStatusIconClass *klass)
 {
-	EmpathyContact *contact;
-
-	contact = EMPATHY_CONTACT (event->user_data);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-	empathy_subscription_dialog_show (contact, NULL);
+	object_class->finalize = status_icon_finalize;
 
-	g_object_unref (contact);
+	g_type_class_add_private (object_class, sizeof (EmpathyStatusIconPriv));
 }
 
 static void
-status_icon_event_flash_state_cb (StatusIconEvent *event)
+empathy_status_icon_init (EmpathyStatusIcon *icon)
 {
-	EmpathyStatusIconPriv *priv;
-
-	priv = GET_PRIV (event->user_data);
-
-	empathy_idle_set_flash_state (priv->idle, MC_PRESENCE_UNSET);
-}
+	EmpathyStatusIconPriv *priv = GET_PRIV (icon);
 
-static void
-status_icon_event_msg_cb (StatusIconEvent *event)
-{
-	EmpathyFilter *filter;
-	EmpathyTpChat *tp_chat;
-	TpChannel     *channel;
+	priv->icon = gtk_status_icon_new ();
+	priv->idle = empathy_idle_new ();
+	priv->filter = empathy_filter_new ();
 
-	empathy_debug (DEBUG_DOMAIN, "Dispatching text channel");
+	/* make icon listen and respond to MAIN_WINDOW_HIDDEN changes */
+	empathy_conf_notify_add (empathy_conf_get (),
+				 EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN,
+				 status_icon_notify_visibility_cb,
+				 icon);
 
-	tp_chat = event->user_data;
-	filter = g_object_get_data (G_OBJECT (tp_chat), "filter");
-	channel = g_object_get_data (G_OBJECT (tp_chat), "channel");
-	empathy_filter_process (filter, channel, TRUE);
+	status_icon_create_menu (icon);
+	status_icon_idle_notify_cb (icon);
 
-	g_object_unref (tp_chat);
+	g_signal_connect_swapped (priv->idle, "notify",
+				  G_CALLBACK (status_icon_idle_notify_cb),
+				  icon);
+	g_signal_connect_swapped (priv->filter, "notify::top-event",
+				  G_CALLBACK (status_icon_top_event_notify_cb),
+				  icon);
+	g_signal_connect (priv->icon, "activate",
+			  G_CALLBACK (status_icon_activate_cb),
+			  icon);
+	g_signal_connect (priv->icon, "popup-menu",
+			  G_CALLBACK (status_icon_popup_menu_cb),
+			  icon);
 }
 
-static StatusIconEvent *
-status_icon_event_new (EmpathyStatusIcon *icon,
-		       const gchar       *icon_name,
-		       const gchar       *message)
+EmpathyStatusIcon *
+empathy_status_icon_new (GtkWindow *window)
 {
 	EmpathyStatusIconPriv *priv;
-	StatusIconEvent       *event;
-
-	priv = GET_PRIV (icon);
-
-	event = g_slice_new0 (StatusIconEvent);
-	event->icon_name = g_strdup (icon_name);	
-	event->message = g_strdup (message);
-
-	priv->events = g_list_append (priv->events, event);
-	if (!priv->blink_timeout) {
-		priv->showing_event_icon = FALSE;
-		priv->blink_timeout = g_timeout_add (BLINK_TIMEOUT,
-						     (GSourceFunc) status_icon_event_timeout_cb,
-						     icon);
-		status_icon_event_timeout_cb (icon);
-		status_icon_update_tooltip (icon);
-	}
-
-	return event;
-}
+	EmpathyStatusIcon     *icon;
+	gboolean               should_hide;
 
-static void
-status_icon_event_remove (EmpathyStatusIcon *icon,
-			  StatusIconEvent   *event)
-{
-	EmpathyStatusIconPriv *priv;
+	g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
 
+	icon = g_object_new (EMPATHY_TYPE_STATUS_ICON, NULL);
 	priv = GET_PRIV (icon);
 
-	if (event->func) {
-		event->func (event);
-	}
-	priv->events = g_list_remove (priv->events, event);
-	status_icon_event_free (event);
-	priv->showing_event_icon = FALSE;
-	status_icon_update_tooltip (icon);
-	status_icon_set_from_state (icon);
-
-	if (priv->events) {
-		return;
-	}
-
-	if (priv->blink_timeout) {
-		g_source_remove (priv->blink_timeout);
-		priv->blink_timeout = 0;
-	}
-}
-
-static gboolean
-status_icon_event_timeout_cb (EmpathyStatusIcon *icon)
-{
-	EmpathyStatusIconPriv *priv;
-
-	priv = GET_PRIV (icon);
+	priv->window = g_object_ref (window);
 
-	priv->showing_event_icon = !priv->showing_event_icon;
+	g_signal_connect (priv->window, "delete-event",
+			  G_CALLBACK (status_icon_delete_event_cb),
+			  icon);
 
-	if (!priv->showing_event_icon) {
-		status_icon_set_from_state (icon);
-	} else {
-		StatusIconEvent *event;
+	empathy_conf_get_bool (empathy_conf_get (),
+			      EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN,
+			      &should_hide);
 
-		event = priv->events->data;
-		gtk_status_icon_set_from_icon_name (priv->icon, event->icon_name);
+	if (gtk_window_is_active (priv->window) == should_hide) {
+		status_icon_set_visibility (icon, !should_hide, FALSE);
 	}
 
-	return TRUE;
-}
-
-static void
-status_icon_event_free (StatusIconEvent *event)
-{
-	g_free (event->icon_name);
-	g_free (event->message);
-	g_slice_free (StatusIconEvent, event);
+	return icon;
 }
 

Modified: trunk/src/empathy.c
==============================================================================
--- trunk/src/empathy.c	(original)
+++ trunk/src/empathy.c	Sat Apr 19 18:36:22 2008
@@ -33,92 +33,24 @@
 #include <libebook/e-book.h>
 
 #include <telepathy-glib/util.h>
-#include <telepathy-glib/channel.h>
-#include <telepathy-glib/connection.h>
 #include <libmissioncontrol/mc-account.h>
 #include <libmissioncontrol/mission-control.h>
 
 #include <libempathy/empathy-idle.h>
-#include <libempathy/empathy-tp-chat.h>
-#include <libempathy/empathy-chandler.h>
 #include <libempathy/empathy-utils.h>
 #include <libempathy/empathy-debug.h>
 
 #include <libempathy-gtk/empathy-conf.h>
-#include <libempathy-gtk/empathy-chat.h>
 
 #include "empathy-main-window.h"
 #include "empathy-status-icon.h"
-#include "empathy-chat-window.h"
 #include "bacon-message-connection.h"
 
 #define DEBUG_DOMAIN "EmpathyMain"
-#define BUS_NAME "org.gnome.Empathy.ChatChandler"
-#define OBJECT_PATH "/org/gnome/Empathy/ChatChandler"
 
 static BaconMessageConnection *connection = NULL;
 
 static void
-new_text_channel_cb (EmpathyChandler *chandler,
-		     TpChannel       *channel,
-		     MissionControl  *mc)
-{
-	EmpathyTpChat *tp_chat;
-	TpConnection  *connection;
-	guint          handle_type;
-	guint          handle;
-	gchar        **names;
-	McAccount     *account;
-	EmpathyChat   *chat;
-	gchar         *id;
-	GArray        *handles;
-
-	g_object_get (channel,
-		      "connection", &connection,
-		      "handle-type", &handle_type,
-		      "handle", &handle,
-		      NULL);
-	handles = g_array_new (FALSE, FALSE, sizeof (guint));
-	g_array_append_val (handles, handle);
-	tp_cli_connection_run_inspect_handles (connection, -1,
-					       handle_type, handles,
-					       &names,
-					       NULL, NULL);
-	id = *names;
-	g_free (names);
-	g_object_unref (connection);
-	g_array_free (handles, TRUE);
-
-	account = empathy_channel_get_account (channel);
-	chat = empathy_chat_window_find_chat (account, id);
-	g_free (id);
-
-	if (chat) {
-		/* The chat already exists */
-		if (!empathy_chat_get_tp_chat (chat)) {
-			/* The chat died, give him the new text channel */
-			tp_chat = empathy_tp_chat_new (channel, TRUE);
-			empathy_run_until_ready (tp_chat);
-			empathy_chat_set_tp_chat (chat, tp_chat);
-			g_object_unref (tp_chat);
-		}
-		empathy_chat_window_present_chat (chat);
-
-		g_object_unref (account);
-		return;
-	}
-
-	tp_chat = empathy_tp_chat_new (channel, TRUE);
-	empathy_run_until_ready (tp_chat);
-
-	chat = empathy_chat_new (tp_chat);
-	empathy_chat_window_present_chat (chat);
-
-	g_object_unref (account);
-	g_object_unref (tp_chat);
-}
-
-static void
 service_ended_cb (MissionControl *mc,
 		  gpointer        user_data)
 {
@@ -374,7 +306,6 @@
 	GtkWidget         *window;
 	MissionControl    *mc;
 	EmpathyIdle       *idle;
-	EmpathyChandler   *chandler;
 	gboolean           autoconnect = TRUE;
 	gboolean           no_connect = FALSE; 
 	GError            *error = NULL;
@@ -470,18 +401,10 @@
 						       window);
 	}
 
-	/* Handle text channels */
-	chandler = empathy_chandler_new (BUS_NAME, OBJECT_PATH);
-	g_signal_connect (chandler, "new-channel",
-			  G_CALLBACK (new_text_channel_cb),
-			  mc);
-	empathy_debug (DEBUG_DOMAIN, "Ready to handle new text channels");
-
 	gtk_main ();
 
 	empathy_idle_set_state (idle, MC_PRESENCE_OFFLINE);
 
-	g_object_unref (chandler);
 	g_object_unref (mc);
 	g_object_unref (idle);
 	g_object_unref (icon);



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