[Telepathy-commits] [telepathy-gabble/master] move most of the view code to a OlpcView abstract class

Guillaume Desmottes guillaume.desmottes at collabora.co.uk
Thu Oct 16 03:18:52 PDT 2008


---
 src/Makefile.am           |    2 +
 src/olpc-buddy-view.c     | 1137 ++++++---------------------------------------
 src/olpc-buddy-view.h     |   86 ++---
 src/olpc-gadget-manager.c |    8 +-
 src/olpc-gadget-manager.h |    2 +-
 src/olpc-view.c           | 1083 ++++++++++++++++++++++++++++++++++++++++++
 src/olpc-view.h           |  103 ++++
 7 files changed, 1353 insertions(+), 1068 deletions(-)
 create mode 100644 src/olpc-view.c
 create mode 100644 src/olpc-view.h

diff --git a/src/Makefile.am b/src/Makefile.am
index f022b05..a29e571 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -75,6 +75,8 @@ libgabble_convenience_la_SOURCES = \
     olpc-buddy-view.c \
     olpc-gadget-manager.h \
     olpc-gadget-manager.c \
+    olpc-view.h \
+    olpc-view.c \
     pubsub.h \
     pubsub.c \
     presence.h \
diff --git a/src/olpc-buddy-view.c b/src/olpc-buddy-view.c
index 80726d1..9efb190 100644
--- a/src/olpc-buddy-view.c
+++ b/src/olpc-buddy-view.c
@@ -1,5 +1,5 @@
 /*
- * olpc-buddy-view.c - Source for GabbleOlpcView
+ * olpc-buddy-view.c - Source for GabbleOlpcBuddyView
  * Copyright (C) 2008 Collabora Ltd.
  *
  * This library is free software; you can redistribute it and/or
@@ -37,251 +37,78 @@
 #include "conn-olpc.h"
 #include "debug.h"
 #include "extensions/extensions.h"
-#include "gabble-signals-marshal.h"
 #include "olpc-activity.h"
 #include "namespaces.h"
 #include "util.h"
 
-#define GABBLE_ARRAY_TYPE_HANDLE (dbus_g_type_get_collection ("GArray", \
-    G_TYPE_UINT))
-
-/* signals */
-enum
-{
-  BUDDY_ACTIVITIES_CHANGED,
-  LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
 /* properties */
 enum
 {
-  PROP_OBJECT_PATH = 1,
-  /* org.freedesktop.Telepathy.Channel D-Bus properties */
-  PROP_CHANNEL_TYPE,
-  PROP_INTERFACES,
-  PROP_HANDLE,
-  PROP_TARGET_ID,
-  PROP_HANDLE_TYPE,
-
-  /* org.freedesktop.Telepathy.Channel.FUTURE D-Bus properties */
-  PROP_REQUESTED,
-  PROP_INITIATOR_HANDLE,
-  PROP_INITIATOR_ID,
-
-  PROP_CHANNEL_DESTROYED,
-  PROP_CHANNEL_PROPERTIES,
-
-  /* org.laptop.Telepathy.Channel.Type.View D-Bus properties */
-  PROP_MAX_SIZE,
-  PROP_BUDDIES,
-  PROP_ACTIVITIES,
-
   /* org.laptop.Telepathy.Channel.Type.BuddyView D-Bus properties */
-  PROP_VIEW_PROPERTIES,
+  PROP_VIEW_PROPERTIES = 1,
   PROP_ALIAS,
 
-  PROP_CONNECTION,
-  PROP_ID,
   LAST_PROPERTY
 };
 
-typedef struct _GabbleOlpcViewPrivate GabbleOlpcViewPrivate;
-struct _GabbleOlpcViewPrivate
+typedef struct _GabbleOlpcBuddyViewPrivate GabbleOlpcBuddyViewPrivate;
+struct _GabbleOlpcBuddyViewPrivate
 {
-  GabbleConnection *conn;
-  char *object_path;
-  guint id;
-  gboolean closed;
-  guint max_size;
-
   GHashTable *properties;
   gchar *alias;
 
-  TpHandleSet *buddies;
-  /* TpHandle => GabbleOlpcActivity * */
-  GHashTable *activities;
-
-  /* TpHandle (owned in priv->buddies) => GHashTable * */
-  GHashTable *buddy_properties;
-  /* TpHandle (owned in priv->buddies) => TpHandleSet of activity rooms */
-  GHashTable *buddy_rooms;
-
   gboolean dispose_has_run;
 };
 
-static void channel_iface_init (gpointer, gpointer);
-
 G_DEFINE_TYPE_WITH_CODE (
-    GabbleOlpcView, gabble_olpc_view, G_TYPE_OBJECT,
+    GabbleOlpcBuddyView, gabble_olpc_buddy_view, GABBLE_TYPE_OLPC_VIEW,
     G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_OLPC_CHANNEL_TYPE_BUDDYVIEW,
       NULL);
-    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
-      tp_dbus_properties_mixin_iface_init);
-    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
-    G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL);
-    G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_CHANNEL_FUTURE, NULL);
-    G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_OLPC_CHANNEL_INTERFACE_VIEW, NULL);
-    G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL);
     );
 
-static const gchar *gabble_olpc_buddy_view_interfaces[] = {
-    GABBLE_IFACE_CHANNEL_FUTURE,
-    GABBLE_IFACE_OLPC_CHANNEL_INTERFACE_VIEW,
-    NULL
-};
-
-#define GABBLE_OLPC_VIEW_GET_PRIVATE(obj) \
-    ((GabbleOlpcViewPrivate *) obj->priv)
+#define GABBLE_OLPC_BUDDY_VIEW_GET_PRIVATE(obj) \
+    ((GabbleOlpcBuddyViewPrivate *) obj->priv)
 
 
 static void
-gabble_olpc_view_init (GabbleOlpcView *self)
+gabble_olpc_buddy_view_init (GabbleOlpcBuddyView *self)
 {
-  GabbleOlpcViewPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
-      GABBLE_TYPE_OLPC_VIEW, GabbleOlpcViewPrivate);
+  GabbleOlpcBuddyViewPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+      GABBLE_TYPE_OLPC_BUDDY_VIEW, GabbleOlpcBuddyViewPrivate);
 
   self->priv = priv;
 
-  priv->closed = FALSE;
-
   priv->dispose_has_run = FALSE;
 }
 
 static void
-gabble_olpc_view_dispose (GObject *object)
+gabble_olpc_buddy_view_dispose (GObject *object)
 {
-  GabbleOlpcView *self = GABBLE_OLPC_VIEW (object);
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  GabbleOlpcBuddyView *self = GABBLE_OLPC_BUDDY_VIEW (object);
+  GabbleOlpcBuddyViewPrivate *priv = GABBLE_OLPC_BUDDY_VIEW_GET_PRIVATE (self);
 
   if (priv->dispose_has_run)
     return;
 
-  if (priv->buddies != NULL)
-    {
-      tp_handle_set_destroy (priv->buddies);
-      priv->buddies = NULL;
-    }
-
-  if (priv->activities != NULL)
-    {
-      g_hash_table_destroy (priv->activities);
-      priv->activities = NULL;
-    }
-
-  if (priv->buddy_properties != NULL)
-    {
-      g_hash_table_destroy (priv->buddy_properties);
-      priv->buddy_properties = NULL;
-    }
-
-  if (priv->buddy_rooms != NULL)
-    {
-      g_hash_table_destroy (priv->buddy_rooms);
-      priv->buddy_rooms = NULL;
-    }
-
   priv->dispose_has_run = TRUE;
 
-  if (G_OBJECT_CLASS (gabble_olpc_view_parent_class)->dispose)
-    G_OBJECT_CLASS (gabble_olpc_view_parent_class)->dispose (object);
-}
-
-static void
-gabble_olpc_view_finalize (GObject *object)
-{
-  GabbleOlpcView *self = GABBLE_OLPC_VIEW (object);
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-
-  g_free (priv->object_path);
-
-  G_OBJECT_CLASS (gabble_olpc_view_parent_class)->finalize (object);
-}
-
-static void
-add_activity_to_array (TpHandle handle,
-                       GabbleOlpcActivity *activity,
-                       GPtrArray *array)
-{
-  GValue gvalue = { 0 };
-
-  g_value_init (&gvalue, GABBLE_STRUCT_TYPE_ACTIVITY);
-  g_value_take_boxed (&gvalue, dbus_g_type_specialized_construct
-      (GABBLE_STRUCT_TYPE_ACTIVITY));
-  dbus_g_type_struct_set (&gvalue,
-      0, activity->id,
-      1, activity->room,
-      G_MAXUINT);
-
-  g_ptr_array_add (array, g_value_get_boxed (&gvalue));
-}
-
-static GPtrArray *
-create_activities_array (GabbleOlpcView *self)
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-  GPtrArray *activities;
-
-  activities = g_ptr_array_new ();
-
-  g_hash_table_foreach (priv->activities, (GHFunc) add_activity_to_array,
-      activities);
-
-  return activities;
+  if (G_OBJECT_CLASS (gabble_olpc_buddy_view_parent_class)->dispose)
+    G_OBJECT_CLASS (gabble_olpc_buddy_view_parent_class)->dispose (object);
 }
 
 static void
