diff --git a/shell/ActivityHost.py b/shell/ActivityHost.py index 9da0a4c6..7ee4164b 100644 --- a/shell/ActivityHost.py +++ b/shell/ActivityHost.py @@ -13,6 +13,7 @@ class ActivityHost: self._shell = shell self._window = window self._xid = window.get_xid() + self._pservice = PresenceService.get_instance() bus = dbus.SessionBus() proxy_obj = bus.get_object(Activity.get_service_name(self._xid), @@ -34,8 +35,7 @@ class ActivityHost: return self._icon_name def get_icon_color(self): - pservice = PresenceService.get_instance() - activity = pservice.get_activity(self._id) + activity = self._pservice.get_activity(self._id) if activity != None: return IconColor(activity.get_color()) else: @@ -45,10 +45,15 @@ class ActivityHost: self._activity.share() def invite(self, buddy): + if not self.get_shared(): + self.share() + + issuer = self._pservice.get_owner().get_name() service = buddy.get_service_of_type("_presence_olpc._tcp") stream = Stream.Stream.new_from_service(service, start_reader=False) writer = stream.new_writer(service) - writer.custom_request("invite", None, None, self._id) + writer.custom_request("invite", None, None, issuer, + self._type, self._id) def get_shared(self): return self._activity.get_shared() diff --git a/shell/Invites.py b/shell/Invites.py new file mode 100644 index 00000000..35993b19 --- /dev/null +++ b/shell/Invites.py @@ -0,0 +1,50 @@ +import gobject + +from sugar.presence import PresenceService +from sugar.canvas.IconColor import IconColor +from sugar import conf + +class Invite: + def __init__(self, issuer, bundle_id, activity_id): + self._issuer = issuer + self._activity_id = activity_id + self._bundle_id = bundle_id + + def get_icon(self): + reg = conf.get_activity_registry() + return reg.get_activity(self._bundle_id).get_icon() + + def get_color(self): + pservice = PresenceService.get_instance() + buddy = pservice.get_buddy_by_name(self._issuer) + if buddy != None: + return IconColor(buddy.get_color()) + else: + return IconColor('white') + + def get_activity_id(self): + return self._activity_id + + def get_bundle_id(self): + return self._bundle_id + +class Invites(gobject.GObject): + __gsignals__ = { + 'invite-added': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([object])), + 'invite-removed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([object])), + } + + def __init__(self): + gobject.GObject.__init__(self) + + self._list = [] + + def add_invite(self, issuer, bundle_id, activity_id): + invite = Invite(issuer, bundle_id, activity_id) + self._list.append(invite) + self.emit('invite-added', invite) + + def __iter__(self): + return self._list.__iter__() diff --git a/shell/Owner.py b/shell/Owner.py index 6b71d124..5cced8c6 100644 --- a/shell/Owner.py +++ b/shell/Owner.py @@ -7,6 +7,7 @@ from sugar.p2p import Stream from sugar.presence import PresenceService from sugar import conf from Friends import Friends +from Invites import Invites PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp" @@ -31,10 +32,14 @@ class ShellOwner(object): self._pservice = PresenceService.get_instance() self._friends = Friends() + self._invites = Invites() def get_friends(self): return self._friends + def get_invites(self): + return self._invites + def announce(self): # Create and announce our presence color = conf.get_profile().get_color() @@ -52,7 +57,7 @@ class ShellOwner(object): return base64.b64encode(self._icon) return "" - def _handle_invite(self, activity_id): + def _handle_invite(self, issuer, bundle_id, activity_id): """XMLRPC method, called when the owner is invited to an activity.""" - print '---------- invited to ' + activity_id - return "" + self._invites.add_invite(issuer, bundle_id, activity_id) + return '' diff --git a/shell/Shell.py b/shell/Shell.py index 204ab67d..7644b1b6 100755 --- a/shell/Shell.py +++ b/shell/Shell.py @@ -158,12 +158,7 @@ class Shell(gobject.GObject): module = registry.get_activity(activity.get_type()) self._console.set_page(module.get_id()) - def join_activity(self, service): - registry = conf.get_activity_registry() - info = registry.get_activity_from_type(service.get_type()) - - activity_id = service.get_activity_id() - + def join_activity(self, bundle_id, activity_id): activity = self.get_activity(activity_id) if activity: activity.present() @@ -171,7 +166,7 @@ class Shell(gobject.GObject): activity_ps = self._pservice.get_activity(activity_id) if activity_ps: - activity = ActivityFactory.create(info.get_id()) + activity = ActivityFactory.create(bundle_id) activity.join(activity_ps.object_path()) else: logging.error('Cannot start activity.') diff --git a/shell/frame/BottomPanel.py b/shell/frame/BottomPanel.py index e3e1fa66..3cbd53e6 100644 --- a/shell/frame/BottomPanel.py +++ b/shell/frame/BottomPanel.py @@ -3,6 +3,7 @@ import goocanvas from sugar.canvas.IconItem import IconItem from sugar.canvas.IconColor import IconColor +from sugar.presence import PresenceService from sugar import conf from frame.Panel import Panel import logging @@ -17,11 +18,23 @@ class ActivityItem(IconItem): color=IconColor('white'), size=size) self._activity = activity - def get_activity_id(self): + def get_bundle_id(self): return self._activity.get_id() +class InviteItem(IconItem): + def __init__(self, invite, size): + IconItem.__init__(self, icon_name=invite.get_icon(), + color=invite.get_color(), size=size) + self._invite = invite + + def get_activity_id(self): + return self._invite.get_activity_id() + + def get_bundle_id(self): + return self._invite.get_bundle_id() + class ActivityBar(goocanvas.Group): - def __init__(self, shell, height): + def __init__(self, shell, invites, height): goocanvas.Group.__init__(self) self._shell = shell @@ -32,6 +45,20 @@ class ActivityBar(goocanvas.Group): if activity.get_show_launcher(): self.add_activity(activity) + for invite in invites: + self.add_invite(invite) + invites.connect('invite-added', self.__invite_added_cb) + + def __activity_clicked_cb(self, icon): + self._shell.start_activity(icon.get_bundle_id()) + + def __invite_clicked_cb(self, icon): + self._shell.join_activity(icon.get_bundle_id(), + icon.get_activity_id()) + + def __invite_added_cb(self, invites, invite): + self.add_invite(invite) + def add_activity(self, activity): # Need an icon to show up on the bar if not activity.get_icon(): @@ -40,6 +67,17 @@ class ActivityBar(goocanvas.Group): return item = ActivityItem(activity, self._height) + item.connect('clicked', self.__activity_clicked_cb) + + icon_size = self._height + x = (icon_size + 6) * self.get_n_children() + item.set_property('x', x) + + self.add_child(item) + + def add_invite(self, invite): + item = InviteItem(invite, self._height) + item.connect('clicked', self.__invite_clicked_cb) icon_size = self._height x = (icon_size + 6) * self.get_n_children() @@ -48,27 +86,17 @@ class ActivityBar(goocanvas.Group): self.add_child(item) class BottomPanel(Panel): - def __init__(self, shell): + def __init__(self, shell, invites): Panel.__init__(self) self._shell = shell - - view = self.get_view() - view.connect("item_view_created", self.__item_view_created_cb) + self._invites = invites def construct(self): Panel.construct(self) root = self.get_root() - activity_bar = ActivityBar(self._shell, self.get_height()) + activity_bar = ActivityBar(self._shell, self._invites, + self.get_height()) root.add_child(activity_bar) - - def __item_view_created_cb(self, view, item_view, item): - if isinstance(item, ActivityItem): - item_view.connect("button_press_event", - self.__activity_button_press_cb, - item.get_activity_id()) - - def __activity_button_press_cb(self, view, target, event, activity_id): - self._shell.start_activity(activity_id) diff --git a/shell/frame/Frame.py b/shell/frame/Frame.py index d0496552..df80c92d 100644 --- a/shell/frame/Frame.py +++ b/shell/frame/Frame.py @@ -12,7 +12,7 @@ class Frame: self._panels = [] - panel = BottomPanel(shell) + panel = BottomPanel(shell, owner.get_invites()) panel.set_position(size, 0) panel.move(0, gtk.gdk.screen_height() - size) panel.resize(gtk.gdk.screen_width(), size) diff --git a/shell/home/MeshGroup.py b/shell/home/MeshGroup.py index 96cb7798..e3d4eab9 100644 --- a/shell/home/MeshGroup.py +++ b/shell/home/MeshGroup.py @@ -79,4 +79,10 @@ class MeshGroup(goocanvas.Group): self._activities[item.get_id()] = item def __activity_clicked_cb(self, item): - self._shell.join_activity(item.get_service()) + default_type = item.get_service().get_type() + registry = conf.get_activity_registry() + + bundle_id = registry.get_activity_from_type().get_id() + activity_id = service.get_activity_id() + + self._shell.join_activity(bundle_id, activity_id)