aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--TODO8
-rw-r--r--libempathy-gtk/empathy-status-icon.c333
-rw-r--r--libempathy-gtk/gossip-contact-list-store.c6
-rw-r--r--libempathy-gtk/gossip-contact-list-view.c2
-rw-r--r--libempathy/empathy-contact-list.c58
-rw-r--r--libempathy/empathy-contact-list.h52
-rw-r--r--libempathy/empathy-contact-manager.c78
-rw-r--r--libempathy/empathy-idle.c233
-rw-r--r--libempathy/empathy-idle.h15
-rw-r--r--libempathy/empathy-marshal.list8
-rw-r--r--libempathy/empathy-tp-chatroom.c14
-rw-r--r--libempathy/empathy-tp-contact-list.c355
13 files changed, 898 insertions, 287 deletions
diff --git a/ChangeLog b/ChangeLog
index c54d06c68..c7b9ecb8d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2007-06-06 Xavier Claessens <xclaesse@gmail.com>
+
+ * libempathy-gtk/empathy-status-icon.c: Add support for blinking when
+ there is an event. Make use of EmpathyIdle for presence handling. Add
+ an event when a contact requets subscription.
+
+ * libempathy-gtk/gossip-contact-list-store.c:
+ * libempathy-gtk/gossip-contact-list-view.c:
+ * libempathy/empathy-contact-manager.c:
+ * libempathy/empathy-tp-contact-list.c:
+ * libempathy/empathy-tp-chatroom.c:
+ * libempathy/empathy-contact-list.c:
+ * libempathy/empathy-contact-list.h: get_contacts() is renamed to
+ get_members(). Adding a signal and a method for local-pending with
+ contacts with the message. Rework completely the contact-list handling in
+ EmpathyTpContactList to follow tp spec.
+
+ * libempathy/empathy-idle.c:
+ * libempathy/empathy-idle.h: Add properties for the state and the
+ status message. EmpathyIdle is now a singleton to manager self presence.
+
+ * TODO: Updated.
+
2007-06-03 Xavier Claessens <xclaesse@gmail.com>
* libempathy-gtk/gossip-accounts-dialog.glade: Set use_stock for
diff --git a/TODO b/TODO
index f6d5d9cd5..5be759c2e 100644
--- a/TODO
+++ b/TODO
@@ -1,15 +1,13 @@
Things you can do if you want to help:
- - Rename all files and functions name to use the empathy namespace.
+ - Rename all files and functions name to use the empathy namespace. Bug #444490.
- Porting gossip-account-widget-*.{c,h} from gossip project (Guillaume is already working on IRC widget).
- Porting various UI widgets from gossip to libempathy-gtk for contact info, adding contact, personal info, etc.
- GtkWidget-ify gossip widgets imported in libempathy-gtk. Actually most window/dialog do not inherit from GtkWindow/GtkDialog. Need to create a glade catalog.
- - Fix setting subscription for contacts in EmpathyTpContactList.
- - Filter channels before dispatching them. For example we need a GtkStatusIcon that blink when an event arrives (text/voip/ft channel) and tells the MC to dispatch the channel only when the user clicked the icon. Like in gossip. For that we need a filter DBus API in MC, not yet written.
+ - Filter channels before dispatching them. For example we need a GtkStatusIcon that blink when an event arrives (text/voip/ft channel) and tells the MC to dispatch the channel only when the user clicked the icon. Like in gossip. For that we need a filter DBus API in MC, not yet written, a draft spec is proposed on the telepathy ML.
- Make use of NetworkManager to set the presence
- Remove Quit option everywhere, empathy is a session service and shouldn't be leaved.
- Add sound events
- - Import loggin system from gossip
- Add register capability in GossipAccountsDialog if the profile says it's supported.
- Testing and Bugfixing.
@@ -19,4 +17,4 @@ SoC projects:
If you want to contribute you can ask for information at
- #telepathy on freenode
- - Telepathy's mailing list.
+ - Telepathy's mailing list: telepathy@lists.freedesktop.org
diff --git a/libempathy-gtk/empathy-status-icon.c b/libempathy-gtk/empathy-status-icon.c
index 01a542493..5c364083b 100644
--- a/libempathy-gtk/empathy-status-icon.c
+++ b/libempathy-gtk/empathy-status-icon.c
@@ -26,9 +26,13 @@
#include <gtk/gtk.h>
#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/gossip-contact.h>
#include <libempathy/gossip-debug.h>
#include <libempathy/gossip-utils.h>
#include <libempathy/gossip-conf.h>
@@ -46,42 +50,74 @@
#define DEBUG_DOMAIN "StatusIcon"
+/* Number of ms to wait when blinking */
+#define BLINK_TIMEOUT 500
+
struct _EmpathyStatusIconPriv {
- MissionControl *mc;
- GtkStatusIcon *icon;
- EmpathyIdle *idle;
+ GtkStatusIcon *icon;
+ EmpathyContactManager *manager;
+ EmpathyIdle *idle;
+ GList *events;
+ guint blink_timeout;
+ gboolean showing_state_icon;
+
+ GtkWindow *window;
+
+ GtkWidget *popup_menu;
+ GtkWidget *show_window_item;
+ GtkWidget *message_item;
+ GtkWidget *status_item;
+};
- GtkWindow *window;
+typedef struct _StatusIconEvent StatusIconEvent;
- GtkWidget *popup_menu;
- GtkWidget *show_window_item;
- GtkWidget *message_item;
- GtkWidget *status_item;
+typedef void (*EventActivatedFunc) (StatusIconEvent *event);
+
+struct _StatusIconEvent {
+ gchar *icon_name;
+ gchar *message;
+ EventActivatedFunc func;
+ gpointer user_data;
};
-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_presence_changed_cb (MissionControl *mc,
- McPresence state,
- EmpathyStatusIcon *icon);
-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 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_idle_notify_cb (EmpathyIdle *idle,
+ GParamSpec *param,
+ EmpathyStatusIcon *icon);
+static void status_icon_update_tooltip (EmpathyStatusIcon *icon);
+static void status_icon_set_from_state (EmpathyStatusIcon *icon);
+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_local_pending_cb (EmpathyContactManager *manager,
+ GossipContact *contact,
+ gchar *message,
+ EmpathyStatusIcon *icon);
+static void status_icon_event_subscribe_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);
G_DEFINE_TYPE (EmpathyStatusIcon, empathy_status_icon, G_TYPE_OBJECT);
@@ -99,29 +135,43 @@ static void
empathy_status_icon_init (EmpathyStatusIcon *icon)
{
EmpathyStatusIconPriv *priv;
- McPresence state;
+ GList *pending, *l;
priv = GET_PRIV (icon);
priv->icon = gtk_status_icon_new ();
- priv->mc = gossip_mission_control_new ();
priv->idle = empathy_idle_new ();
+ priv->manager = empathy_contact_manager_new ();
+ priv->showing_state_icon = TRUE;
status_icon_create_menu (icon);
+ status_icon_set_from_state (icon);
+ status_icon_update_tooltip (icon);
- state = mission_control_get_presence_actual (priv->mc, NULL);
- status_icon_presence_changed_cb (priv->mc, state, icon);
-
- dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
- "PresenceStatusActual",
- G_CALLBACK (status_icon_presence_changed_cb),
- icon, NULL);
+ g_signal_connect (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, "local-pending",
+ G_CALLBACK (status_icon_local_pending_cb),
+ icon);
+
+ pending = empathy_contact_list_get_local_pending (EMPATHY_CONTACT_LIST (priv->manager));
+ for (l = pending; l; l = l->next) {
+ EmpathyContactListInfo *info;
+
+ info = l->data;
+ status_icon_local_pending_cb (priv->manager,
+ info->contact,
+ info->message,
+ icon);
+ }
+ g_list_free (pending);
}
static void
@@ -131,15 +181,17 @@ status_icon_finalize (GObject *object)
priv = GET_PRIV (object);
- dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
- "PresenceStatusActual",
- G_CALLBACK (status_icon_presence_changed_cb),
- object);
+ g_list_foreach (priv->events, (GFunc) status_icon_event_free, NULL);
+ g_list_free (priv->events);
+
+ if (priv->blink_timeout) {
+ g_source_remove (priv->blink_timeout);
+ }
- g_object_unref (priv->mc);
g_object_unref (priv->icon);
g_object_unref (priv->window);
g_object_unref (priv->idle);
+ g_object_unref (priv->manager);
}
EmpathyStatusIcon *
@@ -174,33 +226,55 @@ empathy_status_icon_new (GtkWindow *window)
}
static void
-status_icon_presence_changed_cb (MissionControl *mc,
- McPresence state,
- EmpathyStatusIcon *icon)
+status_icon_idle_notify_cb (EmpathyIdle *idle,
+ GParamSpec *param,
+ EmpathyStatusIcon *icon)
{
EmpathyStatusIconPriv *priv;
- const gchar *icon_name;
- gchar *status;
priv = GET_PRIV (icon);
- icon_name = gossip_icon_name_for_presence_state (state);
- status = mission_control_get_presence_message_actual (priv->mc, NULL);
- if (G_STR_EMPTY (status)) {
- g_free (status);
- status = g_strdup (gossip_presence_state_get_default_status (state));
+ if (priv->showing_state_icon) {
+ status_icon_set_from_state (icon);
}
- gtk_status_icon_set_from_icon_name (priv->icon, icon_name);
- gtk_status_icon_set_tooltip (priv->icon, status);
+ status_icon_update_tooltip (icon);
+}
+
+static void
+status_icon_update_tooltip (EmpathyStatusIcon *icon)
+{
+ EmpathyStatusIconPriv *priv;
+ const gchar *tooltip = NULL;
- g_free (status);
+ priv = GET_PRIV (icon);
- if (state < MC_PRESENCE_AVAILABLE) {
- gtk_widget_set_sensitive (priv->message_item, FALSE);
- } else {
- gtk_widget_set_sensitive (priv->message_item, TRUE);
+ 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)
+{
+ EmpathyStatusIconPriv *priv;
+ McPresence state;
+ const gchar *icon_name;
+
+ priv = GET_PRIV (icon);
+
+ state = empathy_idle_get_state (priv->idle);
+ icon_name = gossip_icon_name_for_presence_state (state);
+ gtk_status_icon_set_from_icon_name (priv->icon, icon_name);
}
static void
@@ -240,7 +314,15 @@ static void
status_icon_activate_cb (GtkStatusIcon *status_icon,
EmpathyStatusIcon *icon)
{
- status_icon_toggle_visibility (icon);
+ EmpathyStatusIconPriv *priv;
+
+ priv = GET_PRIV (icon);
+
+ if (priv->events) {
+ status_icon_event_remove (icon, priv->events->data);
+ } else {
+ status_icon_toggle_visibility (icon);
+ }
}
static gboolean
@@ -343,3 +425,128 @@ status_icon_show_hide_window_cb (GtkWidget *widget,
status_icon_toggle_visibility (icon);
}
+static void
+status_icon_local_pending_cb (EmpathyContactManager *manager,
+ GossipContact *contact,
+ gchar *message,
+ EmpathyStatusIcon *icon)
+{
+ EmpathyStatusIconPriv *priv;
+ StatusIconEvent *event;
+ gchar *str;
+ GList *l;
+
+ priv = GET_PRIV (icon);
+
+ for (l = priv->events; l; l = l->next) {
+ if (gossip_contact_equal (contact, ((StatusIconEvent*)l->data)->user_data)) {
+ return;
+ }
+ }
+
+ str = g_strdup_printf (_("Subscription requested for %s\n"
+ "Message: %s"),
+ gossip_contact_get_name (contact),
+ message);
+
+ event = status_icon_event_new (icon, GTK_STOCK_DIALOG_QUESTION, str);
+ event->user_data = g_object_ref (contact);
+ event->func = status_icon_event_subscribe_cb;
+
+ g_free (str);
+}
+
+static void
+status_icon_event_subscribe_cb (StatusIconEvent *event)
+{
+ GossipContact *contact;
+
+ contact = GOSSIP_CONTACT (event->user_data);
+
+ g_object_unref (contact);
+}
+
+static StatusIconEvent *
+status_icon_event_new (EmpathyStatusIcon *icon,
+ const gchar *icon_name,
+ const gchar *message)
+{
+ 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->blink_timeout = g_timeout_add (BLINK_TIMEOUT,
+ (GSourceFunc) status_icon_event_timeout_cb,
+ icon);
+ status_icon_event_timeout_cb (icon);
+ }
+
+ return event;
+}
+
+static void
+status_icon_event_remove (EmpathyStatusIcon *icon,
+ StatusIconEvent *event)
+{
+ EmpathyStatusIconPriv *priv;
+
+ priv = GET_PRIV (icon);
+
+ if (event->func) {
+ event->func (event);
+ }
+ priv->events = g_list_remove (priv->events, event);
+ status_icon_event_free (event);
+ status_icon_update_tooltip (icon);
+
+ if (priv->events) {
+ return;
+ }
+
+ status_icon_set_from_state (icon);
+ priv->showing_state_icon = TRUE;
+
+ 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->showing_state_icon = !priv->showing_state_icon;
+
+ if (priv->showing_state_icon) {
+ status_icon_set_from_state (icon);
+ } else {
+ StatusIconEvent *event;
+
+ event = priv->events->data;
+ gtk_status_icon_set_from_icon_name (priv->icon, event->icon_name);
+ }
+ status_icon_update_tooltip (icon);
+
+ return TRUE;
+}
+
+static void
+status_icon_event_free (StatusIconEvent *event)
+{
+ g_free (event->icon_name);
+ g_free (event->message);
+ g_slice_free (StatusIconEvent, event);
+}
+
diff --git a/libempathy-gtk/gossip-contact-list-store.c b/libempathy-gtk/gossip-contact-list-store.c
index f0ff476dd..4a5b5506e 100644
--- a/libempathy-gtk/gossip-contact-list-store.c
+++ b/libempathy-gtk/gossip-contact-list-store.c
@@ -343,7 +343,7 @@ gossip_contact_list_store_new (EmpathyContactList *list_iface)
/* Add contacts already created. Do not highlight them. */
show_active = priv->show_active;
priv->show_active = FALSE;
- contacts = empathy_contact_list_get_contacts (priv->list);
+ contacts = empathy_contact_list_get_members (priv->list);
for (l = contacts; l; l = l->next) {
GossipContact *contact;
@@ -401,7 +401,7 @@ gossip_contact_list_store_set_show_offline (GossipContactListStore *store,
/* Disable temporarily. */
priv->show_active = FALSE;
- contacts = empathy_contact_list_get_contacts (priv->list);
+ contacts = empathy_contact_list_get_members (priv->list);
for (l = contacts; l; l = l->next) {
GossipContact *contact;
@@ -654,7 +654,7 @@ gossip_contact_list_store_set_contact_groups_func (GossipContactListStore *stor
* to call himself gossip_contact_list_store_update_contact_groups ()
* when needed. If func is NULL we come back to default.
*/
- contacts = empathy_contact_list_get_contacts (priv->list);
+ contacts = empathy_contact_list_get_members (priv->list);
for (l = contacts; l; l = l->next) {
GossipContact *contact;
diff --git a/libempathy-gtk/gossip-contact-list-view.c b/libempathy-gtk/gossip-contact-list-view.c
index 3cad7821d..368ba8be4 100644
--- a/libempathy-gtk/gossip-contact-list-view.c
+++ b/libempathy-gtk/gossip-contact-list-view.c
@@ -1383,7 +1383,7 @@ contact_list_view_filter_show_group (GossipContactListView *view,
* show exists in it.
*/
list = gossip_contact_list_store_get_list_iface (priv->store);
- contacts = empathy_contact_list_get_contacts (list);
+ contacts = empathy_contact_list_get_members (list);
for (l = contacts; l && !show_group; l = l->next) {
if (!gossip_contact_is_in_group (l->data, group)) {
continue;
diff --git a/libempathy/empathy-contact-list.c b/libempathy/empathy-contact-list.c
index b7d02010b..c55d0abf9 100644
--- a/libempathy/empathy-contact-list.c
+++ b/libempathy/empathy-contact-list.c
@@ -23,6 +23,7 @@
#include "config.h"
#include "empathy-contact-list.h"
+#include "empathy-marshal.h"
static void contact_list_base_init (gpointer klass);
@@ -70,10 +71,49 @@ contact_list_base_init (gpointer klass)
G_TYPE_NONE,
1, GOSSIP_TYPE_CONTACT);
+ g_signal_new ("local-pending",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ empathy_marshal_VOID__OBJECT_STRING,
+ G_TYPE_NONE,
+ 2, GOSSIP_TYPE_CONTACT, G_TYPE_STRING);
+
initialized = TRUE;
}
}
+EmpathyContactListInfo *
+empathy_contact_list_info_new (GossipContact *contact,
+ const gchar *message)
+{
+ EmpathyContactListInfo *info;
+
+ g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
+
+ info = g_slice_new0 (EmpathyContactListInfo);
+ info->contact = g_object_ref (contact);
+ info->message = g_strdup (message);
+
+ return info;
+}
+
+void
+empathy_contact_list_info_free (EmpathyContactListInfo *info)
+{
+ if (!info) {
+ return;
+ }
+
+ if (info->contact) {
+ g_object_unref (info->contact);
+ }
+ g_free (info->message);
+
+ g_slice_free (EmpathyContactListInfo, info);
+}
+
void
empathy_contact_list_setup (EmpathyContactList *list)
{
@@ -122,12 +162,24 @@ empathy_contact_list_remove (EmpathyContactList *list,
}
GList *
-empathy_contact_list_get_contacts (EmpathyContactList *list)
+empathy_contact_list_get_members (EmpathyContactList *list)
+{
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
+
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members) {
+ return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members (list);
+ }
+
+ return NULL;
+}
+
+GList *
+empathy_contact_list_get_local_pending (EmpathyContactList *list)
{
g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
- if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_contacts) {
- return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_contacts (list);
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_local_pending) {
+ return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_local_pending (list);
}
return NULL;
diff --git a/libempathy/empathy-contact-list.h b/libempathy/empathy-contact-list.h
index 02ec3186d..09f54621d 100644
--- a/libempathy/empathy-contact-list.h
+++ b/libempathy/empathy-contact-list.h
@@ -37,33 +37,43 @@ G_BEGIN_DECLS
typedef struct _EmpathyContactList EmpathyContactList;
typedef struct _EmpathyContactListIface EmpathyContactListIface;
+typedef struct {
+ GossipContact *contact;
+ gchar *message;
+} EmpathyContactListInfo;
+
struct _EmpathyContactListIface {
GTypeInterface base_iface;
/* VTabled */
- void (*setup) (EmpathyContactList *list);
- GossipContact * (*find) (EmpathyContactList *list,
- const gchar *id);
- void (*add) (EmpathyContactList *list,
- GossipContact *contact,
- const gchar *message);
- void (*remove) (EmpathyContactList *list,
- GossipContact *contact,
- const gchar *message);
- GList * (*get_contacts) (EmpathyContactList *list);
+ void (*setup) (EmpathyContactList *list);
+ GossipContact * (*find) (EmpathyContactList *list,
+ const gchar *id);
+ void (*add) (EmpathyContactList *list,
+ GossipContact *contact,
+ const gchar *message);
+ void (*remove) (EmpathyContactList *list,
+ GossipContact *contact,
+ const gchar *message);
+ GList * (*get_members) (EmpathyContactList *list);
+ GList * (*get_local_pending) (EmpathyContactList *list);
};
-GType empathy_contact_list_get_type (void) G_GNUC_CONST;
-void empathy_contact_list_setup (EmpathyContactList *list);
-GossipContact * empathy_contact_list_find (EmpathyContactList *list,
- const gchar *id);
-void empathy_contact_list_add (EmpathyContactList *list,
- GossipContact *contact,
- const gchar *message);
-void empathy_contact_list_remove (EmpathyContactList *list,
- GossipContact *contact,
- const gchar *message);
-GList * empathy_contact_list_get_contacts (EmpathyContactList *list);
+GType empathy_contact_list_get_type (void) G_GNUC_CONST;
+EmpathyContactListInfo *empathy_contact_list_info_new (GossipContact *contact,
+ const gchar *message);
+void empathy_contact_list_info_free (EmpathyContactListInfo *info);
+void empathy_contact_list_setup (EmpathyContactList *list);
+GossipContact * empathy_contact_list_find (EmpathyContactList *list,
+ const gchar *id);
+void empathy_contact_list_add (EmpathyContactList *list,
+ GossipContact *contact,
+ const gchar *message);
+void empathy_contact_list_remove (EmpathyContactList *list,
+ GossipContact *contact,
+ const gchar *message);
+GList * empathy_contact_list_get_members (EmpathyContactList *list);
+GList * empathy_contact_list_get_local_pending (EmpathyContactList *list);
G_END_DECLS
diff --git a/libempathy/empathy-contact-manager.c b/libempathy/empathy-contact-manager.c
index fa62da98f..5e5f09a43 100644
--- a/libempathy/empathy-contact-manager.c
+++ b/libempathy/empathy-contact-manager.c
@@ -65,7 +65,8 @@ static void contact_manager_add (EmpathyContactList
static void contact_manager_remove (EmpathyContactList *manager,
GossipContact *contact,
const gchar *message);
-static GList * contact_manager_get_contacts (EmpathyContactList *manager);
+static GList * contact_manager_get_members (EmpathyContactList *manager);
+static GList * contact_manager_get_local_pending (EmpathyContactList *manager);
static void contact_manager_setup_foreach (McAccount *account,
EmpathyTpContactList *list,
EmpathyContactManager *manager);
@@ -80,6 +81,10 @@ static void contact_manager_added_cb (EmpathyTpContactList
static void contact_manager_removed_cb (EmpathyTpContactList *list,
GossipContact *contact,
EmpathyContactManager *manager);
+static void contact_manager_local_pending_cb (EmpathyTpContactList *list,
+ GossipContact *contact,
+ const gchar *message,
+ EmpathyContactManager *manager);
static void contact_manager_destroy_cb (EmpathyTpContactList *list,
EmpathyContactManager *manager);
static void contact_manager_rename_group_foreach (McAccount *account,
@@ -88,7 +93,10 @@ static void contact_manager_rename_group_foreach (McAccount
static void contact_manager_get_groups_foreach (McAccount *account,
EmpathyTpContactList *list,
GList **all_groups);
-static void contact_manager_get_contacts_foreach (McAccount *account,
+static void contact_manager_get_members_foreach (McAccount *account,
+ EmpathyTpContactList *list,
+ GList **contacts);
+static void contact_manager_get_local_pending_foreach (McAccount *account,
EmpathyTpContactList *list,
GList **contacts);
static void contact_manager_status_changed_cb (MissionControl *mc,
@@ -115,11 +123,12 @@ empathy_contact_manager_class_init (EmpathyContactManagerClass *klass)
static void
contact_manager_iface_init (EmpathyContactListIface *iface)
{
- iface->setup = contact_manager_setup;
- iface->find = contact_manager_find;
- iface->add = contact_manager_add;
- iface->remove = contact_manager_remove;
- iface->get_contacts = contact_manager_get_contacts;
+ iface->setup = contact_manager_setup;
+ iface->find = contact_manager_find;
+ iface->add = contact_manager_add;
+ iface->remove = contact_manager_remove;
+ iface->get_members = contact_manager_get_members;
+ iface->get_local_pending = contact_manager_get_local_pending;
}
static void
@@ -269,7 +278,7 @@ contact_manager_remove (EmpathyContactList *manager,
}
static GList *
-contact_manager_get_contacts (EmpathyContactList *manager)
+contact_manager_get_members (EmpathyContactList *manager)
{
EmpathyContactManagerPriv *priv;
GList *contacts = NULL;
@@ -279,12 +288,29 @@ contact_manager_get_contacts (EmpathyContactList *manager)
priv = GET_PRIV (manager);
g_hash_table_foreach (priv->lists,
- (GHFunc) contact_manager_get_contacts_foreach,
+ (GHFunc) contact_manager_get_members_foreach,
&contacts);
return contacts;
}
+static GList *
+contact_manager_get_local_pending (EmpathyContactList *manager)
+{
+ EmpathyContactManagerPriv *priv;
+ GList *pending = NULL;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
+
+ priv = GET_PRIV (manager);
+
+ g_hash_table_foreach (priv->lists,
+ (GHFunc) contact_manager_get_local_pending_foreach,
+ &pending);
+
+ return pending;
+}
+
EmpathyTpContactList *
empathy_contact_manager_get_list (EmpathyContactManager *manager,
McAccount *account)
@@ -435,6 +461,9 @@ contact_manager_add_account (EmpathyContactManager *manager,
g_signal_connect (list, "contact-removed",
G_CALLBACK (contact_manager_removed_cb),
manager);
+ g_signal_connect (list, "local-pending",
+ G_CALLBACK (contact_manager_local_pending_cb),
+ manager);
g_signal_connect (list, "destroy",
G_CALLBACK (contact_manager_destroy_cb),
manager);
@@ -461,6 +490,15 @@ contact_manager_removed_cb (EmpathyTpContactList *list,
}
static void
+contact_manager_local_pending_cb (EmpathyTpContactList *list,
+ GossipContact *contact,
+ const gchar *message,
+ EmpathyContactManager *manager)
+{
+ g_signal_emit_by_name (manager, "local-pending", contact, message);
+}
+
+static void
contact_manager_destroy_cb (EmpathyTpContactList *list,
EmpathyContactManager *manager)
{
@@ -482,6 +520,9 @@ contact_manager_destroy_cb (EmpathyTpContactList *list,
contact_manager_removed_cb,
manager);
g_signal_handlers_disconnect_by_func (list,
+ contact_manager_local_pending_cb,
+ manager);
+ g_signal_handlers_disconnect_by_func (list,
contact_manager_destroy_cb,
manager);
@@ -520,13 +561,24 @@ contact_manager_get_groups_foreach (McAccount *account,
}
static void
-contact_manager_get_contacts_foreach (McAccount *account,
- EmpathyTpContactList *list,
- GList **contacts)
+contact_manager_get_members_foreach (McAccount *account,
+ EmpathyTpContactList *list,
+ GList **contacts)
+{
+ GList *l;
+
+ l = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (list));
+ *contacts = g_list_concat (*contacts, l);
+}
+
+static void
+contact_manager_get_local_pending_foreach (McAccount *account,
+ EmpathyTpContactList *list,
+ GList **contacts)
{
GList *l;
- l = empathy_contact_list_get_contacts (EMPATHY_CONTACT_LIST (list));
+ l = empathy_contact_list_get_local_pending (EMPATHY_CONTACT_LIST (list));
*contacts = g_list_concat (*contacts, l);
}
diff --git a/libempathy/empathy-idle.c b/libempathy/empathy-idle.c
index 6b9cfb3b9..f9b50bd40 100644
--- a/libempathy/empathy-idle.c
+++ b/libempathy/empathy-idle.c
@@ -27,8 +27,6 @@
#include <libtelepathy/tp-helpers.h>
-#include <libmissioncontrol/mission-control.h>
-
#include "empathy-idle.h"
#include "gossip-utils.h"
#include "gossip-debug.h"
@@ -49,6 +47,9 @@ struct _EmpathyIdlePriv {
MissionControl *mc;
DBusGProxy *gs_proxy;
gboolean is_idle;
+ McPresence state;
+ McPresence slack_state;
+ gchar *status;
McPresence saved_state;
gchar *saved_status;
guint ext_away_timeout;
@@ -57,6 +58,17 @@ struct _EmpathyIdlePriv {
static void empathy_idle_class_init (EmpathyIdleClass *klass);
static void empathy_idle_init (EmpathyIdle *idle);
static void idle_finalize (GObject *object);
+static void idle_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void idle_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void idle_presence_changed_cb (MissionControl *mc,
+ McPresence state,
+ EmpathyIdle *idle);
static void idle_session_idle_changed_cb (DBusGProxy *gs_proxy,
gboolean is_idle,
EmpathyIdle *idle);
@@ -64,7 +76,12 @@ static void idle_ext_away_start (EmpathyIdle *idle);
static void idle_ext_away_stop (EmpathyIdle *idle);
static gboolean idle_ext_away_cb (EmpathyIdle *idle);
-//static guint signals[LAST_SIGNAL];
+enum {
+ PROP_0,
+ PROP_STATE,
+ PROP_STATUS,
+ PROP_SLACK_STATE
+};
G_DEFINE_TYPE (EmpathyIdle, empathy_idle, G_TYPE_OBJECT)
@@ -74,6 +91,34 @@ empathy_idle_class_init (EmpathyIdleClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = idle_finalize;
+ object_class->get_property = idle_get_property;
+ object_class->set_property = idle_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_STATE,
+ g_param_spec_uint ("state",
+ "state",
+ "state",
+ MC_PRESENCE_UNSET,
+ LAST_MC_PRESENCE,
+ MC_PRESENCE_AVAILABLE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_STATUS,
+ g_param_spec_string ("status",
+ "status",
+ "status",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_SLACK_STATE,
+ g_param_spec_uint ("slack-state",
+ "slack-state",
+ "slack-state",
+ MC_PRESENCE_UNSET,
+ LAST_MC_PRESENCE,
+ MC_PRESENCE_UNSET,
+ G_PARAM_READWRITE));
g_type_class_add_private (object_class, sizeof (EmpathyIdlePriv));
}
@@ -87,6 +132,8 @@ empathy_idle_init (EmpathyIdle *idle)
priv->is_idle = FALSE;
priv->mc = gossip_mission_control_new ();
+ priv->state = mission_control_get_presence_actual (priv->mc, NULL);
+ priv->status = mission_control_get_presence_message_actual (priv->mc, NULL);
priv->gs_proxy = dbus_g_proxy_new_for_name (tp_get_bus (),
"org.gnome.ScreenSaver",
"/org/gnome/ScreenSaver",
@@ -102,6 +149,10 @@ empathy_idle_init (EmpathyIdle *idle)
dbus_g_proxy_connect_signal (priv->gs_proxy, "SessionIdleChanged",
G_CALLBACK (idle_session_idle_changed_cb),
idle, NULL);
+ dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
+ "PresenceStatusActual",
+ G_CALLBACK (idle_presence_changed_cb),
+ idle, NULL);
}
static void
@@ -111,6 +162,7 @@ idle_finalize (GObject *object)
priv = GET_PRIV (object);
+ g_free (priv->status);
g_free (priv->saved_status);
g_object_unref (priv->mc);
@@ -121,6 +173,62 @@ idle_finalize (GObject *object)
idle_ext_away_stop (EMPATHY_IDLE (object));
}
+static void
+idle_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIdlePriv *priv;
+ EmpathyIdle *idle;
+
+ priv = GET_PRIV (object);
+ idle = EMPATHY_IDLE (object);
+
+ switch (param_id) {
+ case PROP_STATE:
+ g_value_set_uint (value, empathy_idle_get_state (idle));
+ break;
+ case PROP_STATUS:
+ g_value_set_string (value, empathy_idle_get_status (idle));
+ break;
+ case PROP_SLACK_STATE:
+ g_value_set_uint (value, empathy_idle_get_slack_state (idle));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ };
+}
+
+static void
+idle_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIdlePriv *priv;
+ EmpathyIdle *idle;
+
+ priv = GET_PRIV (object);
+ idle = EMPATHY_IDLE (object);
+
+ switch (param_id) {
+ case PROP_STATE:
+ empathy_idle_set_state (idle, g_value_get_uint (value));
+ break;
+ case PROP_STATUS:
+ empathy_idle_set_status (idle, g_value_get_string (value));
+ break;
+ case PROP_SLACK_STATE:
+ empathy_idle_set_slack_state (idle, g_value_get_uint (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ };
+}
+
EmpathyIdle *
empathy_idle_new (void)
{
@@ -136,6 +244,99 @@ empathy_idle_new (void)
return idle;
}
+McPresence
+empathy_idle_get_state (EmpathyIdle *idle)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ return priv->state;
+}
+
+void
+empathy_idle_set_state (EmpathyIdle *idle,
+ McPresence state)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ mission_control_set_presence (priv->mc,
+ state,
+ priv->status,
+ NULL, NULL);
+}
+
+const gchar *
+empathy_idle_get_status (EmpathyIdle *idle)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ return priv->status;
+}
+
+void
+empathy_idle_set_status (EmpathyIdle *idle,
+ const gchar *status)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ mission_control_set_presence (priv->mc,
+ priv->state,
+ status,
+ NULL, NULL);
+}
+
+McPresence
+empathy_idle_get_slack_state (EmpathyIdle *idle)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ return priv->slack_state;
+}
+
+void
+empathy_idle_set_slack_state (EmpathyIdle *idle,
+ McPresence state)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ priv->slack_state = state;
+
+ g_object_notify (G_OBJECT (idle), "slack-state");
+}
+
+static void
+idle_presence_changed_cb (MissionControl *mc,
+ McPresence state,
+ EmpathyIdle *idle)
+{
+ EmpathyIdlePriv *priv;
+
+ priv = GET_PRIV (idle);
+
+ g_free (priv->status);
+ priv->state = state;
+ priv->status = mission_control_get_presence_message_actual (priv->mc, NULL);
+
+ if (G_STR_EMPTY (priv->status)) {
+ g_free (priv->status);
+ priv->status = g_strdup (gossip_presence_state_get_default_status (state));
+ }
+
+ g_object_notify (G_OBJECT (idle), "state");
+ g_object_notify (G_OBJECT (idle), "status");
+}
+
static void
idle_session_idle_changed_cb (DBusGProxy *gs_proxy,
gboolean is_idle,
@@ -150,30 +351,29 @@ idle_session_idle_changed_cb (DBusGProxy *gs_proxy,
is_idle ? "yes" : "no");
if (is_idle && !priv->is_idle) {
- McPresence new_state = MC_PRESENCE_AWAY;
+ McPresence new_state;
/* We are now idle, set state to away */
- priv->saved_state = mission_control_get_presence_actual (priv->mc, NULL);
- priv->saved_status = mission_control_get_presence_message_actual (priv->mc, NULL);
-
- if (priv->saved_state <= MC_PRESENCE_OFFLINE ||
- priv->saved_state == MC_PRESENCE_HIDDEN) {
+ if (priv->state <= MC_PRESENCE_OFFLINE ||
+ priv->state == MC_PRESENCE_HIDDEN) {
/* We are not online so nothing to do here */
return;
- } else if (priv->saved_state == MC_PRESENCE_AWAY ||
- priv->saved_state == MC_PRESENCE_EXTENDED_AWAY) {
+ } else if (priv->state == MC_PRESENCE_AWAY ||
+ priv->state == MC_PRESENCE_EXTENDED_AWAY) {
/* User set away manually, when coming back we restore
* default presence. */
- new_state = priv->saved_state;
+ new_state = priv->state;
priv->saved_state = MC_PRESENCE_AVAILABLE;
priv->saved_status = NULL;
+ } else {
+ new_state = MC_PRESENCE_AWAY;
+ priv->saved_state = priv->state;
+ priv->saved_status = g_strdup (priv->status);
}
gossip_debug (DEBUG_DOMAIN, "Going to autoaway");
- mission_control_set_presence (priv->mc,
- new_state,
- priv->saved_status,
- NULL, NULL);
+ empathy_idle_set_state (idle, new_state);
+
idle_ext_away_start (idle);
} else if (!is_idle && priv->is_idle) {
/* We are no more idle, restore state */
@@ -187,6 +387,7 @@ idle_session_idle_changed_cb (DBusGProxy *gs_proxy,
priv->saved_state,
priv->saved_status,
NULL, NULL);
+
g_free (priv->saved_status);
priv->saved_status = NULL;
}
diff --git a/libempathy/empathy-idle.h b/libempathy/empathy-idle.h
index df8846b9b..13c5dd293 100644
--- a/libempathy/empathy-idle.h
+++ b/libempathy/empathy-idle.h
@@ -25,6 +25,8 @@
#include <glib.h>
+#include <libmissioncontrol/mission-control.h>
+
G_BEGIN_DECLS
#define EMPATHY_TYPE_IDLE (empathy_idle_get_type ())
@@ -46,8 +48,17 @@ struct _EmpathyIdleClass {
GObjectClass parent_class;
};
-GType empathy_idle_get_type (void) G_GNUC_CONST;
-EmpathyIdle *empathy_idle_new (void);
+GType empathy_idle_get_type (void) G_GNUC_CONST;
+EmpathyIdle *empathy_idle_new (void);
+McPresence empathy_idle_get_state (EmpathyIdle *idle);
+void empathy_idle_set_state (EmpathyIdle *idle,
+ McPresence state);
+const gchar *empathy_idle_get_status (EmpathyIdle *idle);
+void empathy_idle_set_status (EmpathyIdle *idle,
+ const gchar *message);
+McPresence empathy_idle_get_slack_state (EmpathyIdle *idle);
+void empathy_idle_set_slack_state (EmpathyIdle *idle,
+ McPresence state);
G_END_DECLS
diff --git a/libempathy/empathy-marshal.list b/libempathy/empathy-marshal.list
index f13e9f08d..3b36b7be0 100644
--- a/libempathy/empathy-marshal.list
+++ b/libempathy/empathy-marshal.list
@@ -1,8 +1,10 @@
-VOID:POINTER,UINT,UINT,STRING
VOID:OBJECT,UINT
VOID:OBJECT,OBJECT
-VOID:INT,STRING
VOID:OBJECT,OBJECT,UINT
-VOID:UINT,BOOLEAN
VOID:OBJECT,BOOLEAN
VOID:OBJECT,STRING,STRING
+VOID:OBJECT,STRING
+VOID:POINTER,UINT,UINT,STRING
+VOID:INT,STRING
+VOID:UINT,BOOLEAN
+
diff --git a/libempathy/empathy-tp-chatroom.c b/libempathy/empathy-tp-chatroom.c
index eb47c9bb3..232db30fd 100644
--- a/libempathy/empathy-tp-chatroom.c
+++ b/libempathy/empathy-tp-chatroom.c
@@ -72,7 +72,7 @@ static void tp_chatroom_add (EmpathyContactList *
static void tp_chatroom_remove (EmpathyContactList *list,
GossipContact *contact,
const gchar *message);
-static GList * tp_chatroom_get_contacts (EmpathyContactList *list);
+static GList * tp_chatroom_get_members (EmpathyContactList *list);
G_DEFINE_TYPE_WITH_CODE (EmpathyTpChatroom, empathy_tp_chatroom, EMPATHY_TYPE_TP_CHAT,
G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
@@ -91,11 +91,11 @@ empathy_tp_chatroom_class_init (EmpathyTpChatroomClass *klass)
static void
tp_chatroom_iface_init (EmpathyContactListIface *iface)
{
- iface->setup = tp_chatroom_setup;
- iface->find = tp_chatroom_find;
- iface->add = tp_chatroom_add;
- iface->remove = tp_chatroom_remove;
- iface->get_contacts = tp_chatroom_get_contacts;
+ iface->setup = tp_chatroom_setup;
+ iface->find = tp_chatroom_find;
+ iface->add = tp_chatroom_add;
+ iface->remove = tp_chatroom_remove;
+ iface->get_members = tp_chatroom_get_members;
}
static void
@@ -339,7 +339,7 @@ tp_chatroom_remove (EmpathyContactList *list,
}
static GList *
-tp_chatroom_get_contacts (EmpathyContactList *list)
+tp_chatroom_get_members (EmpathyContactList *list)
{
EmpathyTpChatroomPriv *priv;
GArray *members;
diff --git a/libempathy/empathy-tp-contact-list.c b/libempathy/empathy-tp-contact-list.c
index 7668057e7..284f51138 100644
--- a/libempathy/empathy-tp-contact-list.c
+++ b/libempathy/empathy-tp-contact-list.c
@@ -52,12 +52,12 @@ struct _EmpathyTpContactListPriv {
GossipContact *user_contact;
gboolean setup;
- GossipTelepathyGroup *known;
GossipTelepathyGroup *publish;
GossipTelepathyGroup *subscribe;
GHashTable *groups;
GHashTable *contacts;
+ GList *local_pending;
DBusGProxy *aliasing_iface;
DBusGProxy *avatars_iface;
@@ -67,7 +67,6 @@ struct _EmpathyTpContactListPriv {
};
typedef enum {
- TP_CONTACT_LIST_TYPE_KNOWN,
TP_CONTACT_LIST_TYPE_PUBLISH,
TP_CONTACT_LIST_TYPE_SUBSCRIBE,
TP_CONTACT_LIST_TYPE_UNKNOWN,
@@ -103,7 +102,10 @@ static void tp_contact_list_add (EmpathyC
static void tp_contact_list_remove (EmpathyContactList *list,
GossipContact *contact,
const gchar *message);
-static GList * tp_contact_list_get_contacts (EmpathyContactList *list);
+static GList * tp_contact_list_get_members (EmpathyContactList *list);
+static GList * tp_contact_list_get_local_pending (EmpathyContactList *list);
+static void tp_contact_list_remove_local_pending (EmpathyTpContactList *list,
+ GossipContact *contact);
static void tp_contact_list_contact_removed_foreach (guint handle,
GossipContact *contact,
EmpathyTpContactList *list);
@@ -120,20 +122,20 @@ static void tp_contact_list_newchannel_cb (DBusGPro
gboolean suppress_handle,
EmpathyTpContactList *list);
static TpContactListType tp_contact_list_get_type (EmpathyTpContactList *list,
- TpChan *list_chan);
-static void tp_contact_list_contact_added_cb (GossipTelepathyGroup *group,
+ GossipTelepathyGroup *group);
+static void tp_contact_list_added_cb (GossipTelepathyGroup *group,
GArray *handles,
guint actor_handle,
guint reason,
const gchar *message,
EmpathyTpContactList *list);
-static void tp_contact_list_contact_removed_cb (GossipTelepathyGroup *group,
+static void tp_contact_list_removed_cb (GossipTelepathyGroup *group,
GArray *handles,
guint actor_handle,
guint reason,
const gchar *message,
EmpathyTpContactList *list);
-static void tp_contact_list_local_pending_cb (GossipTelepathyGroup *group,
+static void tp_contact_list_pending_cb (GossipTelepathyGroup *group,
GArray *handles,
guint actor_handle,
guint reason,
@@ -173,7 +175,7 @@ static void tp_contact_list_group_members_removed_cb (GossipTe
guint reason,
const gchar *message,
EmpathyTpContactList *list);
-static void tp_contact_list_get_contacts_foreach (guint handle,
+static void tp_contact_list_get_members_foreach (guint handle,
GossipContact *contact,
GList **contacts);
static void tp_contact_list_get_info (EmpathyTpContactList *list,
@@ -248,11 +250,12 @@ empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass)
static void
tp_contact_list_iface_init (EmpathyContactListIface *iface)
{
- iface->setup = tp_contact_list_setup;
- iface->find = tp_contact_list_find;
- iface->add = tp_contact_list_add;
- iface->remove = tp_contact_list_remove;
- iface->get_contacts = tp_contact_list_get_contacts;
+ iface->setup = tp_contact_list_setup;
+ iface->find = tp_contact_list_find;
+ iface->add = tp_contact_list_add;
+ iface->remove = tp_contact_list_remove;
+ iface->get_members = tp_contact_list_get_members;
+ iface->get_local_pending = tp_contact_list_get_local_pending;
}
static void
@@ -293,15 +296,9 @@ tp_contact_list_finalize (GObject *object)
if (priv->tp_conn) {
g_object_unref (priv->tp_conn);
}
-
- if (priv->known) {
- g_object_unref (priv->known);
- }
-
if (priv->subscribe) {
g_object_unref (priv->subscribe);
}
-
if (priv->publish) {
g_object_unref (priv->publish);
}
@@ -312,6 +309,9 @@ tp_contact_list_finalize (GObject *object)
g_hash_table_destroy (priv->groups);
g_hash_table_destroy (priv->contacts);
+ g_list_foreach (priv->local_pending, (GFunc) empathy_contact_list_info_free, NULL);
+ g_list_free (priv->local_pending);
+
G_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object);
}
@@ -383,6 +383,7 @@ empathy_tp_contact_list_new (McAccount *account)
error ? error->message : "No error given");
g_clear_error (&error);
} else {
+ /* FIXME: this adds the handle to the roster */
priv->user_contact = empathy_tp_contact_list_get_from_handle (list, handle);
}
@@ -490,11 +491,10 @@ tp_contact_list_remove (EmpathyContactList *list,
handle = gossip_contact_get_handle (contact);
gossip_telepathy_group_remove_member (priv->subscribe, handle, message);
gossip_telepathy_group_remove_member (priv->publish, handle, message);
- gossip_telepathy_group_remove_member (priv->known, handle, message);
}
static GList *
-tp_contact_list_get_contacts (EmpathyContactList *list)
+tp_contact_list_get_members (EmpathyContactList *list)
{
EmpathyTpContactListPriv *priv;
GList *contacts = NULL;
@@ -503,14 +503,25 @@ tp_contact_list_get_contacts (EmpathyContactList *list)
priv = GET_PRIV (list);
- /* FIXME: we should only return contacts that are in the contact list */
g_hash_table_foreach (priv->contacts,
- (GHFunc) tp_contact_list_get_contacts_foreach,
+ (GHFunc) tp_contact_list_get_members_foreach,
&contacts);
return contacts;
}
+static GList *
+tp_contact_list_get_local_pending (EmpathyContactList *list)
+{
+ EmpathyTpContactListPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
+
+ priv = GET_PRIV (list);
+
+ return g_list_copy (priv->local_pending);
+}
+
McAccount *
empathy_tp_contact_list_get_account (EmpathyTpContactList *list)
{
@@ -943,87 +954,77 @@ tp_contact_list_newchannel_cb (DBusGProxy *proxy,
if (handle_type == TP_HANDLE_TYPE_LIST) {
TpContactListType list_type;
- list_type = tp_contact_list_get_type (list, new_chan);
+ group = gossip_telepathy_group_new (new_chan, priv->tp_conn);
+
+ list_type = tp_contact_list_get_type (list, group);
if (list_type == TP_CONTACT_LIST_TYPE_UNKNOWN) {
- gossip_debug (DEBUG_DOMAIN, "Unknown contact list channel");
+ gossip_debug (DEBUG_DOMAIN,
+ "Type of contact list channel unknown: %s",
+ gossip_telepathy_group_get_name (group));
+
g_object_unref (new_chan);
+ g_object_unref (group);
return;
+ } else {
+ gossip_debug (DEBUG_DOMAIN,
+ "New contact list channel of type: %d",
+ list_type);
}
- gossip_debug (DEBUG_DOMAIN, "New contact list channel of type: %d",
- list_type);
+ g_signal_connect (group, "members-added",
+ G_CALLBACK (tp_contact_list_added_cb),
+ list);
+ g_signal_connect (group, "members-removed",
+ G_CALLBACK (tp_contact_list_removed_cb),
+ list);
- group = gossip_telepathy_group_new (new_chan, priv->tp_conn);
+ members = gossip_telepathy_group_get_members (group);
+ tp_contact_list_added_cb (group, members, 0,
+ TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
+ NULL, list);
+ g_array_free (members, TRUE);
+
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ GList *pendings, *l;
- switch (list_type) {
- case TP_CONTACT_LIST_TYPE_KNOWN:
- if (priv->known) {
- g_object_unref (priv->known);
- }
- priv->known = group;
- break;
- case TP_CONTACT_LIST_TYPE_PUBLISH:
if (priv->publish) {
g_object_unref (priv->publish);
}
priv->publish = group;
- break;
- case TP_CONTACT_LIST_TYPE_SUBSCRIBE:
- if (priv->subscribe) {
- g_object_unref (priv->subscribe);
- }
- priv->subscribe = group;
- break;
- default:
- g_assert_not_reached ();
- }
-
- /* Connect and setup the new contact-list group */
- if (list_type == TP_CONTACT_LIST_TYPE_KNOWN ||
- list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
- g_signal_connect (group, "members-added",
- G_CALLBACK (tp_contact_list_contact_added_cb),
- list);
- g_signal_connect (group, "members-removed",
- G_CALLBACK (tp_contact_list_contact_removed_cb),
- list);
-
- members = gossip_telepathy_group_get_members (group);
- tp_contact_list_contact_added_cb (group, members, 0,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
- NULL, list);
- g_array_free (members, TRUE);
- }
- if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
- GList *members, *l;
- GArray *pending;
+ /* Makes no sense to be in remote-pending */
g_signal_connect (group, "local-pending",
- G_CALLBACK (tp_contact_list_local_pending_cb),
+ G_CALLBACK (tp_contact_list_pending_cb),
list);
- members = gossip_telepathy_group_get_local_pending_members_with_info (group);
- if (!members) {
- g_object_unref (new_chan);
- return;
+ pendings = gossip_telepathy_group_get_local_pending_members_with_info (group);
+ if (pendings) {
+ GArray *pending;
+
+ pending = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
+ for (l = pendings; l; l = l->next) {
+ GossipTpGroupInfo *info;
+
+ info = l->data;
+
+ g_array_insert_val (pending, 0, info->member);
+ tp_contact_list_pending_cb (group, pending,
+ info->actor,
+ info->reason,
+ info->message,
+ list);
+ }
+ g_array_free (pending, TRUE);
+ gossip_telepathy_group_info_list_free (pendings);
}
-
- pending = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
- for (l = members; l; l = l->next) {
- GossipTpGroupInfo *info;
-
- info = l->data;
-
- g_array_insert_val (pending, 0, info->member);
- tp_contact_list_local_pending_cb (group, pending,
- info->actor,
- info->reason,
- info->message,
- list);
+ }
+ else if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+ if (priv->subscribe) {
+ g_object_unref (priv->subscribe);
}
-
- gossip_telepathy_group_info_list_free (members);
- g_array_free (pending, TRUE);
+ priv->subscribe = group;
+ } else {
+ g_assert_not_reached ();
}
}
else if (handle_type == TP_HANDLE_TYPE_GROUP) {
@@ -1065,72 +1066,69 @@ tp_contact_list_newchannel_cb (DBusGProxy *proxy,
static TpContactListType
tp_contact_list_get_type (EmpathyTpContactList *list,
- TpChan *list_chan)
+ GossipTelepathyGroup *group)
{
EmpathyTpContactListPriv *priv;
- GArray *handles;
- gchar **handle_name;
TpContactListType list_type;
- GError *error = NULL;
+ const gchar *name;
priv = GET_PRIV (list);
- handles = g_array_new (FALSE, FALSE, sizeof (guint));
- g_array_append_val (handles, list_chan->handle);
-
- if (!tp_conn_inspect_handles (DBUS_G_PROXY (priv->tp_conn),
- TP_HANDLE_TYPE_LIST,
- handles,
- &handle_name,
- &error)) {
- gossip_debug (DEBUG_DOMAIN,
- "InspectHandle Error: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- g_array_free (handles, TRUE);
- return TP_CONTACT_LIST_TYPE_UNKNOWN;
- }
-
- if (strcmp (*handle_name, "subscribe") == 0) {
+ name = gossip_telepathy_group_get_name (group);
+ if (strcmp (name, "subscribe") == 0) {
list_type = TP_CONTACT_LIST_TYPE_SUBSCRIBE;
- } else if (strcmp (*handle_name, "publish") == 0) {
+ } else if (strcmp (name, "publish") == 0) {
list_type = TP_CONTACT_LIST_TYPE_PUBLISH;
- } else if (strcmp (*handle_name, "known") == 0) {
- list_type = TP_CONTACT_LIST_TYPE_KNOWN;
} else {
list_type = TP_CONTACT_LIST_TYPE_UNKNOWN;
}
- g_strfreev (handle_name);
- g_array_free (handles, TRUE);
-
return list_type;
}
static void
-tp_contact_list_contact_added_cb (GossipTelepathyGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_added_cb (GossipTelepathyGroup *group,
+ GArray *handles,
+ guint actor_handle,
+ guint reason,
+ const gchar *message,
+ EmpathyTpContactList *list)
{
EmpathyTpContactListPriv *priv;
GList *added_list, *l;
+ TpContactListType list_type;
priv = GET_PRIV (list);
- added_list = empathy_tp_contact_list_get_from_handles (list, handles);
+ list_type = tp_contact_list_get_type (list, group);
+ added_list = empathy_tp_contact_list_get_from_handles (list, handles);
for (l = added_list; l; l = l->next) {
- GossipContact *contact;
+ GossipContact *contact;
+ GossipSubscription subscription;
contact = GOSSIP_CONTACT (l->data);
+
+ gossip_debug (DEBUG_DOMAIN, "Contact '%s' added to list type %d",
+ gossip_contact_get_name (contact),
+ list_type);
+
+ subscription = gossip_contact_get_subscription (contact);
+ if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+ subscription |= GOSSIP_SUBSCRIPTION_FROM;
+ }
+ else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ subscription |= GOSSIP_SUBSCRIPTION_TO;
+ }
+
tp_contact_list_block_contact (list, contact);
- gossip_contact_set_subscription (contact, GOSSIP_SUBSCRIPTION_BOTH);
+ gossip_contact_set_subscription (contact, subscription);
tp_contact_list_unblock_contact (list, contact);
- g_signal_emit_by_name (list, "contact-added", contact);
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ tp_contact_list_remove_local_pending (list, contact);
+ g_signal_emit_by_name (list, "contact-added", contact);
+ }
g_object_unref (contact);
}
@@ -1139,31 +1137,48 @@ tp_contact_list_contact_added_cb (GossipTelepathyGroup *group,
}
static void
-tp_contact_list_contact_removed_cb (GossipTelepathyGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_removed_cb (GossipTelepathyGroup *group,
+ GArray *handles,
+ guint actor_handle,
+ guint reason,
+ const gchar *message,
+ EmpathyTpContactList *list)
{
EmpathyTpContactListPriv *priv;
GList *removed_list, *l;
+ TpContactListType list_type;
priv = GET_PRIV (list);
- removed_list = empathy_tp_contact_list_get_from_handles (list, handles);
+ list_type = tp_contact_list_get_type (list, group);
+ removed_list = empathy_tp_contact_list_get_from_handles (list, handles);
for (l = removed_list; l; l = l->next) {
- GossipContact *contact;
- guint handle;
+ GossipContact *contact;
+ GossipSubscription subscription;
contact = GOSSIP_CONTACT (l->data);
- handle = gossip_contact_get_handle (contact);
- g_hash_table_remove (priv->contacts, GUINT_TO_POINTER (handle));
+ gossip_debug (DEBUG_DOMAIN, "Contact '%s' removed from list type %d",
+ gossip_contact_get_name (contact),
+ list_type);
+
+ subscription = gossip_contact_get_subscription (contact);
+ if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+ subscription &= !GOSSIP_SUBSCRIPTION_FROM;
+ }
+ else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ subscription &= !GOSSIP_SUBSCRIPTION_TO;
+ }
- g_signal_emit_by_name (list, "contact-removed", contact);
+ tp_contact_list_block_contact (list, contact);
+ gossip_contact_set_subscription (contact, subscription);
+ tp_contact_list_unblock_contact (list, contact);
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ tp_contact_list_remove_local_pending (list, contact);
+ g_signal_emit_by_name (list, "contact-removed", contact);
+ }
g_object_unref (contact);
}
@@ -1171,30 +1186,41 @@ tp_contact_list_contact_removed_cb (GossipTelepathyGroup *group,
}
static void
-tp_contact_list_local_pending_cb (GossipTelepathyGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_pending_cb (GossipTelepathyGroup *group,
+ GArray *handles,
+ guint actor_handle,
+ guint reason,
+ const gchar *message,
+ EmpathyTpContactList *list)
{
EmpathyTpContactListPriv *priv;
GList *pending_list, *l;
+ TpContactListType list_type;
priv = GET_PRIV (list);
- pending_list = empathy_tp_contact_list_get_from_handles (list, handles);
+ list_type = tp_contact_list_get_type (list, group);
+ pending_list = empathy_tp_contact_list_get_from_handles (list, handles);
for (l = pending_list; l; l = l->next) {
GossipContact *contact;
contact = GOSSIP_CONTACT (l->data);
- /* FIXME: Is that the correct way ? */
- tp_contact_list_block_contact (list, contact);
- gossip_contact_set_subscription (contact, GOSSIP_SUBSCRIPTION_FROM);
- tp_contact_list_unblock_contact (list, contact);
- g_signal_emit_by_name (list, "contact-added", contact);
+ gossip_debug (DEBUG_DOMAIN, "Contact '%s' pending in list type %d",
+ gossip_contact_get_name (contact),
+ list_type);
+
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
+ EmpathyContactListInfo *info;
+
+ info = empathy_contact_list_info_new (contact, message);
+ priv->local_pending = g_list_prepend (priv->local_pending,
+ info);
+
+ g_signal_emit_by_name (list, "local-pending",
+ contact, message);
+ }
g_object_unref (contact);
}
@@ -1203,6 +1229,30 @@ tp_contact_list_local_pending_cb (GossipTelepathyGroup *group,
}
static void
+tp_contact_list_remove_local_pending (EmpathyTpContactList *list,
+ GossipContact *contact)
+{
+ EmpathyTpContactListPriv *priv;
+ GList *l;
+
+ priv = GET_PRIV (list);
+
+ for (l = priv->local_pending; l; l = l->next) {
+ EmpathyContactListInfo *info;
+
+ info = l->data;
+ if (gossip_contact_equal (contact, info->contact)) {
+ gossip_debug (DEBUG_DOMAIN, "Contact no more local-pending: %s",
+ gossip_contact_get_name (contact));
+
+ priv->local_pending = g_list_delete_link (priv->local_pending, l);
+ empathy_contact_list_info_free (info);
+ break;
+ }
+ }
+}
+
+static void
tp_contact_list_groups_updated_cb (GossipContact *contact,
GParamSpec *param,
EmpathyTpContactList *list)
@@ -1531,11 +1581,16 @@ tp_contact_list_group_members_removed_cb (GossipTelepathyGroup *group,
}
static void
-tp_contact_list_get_contacts_foreach (guint handle,
+tp_contact_list_get_members_foreach (guint handle,
GossipContact *contact,
GList **contacts)
{
- *contacts = g_list_append (*contacts, g_object_ref (contact));
+ GossipSubscription subscription;
+
+ subscription = gossip_contact_get_subscription (contact);
+ if (subscription & GOSSIP_SUBSCRIPTION_TO) {
+ *contacts = g_list_append (*contacts, g_object_ref (contact));
+ }
}
static void