-gabble_olpc_view_get_property (GObject *object,
+gabble_olpc_buddy_view_get_property (GObject *object,
                                guint property_id,
                                GValue *value,
                                GParamSpec *pspec)
 {
-  GabbleOlpcView *self = GABBLE_OLPC_VIEW (object);
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-  TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
+  GabbleOlpcBuddyView *self = GABBLE_OLPC_BUDDY_VIEW (object);
+  GabbleOlpcBuddyViewPrivate *priv = GABBLE_OLPC_BUDDY_VIEW_GET_PRIVATE (self);
 
   switch (property_id)
     {
-      case PROP_OBJECT_PATH:
-        g_value_set_string (value, priv->object_path);
-        break;
-      case PROP_CHANNEL_TYPE:
-        g_value_set_static_string (value,
-            GABBLE_IFACE_OLPC_CHANNEL_TYPE_BUDDYVIEW);
-        break;
-      case PROP_HANDLE_TYPE:
-        g_value_set_uint (value, TP_HANDLE_TYPE_NONE);
-        break;
-      case PROP_HANDLE:
-        g_value_set_uint (value, 0);
-        break;
-      case PROP_INITIATOR_HANDLE:
-        g_value_set_uint (value, base_conn->self_handle);
-        break;
-      case PROP_INITIATOR_ID:
-          {
-            TpHandleRepoIface *repo = tp_base_connection_get_handles (
-                base_conn, TP_HANDLE_TYPE_CONTACT);
-
-            g_value_set_string (value,
-                tp_handle_inspect (repo, base_conn->self_handle));
-          }
-        break;
-      case PROP_TARGET_ID:
-          {
-            g_value_set_string (value, NULL);
-        }
-        break;
-      case PROP_REQUESTED:
-        g_value_set_boolean (value, TRUE);
-        break;
-     case PROP_INTERFACES:
-        g_value_set_boxed (value, gabble_olpc_buddy_view_interfaces);
-        break;
-      case PROP_CHANNEL_DESTROYED:
-        g_value_set_boolean (value, priv->closed);
-        break;
+       /* FIXME: we should return the BuddyInfo specific props */
+#if 0
       case PROP_CHANNEL_PROPERTIES:
         g_value_take_boxed (value,
             tp_dbus_properties_mixin_make_properties_hash (object,
@@ -299,22 +126,7 @@ gabble_olpc_view_get_property (GObject *object,
                 GABBLE_IFACE_OLPC_CHANNEL_TYPE_BUDDYVIEW, "Alias",
                 NULL));
         break;
-      case PROP_CONNECTION:
-        g_value_set_object (value, priv->conn);
-        break;
-      case PROP_ID:
-        g_value_set_uint (value, priv->id);
-        break;
-      case PROP_MAX_SIZE:
-        g_value_set_uint (value, priv->max_size);
-        break;
-      case PROP_BUDDIES:
-        g_value_take_boxed (value, tp_handle_set_to_array (priv->buddies));
-        break;
-      case PROP_ACTIVITIES:
-        /* TODO: is that leak free ? */
-        g_value_take_boxed (value, create_activities_array (self));
-        break;
+#endif
       case PROP_VIEW_PROPERTIES:
         g_value_set_boxed (value, priv->properties);
         break;
@@ -328,36 +140,16 @@ gabble_olpc_view_get_property (GObject *object,
 }
 
 static void
-gabble_olpc_view_set_property (GObject *object,
-                               guint property_id,
-                               const GValue *value,
-                               GParamSpec *pspec)
+gabble_olpc_buddy_view_set_property (GObject *object,
+                                     guint property_id,
+                                     const GValue *value,
+                                     GParamSpec *pspec)
 {
-  GabbleOlpcView *self = GABBLE_OLPC_VIEW (object);
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  GabbleOlpcBuddyView *self = GABBLE_OLPC_BUDDY_VIEW (object);
+  GabbleOlpcBuddyViewPrivate *priv = GABBLE_OLPC_BUDDY_VIEW_GET_PRIVATE (self);
 
   switch (property_id)
     {
-      case PROP_OBJECT_PATH:
-        g_free (priv->object_path);
-        priv->object_path = g_value_dup_string (value);
-        break;
-      case PROP_HANDLE:
-      case PROP_INITIATOR_HANDLE:
-      case PROP_HANDLE_TYPE:
-      case PROP_CHANNEL_TYPE:
-        /* these properties are writable in the interface, but not actually
-         * meaningfully changeable on this channel, so we do nothing */
-        break;
-      case PROP_CONNECTION:
-        priv->conn = g_value_get_object (value);
-        break;
-      case PROP_ID:
-        priv->id = g_value_get_uint (value);
-        break;
-      case PROP_MAX_SIZE:
-        priv->max_size = g_value_get_uint (value);
-        break;
       case PROP_VIEW_PROPERTIES:
         priv->properties = g_value_dup_boxed (value);
         break;
@@ -371,39 +163,33 @@ gabble_olpc_view_set_property (GObject *object,
 }
 
 static GObject *
-gabble_olpc_view_constructor (GType type,
-                              guint n_props,
-                              GObjectConstructParam *props)
+gabble_olpc_buddy_view_constructor (GType type,
+                                    guint n_props,
+                                    GObjectConstructParam *props)
 {
   GObject *obj;
-  GabbleOlpcViewPrivate *priv;
+  GabbleOlpcView *view;
+  GabbleOlpcBuddyViewPrivate *priv;
   DBusGConnection *bus;
   TpBaseConnection *conn;
   TpHandleRepoIface *contact_handles;
 
-  obj = G_OBJECT_CLASS (gabble_olpc_view_parent_class)->
+  obj = G_OBJECT_CLASS (gabble_olpc_buddy_view_parent_class)->
            constructor (type, n_props, props);
 
-  priv = GABBLE_OLPC_VIEW_GET_PRIVATE (GABBLE_OLPC_VIEW (obj));
-  conn = (TpBaseConnection *) priv->conn;
+  view = GABBLE_OLPC_VIEW (obj);
+
+  priv = GABBLE_OLPC_BUDDY_VIEW_GET_PRIVATE (GABBLE_OLPC_BUDDY_VIEW (obj));
+  conn = (TpBaseConnection *) view->conn;
 
-  priv->object_path = g_strdup_printf ("%s/OlpcView%u",
-      conn->object_path, priv->id);
+  view->object_path = g_strdup_printf ("%s/OlpcBuddyView%u",
+      conn->object_path, view->id);
   bus = tp_get_bus ();
-  dbus_g_connection_register_g_object (bus, priv->object_path, obj);
+  dbus_g_connection_register_g_object (bus, view->object_path, obj);
 
   contact_handles = tp_base_connection_get_handles (conn,
       TP_HANDLE_TYPE_CONTACT);
 
-  priv->buddies = tp_handle_set_new (contact_handles);
-
-  priv->activities = g_hash_table_new_full (g_direct_hash, g_direct_equal,
-      NULL, g_object_unref);
-  priv->buddy_properties = g_hash_table_new_full (g_direct_hash,
-      g_direct_equal, NULL, (GDestroyNotify) g_hash_table_unref);
-  priv->buddy_rooms = g_hash_table_new_full (g_direct_hash, g_direct_equal,
-      NULL, (GDestroyNotify) tp_handle_set_destroy);
-
   if (priv->properties == NULL)
     {
       priv->properties = g_hash_table_new (g_direct_hash, g_direct_equal);
@@ -412,751 +198,36 @@ gabble_olpc_view_constructor (GType type,
   return obj;
 }
 
-static void
-gabble_olpc_view_class_init (GabbleOlpcViewClass *gabble_olpc_view_class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (gabble_olpc_view_class);
-  GParamSpec *param_spec;
-   static TpDBusPropertiesMixinPropImpl channel_props[] = {
-      { "TargetHandleType", "handle-type", NULL },
-      { "TargetHandle", "handle", NULL },
-      { "TargetID", "target-id", NULL },
-      { "ChannelType", "channel-type", NULL },
-      { "Interfaces", "interfaces", NULL },
-      { NULL }
-  };
-  static TpDBusPropertiesMixinPropImpl future_props[] = {
-      { "Requested", "requested", NULL },
-      { "InitiatorHandle", "initiator-handle", NULL },
-      { "InitiatorID", "initiator-id", NULL },
-      { NULL }
-  };
-  static TpDBusPropertiesMixinPropImpl view_props[] = {
-      { "MaxSize", "max-size", NULL },
-      { "Buddies", "buddies", NULL },
-      { "Activities", "activities", NULL },
-      { NULL }
-  };
-  static TpDBusPropertiesMixinPropImpl buddy_view_props[] = {
-      { "Properties", "view-properties", NULL },
-      { "Alias", "alias", NULL },
-      { NULL }
-  };
-  /* Add view properties */
-  static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
-      { TP_IFACE_CHANNEL,
-        tp_dbus_properties_mixin_getter_gobject_properties,
-        NULL,
-        channel_props,
-      },
-      { GABBLE_IFACE_CHANNEL_FUTURE,
-        tp_dbus_properties_mixin_getter_gobject_properties,
-        NULL,
-        future_props,
-      },
-      { GABBLE_IFACE_OLPC_CHANNEL_INTERFACE_VIEW,
-        tp_dbus_properties_mixin_getter_gobject_properties,
-        NULL,
-        view_props,
-      },
-      { GABBLE_IFACE_OLPC_CHANNEL_TYPE_BUDDYVIEW,
-        tp_dbus_properties_mixin_getter_gobject_properties,
-        NULL,
-        buddy_view_props,
-      },
-      { NULL }
-  };
-
-  object_class->get_property = gabble_olpc_view_get_property;
-  object_class->set_property = gabble_olpc_view_set_property;
-  object_class->constructor = gabble_olpc_view_constructor;
-
-  g_type_class_add_private (gabble_olpc_view_class,
-      sizeof (GabbleOlpcViewPrivate));
-
-  object_class->dispose = gabble_olpc_view_dispose;
-  object_class->finalize = gabble_olpc_view_finalize;
-
-  g_object_class_override_property (object_class, PROP_OBJECT_PATH,
-      "object-path");
-  g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
-      "channel-type");
-  g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
-      "handle-type");
-  g_object_class_override_property (object_class, PROP_HANDLE, "handle");
-  g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED,
-      "channel-destroyed");
-  g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES,
-      "channel-properties");
-
-  param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
-      "Additional Channel.Interface.* interfaces",
-      G_TYPE_STRV,
-      G_PARAM_READABLE |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
-
-  param_spec = g_param_spec_string ("target-id", "Peer's bare JID",
-      "The string obtained by inspecting the peer handle (never the full JID)",
-      NULL,
-      G_PARAM_READABLE |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec);
-
-  param_spec = g_param_spec_boolean ("requested", "Requested?",
-      "True if this channel was requested by the local user",
-      FALSE,
-      G_PARAM_READABLE |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
-
-  param_spec = g_param_spec_uint ("initiator-handle", "Initiator's handle",
-      "The contact who initiated the channel",
-      0, G_MAXUINT32, 0,
-      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE,
-      param_spec);
-
-  param_spec = g_param_spec_string ("initiator-id", "Initiator's bare JID",
-      "The string obtained by inspecting the initiator-handle",
-      NULL,
-      G_PARAM_READABLE |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_INITIATOR_ID,
-      param_spec);
-
-  param_spec = g_param_spec_uint ("max-size", "View's max size",
-      "The maximum number of elements that Gadget has to return to the "
-      "search request.",
-      0, G_MAXUINT32, 0,
-      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_MAX_SIZE,
-      param_spec);
-
-  param_spec = g_param_spec_boxed ("buddies", "View's buddies",
-      "The contact handles of the buddies who are in this view channel",
-      GABBLE_ARRAY_TYPE_HANDLE,
-      G_PARAM_READABLE |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_BUDDIES,
-      param_spec);
-
-  param_spec = g_param_spec_boxed ("activities", "View's activities",
-      "The activities which are in this view channel",
-      GABBLE_ARRAY_TYPE_ACTIVITY_LIST,
-      G_PARAM_READABLE |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_ACTIVITIES,
-      param_spec);
-
-  param_spec = g_param_spec_boxed ("view-properties", "View's search properties",
-      "The buddy properties Gadget should look for",
-      TP_HASH_TYPE_STRING_VARIANT_MAP,
-      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_VIEW_PROPERTIES,
-      param_spec);
-
-  param_spec = g_param_spec_string ("alias", "View's search alias",
-      "The buddy alias Gadget should look for",
-      NULL,
-      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_ALIAS,
-      param_spec);
-
-   param_spec = g_param_spec_object (
-      "connection",
-      "GabbleConnection object",
-      "Gabble connection object that owns this view object.",
-      GABBLE_TYPE_CONNECTION,
-      G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NAME |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
-  param_spec = g_param_spec_uint (
-      "id",
-      "query ID",
-      "The ID of the query associated with this view",
-      0, G_MAXUINT, 0,
-      G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NAME |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_ID, param_spec);
-
-  signals[BUDDY_ACTIVITIES_CHANGED] =
-    g_signal_new ("buddy-activities-changed",
-        G_OBJECT_CLASS_TYPE (gabble_olpc_view_class),
-        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
-        0,
-        NULL, NULL,
-        gabble_marshal_VOID__UINT,
-        G_TYPE_NONE, 1, G_TYPE_UINT);
-
-  gabble_olpc_view_class->dbus_props_class.interfaces = prop_interfaces;
-  tp_dbus_properties_mixin_class_init (object_class,
-      G_STRUCT_OFFSET (GabbleOlpcViewClass, dbus_props_class));
-}
-
-GabbleOlpcView *
-gabble_olpc_buddy_view_new (GabbleConnection *conn,
-                            const gchar *object_path,
-                            guint id,
-                            guint max_size,
-                            GHashTable *properties,
-                            const gchar *alias)
-
-{
-  return g_object_new (GABBLE_TYPE_OLPC_VIEW,
-      "object-path", object_path,
-      "connection", conn,
-      "id", id,
-      "max-size", max_size,
-      "view-properties", properties,
-      "alias", alias,
-      NULL);
-}
-
-static void
-free_activities_array (GPtrArray *activities)
-{
-  guint i;
-
-  for (i = 0; i < activities->len; i++)
-    g_boxed_free (GABBLE_STRUCT_TYPE_ACTIVITY, activities->pdata[i]);
-
-  g_ptr_array_free (activities, TRUE);
-}
-
-static void
-buddy_left_activities_foreach (TpHandleSet *set,
-                               TpHandle buddy,
-                               GabbleOlpcView *self)
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-
-  /* Remove all the activity of this buddy */
-  if (!g_hash_table_remove (priv->buddy_rooms, GUINT_TO_POINTER (buddy)))
-    return;
-
-  g_signal_emit (G_OBJECT (self), signals[BUDDY_ACTIVITIES_CHANGED],
-      0, buddy);
-}
-
-static gboolean
-do_close (GabbleOlpcView *self,
-          GError **error)
+static LmMessage *
+gabble_olpc_buddy_view_create_close_msg (GabbleOlpcView *view)
 {
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-  LmMessage *msg;
   gchar *id_str;
+  LmMessage *msg;
 
-  id_str = g_strdup_printf ("%u", priv->id);
+  id_str = g_strdup_printf ("%u", view->id);
 
-  msg = lm_message_build (priv->conn->olpc_gadget_buddy,
+  msg = lm_message_build (view->conn->olpc_gadget_buddy,
       LM_MESSAGE_TYPE_MESSAGE,
       '(', "close", "",
         '@', "xmlns", NS_OLPC_BUDDY,
         '@', "id", id_str,
       ')', NULL);
 
-#if 0
-  else if (priv->type == GABBLE_OLPC_VIEW_TYPE_ACTIVITY)
-    {
-      msg = lm_message_build (priv->conn->olpc_gadget_activity,
-          LM_MESSAGE_TYPE_MESSAGE,
-          '(', "close", "",
-            '@', "xmlns", NS_OLPC_ACTIVITY,
-            '@', "id", id_str,
-          ')', NULL);
-#endif
-
   g_free (id_str);
 
-  if (!_gabble_connection_send (priv->conn, msg, error))
-    {
-      lm_message_unref (msg);
-      return FALSE;
-    }
-
-  lm_message_unref (msg);
-
-  /* Claim that all the buddies left their activities */
-  tp_handle_set_foreach (priv->buddies,
-      (TpHandleSetMemberFunc) buddy_left_activities_foreach, self);
-
-  priv->closed = TRUE;
-
-  tp_svc_channel_emit_closed (self);
-
-  return TRUE;
-}
-
-/**
- * gabble_olpc_buddy_view_close
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_olpc_buddy_view_close (TpSvcChannel *iface,
-                              DBusGMethodInvocation *context)
-{
-  GabbleOlpcView *self = GABBLE_OLPC_VIEW (iface);
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-  GError *error = NULL;
-
-  if (priv->closed)
-    {
-      DEBUG ("Already closed. Doing nothing");
-    }
-  else
-    {
-      /* FIXME: set closed */
-      if (!do_close (self, &error))
-        {
-          dbus_g_method_return_error (context, error);
-          g_error_free (error);
-        }
-    }
-
-  tp_svc_channel_return_from_close (context);
-}
-
-/**
- * gabble_olpc_buddy_view_get_channel_type
- *
- * Implements D-Bus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_olpc_buddy_view_get_channel_type (TpSvcChannel *iface,
-                                         DBusGMethodInvocation *context)
-{
-  tp_svc_channel_return_from_get_channel_type (context,
-      GABBLE_IFACE_OLPC_CHANNEL_TYPE_BUDDYVIEW);
-}
-
-/**
- * gabble_olpc_buddy_view_get_handle
- *
- * Implements D-Bus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_olpc_buddy_view_get_handle (TpSvcChannel *iface,
-                                   DBusGMethodInvocation *context)
-{
-  tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_NONE, 0);
-}
-
-/**
- * gabble_olpc_buddy_view_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-gabble_olpc_buddy_view_get_interfaces (TpSvcChannel *iface,
-                                       DBusGMethodInvocation *context)
-{
-  tp_svc_channel_return_from_get_interfaces (context,
-      gabble_olpc_buddy_view_interfaces);
-}
-
-/* If room is not zero, these buddies are associated with the activity
- * of this room. They'll leave the view if the activity is removed.
- */
-void
-gabble_olpc_view_add_buddies (GabbleOlpcView *self,
-                              GArray *buddies,
-                              GPtrArray *buddies_properties,
-                              TpHandle room)
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-  guint i;
-  GArray *empty;
-  TpHandleRepoIface *room_repo;
-  GArray *buddies_changed;
-
-  g_assert (buddies->len == buddies_properties->len);
-  if (buddies->len == 0)
-    return;
-
-  room_repo = tp_base_connection_get_handles ((TpBaseConnection *) priv->conn,
-      TP_HANDLE_TYPE_ROOM);
-
-  empty = g_array_new (FALSE, FALSE, sizeof (TpHandle));
-  buddies_changed = g_array_new (FALSE, FALSE, sizeof (TpHandle));
-
-  /* store properties */
-  for (i = 0; i < buddies->len; i++)
-    {
-      TpHandle handle;
-      GHashTable *properties;
-
-      handle = g_array_index (buddies, TpHandle, i);
-      properties = g_ptr_array_index (buddies_properties, i);
-
-      tp_handle_set_add (priv->buddies, handle);
-      g_hash_table_insert (priv->buddy_properties, GUINT_TO_POINTER (handle),
-          properties);
-      g_hash_table_ref (properties);
-
-      if (room != 0)
-        {
-          /* buddies are in an activity */
-          TpHandleSet *set;
-
-          set = g_hash_table_lookup (priv->buddy_rooms, GUINT_TO_POINTER (
-                handle));
-
-          if (set == NULL)
-            {
-              set = tp_handle_set_new (room_repo);
-
-              g_hash_table_insert (priv->buddy_rooms, GUINT_TO_POINTER (
-                    handle), set);
-            }
-
-          if (!tp_handle_set_is_member (set, room))
-            {
-              tp_handle_set_add (set, room);
-
-              /* We fire BuddyInfo.ActivitiesChanged signal after
-               * View.BuddiesChanged so client knows where these buddies
-               * come from */
-              g_array_append_val (buddies_changed, handle);
-            }
-        }
-    }
-
-  gabble_svc_olpc_channel_interface_view_emit_buddies_changed (self, buddies,
-      empty);
-
-  for (i = 0; i < buddies_changed->len; i++)
-    {
-      TpHandle handle;
-
-      handle = g_array_index (buddies_changed, TpHandle, i);
-      g_signal_emit (G_OBJECT (self),
-          signals[BUDDY_ACTIVITIES_CHANGED], 0, handle);
-    }
-
-  g_array_free (buddies_changed, TRUE);
-  g_array_free (empty, TRUE);
-}
-
-static void
-remove_buddy_foreach (TpHandleSet *buddies,
-                      TpHandle handle,
-                      GabbleOlpcView *self)
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-
-  tp_handle_set_remove (priv->buddies, handle);
-  g_hash_table_remove (priv->buddy_properties, GUINT_TO_POINTER (handle));
-  g_hash_table_remove (priv->buddy_rooms, GUINT_TO_POINTER (handle));
-}
-
-void
-gabble_olpc_view_remove_buddies (GabbleOlpcView *self,
-                                 TpHandleSet *buddies)
-{
-  GArray *removed, *empty;
-
-  if (tp_handle_set_size (buddies) == 0)
-    return;
-
-  tp_handle_set_foreach (buddies,
-      (TpHandleSetMemberFunc) remove_buddy_foreach, self);
-
-  empty = g_array_new (FALSE, FALSE, sizeof (TpHandle));
-  removed = tp_handle_set_to_array (buddies);
-
-  gabble_svc_olpc_channel_interface_view_emit_buddies_changed (self, empty,
-      removed);
-
-  g_array_free (empty, TRUE);
-  g_array_free (removed, TRUE);
-}
-
-gboolean
-gabble_olpc_view_set_buddy_properties (GabbleOlpcView *self,
-                                       TpHandle buddy,
-                                       GHashTable *properties)
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-
-  if (!tp_handle_set_is_member (priv->buddies, buddy))
-    {
-      DEBUG ("buddy %d is not member of this view", buddy);
-      return FALSE;
-    }
-
-  tp_handle_set_add (priv->buddies, buddy);
-  g_hash_table_insert (priv->buddy_properties, GUINT_TO_POINTER (buddy),
-      properties);
-  g_hash_table_ref (properties);
-
-  return TRUE;
-}
-
-GHashTable *
-gabble_olpc_view_get_buddy_properties (GabbleOlpcView *self,
-                                       TpHandle buddy)
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-
-  return g_hash_table_lookup (priv->buddy_properties,
-      GUINT_TO_POINTER (buddy));
-}
-
-void
-gabble_olpc_view_add_activities (GabbleOlpcView *self,
-                                 GHashTable *activities)
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-  GPtrArray *added, *empty;
-
-  if (g_hash_table_size (activities) == 0)
-    return;
-
-  tp_g_hash_table_update (priv->activities, activities, NULL, g_object_ref);
-
-  added = g_ptr_array_new ();
-  g_hash_table_foreach (activities, (GHFunc) add_activity_to_array, added);
-
-  empty = g_ptr_array_new ();
-
-  gabble_svc_olpc_channel_interface_view_emit_activities_changed (self, added,
-      empty);
-
-  free_activities_array (added);
-  g_ptr_array_free (empty, TRUE);
-}
-
-struct remove_activity_foreach_buddy_ctx
-{
-  GabbleOlpcView *view;
-  TpHandle room;
-  /* buddies who have to be removed */
-  TpHandleSet *removed;
-};
-
-static void
-remove_activity_foreach_buddy (TpHandle buddy,
-                               TpHandleSet *set,
-                               struct remove_activity_foreach_buddy_ctx *ctx)
-{
-  if (set == NULL)
-    return;
-
-  if (tp_handle_set_remove (set, ctx->room))
-    {
-      if (tp_handle_set_size (set) == 0)
-        {
-          /* No more activity for this buddy. Remove it */
-          tp_handle_set_add (ctx->removed, buddy);
-        }
-
-      g_signal_emit (G_OBJECT (ctx->view), signals[BUDDY_ACTIVITIES_CHANGED],
-          0, buddy);
-    }
-}
-
-void
-gabble_olpc_view_remove_activities (GabbleOlpcView *self,
-                                    TpHandleSet *rooms)
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-  GPtrArray *removed, *empty;
-  GArray *array;
-  guint i;
-  TpHandleRepoIface *contact_repo;
-
-  if (tp_handle_set_size (rooms) == 0)
-    return;
-
-  contact_repo = tp_base_connection_get_handles (
-      (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
-
-  /* for easier iteration */
-  array = tp_handle_set_to_array (rooms);
-
-  removed = g_ptr_array_new ();
-  empty = g_ptr_array_new ();
-
-  for (i = 0; i < array->len; i++)
-    {
-      TpHandle room;
-      GabbleOlpcActivity *activity;
-      struct remove_activity_foreach_buddy_ctx ctx;
-
-      room = g_array_index (array, TpHandle, i);
-
-      activity = g_hash_table_lookup (priv->activities,
-          GUINT_TO_POINTER (room));
-      if (activity == NULL)
-        continue;
-
-      add_activity_to_array (room, activity, removed);
-      g_hash_table_remove (priv->activities, GUINT_TO_POINTER (room));
-
-      /* remove the activity from all rooms set */
-      ctx.view = self;
-      ctx.room = room;
-      ctx.removed = tp_handle_set_new (contact_repo);
-
-      g_hash_table_foreach (priv->buddy_rooms,
-          (GHFunc) remove_activity_foreach_buddy, &ctx);
-
-      gabble_olpc_view_remove_buddies (self, ctx.removed);
-
-      tp_handle_set_destroy (ctx.removed);
-    }
-
-  gabble_svc_olpc_channel_interface_view_emit_activities_changed (self, empty,
-      removed);
-
-  free_activities_array (removed);
-  g_ptr_array_free (empty, TRUE);
-  g_array_free (array, TRUE);
-}
-
-GPtrArray *
-gabble_olpc_view_get_buddy_activities (GabbleOlpcView *self,
-                                       TpHandle buddy)
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-  GPtrArray *activities;
-  TpHandleSet *rooms_set;
-  GArray *rooms;
-  guint i;
-
-  activities = g_ptr_array_new ();
-
-  rooms_set = g_hash_table_lookup (priv->buddy_rooms,
-      GUINT_TO_POINTER (buddy));
-  if (rooms_set == NULL || tp_handle_set_size (rooms_set) == 0)
-    return activities;
-
-  /* Convert to an array for easier iteration */
-  rooms = tp_handle_set_to_array (rooms_set);
-  for (i = 0; i < rooms->len; i++)
-    {
-      TpHandle room;
-      GabbleOlpcActivity *activity;
-
-      room = g_array_index (rooms, TpHandle, i);
-
-      activity = g_hash_table_lookup (priv->activities,
-          GUINT_TO_POINTER (room));
-      if (activity == NULL)
-        {
-          /* This shouldn't happen as long as:
-           *
-           * - Gadget doesn't send us <joined> stanzas about an activity
-           *   which was not previously announced as being part of the view.
-           *
-           * - We don't call gabble_olpc_view_add_buddies with an activity
-           *   which was not previoulsy added to the view.
-           */
-          DEBUG ("Buddy %d is supposed to be in activity %d but view doesn't"
-              " contain its info", buddy, room);
-          continue;
-        }
-
-      g_ptr_array_add (activities, activity);
-    }
-
-  g_array_free (rooms, TRUE);
-
-  return activities;
-}
-
-void
-gabble_olpc_view_buddies_left_activity (GabbleOlpcView *self,
-                                        GArray *buddies,
-                                        TpHandle room)
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
-  guint i;
-  TpHandleRepoIface *contact_repo;
-  TpHandleSet *removed;
-
-  contact_repo = tp_base_connection_get_handles (
-      (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
-
-  removed = tp_handle_set_new (contact_repo);
-
-  for (i = 0; i < buddies->len; i++)
-    {
-      TpHandleSet *set;
-      TpHandle buddy;
-
-      buddy = g_array_index (buddies, TpHandle, i);
-      set = g_hash_table_lookup (priv->buddy_rooms, GUINT_TO_POINTER (buddy));
-      if (set == NULL)
-        continue;
-
-      if (tp_handle_set_remove (set, room))
-        {
-          if (tp_handle_set_size (set) == 0)
-            {
-              /* Remove from the view */
-              tp_handle_set_add (removed, buddy);
-            }
-
-          g_signal_emit (G_OBJECT (self), signals[BUDDY_ACTIVITIES_CHANGED],
-              0, buddy);
-        }
-    }
-
-  gabble_olpc_view_remove_buddies (self, removed);
-
-  tp_handle_set_destroy (removed);
+  return msg;
 }
 
-static LmHandlerResult
-buddy_view_query_result_cb (GabbleConnection *conn,
-                            LmMessage *sent_msg,
-                            LmMessage *reply_msg,
-                            GObject *_view,
-                            gpointer user_data)
+static LmMessage *
+gabble_olpc_buddy_view_create_request (GabbleOlpcView *view)
 {
-  LmMessageNode *view_node;
-  GabbleOlpcView *self = GABBLE_OLPC_VIEW (_view);
-
-  view_node = lm_message_node_get_child_with_namespace (reply_msg->node,
-      "view", NS_OLPC_BUDDY);
-  if (view_node == NULL)
-    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-
-  /* FIXME: make sense to call this conn-olpc function ? */
-  add_buddies_to_view_from_node (conn, self, view_node, "buddy", 0);
-
-  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-gboolean
-gabble_olpc_buddy_view_send_request (GabbleOlpcView *self,
-                                     GError **error)
-
-{
-  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  GabbleOlpcBuddyView *self = GABBLE_OLPC_BUDDY_VIEW (view);
+  GabbleOlpcBuddyViewPrivate *priv = GABBLE_OLPC_BUDDY_VIEW_GET_PRIVATE (self);
   LmMessage *query;
   gchar *max_str, *id_str;
 
-  max_str = g_strdup_printf ("%u", priv->max_size);
-  id_str = g_strdup_printf ("%u", priv->id);
+  max_str = g_strdup_printf ("%u", view->max_size);
+  id_str = g_strdup_printf ("%u", view->id);
 
   /* TODO: Implement multi criterias properties */
   /* TODO: Always use the max_size argument */
@@ -1164,7 +235,7 @@ gabble_olpc_buddy_view_send_request (GabbleOlpcView *self,
     {
       LmMessageNode *properties_node;
 
-      query = lm_message_build_with_sub_type (priv->conn->olpc_gadget_buddy,
+      query = lm_message_build_with_sub_type (view->conn->olpc_gadget_buddy,
         LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
         '(', "view", "",
             '@', "xmlns", NS_OLPC_BUDDY,
@@ -1183,7 +254,7 @@ gabble_olpc_buddy_view_send_request (GabbleOlpcView *self,
     }
   else if (priv->alias != NULL)
     {
-      query = lm_message_build_with_sub_type (priv->conn->olpc_gadget_buddy,
+      query = lm_message_build_with_sub_type (view->conn->olpc_gadget_buddy,
         LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
         '(', "view", "",
             '@', "xmlns", NS_OLPC_BUDDY,
@@ -1196,7 +267,7 @@ gabble_olpc_buddy_view_send_request (GabbleOlpcView *self,
     }
   else
     {
-      query = lm_message_build_with_sub_type (priv->conn->olpc_gadget_buddy,
+      query = lm_message_build_with_sub_type (view->conn->olpc_gadget_buddy,
           LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
           '(', "view", "",
               '@', "xmlns", NS_OLPC_BUDDY,
@@ -1211,32 +282,86 @@ gabble_olpc_buddy_view_send_request (GabbleOlpcView *self,
   g_free (max_str);
   g_free (id_str);
 
-  if (!_gabble_connection_send_with_reply (priv->conn, query,
-        buddy_view_query_result_cb, G_OBJECT (self), NULL, NULL))
-    {
-      g_set_error (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
-        "Failed to send buddy search query to server");
+  return query;
+}
 
-      DEBUG ("Failed to send buddy search query to server");
-      lm_message_unref (query);
-      return FALSE;
-    }
+static void
+gabble_olpc_buddy_view_class_init (
+    GabbleOlpcBuddyViewClass *gabble_olpc_buddy_view_class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (gabble_olpc_buddy_view_class);
+  GabbleOlpcViewClass *view_class = GABBLE_OLPC_VIEW_CLASS (
+      gabble_olpc_buddy_view_class);
+  GParamSpec *param_spec;
+  /* FIXME: Implement these props ! */
+  /*
+  static TpDBusPropertiesMixinPropImpl buddy_view_props[] = {
+      { "Properties", "view-properties", NULL },
+      { "Alias", "alias", NULL },
+      { NULL }
+  };
+  static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
+      { GABBLE_IFACE_OLPC_CHANNEL_TYPE_BUDDYVIEW,
+        tp_dbus_properties_mixin_getter_gobject_properties,
+        NULL,
+        buddy_view_props,
+      },
+      { NULL }
+  };
+  */
+
+  object_class->get_property = gabble_olpc_buddy_view_get_property;
+  object_class->set_property = gabble_olpc_buddy_view_set_property;
+  object_class->constructor = gabble_olpc_buddy_view_constructor;
+
+  g_type_class_add_private (gabble_olpc_buddy_view_class,
+      sizeof (GabbleOlpcBuddyViewPrivate));
+
+  object_class->dispose = gabble_olpc_buddy_view_dispose;
+
+  view_class->create_close_msg = gabble_olpc_buddy_view_create_close_msg;
+  view_class->create_request = gabble_olpc_buddy_view_create_request;
+
+  param_spec = g_param_spec_boxed ("view-properties", "View's search properties",
+      "The buddy properties Gadget should look for",
+      TP_HASH_TYPE_STRING_VARIANT_MAP,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_VIEW_PROPERTIES,
+      param_spec);
+
+  param_spec = g_param_spec_string ("alias", "View's search alias",
+      "The buddy alias Gadget should look for",
+      NULL,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_ALIAS,
+      param_spec);
 
-  lm_message_unref (query);
 
-  return TRUE;
+  /* FIXME: how am I suppose to do that with inheritance ? */
+  /*
+  gabble_olpc_buddy_view_class->dbus_props_class.interfaces = prop_interfaces;
+  tp_dbus_properties_mixin_class_init (object_class,
+      G_STRUCT_OFFSET (GabbleOlpcBuddyViewClass, dbus_props_class));
+      */
 }
 
-static void
-channel_iface_init (gpointer g_iface, gpointer iface_data)
-{
-  TpSvcChannelClass *klass = (TpSvcChannelClass *) g_iface;
+GabbleOlpcBuddyView *
+gabble_olpc_buddy_view_new (GabbleConnection *conn,
+                            const gchar *object_path,
+                            guint id,
+                            guint max_size,
+                            GHashTable *properties,
+                            const gchar *alias)
 
-#define IMPLEMENT(x) tp_svc_channel_implement_##x (\
-    klass, gabble_olpc_buddy_view_##x)
-  IMPLEMENT(close);
-  IMPLEMENT(get_channel_type);
-  IMPLEMENT(get_handle);
-  IMPLEMENT(get_interfaces);
-#undef IMPLEMENT
+{
+  return g_object_new (GABBLE_TYPE_OLPC_BUDDY_VIEW,
+      "object-path", object_path,
+      "connection", conn,
+      "id", id,
+      "max-size", max_size,
+      "view-properties", properties,
+      "alias", alias,
+      NULL);
 }
diff --git a/src/olpc-buddy-view.h b/src/olpc-buddy-view.h
index 5b4c023..c193b9a 100644
--- a/src/olpc-buddy-view.h
+++ b/src/olpc-buddy-view.h
@@ -1,5 +1,5 @@
 /*
- * olpc-buddy-view.h - Header for GabbleOlpcView
+ * olpc-buddy-view.h - Header for GabbleOlpcBuddyView
  * Copyright (C) 2008 Collabora Ltd.
  *
  * This library is free software; you can redistribute it and/or
@@ -17,83 +17,53 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#ifndef __GABBLE_OLPC_VIEW_H__
-#define __GABBLE_OLPC_VIEW_H__
+#ifndef __GABBLE_OLPC_BUDDY_VIEW_H__
+#define __GABBLE_OLPC_BUDDY_VIEW_H__
 
 #include <glib-object.h>
 
 #include <telepathy-glib/enums.h>
 #include <telepathy-glib/handle-repo.h>
 
-#include "connection.h"
+#include "olpc-view.h"
 
 G_BEGIN_DECLS
 
-typedef struct _GabbleOlpcViewClass GabbleOlpcViewClass;
+typedef struct _GabbleOlpcBuddyView GabbleOlpcBuddyView;
+typedef struct _GabbleOlpcBuddyViewClass GabbleOlpcBuddyViewClass;
 
-struct _GabbleOlpcViewClass {
-  GObjectClass parent_class;
-
-  TpDBusPropertiesMixinClass dbus_props_class;
+struct _GabbleOlpcBuddyViewClass {
+  GabbleOlpcViewClass parent_class;
 };
 
-struct _GabbleOlpcView {
-  GObject parent;
+struct _GabbleOlpcBuddyView {
+  GabbleOlpcView parent;
 
   gpointer priv;
 };
 
-GType gabble_olpc_view_get_type (void);
+GType gabble_olpc_buddy_view_get_type (void);
 
 /* TYPE MACROS */
-#define GABBLE_TYPE_OLPC_VIEW \
-  (gabble_olpc_view_get_type ())
-#define GABBLE_OLPC_VIEW(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_OLPC_VIEW, GabbleOlpcView))
-#define GABBLE_OLPC_VIEW_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_OLPC_VIEW,\
-                           GabbleOlpcViewClass))
-#define GABBLE_IS_OLPC_VIEW(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_OLPC_VIEW))
-#define GABBLE_IS_OLPC_VIEW_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_OLPC_VIEW))
-#define GABBLE_OLPC_VIEW_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_OLPC_VIEW,\
-                              GabbleOlpcViewClass))
-
-GabbleOlpcView * gabble_olpc_buddy_view_new (GabbleConnection *conn,
+#define GABBLE_TYPE_OLPC_BUDDY_VIEW \
+  (gabble_olpc_buddy_view_get_type ())
+#define GABBLE_OLPC_BUDDY_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_OLPC_BUDDY_VIEW, GabbleOlpcBuddyView))
+#define GABBLE_OLPC_BUDDY_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_OLPC_BUDDY_VIEW,\
+                           GabbleOlpcBuddyViewClass))
+#define GABBLE_IS_OLPC_BUDDY_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_OLPC_BUDDY_VIEW))
+#define GABBLE_IS_OLPC_BUDDY_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_OLPC_BUDDY_VIEW))
+#define GABBLE_OLPC_BUDDY_VIEW_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_OLPC_BUDDY_VIEW,\
+                              GabbleOlpcBuddyViewClass))
+
+GabbleOlpcBuddyView * gabble_olpc_buddy_view_new (GabbleConnection *conn,
     const gchar *object_path, guint id, guint max_size, GHashTable *properties,
     const gchar *alias);
 
-gboolean gabble_olpc_buddy_view_send_request (GabbleOlpcView *view,
-    GError **error);
-
-/* FIXME: fix method names */
-/* FIXME: most of this should be moved to an abstract class */
-void gabble_olpc_view_add_buddies (GabbleOlpcView *self,
-    GArray *handles, GPtrArray *buddies_properties, TpHandle room);
-
-void gabble_olpc_view_remove_buddies (GabbleOlpcView *self,
-    TpHandleSet *handles);
-
-gboolean gabble_olpc_view_set_buddy_properties (GabbleOlpcView *self,
-    TpHandle buddy, GHashTable *properties);
-
-GHashTable * gabble_olpc_view_get_buddy_properties (GabbleOlpcView *self,
-    TpHandle buddy);
-
-void gabble_olpc_view_add_activities (GabbleOlpcView *self,
-    GHashTable *activities);
-
-void gabble_olpc_view_remove_activities (GabbleOlpcView *self,
-    TpHandleSet *rooms);
-
-GPtrArray * gabble_olpc_view_get_buddy_activities (GabbleOlpcView *self,
-    TpHandle buddy);
-
-void gabble_olpc_view_buddies_left_activity (GabbleOlpcView *self,
-    GArray *buddies, TpHandle room);
-
 G_END_DECLS
 
-#endif /* #ifndef __GABBLE_OLPC_VIEW_H__ */
+#endif /* #ifndef __GABBLE_OLPC_BUDDY_VIEW_H__ */
diff --git a/src/olpc-gadget-manager.c b/src/olpc-gadget-manager.c
index c985990..248400d 100644
--- a/src/olpc-gadget-manager.c
+++ b/src/olpc-gadget-manager.c
@@ -342,8 +342,10 @@ gabble_olpc_gadget_manager_handle_request (TpChannelManager *manager,
   object_path = g_strdup_printf ("%s/OlpcBuddyViewChannel%u", conn->object_path,
       self->priv->next_view_number++);
 
-  channel = gabble_olpc_buddy_view_new (self->priv->conn, object_path,
-      self->priv->next_view_number, max_size, properties, alias);
+  channel = GABBLE_OLPC_VIEW (gabble_olpc_buddy_view_new (self->priv->conn,
+        object_path, self->priv->next_view_number, max_size, properties,
+        alias));
+
   g_assert (channel != NULL);
   g_signal_connect (channel, "closed",
       (GCallback) olpc_gadget_channel_closed_cb, self);
@@ -358,7 +360,7 @@ gabble_olpc_gadget_manager_handle_request (TpChannelManager *manager,
   g_free (object_path);
 
   /* FIXME: raise a D-Bus error if failed */
-  gabble_olpc_buddy_view_send_request (channel, NULL);
+  gabble_olpc_view_send_request (channel, NULL);
 
   return TRUE;
 
diff --git a/src/olpc-gadget-manager.h b/src/olpc-gadget-manager.h
index bccfd46..c508c11 100644
--- a/src/olpc-gadget-manager.h
+++ b/src/olpc-gadget-manager.h
@@ -23,7 +23,7 @@
 #include <glib-object.h>
 #include <telepathy-glib/handle.h>
 
-#include "olpc-buddy-view.h"
+#include "olpc-view.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/olpc-view.c b/src/olpc-view.c
new file mode 100644
index 0000000..268525d
--- /dev/null
+++ b/src/olpc-view.c
@@ -0,0 +1,1083 @@
+/*
+ * olpc-buddy-view.c - Source for GabbleOlpcView
+ * Copyright (C) 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
+ */
+
+#include "olpc-view.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <loudmouth/loudmouth.h>
+#include <telepathy-glib/channel-iface.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/svc-channel.h>
+#include <telepathy-glib/svc-generic.h>
+
+#define DEBUG_FLAG GABBLE_DEBUG_OLPC
+
+#include "conn-olpc.h"
+#include "debug.h"
+#include "extensions/extensions.h"
+#include "gabble-signals-marshal.h"
+#include "olpc-activity.h"
+#include "namespaces.h"
+#include "util.h"
+
+#define GABBLE_ARRAY_TYPE_HANDLE (dbus_g_type_get_collection ("GArray", \
+    G_TYPE_UINT))
+
+/* signals */
+enum
+{
+  BUDDY_ACTIVITIES_CHANGED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+/* properties */
+enum
+{
+  PROP_OBJECT_PATH = 1,
+  /* org.freedesktop.Telepathy.Channel D-Bus properties */
+  PROP_CHANNEL_TYPE,
+  PROP_INTERFACES,
+  PROP_HANDLE,
+  PROP_TARGET_ID,
+  PROP_HANDLE_TYPE,
+
+  /* org.freedesktop.Telepathy.Channel.FUTURE D-Bus properties */
+  PROP_REQUESTED,
+  PROP_INITIATOR_HANDLE,
+  PROP_INITIATOR_ID,
+
+  PROP_CHANNEL_DESTROYED,
+  PROP_CHANNEL_PROPERTIES,
+
+  /* org.laptop.Telepathy.Channel.Type.View D-Bus properties */
+  PROP_MAX_SIZE,
+  PROP_BUDDIES,
+  PROP_ACTIVITIES,
+
+  PROP_CONNECTION,
+  PROP_ID,
+  LAST_PROPERTY
+};
+
+typedef struct _GabbleOlpcViewPrivate GabbleOlpcViewPrivate;
+struct _GabbleOlpcViewPrivate
+{
+  gboolean closed;
+
+  TpHandleSet *buddies;
+  /* TpHandle => GabbleOlpcActivity * */
+  GHashTable *activities;
+
+  /* TpHandle (owned in priv->buddies) => GHashTable * */
+  GHashTable *buddy_properties;
+  /* TpHandle (owned in priv->buddies) => TpHandleSet of activity rooms */
+  GHashTable *buddy_rooms;
+
+  gboolean dispose_has_run;
+};
+
+static void channel_iface_init (gpointer, gpointer);
+
+G_DEFINE_TYPE_WITH_CODE (
+    GabbleOlpcView, gabble_olpc_view, G_TYPE_OBJECT,
+    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
+      tp_dbus_properties_mixin_iface_init);
+    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
+    G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL);
+    G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_CHANNEL_FUTURE, NULL);
+    G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_OLPC_CHANNEL_INTERFACE_VIEW, NULL);
+    G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL);
+    );
+
+static const gchar *gabble_olpc_buddy_view_interfaces[] = {
+    GABBLE_IFACE_CHANNEL_FUTURE,
+    GABBLE_IFACE_OLPC_CHANNEL_INTERFACE_VIEW,
+    NULL
+};
+
+#define GABBLE_OLPC_VIEW_GET_PRIVATE(obj) \
+    ((GabbleOlpcViewPrivate *) obj->priv)
+
+
+static void
+gabble_olpc_view_init (GabbleOlpcView *self)
+{
+  GabbleOlpcViewPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+      GABBLE_TYPE_OLPC_VIEW, GabbleOlpcViewPrivate);
+
+  self->priv = priv;
+
+  priv->closed = FALSE;
+
+  priv->dispose_has_run = FALSE;
+}
+
+static void
+gabble_olpc_view_dispose (GObject *object)
+{
+  GabbleOlpcView *self = GABBLE_OLPC_VIEW (object);
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+
+  if (priv->dispose_has_run)
+    return;
+
+  if (priv->buddies != NULL)
+    {
+      tp_handle_set_destroy (priv->buddies);
+      priv->buddies = NULL;
+    }
+
+  if (priv->activities != NULL)
+    {
+      g_hash_table_destroy (priv->activities);
+      priv->activities = NULL;
+    }
+
+  if (priv->buddy_properties != NULL)
+    {
+      g_hash_table_destroy (priv->buddy_properties);
+      priv->buddy_properties = NULL;
+    }
+
+  if (priv->buddy_rooms != NULL)
+    {
+      g_hash_table_destroy (priv->buddy_rooms);
+      priv->buddy_rooms = NULL;
+    }
+
+  priv->dispose_has_run = TRUE;
+
+  if (G_OBJECT_CLASS (gabble_olpc_view_parent_class)->dispose)
+    G_OBJECT_CLASS (gabble_olpc_view_parent_class)->dispose (object);
+}
+
+static void
+gabble_olpc_view_finalize (GObject *object)
+{
+  GabbleOlpcView *self = GABBLE_OLPC_VIEW (object);
+
+  g_free (self->object_path);
+
+  G_OBJECT_CLASS (gabble_olpc_view_parent_class)->finalize (object);
+}
+
+static void
+add_activity_to_array (TpHandle handle,
+                       GabbleOlpcActivity *activity,
+                       GPtrArray *array)
+{
+  GValue gvalue = { 0 };
+
+  g_value_init (&gvalue, GABBLE_STRUCT_TYPE_ACTIVITY);
+  g_value_take_boxed (&gvalue, dbus_g_type_specialized_construct
+      (GABBLE_STRUCT_TYPE_ACTIVITY));
+  dbus_g_type_struct_set (&gvalue,
+      0, activity->id,
+      1, activity->room,
+      G_MAXUINT);
+
+  g_ptr_array_add (array, g_value_get_boxed (&gvalue));
+}
+
+static GPtrArray *
+create_activities_array (GabbleOlpcView *self)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  GPtrArray *activities;
+
+  activities = g_ptr_array_new ();
+
+  g_hash_table_foreach (priv->activities, (GHFunc) add_activity_to_array,
+      activities);
+
+  return activities;
+}
+
+static void
+gabble_olpc_view_get_property (GObject *object,
+                               guint property_id,
+                               GValue *value,
+                               GParamSpec *pspec)
+{
+  GabbleOlpcView *self = GABBLE_OLPC_VIEW (object);
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  TpBaseConnection *base_conn = (TpBaseConnection *) self->conn;
+
+  switch (property_id)
+    {
+      case PROP_OBJECT_PATH:
+        g_value_set_string (value, self->object_path);
+        break;
+      case PROP_CHANNEL_TYPE:
+        g_value_set_static_string (value,
+            GABBLE_IFACE_OLPC_CHANNEL_TYPE_BUDDYVIEW);
+        break;
+      case PROP_HANDLE_TYPE:
+        g_value_set_uint (value, TP_HANDLE_TYPE_NONE);
+        break;
+      case PROP_HANDLE:
+        g_value_set_uint (value, 0);
+        break;
+      case PROP_INITIATOR_HANDLE:
+        g_value_set_uint (value, base_conn->self_handle);
+        break;
+      case PROP_INITIATOR_ID:
+          {
+            TpHandleRepoIface *repo = tp_base_connection_get_handles (
+                base_conn, TP_HANDLE_TYPE_CONTACT);
+
+            g_value_set_string (value,
+                tp_handle_inspect (repo, base_conn->self_handle));
+          }
+        break;
+      case PROP_TARGET_ID:
+          {
+            g_value_set_string (value, NULL);
+        }
+        break;
+      case PROP_REQUESTED:
+        g_value_set_boolean (value, TRUE);
+        break;
+     case PROP_INTERFACES:
+        g_value_set_boxed (value, gabble_olpc_buddy_view_interfaces);
+        break;
+      case PROP_CHANNEL_DESTROYED:
+        g_value_set_boolean (value, priv->closed);
+        break;
+      case PROP_CHANNEL_PROPERTIES:
+        g_value_take_boxed (value,
+            tp_dbus_properties_mixin_make_properties_hash (object,
+                TP_IFACE_CHANNEL, "TargetHandle",
+                TP_IFACE_CHANNEL, "TargetHandleType",
+                TP_IFACE_CHANNEL, "ChannelType",
+                TP_IFACE_CHANNEL, "TargetID",
+                GABBLE_IFACE_CHANNEL_FUTURE, "InitiatorHandle",
+                GABBLE_IFACE_CHANNEL_FUTURE, "InitiatorID",
+                GABBLE_IFACE_CHANNEL_FUTURE, "Requested",
+                GABBLE_IFACE_OLPC_CHANNEL_INTERFACE_VIEW, "MaxSize",
+                GABBLE_IFACE_OLPC_CHANNEL_INTERFACE_VIEW, "Buddies",
+                GABBLE_IFACE_OLPC_CHANNEL_INTERFACE_VIEW, "Activities",
+                NULL));
+        break;
+      case PROP_CONNECTION:
+        g_value_set_object (value, self->conn);
+        break;
+      case PROP_ID:
+        g_value_set_uint (value, self->id);
+        break;
+      case PROP_MAX_SIZE:
+        g_value_set_uint (value, self->max_size);
+        break;
+      case PROP_BUDDIES:
+        g_value_take_boxed (value, tp_handle_set_to_array (priv->buddies));
+        break;
+      case PROP_ACTIVITIES:
+        /* TODO: is that leak free ? */
+        g_value_take_boxed (value, create_activities_array (self));
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+gabble_olpc_view_set_property (GObject *object,
+                               guint property_id,
+                               const GValue *value,
+                               GParamSpec *pspec)
+{
+  GabbleOlpcView *self = GABBLE_OLPC_VIEW (object);
+
+  switch (property_id)
+    {
+      case PROP_OBJECT_PATH:
+        g_free (self->object_path);
+        self->object_path = g_value_dup_string (value);
+        break;
+      case PROP_HANDLE:
+      case PROP_INITIATOR_HANDLE:
+      case PROP_HANDLE_TYPE:
+      case PROP_CHANNEL_TYPE:
+        /* these properties are writable in the interface, but not actually
+         * meaningfully changeable on this channel, so we do nothing */
+        break;
+      case PROP_CONNECTION:
+        self->conn = g_value_get_object (value);
+        break;
+      case PROP_ID:
+        self->id = g_value_get_uint (value);
+        break;
+      case PROP_MAX_SIZE:
+        self->max_size = g_value_get_uint (value);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static GObject *
+gabble_olpc_view_constructor (GType type,
+                              guint n_props,
+                              GObjectConstructParam *props)
+{
+  GObject *obj;
+  GabbleOlpcView *self;
+  GabbleOlpcViewPrivate *priv;
+  TpBaseConnection *conn;
+  TpHandleRepoIface *contact_handles;
+
+  obj = G_OBJECT_CLASS (gabble_olpc_view_parent_class)->
+           constructor (type, n_props, props);
+
+  self = GABBLE_OLPC_VIEW (obj);
+  priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  conn = (TpBaseConnection *) self->conn;
+
+  contact_handles = tp_base_connection_get_handles (conn,
+      TP_HANDLE_TYPE_CONTACT);
+
+  priv->buddies = tp_handle_set_new (contact_handles);
+
+  priv->activities = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+      NULL, g_object_unref);
+  priv->buddy_properties = g_hash_table_new_full (g_direct_hash,
+      g_direct_equal, NULL, (GDestroyNotify) g_hash_table_unref);
+  priv->buddy_rooms = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+      NULL, (GDestroyNotify) tp_handle_set_destroy);
+
+  return obj;
+}
+
+static void
+gabble_olpc_view_class_init (GabbleOlpcViewClass *gabble_olpc_view_class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (gabble_olpc_view_class);
+  GParamSpec *param_spec;
+   static TpDBusPropertiesMixinPropImpl channel_props[] = {
+      { "TargetHandleType", "handle-type", NULL },
+      { "TargetHandle", "handle", NULL },
+      { "TargetID", "target-id", NULL },
+      { "ChannelType", "channel-type", NULL },
+      { "Interfaces", "interfaces", NULL },
+      { NULL }
+  };
+  static TpDBusPropertiesMixinPropImpl future_props[] = {
+      { "Requested", "requested", NULL },
+      { "InitiatorHandle", "initiator-handle", NULL },
+      { "InitiatorID", "initiator-id", NULL },
+      { NULL }
+  };
+  static TpDBusPropertiesMixinPropImpl view_props[] = {
+      { "MaxSize", "max-size", NULL },
+      { "Buddies", "buddies", NULL },
+      { "Activities", "activities", NULL },
+      { NULL }
+  };
+  static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
+      { TP_IFACE_CHANNEL,
+        tp_dbus_properties_mixin_getter_gobject_properties,
+        NULL,
+        channel_props,
+      },
+      { GABBLE_IFACE_CHANNEL_FUTURE,
+        tp_dbus_properties_mixin_getter_gobject_properties,
+        NULL,
+        future_props,
+      },
+      { GABBLE_IFACE_OLPC_CHANNEL_INTERFACE_VIEW,
+        tp_dbus_properties_mixin_getter_gobject_properties,
+        NULL,
+        view_props,
+      },
+      { NULL }
+  };
+
+  object_class->get_property = gabble_olpc_view_get_property;
+  object_class->set_property = gabble_olpc_view_set_property;
+  object_class->constructor = gabble_olpc_view_constructor;
+
+  g_type_class_add_private (gabble_olpc_view_class,
+      sizeof (GabbleOlpcViewPrivate));
+
+  object_class->dispose = gabble_olpc_view_dispose;
+  object_class->finalize = gabble_olpc_view_finalize;
+
+  g_object_class_override_property (object_class, PROP_OBJECT_PATH,
+      "object-path");
+  g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
+      "channel-type");
+  g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
+      "handle-type");
+  g_object_class_override_property (object_class, PROP_HANDLE, "handle");
+  g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED,
+      "channel-destroyed");
+  g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES,
+      "channel-properties");
+
+  param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
+      "Additional Channel.Interface.* interfaces",
+      G_TYPE_STRV,
+      G_PARAM_READABLE |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
+
+  param_spec = g_param_spec_string ("target-id", "Peer's bare JID",
+      "The string obtained by inspecting the peer handle (never the full JID)",
+      NULL,
+      G_PARAM_READABLE |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec);
+
+  param_spec = g_param_spec_boolean ("requested", "Requested?",
+      "True if this channel was requested by the local user",
+      FALSE,
+      G_PARAM_READABLE |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
+
+  param_spec = g_param_spec_uint ("initiator-handle", "Initiator's handle",
+      "The contact who initiated the channel",
+      0, G_MAXUINT32, 0,
+      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE,
+      param_spec);
+
+  param_spec = g_param_spec_string ("initiator-id", "Initiator's bare JID",
+      "The string obtained by inspecting the initiator-handle",
+      NULL,
+      G_PARAM_READABLE |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_INITIATOR_ID,
+      param_spec);
+
+  param_spec = g_param_spec_uint ("max-size", "View's max size",
+      "The maximum number of elements that Gadget has to return to the "
+      "search request.",
+      0, G_MAXUINT32, 0,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_MAX_SIZE,
+      param_spec);
+
+  param_spec = g_param_spec_boxed ("buddies", "View's buddies",
+      "The contact handles of the buddies who are in this view channel",
+      GABBLE_ARRAY_TYPE_HANDLE,
+      G_PARAM_READABLE |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_BUDDIES,
+      param_spec);
+
+  param_spec = g_param_spec_boxed ("activities", "View's activities",
+      "The activities which are in this view channel",
+      GABBLE_ARRAY_TYPE_ACTIVITY_LIST,
+      G_PARAM_READABLE |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_ACTIVITIES,
+      param_spec);
+
+   param_spec = g_param_spec_object (
+      "connection",
+      "GabbleConnection object",
+      "Gabble connection object that owns this view object.",
+      GABBLE_TYPE_CONNECTION,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NAME |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
+
+  param_spec = g_param_spec_uint (
+      "id",
+      "query ID",
+      "The ID of the query associated with this view",
+      0, G_MAXUINT, 0,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NAME |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_ID, param_spec);
+
+  signals[BUDDY_ACTIVITIES_CHANGED] =
+    g_signal_new ("buddy-activities-changed",
+        G_OBJECT_CLASS_TYPE (gabble_olpc_view_class),
+        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+        0,
+        NULL, NULL,
+        gabble_marshal_VOID__UINT,
+        G_TYPE_NONE, 1, G_TYPE_UINT);
+
+  gabble_olpc_view_class->dbus_props_class.interfaces = prop_interfaces;
+  tp_dbus_properties_mixin_class_init (object_class,
+      G_STRUCT_OFFSET (GabbleOlpcViewClass, dbus_props_class));
+}
+
+static void
+free_activities_array (GPtrArray *activities)
+{
+  guint i;
+
+  for (i = 0; i < activities->len; i++)
+    g_boxed_free (GABBLE_STRUCT_TYPE_ACTIVITY, activities->pdata[i]);
+
+  g_ptr_array_free (activities, TRUE);
+}
+
+static void
+buddy_left_activities_foreach (TpHandleSet *set,
+                               TpHandle buddy,
+                               GabbleOlpcView *self)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+
+  /* Remove all the activity of this buddy */
+  if (!g_hash_table_remove (priv->buddy_rooms, GUINT_TO_POINTER (buddy)))
+    return;
+
+  g_signal_emit (G_OBJECT (self), signals[BUDDY_ACTIVITIES_CHANGED],
+      0, buddy);
+}
+
+static gboolean
+do_close (GabbleOlpcView *self,
+          GError **error)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  LmMessage *msg;
+
+  msg = GABBLE_OLPC_VIEW_GET_CLASS (self)->create_close_msg (self);
+
+  if (!_gabble_connection_send (self->conn, msg, error))
+    {
+      lm_message_unref (msg);
+      return FALSE;
+    }
+
+  lm_message_unref (msg);
+
+  /* Claim that all the buddies left their activities */
+  tp_handle_set_foreach (priv->buddies,
+      (TpHandleSetMemberFunc) buddy_left_activities_foreach, self);
+
+  priv->closed = TRUE;
+
+  tp_svc_channel_emit_closed (self);
+
+  return TRUE;
+}
+
+/**
+ * gabble_olpc_buddy_view_close
+ *
+ * Implements D-Bus method Close
+ * on interface org.freedesktop.Telepathy.Channel
+ */
+static void
+gabble_olpc_buddy_view_close (TpSvcChannel *iface,
+                              DBusGMethodInvocation *context)
+{
+  GabbleOlpcView *self = GABBLE_OLPC_VIEW (iface);
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  GError *error = NULL;
+
+  if (priv->closed)
+    {
+      DEBUG ("Already closed. Doing nothing");
+    }
+  else
+    {
+      /* FIXME: set closed */
+      if (!do_close (self, &error))
+        {
+          dbus_g_method_return_error (context, error);
+          g_error_free (error);
+        }
+    }
+
+  tp_svc_channel_return_from_close (context);
+}
+
+/**
+ * gabble_olpc_buddy_view_get_channel_type
+ *
+ * Implements D-Bus method GetChannelType
+ * on interface org.freedesktop.Telepathy.Channel
+ */
+static void
+gabble_olpc_buddy_view_get_channel_type (TpSvcChannel *iface,
+                                         DBusGMethodInvocation *context)
+{
+  tp_svc_channel_return_from_get_channel_type (context,
+      GABBLE_IFACE_OLPC_CHANNEL_TYPE_BUDDYVIEW);
+}
+
+/**
+ * gabble_olpc_buddy_view_get_handle
+ *
+ * Implements D-Bus method GetHandle
+ * on interface org.freedesktop.Telepathy.Channel
+ */
+static void
+gabble_olpc_buddy_view_get_handle (TpSvcChannel *iface,
+                                   DBusGMethodInvocation *context)
+{
+  tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_NONE, 0);
+}
+
+/**
+ * gabble_olpc_buddy_view_get_interfaces
+ *
+ * Implements D-Bus method GetInterfaces
+ * on interface org.freedesktop.Telepathy.Channel
+ */
+static void
+gabble_olpc_buddy_view_get_interfaces (TpSvcChannel *iface,
+                                       DBusGMethodInvocation *context)
+{
+  tp_svc_channel_return_from_get_interfaces (context,
+      gabble_olpc_buddy_view_interfaces);
+}
+
+/* If room is not zero, these buddies are associated with the activity
+ * of this room. They'll leave the view if the activity is removed.
+ */
+void
+gabble_olpc_view_add_buddies (GabbleOlpcView *self,
+                              GArray *buddies,
+                              GPtrArray *buddies_properties,
+                              TpHandle room)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  guint i;
+  GArray *empty;
+  TpHandleRepoIface *room_repo;
+  GArray *buddies_changed;
+
+  g_assert (buddies->len == buddies_properties->len);
+  if (buddies->len == 0)
+    return;
+
+  room_repo = tp_base_connection_get_handles ((TpBaseConnection *) self->conn,
+      TP_HANDLE_TYPE_ROOM);
+
+  empty = g_array_new (FALSE, FALSE, sizeof (TpHandle));
+  buddies_changed = g_array_new (FALSE, FALSE, sizeof (TpHandle));
+
+  /* store properties */
+  for (i = 0; i < buddies->len; i++)
+    {
+      TpHandle handle;
+      GHashTable *properties;
+
+      handle = g_array_index (buddies, TpHandle, i);
+      properties = g_ptr_array_index (buddies_properties, i);
+
+      tp_handle_set_add (priv->buddies, handle);
+      g_hash_table_insert (priv->buddy_properties, GUINT_TO_POINTER (handle),
+          properties);
+      g_hash_table_ref (properties);
+
+      if (room != 0)
+        {
+          /* buddies are in an activity */
+          TpHandleSet *set;
+
+          set = g_hash_table_lookup (priv->buddy_rooms, GUINT_TO_POINTER (
+                handle));
+
+          if (set == NULL)
+            {
+              set = tp_handle_set_new (room_repo);
+
+              g_hash_table_insert (priv->buddy_rooms, GUINT_TO_POINTER (
+                    handle), set);
+            }
+
+          if (!tp_handle_set_is_member (set, room))
+            {
+              tp_handle_set_add (set, room);
+
+              /* We fire BuddyInfo.ActivitiesChanged signal after
+               * View.BuddiesChanged so client knows where these buddies
+               * come from */
+              g_array_append_val (buddies_changed, handle);
+            }
+        }
+    }
+
+  gabble_svc_olpc_channel_interface_view_emit_buddies_changed (self, buddies,
+      empty);
+
+  for (i = 0; i < buddies_changed->len; i++)
+    {
+      TpHandle handle;
+
+      handle = g_array_index (buddies_changed, TpHandle, i);
+      g_signal_emit (G_OBJECT (self),
+          signals[BUDDY_ACTIVITIES_CHANGED], 0, handle);
+    }
+
+  g_array_free (buddies_changed, TRUE);
+  g_array_free (empty, TRUE);
+}
+
+static void
+remove_buddy_foreach (TpHandleSet *buddies,
+                      TpHandle handle,
+                      GabbleOlpcView *self)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+
+  tp_handle_set_remove (priv->buddies, handle);
+  g_hash_table_remove (priv->buddy_properties, GUINT_TO_POINTER (handle));
+  g_hash_table_remove (priv->buddy_rooms, GUINT_TO_POINTER (handle));
+}
+
+void
+gabble_olpc_view_remove_buddies (GabbleOlpcView *self,
+                                 TpHandleSet *buddies)
+{
+  GArray *removed, *empty;
+
+  if (tp_handle_set_size (buddies) == 0)
+    return;
+
+  tp_handle_set_foreach (buddies,
+      (TpHandleSetMemberFunc) remove_buddy_foreach, self);
+
+  empty = g_array_new (FALSE, FALSE, sizeof (TpHandle));
+  removed = tp_handle_set_to_array (buddies);
+
+  gabble_svc_olpc_channel_interface_view_emit_buddies_changed (self, empty,
+      removed);
+
+  g_array_free (empty, TRUE);
+  g_array_free (removed, TRUE);
+}
+
+gboolean
+gabble_olpc_view_set_buddy_properties (GabbleOlpcView *self,
+                                       TpHandle buddy,
+                                       GHashTable *properties)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+
+  if (!tp_handle_set_is_member (priv->buddies, buddy))
+    {
+      DEBUG ("buddy %d is not member of this view", buddy);
+      return FALSE;
+    }
+
+  tp_handle_set_add (priv->buddies, buddy);
+  g_hash_table_insert (priv->buddy_properties, GUINT_TO_POINTER (buddy),
+      properties);
+  g_hash_table_ref (properties);
+
+  return TRUE;
+}
+
+GHashTable *
+gabble_olpc_view_get_buddy_properties (GabbleOlpcView *self,
+                                       TpHandle buddy)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+
+  return g_hash_table_lookup (priv->buddy_properties,
+      GUINT_TO_POINTER (buddy));
+}
+
+void
+gabble_olpc_view_add_activities (GabbleOlpcView *self,
+                                 GHashTable *activities)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  GPtrArray *added, *empty;
+
+  if (g_hash_table_size (activities) == 0)
+    return;
+
+  tp_g_hash_table_update (priv->activities, activities, NULL, g_object_ref);
+
+  added = g_ptr_array_new ();
+  g_hash_table_foreach (activities, (GHFunc) add_activity_to_array, added);
+
+  empty = g_ptr_array_new ();
+
+  gabble_svc_olpc_channel_interface_view_emit_activities_changed (self, added,
+      empty);
+
+  free_activities_array (added);
+  g_ptr_array_free (empty, TRUE);
+}
+
+struct remove_activity_foreach_buddy_ctx
+{
+  GabbleOlpcView *view;
+  TpHandle room;
+  /* buddies who have to be removed */
+  TpHandleSet *removed;
+};
+
+static void
+remove_activity_foreach_buddy (TpHandle buddy,
+                               TpHandleSet *set,
+                               struct remove_activity_foreach_buddy_ctx *ctx)
+{
+  if (set == NULL)
+    return;
+
+  if (tp_handle_set_remove (set, ctx->room))
+    {
+      if (tp_handle_set_size (set) == 0)
+        {
+          /* No more activity for this buddy. Remove it */
+          tp_handle_set_add (ctx->removed, buddy);
+        }
+
+      g_signal_emit (G_OBJECT (ctx->view), signals[BUDDY_ACTIVITIES_CHANGED],
+          0, buddy);
+    }
+}
+
+void
+gabble_olpc_view_remove_activities (GabbleOlpcView *self,
+                                    TpHandleSet *rooms)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  GPtrArray *removed, *empty;
+  GArray *array;
+  guint i;
+  TpHandleRepoIface *contact_repo;
+
+  if (tp_handle_set_size (rooms) == 0)
+    return;
+
+  contact_repo = tp_base_connection_get_handles (
+      (TpBaseConnection *) self->conn, TP_HANDLE_TYPE_CONTACT);
+
+  /* for easier iteration */
+  array = tp_handle_set_to_array (rooms);
+
+  removed = g_ptr_array_new ();
+  empty = g_ptr_array_new ();
+
+  for (i = 0; i < array->len; i++)
+    {
+      TpHandle room;
+      GabbleOlpcActivity *activity;
+      struct remove_activity_foreach_buddy_ctx ctx;
+
+      room = g_array_index (array, TpHandle, i);
+
+      activity = g_hash_table_lookup (priv->activities,
+          GUINT_TO_POINTER (room));
+      if (activity == NULL)
+        continue;
+
+      add_activity_to_array (room, activity, removed);
+      g_hash_table_remove (priv->activities, GUINT_TO_POINTER (room));
+
+      /* remove the activity from all rooms set */
+      ctx.view = self;
+      ctx.room = room;
+      ctx.removed = tp_handle_set_new (contact_repo);
+
+      g_hash_table_foreach (priv->buddy_rooms,
+          (GHFunc) remove_activity_foreach_buddy, &ctx);
+
+      gabble_olpc_view_remove_buddies (self, ctx.removed);
+
+      tp_handle_set_destroy (ctx.removed);
+    }
+
+  gabble_svc_olpc_channel_interface_view_emit_activities_changed (self, empty,
+      removed);
+
+  free_activities_array (removed);
+  g_ptr_array_free (empty, TRUE);
+  g_array_free (array, TRUE);
+}
+
+GPtrArray *
+gabble_olpc_view_get_buddy_activities (GabbleOlpcView *self,
+                                       TpHandle buddy)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  GPtrArray *activities;
+  TpHandleSet *rooms_set;
+  GArray *rooms;
+  guint i;
+
+  activities = g_ptr_array_new ();
+
+  rooms_set = g_hash_table_lookup (priv->buddy_rooms,
+      GUINT_TO_POINTER (buddy));
+  if (rooms_set == NULL || tp_handle_set_size (rooms_set) == 0)
+    return activities;
+
+  /* Convert to an array for easier iteration */
+  rooms = tp_handle_set_to_array (rooms_set);
+  for (i = 0; i < rooms->len; i++)
+    {
+      TpHandle room;
+      GabbleOlpcActivity *activity;
+
+      room = g_array_index (rooms, TpHandle, i);
+
+      activity = g_hash_table_lookup (priv->activities,
+          GUINT_TO_POINTER (room));
+      if (activity == NULL)
+        {
+          /* This shouldn't happen as long as:
+           *
+           * - Gadget doesn't send us <joined> stanzas about an activity
+           *   which was not previously announced as being part of the view.
+           *
+           * - We don't call gabble_olpc_view_add_buddies with an activity
+           *   which was not previoulsy added to the view.
+           */
+          DEBUG ("Buddy %d is supposed to be in activity %d but view doesn't"
+              " contain its info", buddy, room);
+          continue;
+        }
+
+      g_ptr_array_add (activities, activity);
+    }
+
+  g_array_free (rooms, TRUE);
+
+  return activities;
+}
+
+void
+gabble_olpc_view_buddies_left_activity (GabbleOlpcView *self,
+                                        GArray *buddies,
+                                        TpHandle room)
+{
+  GabbleOlpcViewPrivate *priv = GABBLE_OLPC_VIEW_GET_PRIVATE (self);
+  guint i;
+  TpHandleRepoIface *contact_repo;
+  TpHandleSet *removed;
+
+  contact_repo = tp_base_connection_get_handles (
+      (TpBaseConnection *) self->conn, TP_HANDLE_TYPE_CONTACT);
+
+  removed = tp_handle_set_new (contact_repo);
+
+  for (i = 0; i < buddies->len; i++)
+    {
+      TpHandleSet *set;
+      TpHandle buddy;
+
+      buddy = g_array_index (buddies, TpHandle, i);
+      set = g_hash_table_lookup (priv->buddy_rooms, GUINT_TO_POINTER (buddy));
+      if (set == NULL)
+        continue;
+
+      if (tp_handle_set_remove (set, room))
+        {
+          if (tp_handle_set_size (set) == 0)
+            {
+              /* Remove from the view */
+              tp_handle_set_add (removed, buddy);
+            }
+
+          g_signal_emit (G_OBJECT (self), signals[BUDDY_ACTIVITIES_CHANGED],
+              0, buddy);
+        }
+    }
+
+  gabble_olpc_view_remove_buddies (self, removed);
+
+  tp_handle_set_destroy (removed);
+}
+
+static LmHandlerResult
+buddy_view_query_result_cb (GabbleConnection *conn,
+                            LmMessage *sent_msg,
+                            LmMessage *reply_msg,
+                            GObject *_view,
+                            gpointer user_data)
+{
+  LmMessageNode *view_node;
+  GabbleOlpcView *self = GABBLE_OLPC_VIEW (_view);
+
+  view_node = lm_message_node_get_child_with_namespace (reply_msg->node,
+      "view", NS_OLPC_BUDDY);
+  if (view_node == NULL)
+    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+
+  /* FIXME: make sense to call this conn-olpc function ? */
+  add_buddies_to_view_from_node (conn, self, view_node, "buddy", 0);
+
+  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+}
+
+gboolean
+gabble_olpc_view_send_request (GabbleOlpcView *self,
+                               GError **error)
+
+{
+  LmMessage *query;
+
+  query = GABBLE_OLPC_VIEW_GET_CLASS (self)->create_request (self);
+  if (query == NULL)
+    return FALSE;
+
+  if (!_gabble_connection_send_with_reply (self->conn, query,
+        buddy_view_query_result_cb, G_OBJECT (self), NULL, NULL))
+    {
+      g_set_error (error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+        "Failed to send buddy search query to server");
+
+      DEBUG ("Failed to send buddy search query to server");
+      lm_message_unref (query);
+      return FALSE;
+    }
+
+  lm_message_unref (query);
+
+  return TRUE;
+}
+
+static void
+channel_iface_init (gpointer g_iface, gpointer iface_data)
+{
+  TpSvcChannelClass *klass = (TpSvcChannelClass *) g_iface;
+
+#define IMPLEMENT(x) tp_svc_channel_implement_##x (\
+    klass, gabble_olpc_buddy_view_##x)
+  IMPLEMENT(close);
+  IMPLEMENT(get_channel_type);
+  IMPLEMENT(get_handle);
+  IMPLEMENT(get_interfaces);
+#undef IMPLEMENT
+}
diff --git a/src/olpc-view.h b/src/olpc-view.h
new file mode 100644
index 0000000..80bc284
--- /dev/null
+++ b/src/olpc-view.h
@@ -0,0 +1,103 @@
+/*
+ * olpc-buddy-view.h - Header for GabbleOlpcView
+ * Copyright (C) 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
+ */
+
+#ifndef __GABBLE_OLPC_VIEW_H__
+#define __GABBLE_OLPC_VIEW_H__
+
+#include <glib-object.h>
+
+#include <telepathy-glib/enums.h>
+#include <telepathy-glib/handle-repo.h>
+
+#include "connection.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GabbleOlpcViewClass GabbleOlpcViewClass;
+
+struct _GabbleOlpcViewClass {
+  GObjectClass parent_class;
+
+  TpDBusPropertiesMixinClass dbus_props_class;
+
+  /* private abstract methods */
+  LmMessage * (*create_close_msg) (GabbleOlpcView *self);
+  LmMessage * (*create_request) (GabbleOlpcView *self);
+};
+
+struct _GabbleOlpcView {
+  GObject parent;
+
+  /* protected variables */
+  gchar *object_path;
+  GabbleConnection *conn;
+  guint id;
+  guint max_size;
+
+  gpointer priv;
+};
+
+GType gabble_olpc_view_get_type (void);
+
+/* TYPE MACROS */
+#define GABBLE_TYPE_OLPC_VIEW \
+  (gabble_olpc_view_get_type ())
+#define GABBLE_OLPC_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_OLPC_VIEW, GabbleOlpcView))
+#define GABBLE_OLPC_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_OLPC_VIEW,\
+                           GabbleOlpcViewClass))
+#define GABBLE_IS_OLPC_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_OLPC_VIEW))
+#define GABBLE_IS_OLPC_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_OLPC_VIEW))
+#define GABBLE_OLPC_VIEW_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_OLPC_VIEW,\
+                              GabbleOlpcViewClass))
+
+gboolean gabble_olpc_view_send_request (GabbleOlpcView *view,
+    GError **error);
+
+void gabble_olpc_view_add_buddies (GabbleOlpcView *self,
+    GArray *handles, GPtrArray *buddies_properties, TpHandle room);
+
+void gabble_olpc_view_remove_buddies (GabbleOlpcView *self,
+    TpHandleSet *handles);
+
+gboolean gabble_olpc_view_set_buddy_properties (GabbleOlpcView *self,
+    TpHandle buddy, GHashTable *properties);
+
+GHashTable * gabble_olpc_view_get_buddy_properties (GabbleOlpcView *self,
+    TpHandle buddy);
+
+void gabble_olpc_view_add_activities (GabbleOlpcView *self,
+    GHashTable *activities);
+
+void gabble_olpc_view_remove_activities (GabbleOlpcView *self,
+    TpHandleSet *rooms);
+
+GPtrArray * gabble_olpc_view_get_buddy_activities (GabbleOlpcView *self,
+    TpHandle buddy);
+
+void gabble_olpc_view_buddies_left_activity (GabbleOlpcView *self,
+    GArray *buddies, TpHandle room);
+
+G_END_DECLS
+
+#endif /* #ifndef __GABBLE_OLPC_VIEW_H__ */
-- 
1.5.6.5




More information about the Telepathy-commits mailing list