[Telepathy-commits] [telepathy-gabble/master] Re-implement activity views using the new API
Guillaume Desmottes
guillaume.desmottes at collabora.co.uk
Thu Oct 16 03:19:07 PDT 2008
---
src/Makefile.am | 2 +
src/conn-olpc.c | 463 +++------------------------
src/conn-olpc.h | 3 +
src/olpc-activity-view.c | 473 ++++++++++++++++++++++++++++
src/olpc-activity-view.h | 71 +++++
src/olpc-gadget-manager.c | 179 +++++++++++-
src/olpc-gadget-manager.h | 4 +
tests/twisted/olpc/olpc-activity-search.py | 150 +++++++---
tests/twisted/olpc/util.py | 14 +-
9 files changed, 902 insertions(+), 457 deletions(-)
create mode 100644 src/olpc-activity-view.c
create mode 100644 src/olpc-activity-view.h
diff --git a/src/Makefile.am b/src/Makefile.am
index a29e571..8d7cab9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -71,6 +71,8 @@ libgabble_convenience_la_SOURCES = \
namespaces.h \
olpc-activity.h \
olpc-activity.c \
+ olpc-activity-view.h \
+ olpc-activity-view.c \
olpc-buddy-view.h \
olpc-buddy-view.c \
olpc-gadget-manager.h \
diff --git a/src/conn-olpc.c b/src/conn-olpc.c
index 8b6144f..818d732 100644
--- a/src/conn-olpc.c
+++ b/src/conn-olpc.c
@@ -420,33 +420,6 @@ get_properties_reply_cb (GabbleConnection *conn,
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
-#if 0
-static gboolean
-find_view_having_properties_for_buddy (gpointer id,
- gpointer value,
- gpointer buddy)
-{
- GabbleOlpcView *view = GABBLE_OLPC_VIEW (value);
- TpHandle handle = GPOINTER_TO_UINT (buddy);
-
- return gabble_olpc_view_get_buddy_properties (view, handle) != NULL;
-}
-
-static GHashTable *
-find_buddy_properties_from_views (GabbleConnection *conn,
- TpHandle buddy)
-{
- GabbleOlpcView *view;
-
- view = g_hash_table_find (conn->olpc_views,
- find_view_having_properties_for_buddy, GUINT_TO_POINTER (buddy));
- if (view == NULL)
- return NULL;
-
- return gabble_olpc_view_get_buddy_properties (view, buddy);
-}
-#endif
-
static void
olpc_buddy_info_get_properties (GabbleSvcOLPCBuddyInfo *iface,
guint contact,
@@ -916,85 +889,6 @@ check_activity_properties (GabbleConnection *conn,
}
}
-#if 0
-struct find_activities_of_buddy_ctx
-{
- TpHandle buddy;
- GHashTable *activities;
-};
-
-static void
-find_activities_of_buddy (TpHandle contact,
- GabbleOlpcView *view,
- struct find_activities_of_buddy_ctx *ctx)
-{
- GPtrArray *act;
- guint i;
-
- act = gabble_olpc_view_get_buddy_activities (view, ctx->buddy);
-
- for (i = 0; i < act->len; i++)
- {
- GabbleOlpcActivity *activity;
-
- activity = g_ptr_array_index (act, i);
- g_hash_table_insert (ctx->activities, GUINT_TO_POINTER (activity->room),
- activity);
- }
-
- g_ptr_array_free (act, TRUE);
-}
-
-static void
-copy_activity_to_array (TpHandle room,
- GabbleOlpcActivity *activity,
- GPtrArray *activities)
-{
- GValue gvalue = { 0 };
-
- if (activity->id == NULL)
- {
- DEBUG ("... activity #%u has no ID, skipping", room);
- return;
- }
-
- 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);
- DEBUG ("... activity #%u (ID %s)",
- activity->room, activity->id);
- g_ptr_array_add (activities, g_value_get_boxed (&gvalue));
-}
-
-static GPtrArray *
-find_buddy_activities_from_views (GabbleConnection *conn,
- TpHandle contact)
-{
- GPtrArray *result;
- struct find_activities_of_buddy_ctx ctx;
-
- result = g_ptr_array_new ();
-
- /* We use a hash table first so we won't add twice the same activity */
- ctx.activities = g_hash_table_new (g_direct_hash, g_direct_equal);
- ctx.buddy = contact;
-
- g_hash_table_foreach (conn->olpc_views, (GHFunc) find_activities_of_buddy,
- &ctx);
-
- /* Now compute the result array using the hash table */
- g_hash_table_foreach (ctx.activities, (GHFunc) copy_activity_to_array,
- result);
-
- g_hash_table_destroy (ctx.activities);
-
- return result;
-}
-
static void
return_buddy_activities_from_views (GabbleConnection *conn,
TpHandle contact,
@@ -1002,12 +896,12 @@ return_buddy_activities_from_views (GabbleConnection *conn,
{
GPtrArray *activities;
- activities = find_buddy_activities_from_views (conn, contact);
+ activities = gabble_olpc_gadget_manager_find_buddy_activities (
+ conn->olpc_gadget_manager, contact);
gabble_svc_olpc_buddy_info_return_from_get_activities (context, activities);
free_activities (activities);
}
-#endif
static LmHandlerResult
get_activities_reply_cb (GabbleConnection *conn,
@@ -1045,10 +939,8 @@ get_activities_reply_cb (GabbleConnection *conn,
if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
{
-#if 0
DEBUG ("Failed to query PEP node. Compute activities list using views");
return_buddy_activities_from_views (conn, from_handle, context);
-#endif
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
@@ -2999,7 +2891,6 @@ buddy_changed (GabbleConnection *conn,
}
}
-#if 0
static void
activity_changed (GabbleConnection *conn,
LmMessageNode *change)
@@ -3023,7 +2914,6 @@ activity_changed (GabbleConnection *conn,
}
}
}
-#endif
static gboolean
populate_buddies_from_nodes (GabbleConnection *conn,
@@ -3086,8 +2976,7 @@ populate_buddies_from_nodes (GabbleConnection *conn,
return TRUE;
}
-#if 0
-static gboolean
+gboolean
add_activities_to_view_from_node (GabbleConnection *conn,
GabbleOlpcView *view,
LmMessageNode *node)
@@ -3244,7 +3133,8 @@ activity_added (GabbleConnection *conn,
return;
id = strtoul (id_str, NULL, 10);
- view = g_hash_table_lookup (conn->olpc_views, GUINT_TO_POINTER (id));
+ view = gabble_olpc_gadget_manager_get_view (
+ conn->olpc_gadget_manager, id);
if (view == NULL)
{
DEBUG ("no view with ID %u", id);
@@ -3253,7 +3143,6 @@ activity_added (GabbleConnection *conn,
add_activities_to_view_from_node (conn, view, added);
}
-#endif
/* if activity is not zero, buddies are associated with the given
* activity room */
@@ -3402,7 +3291,6 @@ buddy_removed (GabbleConnection *conn,
remove_buddies_from_view_from_node (conn, view, removed);
}
-#if 0
static gboolean
remove_activities_from_view_from_node (GabbleConnection *conn,
GabbleOlpcView *view,
@@ -3456,7 +3344,8 @@ activity_removed (GabbleConnection *conn,
return;
id = strtoul (id_str, NULL, 10);
- view = g_hash_table_lookup (conn->olpc_views, GUINT_TO_POINTER (id));
+ view = gabble_olpc_gadget_manager_get_view (
+ conn->olpc_gadget_manager, id);
if (view == NULL)
{
DEBUG ("no view with ID %u", id);
@@ -3520,7 +3409,8 @@ activity_membership_change (GabbleConnection *conn,
return;
id = strtoul (id_str, NULL, 10);
- view = g_hash_table_lookup (conn->olpc_views, GUINT_TO_POINTER (id));
+ view = gabble_olpc_gadget_manager_get_view (
+ conn->olpc_gadget_manager, id);
if (view == NULL)
{
DEBUG ("no view with ID %u", id);
@@ -3550,7 +3440,6 @@ activity_membership_change (GabbleConnection *conn,
tp_handle_unref (room_repo, handle);
}
-#endif
LmHandlerResult
conn_olpc_msg_cb (LmMessageHandler *handler,
@@ -3584,13 +3473,11 @@ conn_olpc_msg_cb (LmMessageHandler *handler,
{
buddy_changed (conn, node);
}
-#if 0
else if (!tp_strdiff (node->name, "change") &&
!tp_strdiff (ns, NS_OLPC_ACTIVITY))
{
activity_changed (conn, node);
}
-#endif
else if (!tp_strdiff (node->name, "added") &&
!tp_strdiff (ns, NS_OLPC_BUDDY))
{
@@ -3601,7 +3488,6 @@ conn_olpc_msg_cb (LmMessageHandler *handler,
{
buddy_removed (conn, node);
}
-#if 0
else if (!tp_strdiff (node->name, "added") &&
!tp_strdiff (ns, NS_OLPC_ACTIVITY))
{
@@ -3617,7 +3503,6 @@ conn_olpc_msg_cb (LmMessageHandler *handler,
{
activity_membership_change (conn, node);
}
-#endif
}
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
@@ -3673,6 +3558,46 @@ disco_item_found_cb (GabbleDisco *disco,
}
}
+static void
+buddy_activities_changed_cb (GabbleOlpcView *view,
+ TpHandle contact,
+ GabbleConnection *conn)
+{
+ GPtrArray *activities;
+
+ /* FIXME: this is not optimal as we completely ignore PEP-announced
+ * activities. Ideally we should cache PEP activities. */
+ activities = gabble_olpc_gadget_manager_find_buddy_activities (
+ conn->olpc_gadget_manager, contact);
+
+ gabble_svc_olpc_buddy_info_emit_activities_changed (conn, contact,
+ activities);
+
+ free_activities (activities);
+}
+
+static void
+gadget_manager_new_channels_cb (GabbleOlpcGadgetManager *mgr,
+ GHashTable *channels,
+ GabbleConnection *conn)
+{
+ /* new views has been created */
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, channels);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ if (GABBLE_IS_OLPC_VIEW (key))
+ {
+ GabbleOlpcView *view = GABBLE_OLPC_VIEW (key);
+
+ g_signal_connect (view, "buddy-activities-changed",
+ G_CALLBACK (buddy_activities_changed_cb), conn);
+ }
+ }
+}
+
void
conn_olpc_activity_properties_init (GabbleConnection *conn)
{
@@ -3723,6 +3648,9 @@ conn_olpc_activity_properties_init (GabbleConnection *conn)
g_signal_connect (conn->presence_cache, "presences-updated",
G_CALLBACK (connection_presences_updated_cb), conn);
+
+ g_signal_connect (conn->olpc_gadget_manager, "new-channels",
+ G_CALLBACK (gadget_manager_new_channels_cb), conn);
}
static void
@@ -3766,293 +3694,6 @@ olpc_activity_properties_iface_init (gpointer g_iface,
#undef IMPLEMENT
}
-#if 0
-
-/* FIXME: connect this
- g_signal_connect (view, "buddy-activities-changed",
- G_CALLBACK (buddy_activities_changed_cb), conn);
-*/
-
-static void
-buddy_activities_changed_cb (GabbleOlpcView *view,
- TpHandle contact,
- GabbleConnection *conn)
-{
- GPtrArray *activities;
-
- /* FIXME: this is not optimal as we completely ignore PEP-announced
- * activities. Ideally we should cache PEP activities. */
- activities = find_buddy_activities_from_views (conn, contact);
-
- gabble_svc_olpc_buddy_info_emit_activities_changed (conn, contact,
- activities);
-
- free_activities (activities);
-}
-
-static LmHandlerResult
-activity_view_query_result_cb (GabbleConnection *conn,
- LmMessage *sent_msg,
- LmMessage *reply_msg,
- GObject *_view,
- gpointer user_data)
-{
- LmMessageNode *view_node;
- GabbleOlpcView *view = GABBLE_OLPC_VIEW (_view);
-
- view_node = lm_message_node_get_child_with_namespace (reply_msg->node,
- "view", NS_OLPC_ACTIVITY);
- if (view_node == NULL)
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-
- add_activities_to_view_from_node (conn, view, view_node);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-olpc_gadget_request_random_activities (GabbleSvcOLPCGadget *iface,
- guint max,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (iface);
- LmMessage *query;
- gchar *max_str, *id_str;
- gchar *object_path;
- guint id;
- GabbleOlpcView *view;
-
- if (!check_gadget_activity (conn, context))
- return;
-
- if (max == 0)
- {
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "max have to be greater than 0" };
-
- DEBUG ("%s", error.message);
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- view = create_view (conn, GABBLE_OLPC_VIEW_TYPE_ACTIVITY);
- if (view == NULL)
- {
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
- "can't create view" };
-
- DEBUG ("%s", error.message);
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (view,
- "id", &id,
- "object-path", &object_path,
- NULL);
-
- max_str = g_strdup_printf ("%u", max);
- id_str = g_strdup_printf ("%u", id);
-
- query = lm_message_build_with_sub_type (conn->olpc_gadget_activity,
- LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
- '(', "view", "",
- '@', "xmlns", NS_OLPC_ACTIVITY,
- '@', "id", id_str,
- '(', "random", "",
- '@', "max", max_str,
- ')',
- ')',
- NULL);
-
- g_free (max_str);
- g_free (id_str);
-
- if (!_gabble_connection_send_with_reply (conn, query,
- activity_view_query_result_cb, G_OBJECT (view), NULL, NULL))
- {
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
- "Failed to send activity search query to server" };
-
- DEBUG ("%s", error.message);
- dbus_g_method_return_error (context, &error);
- lm_message_unref (query);
- g_free (object_path);
- return;
- }
-
- gabble_svc_olpc_gadget_return_from_request_random_activities (context,
- object_path);
-
- g_free (object_path);
- lm_message_unref (query);
-}
-
-static void
-olpc_gadget_search_activities_by_properties (GabbleSvcOLPCGadget *iface,
- GHashTable *properties,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (iface);
- LmMessage *query;
- LmMessageNode *properties_node;
- gchar *id_str;
- gchar *object_path;
- guint id;
- GabbleOlpcView *view;
-
- if (!check_gadget_activity (conn, context))
- return;
-
- view = create_view (conn, GABBLE_OLPC_VIEW_TYPE_ACTIVITY);
- if (view == NULL)
- {
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
- "can't create view" };
-
- DEBUG ("%s", error.message);
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (view,
- "id", &id,
- "object-path", &object_path,
- NULL);
-
- id_str = g_strdup_printf ("%u", id);
-
- query = lm_message_build_with_sub_type (conn->olpc_gadget_activity,
- LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
- '(', "view", "",
- '@', "xmlns", NS_OLPC_ACTIVITY,
- '@', "id", id_str,
- '(', "activity", "",
- '(', "properties", "",
- '*', &properties_node,
- '@', "xmlns", NS_OLPC_ACTIVITY_PROPS,
- ')',
- ')',
- ')',
- NULL);
-
- g_free (id_str);
-
- lm_message_node_add_children_from_properties (properties_node, properties,
- "property");
-
- if (!_gabble_connection_send_with_reply (conn, query,
- activity_view_query_result_cb, G_OBJECT (view), NULL, NULL))
- {
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
- "Failed to send activity search query to server" };
-
- DEBUG ("%s", error.message);
- dbus_g_method_return_error (context, &error);
- lm_message_unref (query);
- g_free (object_path);
- return;
- }
-
- gabble_svc_olpc_gadget_return_from_search_activities_by_properties (context,
- object_path);
-
- g_free (object_path);
- lm_message_unref (query);
-}
-
-static void
-olpc_gadget_search_activities_by_participants (GabbleSvcOLPCGadget *iface,
- const GArray *participants,
- DBusGMethodInvocation *context)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (iface);
- LmMessage *query;
- LmMessageNode *activity_node;
- gchar *id_str;
- gchar *object_path;
- guint id, i;
- GabbleOlpcView *view;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT);
-
- if (participants->len == 0)
- {
- GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "you must pass at least one participant" };
-
- DEBUG ("%s", error.message);
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- if (!check_gadget_activity (conn, context))
- return;
-
- view = create_view (conn, GABBLE_OLPC_VIEW_TYPE_ACTIVITY);
- if (view == NULL)
- {
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
- "can't create view" };
-
- DEBUG ("%s", error.message);
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (view,
- "id", &id,
- "object-path", &object_path,
- NULL);
-
- id_str = g_strdup_printf ("%u", id);
-
- query = lm_message_build_with_sub_type (conn->olpc_gadget_activity,
- LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
- '(', "view", "",
- '@', "xmlns", NS_OLPC_ACTIVITY,
- '@', "id", id_str,
- '(', "activity", "",
- '*', &activity_node,
- ')',
- ')',
- NULL);
-
- g_free (id_str);
-
- for (i = 0; i < participants->len; i++)
- {
- LmMessageNode *buddy;
- const gchar *jid;
-
- jid = tp_handle_inspect (contact_repo,
- g_array_index (participants, TpHandle, i));
-
- buddy = lm_message_node_add_child (activity_node, "buddy", "");
- lm_message_node_set_attribute (buddy, "jid", jid);
- }
-
- if (!_gabble_connection_send_with_reply (conn, query,
- activity_view_query_result_cb, G_OBJECT (view), NULL, NULL))
- {
- GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
- "Failed to send activity search query to server" };
-
- DEBUG ("%s", error.message);
- dbus_g_method_return_error (context, &error);
- lm_message_unref (query);
- g_free (object_path);
- return;
- }
-
- gabble_svc_olpc_gadget_return_from_search_activities_by_participants (
- context, object_path);
-
- g_free (object_path);
- lm_message_unref (query);
-}
-#endif
-
static gboolean
send_presence_to_gadget (GabbleConnection *conn,
LmMessageSubType sub_type,
diff --git a/src/conn-olpc.h b/src/conn-olpc.h
index 24f53c4..7fe585b 100644
--- a/src/conn-olpc.h
+++ b/src/conn-olpc.h
@@ -72,6 +72,9 @@ gboolean add_buddies_to_view_from_node (GabbleConnection *conn,
GabbleOlpcView *view, LmMessageNode *node, const gchar *node_name,
TpHandle activity);
+gboolean add_activities_to_view_from_node (GabbleConnection *conn,
+ GabbleOlpcView *view, LmMessageNode *node);
+
void olpc_gadget_iface_init (gpointer g_iface, gpointer iface_data);
#endif /* __CONN_OLPC_H__ */
diff --git a/src/olpc-activity-view.c b/src/olpc-activity-view.c
new file mode 100644
index 0000000..43659ac
--- /dev/null
+++ b/src/olpc-activity-view.c
@@ -0,0 +1,473 @@
+/*
+ * olpc-activity-view.c - Source for GabbleOlpcActivityView
+ * 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-activity-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 "olpc-activity.h"
+#include "namespaces.h"
+#include "util.h"
+
+/* properties */
+enum
+{
+ /* org.laptop.Telepathy.Channel.Type.ActivityView D-Bus properties */
+ PROP_VIEW_PROPERTIES = 1,
+ PROP_PARTICIPANTS,
+
+ PROP_CHANNEL_TYPE,
+ PROP_CHANNEL_PROPERTIES,
+
+ LAST_PROPERTY
+};
+
+typedef struct _GabbleOlpcActivityViewPrivate GabbleOlpcActivityViewPrivate;
+struct _GabbleOlpcActivityViewPrivate
+{
+ GHashTable *properties;
+ TpHandleSet *participants;
+
+ gboolean dispose_has_run;
+};
+
+G_DEFINE_TYPE_WITH_CODE (
+ GabbleOlpcActivityView, gabble_olpc_activity_view, GABBLE_TYPE_OLPC_VIEW,
+ G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_OLPC_CHANNEL_TYPE_ACTIVITYVIEW,
+ NULL);
+ );
+
+#define GABBLE_OLPC_ACTIVITY_VIEW_GET_PRIVATE(obj) \
+ ((GabbleOlpcActivityViewPrivate *) obj->priv)
+
+
+static void
+gabble_olpc_activity_view_init (GabbleOlpcActivityView *self)
+{
+ GabbleOlpcActivityViewPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ GABBLE_TYPE_OLPC_ACTIVITY_VIEW, GabbleOlpcActivityViewPrivate);
+
+ self->priv = priv;
+
+ priv->dispose_has_run = FALSE;
+}
+
+static void
+gabble_olpc_activity_view_dispose (GObject *object)
+{
+ GabbleOlpcActivityView *self = GABBLE_OLPC_ACTIVITY_VIEW (object);
+ GabbleOlpcActivityViewPrivate *priv = GABBLE_OLPC_ACTIVITY_VIEW_GET_PRIVATE (self);
+
+ if (priv->dispose_has_run)
+ return;
+
+ priv->dispose_has_run = TRUE;
+
+ if (G_OBJECT_CLASS (gabble_olpc_activity_view_parent_class)->dispose)
+ G_OBJECT_CLASS (gabble_olpc_activity_view_parent_class)->dispose (object);
+}
+
+static void
+gabble_olpc_activity_view_finalize (GObject *object)
+{
+ GabbleOlpcActivityView *self = GABBLE_OLPC_ACTIVITY_VIEW (object);
+ GabbleOlpcActivityViewPrivate *priv = GABBLE_OLPC_ACTIVITY_VIEW_GET_PRIVATE (self);
+
+ g_hash_table_destroy (priv->properties);
+ tp_handle_set_destroy (priv->participants);
+
+ if (G_OBJECT_CLASS (gabble_olpc_activity_view_parent_class)->finalize)
+ G_OBJECT_CLASS (gabble_olpc_activity_view_parent_class)->finalize (object);
+}
+
+static void
+gabble_olpc_activity_view_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GabbleOlpcActivityView *self = GABBLE_OLPC_ACTIVITY_VIEW (object);
+ GabbleOlpcActivityViewPrivate *priv = GABBLE_OLPC_ACTIVITY_VIEW_GET_PRIVATE (self);
+
+ switch (property_id)
+ {
+ case PROP_CHANNEL_TYPE:
+ g_value_set_static_string (value,
+ GABBLE_IFACE_OLPC_CHANNEL_TYPE_ACTIVITYVIEW);
+ 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",
+ GABBLE_IFACE_OLPC_CHANNEL_TYPE_ACTIVITYVIEW, "Properties",
+ GABBLE_IFACE_OLPC_CHANNEL_TYPE_ACTIVITYVIEW, "Participants",
+ NULL));
+ break;
+ case PROP_VIEW_PROPERTIES:
+ g_value_set_boxed (value, priv->properties);
+ break;
+ case PROP_PARTICIPANTS:
+ g_value_take_boxed (value, tp_handle_set_to_array (priv->participants));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gabble_olpc_activity_view_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GabbleOlpcActivityView *self = GABBLE_OLPC_ACTIVITY_VIEW (object);
+ GabbleOlpcActivityViewPrivate *priv = GABBLE_OLPC_ACTIVITY_VIEW_GET_PRIVATE (self);
+
+ switch (property_id)
+ {
+ 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_VIEW_PROPERTIES:
+ priv->properties = g_value_dup_boxed (value);
+ break;
+ case PROP_PARTICIPANTS:
+ {
+ GabbleOlpcView *view = GABBLE_OLPC_VIEW (self);
+ GArray *tmp;
+ guint i;
+ TpHandleRepoIface *contact_repo;
+
+ contact_repo = tp_base_connection_get_handles (
+ TP_BASE_CONNECTION (view->conn), TP_HANDLE_TYPE_CONTACT);
+
+ tmp = g_value_get_boxed (value);
+ if (tmp == NULL)
+ break;
+
+ if (priv->participants != NULL)
+ tp_handle_set_destroy (priv->participants);
+
+ priv->participants = tp_handle_set_new (contact_repo);
+
+ for (i = 0; i < tmp->len; i++)
+ {
+ TpHandle handle = g_array_index (tmp, TpHandle, i);
+
+ tp_handle_set_add (priv->participants, handle);
+ }
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gabble_olpc_activity_view_constructor (GType type,
+ guint n_props,
+ GObjectConstructParam *props)
+{
+ GObject *obj;
+ GabbleOlpcView *view;
+ GabbleOlpcActivityViewPrivate *priv;
+ DBusGConnection *bus;
+ TpBaseConnection *conn;
+ TpHandleRepoIface *contact_handles;
+
+ obj = G_OBJECT_CLASS (gabble_olpc_activity_view_parent_class)->
+ constructor (type, n_props, props);
+
+ view = GABBLE_OLPC_VIEW (obj);
+
+ priv = GABBLE_OLPC_ACTIVITY_VIEW_GET_PRIVATE (GABBLE_OLPC_ACTIVITY_VIEW (obj));
+ conn = (TpBaseConnection *) view->conn;
+
+ bus = tp_get_bus ();
+ dbus_g_connection_register_g_object (bus, view->object_path, obj);
+
+ contact_handles = tp_base_connection_get_handles (conn,
+ TP_HANDLE_TYPE_CONTACT);
+
+ if (priv->properties == NULL)
+ {
+ priv->properties = g_hash_table_new (g_direct_hash, g_direct_equal);
+ }
+
+ if (priv->participants == NULL)
+ {
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ TP_BASE_CONNECTION (view->conn), TP_HANDLE_TYPE_CONTACT);
+
+ priv->participants = tp_handle_set_new (contact_repo);
+ }
+
+ return obj;
+}
+
+static LmMessage *
+gabble_olpc_activity_view_create_close_msg (GabbleOlpcView *view)
+{
+ gchar *id_str;
+ LmMessage *msg;
+
+ id_str = g_strdup_printf ("%u", view->id);
+
+ msg = lm_message_build (view->conn->olpc_gadget_activity,
+ LM_MESSAGE_TYPE_MESSAGE,
+ '(', "close", "",
+ '@', "xmlns", NS_OLPC_ACTIVITY,
+ '@', "id", id_str,
+ ')', NULL);
+
+ g_free (id_str);
+
+ return msg;
+}
+
+static LmHandlerResult
+activity_view_query_result_cb (GabbleConnection *conn,
+ LmMessage *sent_msg,
+ LmMessage *reply_msg,
+ GObject *_view,
+ gpointer user_data)
+{
+ LmMessageNode *view_node;
+ GabbleOlpcView *view = GABBLE_OLPC_VIEW (_view);
+
+ view_node = lm_message_node_get_child_with_namespace (reply_msg->node,
+ "view", NS_OLPC_ACTIVITY);
+ if (view_node == NULL)
+ return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+
+ /* FIXME: make sense to call this conn-olpc function ? */
+ add_activities_to_view_from_node (conn, view, view_node);
+
+ return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+}
+
+static gboolean
+gabble_olpc_activity_view_send_request (GabbleOlpcView *view,
+ GError **error)
+{
+ GabbleOlpcActivityView *self = GABBLE_OLPC_ACTIVITY_VIEW (view);
+ GabbleOlpcActivityViewPrivate *priv = \
+ GABBLE_OLPC_ACTIVITY_VIEW_GET_PRIVATE (self);
+ LmMessage *query;
+ gchar *max_str, *id_str;
+
+ 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 */
+ if (g_hash_table_size (priv->properties) != 0)
+ {
+ LmMessageNode *properties_node;
+
+ query = lm_message_build_with_sub_type (view->conn->olpc_gadget_activity,
+ LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
+ '(', "view", "",
+ '@', "xmlns", NS_OLPC_ACTIVITY,
+ '@', "id", id_str,
+ '(', "activity", "",
+ '(', "properties", "",
+ '*', &properties_node,
+ '@', "xmlns", NS_OLPC_ACTIVITY_PROPS,
+ ')',
+ ')',
+ ')',
+ NULL);
+
+ lm_message_node_add_children_from_properties (properties_node,
+ priv->properties, "property");
+ }
+ else if (tp_handle_set_size (priv->participants) != 0)
+ {
+ LmMessageNode *activity_node;
+ GArray *participants;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ TP_BASE_CONNECTION (view->conn), TP_HANDLE_TYPE_CONTACT);
+ guint i;
+
+ query = lm_message_build_with_sub_type (view->conn->olpc_gadget_activity,
+ LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
+ '(', "view", "",
+ '@', "xmlns", NS_OLPC_ACTIVITY,
+ '@', "id", id_str,
+ '(', "activity", "",
+ '*', &activity_node,
+ ')',
+ ')',
+ NULL);
+
+ /* For easier iteration */
+ participants = tp_handle_set_to_array (priv->participants);
+
+ for (i = 0; i < participants->len; i++)
+ {
+ LmMessageNode *buddy;
+ const gchar *jid;
+
+ jid = tp_handle_inspect (contact_repo,
+ g_array_index (participants, TpHandle, i));
+
+ buddy = lm_message_node_add_child (activity_node, "buddy", "");
+ lm_message_node_set_attribute (buddy, "jid", jid);
+ }
+ }
+ else
+ {
+ query = lm_message_build_with_sub_type (view->conn->olpc_gadget_activity,
+ LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
+ '(', "view", "",
+ '@', "xmlns", NS_OLPC_ACTIVITY,
+ '@', "id", id_str,
+ '(', "random", "",
+ '@', "max", max_str,
+ ')',
+ ')',
+ NULL);
+ }
+
+ g_free (max_str);
+ g_free (id_str);
+
+ if (!_gabble_connection_send_with_reply (view->conn, query,
+ activity_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 activity search query to server");
+ lm_message_unref (query);
+ return FALSE;
+ }
+
+ lm_message_unref (query);
+ return TRUE;
+}
+
+static void
+gabble_olpc_activity_view_class_init (
+ GabbleOlpcActivityViewClass *gabble_olpc_activity_view_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (gabble_olpc_activity_view_class);
+ GabbleOlpcViewClass *view_class = GABBLE_OLPC_VIEW_CLASS (
+ gabble_olpc_activity_view_class);
+ GParamSpec *param_spec;
+ static TpDBusPropertiesMixinPropImpl activity_view_props[] = {
+ { "Properties", "view-properties", NULL },
+ { "Participants", "participants", NULL },
+ { NULL }
+ };
+ static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
+ { GABBLE_IFACE_OLPC_CHANNEL_TYPE_ACTIVITYVIEW,
+ tp_dbus_properties_mixin_getter_gobject_properties,
+ NULL,
+ activity_view_props,
+ },
+ { NULL }
+ };
+
+ object_class->get_property = gabble_olpc_activity_view_get_property;
+ object_class->set_property = gabble_olpc_activity_view_set_property;
+ object_class->constructor = gabble_olpc_activity_view_constructor;
+
+ g_type_class_add_private (gabble_olpc_activity_view_class,
+ sizeof (GabbleOlpcActivityViewPrivate));
+
+ object_class->dispose = gabble_olpc_activity_view_dispose;
+ object_class->finalize = gabble_olpc_activity_view_finalize;
+
+ view_class->create_close_msg = gabble_olpc_activity_view_create_close_msg;
+ view_class->send_request = gabble_olpc_activity_view_send_request;
+
+ g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
+ "channel-type");
+ g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES,
+ "channel-properties");
+
+ param_spec = g_param_spec_boxed ("view-properties", "View's search properties",
+ "The activity 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_boxed ("participants", "View's search participants",
+ "The activity participants Gadget should look for",
+ GABBLE_ARRAY_TYPE_HANDLE,
+ 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_PARTICIPANTS,
+ param_spec);
+
+ gabble_olpc_activity_view_class->dbus_props_class.interfaces = prop_interfaces;
+ tp_dbus_properties_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (GabbleOlpcActivityViewClass, dbus_props_class));
+}
+
+GabbleOlpcActivityView *
+gabble_olpc_activity_view_new (GabbleConnection *conn,
+ const gchar *object_path,
+ guint id,
+ guint max_size,
+ GHashTable *properties,
+ const GArray *participants)
+
+{
+ return g_object_new (GABBLE_TYPE_OLPC_ACTIVITY_VIEW,
+ "object-path", object_path,
+ "connection", conn,
+ "id", id,
+ "max-size", max_size,
+ "view-properties", properties,
+ "participants", participants,
+ NULL);
+}
diff --git a/src/olpc-activity-view.h b/src/olpc-activity-view.h
new file mode 100644
index 0000000..a5d3ccb
--- /dev/null
+++ b/src/olpc-activity-view.h
@@ -0,0 +1,71 @@
+/*
+ * olpc-activity-view.h - Header for GabbleOlpcActivityView
+ * 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_ACTIVITY_VIEW_H__
+#define __GABBLE_OLPC_ACTIVITY_VIEW_H__
+
+#include <glib-object.h>
+
+#include <telepathy-glib/enums.h>
+#include <telepathy-glib/handle-repo.h>
+
+#include "olpc-view.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GabbleOlpcActivityView GabbleOlpcActivityView;
+typedef struct _GabbleOlpcActivityViewClass GabbleOlpcActivityViewClass;
+
+struct _GabbleOlpcActivityViewClass {
+ GabbleOlpcViewClass parent_class;
+
+ TpDBusPropertiesMixinClass dbus_props_class;
+};
+
+struct _GabbleOlpcActivityView {
+ GabbleOlpcView parent;
+
+ gpointer priv;
+};
+
+GType gabble_olpc_activity_view_get_type (void);
+
+/* TYPE MACROS */
+#define GABBLE_TYPE_OLPC_ACTIVITY_VIEW \
+ (gabble_olpc_activity_view_get_type ())
+#define GABBLE_OLPC_ACTIVITY_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_OLPC_ACTIVITY_VIEW, GabbleOlpcActivityView))
+#define GABBLE_OLPC_ACTIVITY_VIEW_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_OLPC_ACTIVITY_VIEW,\
+ GabbleOlpcActivityViewClass))
+#define GABBLE_IS_OLPC_ACTIVITY_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_OLPC_ACTIVITY_VIEW))
+#define GABBLE_IS_OLPC_ACTIVITY_VIEW_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_OLPC_ACTIVITY_VIEW))
+#define GABBLE_OLPC_ACTIVITY_VIEW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_OLPC_ACTIVITY_VIEW,\
+ GabbleOlpcActivityViewClass))
+
+GabbleOlpcActivityView * gabble_olpc_activity_view_new (GabbleConnection *conn,
+ const gchar *object_path, guint id, guint max_size, GHashTable *properties,
+ const GArray *participants);
+
+G_END_DECLS
+
+#endif /* #ifndef __GABBLE_OLPC_ACTIVITY_VIEW_H__ */
diff --git a/src/olpc-gadget-manager.c b/src/olpc-gadget-manager.c
index a3cfab4..18fbd13 100644
--- a/src/olpc-gadget-manager.c
+++ b/src/olpc-gadget-manager.c
@@ -39,6 +39,8 @@
#include "connection.h"
#include "debug.h"
#include "namespaces.h"
+#include "olpc-activity.h"
+#include "olpc-activity-view.h"
#include "olpc-buddy-view.h"
#include "util.h"
@@ -235,16 +237,25 @@ static const gchar * const olpc_gadget_channel_buddy_view_allowed_properties[] =
NULL
};
+static const gchar * const olpc_gadget_channel_activity_view_allowed_properties[] =
+{
+ GABBLE_IFACE_OLPC_CHANNEL_INTERFACE_VIEW ".MaxSize",
+ GABBLE_IFACE_OLPC_CHANNEL_TYPE_ACTIVITYVIEW ".Properties",
+ GABBLE_IFACE_OLPC_CHANNEL_TYPE_ACTIVITYVIEW ".Participants",
+ NULL
+};
static void
gabble_olpc_gadget_manager_foreach_channel_class (TpChannelManager *manager,
TpChannelManagerChannelClassFunc func,
gpointer user_data)
{
- GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, (GDestroyNotify) tp_g_value_slice_free);
+ GHashTable *table;
GValue *value;
+ /* BuddyView */
+ table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
value = tp_g_value_slice_new (G_TYPE_STRING);
g_value_set_static_string (value, GABBLE_IFACE_OLPC_CHANNEL_TYPE_BUDDYVIEW);
g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType", value);
@@ -253,6 +264,18 @@ gabble_olpc_gadget_manager_foreach_channel_class (TpChannelManager *manager,
user_data);
g_hash_table_destroy (table);
+
+ /* ActivityView */
+ table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
+ value = tp_g_value_slice_new (G_TYPE_STRING);
+ g_value_set_static_string (value, GABBLE_IFACE_OLPC_CHANNEL_TYPE_ACTIVITYVIEW);
+ g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType", value);
+
+ func (manager, table, olpc_gadget_channel_activity_view_allowed_properties,
+ user_data);
+
+ g_hash_table_destroy (table);
}
static gboolean
@@ -346,6 +369,74 @@ create_buddy_view_channel (GabbleOlpcGadgetManager *self,
return channel;
}
+static GabbleOlpcView *
+create_activity_view_channel (GabbleOlpcGadgetManager *self,
+ GHashTable *request_properties,
+ GError **error)
+{
+ TpBaseConnection *conn = (TpBaseConnection *) self->priv->conn;
+ GabbleOlpcView *channel;
+ guint max_size;
+ gboolean valid;
+ gchar *object_path;
+ GHashTable *properties;
+ GArray *participants;
+
+ /* TODO: check if Gadget is available */
+
+ if ((tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandleType", NULL) != 0) ||
+ (tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandle", NULL) != 0))
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ "Views channels can't have a target handle");
+ return NULL;
+ }
+
+ if (tp_channel_manager_asv_has_unknown_properties (request_properties,
+ olpc_gadget_channel_view_fixed_properties,
+ olpc_gadget_channel_activity_view_allowed_properties,
+ error))
+ return NULL;
+
+ max_size = tp_asv_get_uint32 (request_properties,
+ GABBLE_IFACE_OLPC_CHANNEL_INTERFACE_VIEW ".MaxSize", &valid);
+ if (!valid)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "MaxSize property is mandatory");
+ return NULL;
+ }
+
+ if (max_size == 0)
+ {
+
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "max have to be greater than 0");
+ return NULL;
+ }
+
+ properties = tp_asv_get_boxed (request_properties,
+ GABBLE_IFACE_OLPC_CHANNEL_TYPE_ACTIVITYVIEW ".Properties",
+ TP_HASH_TYPE_STRING_VARIANT_MAP);
+
+ participants = tp_asv_get_boxed (request_properties,
+ GABBLE_IFACE_OLPC_CHANNEL_TYPE_ACTIVITYVIEW ".Participants",
+ GABBLE_ARRAY_TYPE_HANDLE);
+
+ object_path = g_strdup_printf ("%s/OlpcActivityViewChannel%u",
+ conn->object_path, self->priv->next_view_number++);
+
+ channel = GABBLE_OLPC_VIEW (gabble_olpc_activity_view_new (self->priv->conn,
+ object_path, self->priv->next_view_number, max_size, properties,
+ participants));
+
+ g_free (object_path);
+
+ return channel;
+}
+
static gboolean
gabble_olpc_gadget_manager_handle_request (TpChannelManager *manager,
gpointer request_token,
@@ -362,6 +453,12 @@ gabble_olpc_gadget_manager_handle_request (TpChannelManager *manager,
{
channel = create_buddy_view_channel (self, request_properties, &error);
}
+ else if (!tp_strdiff (tp_asv_get_string (request_properties,
+ TP_IFACE_CHANNEL ".ChannelType"),
+ GABBLE_IFACE_OLPC_CHANNEL_TYPE_ACTIVITYVIEW))
+ {
+ channel = create_activity_view_channel (self, request_properties, &error);
+ }
else
{
return FALSE;
@@ -468,3 +565,81 @@ gabble_olpc_gadget_manager_get_view (GabbleOlpcGadgetManager *self,
{
return g_hash_table_lookup (self->priv->channels, GUINT_TO_POINTER (id));
}
+
+struct find_activities_of_buddy_ctx
+{
+ TpHandle buddy;
+ GHashTable *activities;
+};
+
+static void
+find_activities_of_buddy (TpHandle contact,
+ GabbleOlpcView *view,
+ struct find_activities_of_buddy_ctx *ctx)
+{
+ GPtrArray *act;
+ guint i;
+
+ act = gabble_olpc_view_get_buddy_activities (view, ctx->buddy);
+
+ for (i = 0; i < act->len; i++)
+ {
+ GabbleOlpcActivity *activity;
+
+ activity = g_ptr_array_index (act, i);
+ g_hash_table_insert (ctx->activities, GUINT_TO_POINTER (activity->room),
+ activity);
+ }
+
+ g_ptr_array_free (act, TRUE);
+}
+
+static void
+copy_activity_to_array (TpHandle room,
+ GabbleOlpcActivity *activity,
+ GPtrArray *activities)
+{
+ GValue gvalue = { 0 };
+
+ if (activity->id == NULL)
+ {
+ DEBUG ("... activity #%u has no ID, skipping", room);
+ return;
+ }
+
+ 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);
+ DEBUG ("... activity #%u (ID %s)",
+ activity->room, activity->id);
+ g_ptr_array_add (activities, g_value_get_boxed (&gvalue));
+}
+
+GPtrArray *
+gabble_olpc_gadget_manager_find_buddy_activities (GabbleOlpcGadgetManager *self,
+ TpHandle contact)
+{
+ GPtrArray *result;
+ struct find_activities_of_buddy_ctx ctx;
+
+ result = g_ptr_array_new ();
+
+ /* We use a hash table first so we won't add twice the same activity */
+ ctx.activities = g_hash_table_new (g_direct_hash, g_direct_equal);
+ ctx.buddy = contact;
+
+ g_hash_table_foreach (self->priv->channels, (GHFunc) find_activities_of_buddy,
+ &ctx);
+
+ /* Now compute the result array using the hash table */
+ g_hash_table_foreach (ctx.activities, (GHFunc) copy_activity_to_array,
+ result);
+
+ g_hash_table_destroy (ctx.activities);
+
+ return result;
+}
diff --git a/src/olpc-gadget-manager.h b/src/olpc-gadget-manager.h
index c508c11..4b9df38 100644
--- a/src/olpc-gadget-manager.h
+++ b/src/olpc-gadget-manager.h
@@ -59,12 +59,16 @@ GType gabble_olpc_gadget_manager_get_type (void);
(G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_OLPC_GADGET_MANAGER,\
GabbleOlpcGadgetManagerClass))
+/* TODO: remove the _from_views */
GHashTable * gabble_olpc_gadget_manager_find_buddy_properties_from_views (
GabbleOlpcGadgetManager *self, TpHandle buddy);
GabbleOlpcView * gabble_olpc_gadget_manager_get_view (
GabbleOlpcGadgetManager *self, guint id);
+GPtrArray * gabble_olpc_gadget_manager_find_buddy_activities (
+ GabbleOlpcGadgetManager *self, TpHandle contact);
+
G_END_DECLS
#endif
diff --git a/tests/twisted/olpc/olpc-activity-search.py b/tests/twisted/olpc/olpc-activity-search.py
index ba865cc..51c25be 100644
--- a/tests/twisted/olpc/olpc-activity-search.py
+++ b/tests/twisted/olpc/olpc-activity-search.py
@@ -2,10 +2,6 @@
test OLPC search activity
"""
-print "FIXME: olpc/olpc-activity-search.py disabled during requestotronification of the view API"
-# exiting 77 causes automake to consider the test to have been skipped
-raise SystemExit(77)
-
import dbus
from servicetest import call_async, EventPattern
@@ -31,11 +27,19 @@ NS_DISCO_ITEMS = "http://jabber.org/protocol/disco#items"
NS_AMP = "http://jabber.org/protocol/amp"
NS_STANZA = "urn:ietf:params:xml:ns:xmpp-stanzas"
+tp_name_prefix = 'org.freedesktop.Telepathy'
+olpc_name_prefix = 'org.laptop.Telepathy'
+
def check_view(view, conn, activities, buddies):
- act = view.GetActivities()
+ act = view.Get(olpc_name_prefix + '.Channel.Interface.View',
+ 'Activities',
+ dbus_interface='org.freedesktop.DBus.Properties')
+
assert sorted(act) == sorted(activities)
- handles = view.GetBuddies()
+ handles = view.Get(olpc_name_prefix + '.Channel.Interface.View',
+ 'Buddies',
+ dbus_interface='org.freedesktop.DBus.Properties')
assert sorted(conn.InspectHandles(1, handles)) == sorted(buddies)
def test(q, bus, conn, stream):
@@ -56,18 +60,60 @@ def test(q, bus, conn, stream):
'org.laptop.Telepathy.ActivityProperties')
buddy_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo')
gadget_iface = dbus.Interface(conn, 'org.laptop.Telepathy.Gadget')
+ requests_iface = dbus.Interface(conn, tp_name_prefix + '.Connection.Interface.Requests')
sync_stream(q, stream)
+ # TODO: change view var name
+
+ # check if we can request Activity views
+ properties = conn.GetAll(
+ 'org.freedesktop.Telepathy.Connection.Interface.Requests',
+ dbus_interface='org.freedesktop.DBus.Properties')
+
+ assert ({tp_name_prefix + '.Channel.ChannelType':
+ olpc_name_prefix + '.Channel.Type.ActivityView'},
+
+ [olpc_name_prefix + '.Channel.Interface.View.MaxSize',
+ olpc_name_prefix + '.Channel.Type.ActivityView.Properties',
+ olpc_name_prefix + '.Channel.Type.ActivityView.Participants'],
+ ) in properties.get('RequestableChannelClasses'),\
+ properties['RequestableChannelClasses']
+
# request 3 random activities (view 0)
- view_path = request_random_activity_view(q, stream, conn, 3, '0',
+ view_path = request_random_activity_view(q, stream, conn, 3, '1',
[('activity1', 'room1 at conference.localhost',
{'color': ('str', '#005FE4,#00A0FF')},
[('lucien at localhost', {'color': ('str', '#AABBCC,#CCBBAA')}),
('jean at localhost', {})]),])
view0 = bus.get_object(conn.bus_name, view_path)
- view0_iface = dbus.Interface(view0, 'org.laptop.Telepathy.View')
+
+ # check org.freedesktop.Telepathy.Channel D-Bus properties
+ props = view0.GetAll(
+ 'org.freedesktop.Telepathy.Channel',
+ dbus_interface='org.freedesktop.DBus.Properties')
+
+ assert props['ChannelType'] == 'org.laptop.Telepathy.Channel.Type.ActivityView'
+ assert 'org.laptop.Telepathy.Channel.Interface.View' in props['Interfaces']
+ assert props['TargetHandle'] == 0
+ assert props['TargetID'] == ''
+ assert props['TargetHandleType'] == 0
+
+ # check org.laptop.Telepathy.Channel.Interface.View D-Bus properties
+ props = view0.GetAll(
+ 'org.laptop.Telepathy.Channel.Interface.View',
+ dbus_interface='org.freedesktop.DBus.Properties')
+
+ assert props['MaxSize'] == 3
+
+ # check org.laptop.Telepathy.Channel.Type.ActivityView D-Bus properties
+ props = view0.GetAll(
+ 'org.laptop.Telepathy.Channel.Type.ActivityView',
+ dbus_interface='org.freedesktop.DBus.Properties')
+
+ assert props['Properties'] == {}
+ assert props['Participants'] == []
## Current views ##
# view 0: activity 1 (with: Lucien, Jean)
@@ -82,7 +128,7 @@ def test(q, bus, conn, stream):
assert props == {'color': '#005FE4,#00A0FF'}
q.expect('dbus-signal', signal='ActivitiesChanged',
- interface='org.laptop.Telepathy.View',
+ interface='org.laptop.Telepathy.Channel.Interface.View',
args=[[('activity1', handles['room1'])], []])
# participants are added to view
@@ -99,7 +145,7 @@ def test(q, bus, conn, stream):
args=[handles['jean'], [('activity1', handles['room1'])]]))
# check activities and buddies in view
- check_view(view0_iface, conn, [('activity1', handles['room1'])],
+ check_view(view0, conn, [('activity1', handles['room1'])],
['lucien at localhost', 'jean at localhost'])
# we can now get activity properties
@@ -122,13 +168,19 @@ def test(q, bus, conn, stream):
value=([('activity1', handles['room1'])],))
# activity search by properties (view 1)
- props = {'color': '#AABBCC,#001122'}
- call_async(q, gadget_iface, 'SearchActivitiesByProperties', props)
+ props = dbus.Dictionary({'color': '#AABBCC,#001122'}, signature='sv')
+
+ call_async(q, requests_iface, 'CreateChannel',
+ { 'org.freedesktop.Telepathy.Channel.ChannelType':
+ 'org.laptop.Telepathy.Channel.Type.ActivityView',
+ 'org.laptop.Telepathy.Channel.Interface.View.MaxSize': 5,
+ 'org.laptop.Telepathy.Channel.Type.ActivityView.Properties': props,
+ })
iq_event, return_event = q.expect_many(
EventPattern('stream-iq', to='gadget.localhost',
query_ns=NS_OLPC_ACTIVITY),
- EventPattern('dbus-return', method='SearchActivitiesByProperties'))
+ EventPattern('dbus-return', method='CreateChannel'))
properties_nodes = xpath.queryForNodes('/iq/view/activity/properties',
iq_event.stanza)
@@ -137,7 +189,7 @@ def test(q, bus, conn, stream):
view = iq_event.stanza.firstChildElement()
assert view.name == 'view'
- assert view['id'] == '1'
+ assert view['id'] == '2'
send_reply_to_activity_view_request(stream, iq_event.stanza,
[('activity2', 'room2 at conference.localhost',
@@ -149,7 +201,11 @@ def test(q, bus, conn, stream):
view_path = return_event.value[0]
view1 = bus.get_object(conn.bus_name, view_path)
- view1_iface = dbus.Interface(view1, 'org.laptop.Telepathy.View')
+
+ props = return_event.value[1]
+ assert props['org.laptop.Telepathy.Channel.Type.ActivityView.Properties'] == \
+ {'color': '#AABBCC,#001122'}
+ assert props['org.laptop.Telepathy.Channel.Type.ActivityView.Participants'] == []
event = q.expect('dbus-signal', signal='ActivityPropertiesChanged')
handles['room2'], props = event.args
@@ -157,27 +213,38 @@ def test(q, bus, conn, stream):
assert props == {'color': '#AABBCC,#001122'}
q.expect('dbus-signal', signal='ActivitiesChanged',
- interface='org.laptop.Telepathy.View',
+ interface='org.laptop.Telepathy.Channel.Interface.View',
args=[[('activity2', handles['room2'])], []])
- act = view1.GetActivities()
+ act = view1.Get(olpc_name_prefix + '.Channel.Interface.View',
+ 'Activities',
+ dbus_interface='org.freedesktop.DBus.Properties')
assert sorted(act) == [('activity2', handles['room2'])]
- assert view1_iface.GetBuddies() == []
+ buddies = view1.Get(olpc_name_prefix + '.Channel.Interface.View',
+ 'Buddies',
+ dbus_interface='org.freedesktop.DBus.Properties')
+ assert buddies == []
# activity search by participants (view 2)
participants = conn.RequestHandles(1, ["alice at localhost", "bob at localhost"])
- call_async(q, gadget_iface, 'SearchActivitiesByParticipants', participants)
+
+ call_async(q, requests_iface, 'CreateChannel',
+ { 'org.freedesktop.Telepathy.Channel.ChannelType':
+ 'org.laptop.Telepathy.Channel.Type.ActivityView',
+ 'org.laptop.Telepathy.Channel.Interface.View.MaxSize': 5,
+ 'org.laptop.Telepathy.Channel.Type.ActivityView.Participants': participants,
+ })
iq_event, return_event = q.expect_many(
EventPattern('stream-iq', to='gadget.localhost',
query_ns=NS_OLPC_ACTIVITY),
- EventPattern('dbus-return', method='SearchActivitiesByParticipants'))
+ EventPattern('dbus-return', method='CreateChannel'))
buddies = xpath.queryForNodes('/iq/view/activity/buddy', iq_event.stanza)
view = iq_event.stanza.firstChildElement()
assert view.name == 'view'
- assert view['id'] == '2'
+ assert view['id'] == '3'
assert len(buddies) == 2
assert (buddies[0]['jid'], buddies[1]['jid']) == ('alice at localhost',
'bob at localhost')
@@ -193,7 +260,6 @@ def test(q, bus, conn, stream):
view_path = return_event.value[0]
view2 = bus.get_object(conn.bus_name, view_path)
- view2_iface = dbus.Interface(view2, 'org.laptop.Telepathy.View')
event = q.expect('dbus-signal', signal='ActivityPropertiesChanged')
handles['room3'], props = event.args
@@ -201,17 +267,19 @@ def test(q, bus, conn, stream):
assert props == {'color': '#AABBCC,#001122'}
q.expect('dbus-signal', signal='ActivitiesChanged',
- interface='org.laptop.Telepathy.View',
+ interface='org.laptop.Telepathy.Channel.Interface.View',
args=[[('activity3', handles['room3'])], []])
- act = view2.GetActivities()
+ act = view2.Get(olpc_name_prefix + '.Channel.Interface.View',
+ 'Activities',
+ dbus_interface='org.freedesktop.DBus.Properties')
assert sorted(act) == [('activity3', handles['room3'])]
# add activity 4 to view 0
message = create_gadget_message('alice at localhost')
added = message.addElement((NS_OLPC_ACTIVITY, 'added'))
- added['id'] = '0'
+ added['id'] = '1'
activity = added.addElement((None, 'activity'))
activity['id'] = 'activity4'
activity['room'] = 'room4 at conference.localhost'
@@ -238,7 +306,7 @@ def test(q, bus, conn, stream):
# activity is added
event = q.expect('dbus-signal', signal='ActivitiesChanged',
- interface='org.laptop.Telepathy.View')
+ interface='org.laptop.Telepathy.Channel.Interface.View')
added, removed = event.args
assert len(added) == 1
id, handles['room4'] = added[0]
@@ -261,7 +329,7 @@ def test(q, bus, conn, stream):
('activity4', handles['room4'])]]))
# check activities and buddies in view
- check_view(view0_iface, conn, [
+ check_view(view0, conn, [
('activity1', handles['room1']), ('activity4', handles['room4'])],
['fernand at localhost', 'lucien at localhost', 'jean at localhost'])
@@ -275,7 +343,7 @@ def test(q, bus, conn, stream):
change = message.addElement((NS_OLPC_ACTIVITY, 'change'))
change['activity'] = 'activity1'
change['room'] = 'room1 at conference.localhost'
- change['id'] = '0'
+ change['id'] = '1'
properties = change.addElement((NS_OLPC_ACTIVITY_PROPS, 'properties'))
for node in properties_to_xml({'tags': ('str', 'game'), \
'color': ('str', '#AABBAA,#BBAABB')}):
@@ -295,7 +363,7 @@ def test(q, bus, conn, stream):
activity = message.addElement((NS_OLPC_ACTIVITY, 'activity'))
activity['room'] = 'room1 at conference.localhost'
- activity['view'] = '0'
+ activity['view'] = '1'
joined = activity.addElement((None, 'joined'))
joined['jid'] = 'marcel at localhost'
properties = joined.addElement((NS_OLPC_BUDDY_PROPS, "properties"))
@@ -322,7 +390,7 @@ def test(q, bus, conn, stream):
args=[handles['marcel'], [('activity1', handles['room1'])]]))
# check activities and buddies in view
- check_view(view0_iface, conn, [
+ check_view(view0, conn, [
('activity1', handles['room1']),('activity4', handles['room4'])],
['fernand at localhost', 'lucien at localhost', 'jean at localhost',
'marcel at localhost'])
@@ -332,7 +400,7 @@ def test(q, bus, conn, stream):
activity = message.addElement((NS_OLPC_ACTIVITY, 'activity'))
activity['room'] = 'room1 at conference.localhost'
- activity['view'] = '0'
+ activity['view'] = '1'
left = activity.addElement((None, 'left'))
left['jid'] = 'marcel at localhost'
@@ -351,7 +419,7 @@ def test(q, bus, conn, stream):
args=[handles['marcel'], []]))
# check activities and buddies in view
- check_view(view0_iface, conn, [
+ check_view(view0, conn, [
('activity1', handles['room1']),('activity4', handles['room4'])],
['fernand at localhost', 'lucien at localhost', 'jean at localhost'])
@@ -360,7 +428,7 @@ def test(q, bus, conn, stream):
activity = message.addElement((NS_OLPC_ACTIVITY, 'activity'))
activity['room'] = 'room1 at conference.localhost'
- activity['view'] = '0'
+ activity['view'] = '1'
left = activity.addElement((None, 'left'))
left['jid'] = 'jean at localhost'
@@ -376,7 +444,7 @@ def test(q, bus, conn, stream):
args=[handles['jean'], [('activity4', handles['room4'])]])
# Jean wasn't removed from the view as he is still in activity 4
- check_view(view0_iface, conn, [
+ check_view(view0, conn, [
('activity1', handles['room1']),('activity4', handles['room4'])],
['fernand at localhost', 'lucien at localhost', 'jean at localhost'])
@@ -384,7 +452,7 @@ def test(q, bus, conn, stream):
message = create_gadget_message('alice at localhost')
removed = message.addElement((NS_OLPC_ACTIVITY, 'removed'))
- removed['id'] = '0'
+ removed['id'] = '1'
activity = removed.addElement((None, 'activity'))
activity['id'] = 'activity1'
activity['room'] = 'room1 at conference.localhost'
@@ -402,19 +470,19 @@ def test(q, bus, conn, stream):
args=[[], [handles['lucien']]]),
# activity is removed from the view
EventPattern('dbus-signal', signal='ActivitiesChanged',
- interface='org.laptop.Telepathy.View',
+ interface='org.laptop.Telepathy.Channel.Interface.View',
args=[[], [('activity1', handles['room1'])]]),
EventPattern('dbus-signal', signal='ActivitiesChanged',
interface='org.laptop.Telepathy.BuddyInfo',
args=[handles['lucien'], []]))
# check activities and buddies in view
- check_view(view0_iface, conn, [
+ check_view(view0, conn, [
('activity4', handles['room4'])],
['fernand at localhost', 'jean at localhost'])
# close view 0
- call_async(q, view0_iface, 'Close')
+ call_async(q, view0, 'Close')
event_msg, _, _, _ = q.expect_many(
EventPattern('stream-message', to='gadget.localhost'),
EventPattern('dbus-return', method='Close'),
@@ -428,13 +496,13 @@ def test(q, bus, conn, stream):
close = xpath.queryForNodes('/message/close', event_msg.stanza)
assert len(close) == 1
- assert close[0]['id'] == '0'
+ assert close[0]['id'] == '1'
# close view 1
- close_view(q, view1_iface, '1')
+ close_view(q, view1, '2')
# close view 2
- close_view(q, view2_iface, '2')
+ close_view(q, view2, '3')
if __name__ == '__main__':
exec_test(test)
diff --git a/tests/twisted/olpc/util.py b/tests/twisted/olpc/util.py
index 949433a..eafdb84 100644
--- a/tests/twisted/olpc/util.py
+++ b/tests/twisted/olpc/util.py
@@ -183,14 +183,18 @@ def send_reply_to_activity_view_request(stream, stanza, activities):
stream.send(reply)
def request_random_activity_view(q, stream, conn, max, id, activities):
- gadget_iface = dbus.Interface(conn, 'org.laptop.Telepathy.Gadget')
+ requests_iface = dbus.Interface(conn, 'org.freedesktop.Telepathy.Connection.Interface.Requests')
- call_async(q, gadget_iface, 'RequestRandomActivities', max)
+ call_async(q, requests_iface, 'CreateChannel',
+ { 'org.freedesktop.Telepathy.Channel.ChannelType':
+ 'org.laptop.Telepathy.Channel.Type.ActivityView',
+ 'org.laptop.Telepathy.Channel.Interface.View.MaxSize': max
+ })
iq_event, return_event = q.expect_many(
EventPattern('stream-iq', to='gadget.localhost',
query_ns=NS_OLPC_ACTIVITY),
- EventPattern('dbus-return', method='RequestRandomActivities'))
+ EventPattern('dbus-return', method='CreateChannel'))
view = iq_event.stanza.firstChildElement()
assert view.name == 'view'
@@ -201,6 +205,10 @@ def request_random_activity_view(q, stream, conn, max, id, activities):
send_reply_to_activity_view_request(stream, iq_event.stanza, activities)
+ props = return_event.value[1]
+ assert props['org.laptop.Telepathy.Channel.Type.ActivityView.Properties'] == {}
+ assert props['org.laptop.Telepathy.Channel.Type.ActivityView.Participants'] == []
+
return return_event.value[0]
def close_view(q, view, id):
--
1.5.6.5
More information about the Telepathy-commits
mailing list