Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/sugar/activity/activity.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/sugar/activity/activity.py')
-rw-r--r--src/sugar/activity/activity.py138
1 files changed, 112 insertions, 26 deletions
diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py
index 7c797e4..c534d75 100644
--- a/src/sugar/activity/activity.py
+++ b/src/sugar/activity/activity.py
@@ -52,15 +52,25 @@ import logging
import os
import time
from hashlib import sha1
-import gconf
+from functools import partial
+import gconf
import gtk
import gobject
import dbus
import dbus.service
+from dbus import PROPERTIES_IFACE
import cjson
+from telepathy.server import DBusProperties
+from telepathy.interfaces import CONNECTION, \
+ CHANNEL, \
+ CHANNEL_TYPE_TEXT, \
+ CLIENT, \
+ CLIENT_HANDLER
+from telepathy.constants import CONNECTION_HANDLE_TYPE_CONTACT
from sugar import util
+from sugar import dispatch
from sugar.presence import presenceservice
from sugar.activity.activityservice import ActivityService
from sugar.activity.namingalert import NamingAlert
@@ -88,6 +98,7 @@ J_DBUS_SERVICE = 'org.laptop.Journal'
J_DBUS_PATH = '/org/laptop/Journal'
J_DBUS_INTERFACE = 'org.laptop.Journal'
+CONN_INTERFACE_ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties'
class _ActivitySession(gobject.GObject):
@@ -300,10 +311,50 @@ class Activity(Window, gtk.Container):
if self._jobject.metadata.has_key('share-scope'):
share_scope = self._jobject.metadata['share-scope']
+ self.shared_activity = None
+ self._join_id = None
+
+ if handle.handle_invite:
+ wait_loop = gobject.MainLoop()
+ self._client_handler = _ClientHandler(
+ self.get_bundle_id(),
+ partial(self.__got_channel_cb, wait_loop))
+ # The current API requires that self.shared_activity is set before
+ # exiting from __init__, so we wait until we have got the shared
+ # activity.
+ wait_loop.run()
+ else:
+ pservice = presenceservice.get_instance()
+ mesh_instance = pservice.get_activity(self._activity_id,
+ warn_if_none=False)
+ self._set_up_sharing(mesh_instance, share_scope)
+
+ if handle.object_id is None and create_jobject:
+ logging.debug('Creating a jobject.')
+ self._jobject = datastore.create()
+ title = _('%s Activity') % get_bundle_name()
+ self._jobject.metadata['title'] = title
+ self.set_title(self._jobject.metadata['title'])
+ self._jobject.metadata['title_set_by_user'] = '0'
+ self._jobject.metadata['activity'] = self.get_bundle_id()
+ self._jobject.metadata['activity_id'] = self.get_id()
+ self._jobject.metadata['keep'] = '0'
+ self._jobject.metadata['preview'] = ''
+ self._jobject.metadata['share-scope'] = SCOPE_PRIVATE
+ if self.shared_activity is not None:
+ icon_color = self.shared_activity.props.color
+ else:
+ client = gconf.client_get_default()
+ icon_color = client.get_string('/desktop/sugar/user/color')
+ self._jobject.metadata['icon-color'] = icon_color
+
+ self._jobject.file_path = ''
+ # Cannot call datastore.write async for creates:
+ # https://dev.laptop.org/ticket/3071
+ datastore.write(self._jobject)
+
+ def _set_up_sharing(self, mesh_instance, share_scope):
# handle activity share/join
- pservice = presenceservice.get_instance()
- mesh_instance = pservice.get_activity(self._activity_id,
- warn_if_none=False)
logging.debug("*** Act %s, mesh instance %r, scope %s",
self._activity_id, mesh_instance, share_scope)
if mesh_instance is not None:
@@ -331,29 +382,19 @@ class Activity(Window, gtk.Container):
else:
logging.debug('Unknown share scope %r', share_scope)
- if handle.object_id is None and create_jobject:
- logging.debug('Creating a jobject.')
- self._jobject = datastore.create()
- title = _('%s Activity') % get_bundle_name()
- self._jobject.metadata['title'] = title
- self.set_title(self._jobject.metadata['title'])
- self._jobject.metadata['title_set_by_user'] = '0'
- self._jobject.metadata['activity'] = self.get_bundle_id()
- self._jobject.metadata['activity_id'] = self.get_id()
- self._jobject.metadata['keep'] = '0'
- self._jobject.metadata['preview'] = ''
- self._jobject.metadata['share-scope'] = SCOPE_PRIVATE
- if self.shared_activity is not None:
- icon_color = self.shared_activity.props.color
- else:
- client = gconf.client_get_default()
- icon_color = client.get_string('/desktop/sugar/user/color')
- self._jobject.metadata['icon-color'] = icon_color
+ def __got_channel_cb(self, wait_loop, connection_path, channel_path):
+ logging.debug('Activity.__got_channel_cb')
+ connection_name = connection_path.replace('/', '.')[1:]
- self._jobject.file_path = ''
- # Cannot call datastore.write async for creates:
- # https://dev.laptop.org/ticket/3071
- datastore.write(self._jobject)
+ bus = dbus.SessionBus()
+ channel = bus.get_object(connection_name, channel_path)
+ room_handle = channel.Get(CHANNEL, 'TargetHandle')
+
+ pservice = presenceservice.get_instance()
+ mesh_instance = pservice.get_activity_by_handle(connection_path,
+ room_handle)
+ self._set_up_sharing(mesh_instance, SCOPE_PRIVATE)
+ wait_loop.quit()
def get_active(self):
return self._active
@@ -646,6 +687,7 @@ class Activity(Window, gtk.Container):
def __joined_cb(self, activity, success, err):
"""Callback when join has finished"""
+ logging.debug('Activity.__joined_cb %r', success)
self.shared_activity.disconnect(self._join_id)
self._join_id = None
if not success:
@@ -854,6 +896,50 @@ class Activity(Window, gtk.Container):
# DEPRECATED
_shared_activity = property(lambda self: self.shared_activity, None)
+SUGAR_CLIENT_PATH = '/org/freedesktop/Telepathy/Client/Sugar'
+
+class _ClientHandler(dbus.service.Object, DBusProperties):
+ def __init__(self, bundle_id, got_channel_cb):
+ self._interfaces = set([CLIENT, CLIENT_HANDLER, PROPERTIES_IFACE])
+ self._got_channel_cb = got_channel_cb
+
+ bus = dbus.Bus()
+ name = CLIENT + '.' + bundle_id
+ bus_name = dbus.service.BusName(name, bus=bus)
+
+ path = '/' + name.replace('.', '/')
+ dbus.service.Object.__init__(self, bus_name, path)
+ DBusProperties.__init__(self)
+
+ self._implement_property_get(CLIENT, {
+ 'Interfaces': lambda: list(self._interfaces),
+ })
+ self._implement_property_get(CLIENT_HANDLER, {
+ 'HandlerChannelFilter': self.__get_filters_cb,
+ })
+
+ def __get_filters_cb(self):
+ logging.debug('__get_filters_cb')
+ filters = {
+ CHANNEL + '.ChannelType' : CHANNEL_TYPE_TEXT,
+ CHANNEL + '.TargetHandleType': CONNECTION_HANDLE_TYPE_CONTACT,
+ }
+ filter_dict = dbus.Dictionary(filters, signature='sv')
+ logging.debug('__get_filters_cb %r', dbus.Array([filter_dict], signature='a{sv}'))
+ return dbus.Array([filter_dict], signature='a{sv}')
+
+ @dbus.service.method(dbus_interface=CLIENT_HANDLER,
+ in_signature='ooa(oa{sv})aota{sv}', out_signature='')
+ def HandleChannels(self, account, connection, channels, requests_satisfied,
+ user_action_time, handler_info):
+ logging.debug('HandleChannels\n\t%r\n\t%r\n\t%r\n\t%r\n\t%r\n\t%r',
+ account, connection, channels, requests_satisfied,
+ user_action_time, handler_info)
+ try:
+ for channel in channels:
+ self._got_channel_cb(connection, channel[0])
+ except Exception, e:
+ logging.exception(e)
_session = None