diff --git a/activities/chat/ChatActivity.py b/activities/chat/ChatActivity.py index cb3ada89..07d87626 100644 --- a/activities/chat/ChatActivity.py +++ b/activities/chat/ChatActivity.py @@ -1,13 +1,16 @@ import dbus import random +import logging import pygtk pygtk.require('2.0') import gtk +import gobject from sugar.activity.Activity import Activity from sugar.LogWriter import LogWriter -from sugar.presence.Service import Service +from sugar.presence import Service +from sugar.chat.Chat import Chat from sugar.chat.BuddyChat import BuddyChat from sugar.p2p.Stream import Stream from sugar.presence.PresenceService import PresenceService @@ -17,21 +20,24 @@ _CHAT_ACTIVITY_TYPE = "_chat_activity_type._tcp" class ChatActivity(Activity): def __init__(self, service): - Activity.__init__(self, _GMAIL_ACTIVITY_TYPE) + Activity.__init__(self, _CHAT_ACTIVITY_TYPE) self._service = service + self._chat = BuddyChat(self._service) def on_connected_to_shell(self): + self.set_tab_text(self._service.get_name()) self.set_can_close(True) - self.set_tab_icon(icon_name="im") + self.set_tab_icon(name = "im") self.set_show_tab_icon(True) plug = self.gtk_plug() - - chat = BuddyChat(self._service) - plug.add(chat) - chat.show() + plug.add(self._chat) + self._chat.show() plug.show() + + def recv_message(self, message): + self._chat.recv_message(message) class ChatShellDbusService(dbus.service.Object): def __init__(self, parent): @@ -42,8 +48,8 @@ class ChatShellDbusService(dbus.service.Object): dbus.service.Object.__init__(self, bus_name, object_path) @dbus.service.method('com.redhat.Sugar.ChatShell') - def open_chat(self, message): - self._parent.send_text_message(message) + def open_chat(self, serialized_service): + self._parent.open_chat(Service.deserialize(serialized_service)) class ChatShell: instance = None @@ -55,25 +61,49 @@ class ChatShell: get_instance = staticmethod(get_instance) def __init__(self): + ChatShellDbusService(self) + + self._chats = {} + self._pservice = PresenceService.get_instance() self._pservice.start() self._pservice.track_service_type(BuddyChat.SERVICE_TYPE) def start(self): port = random.randint(5000, 65535) - service = Service(sugar.env.get_nick_name(), BuddyChat.SERVICE_TYPE, - 'local', '', port) + service = Service.Service(sugar.env.get_nick_name(), BuddyChat.SERVICE_TYPE, + 'local', '', port) self._buddy_stream = Stream.new_from_service(service) - self._buddy_stream.set_data_listener(getattr(self, "_recv_message")) + self._buddy_stream.set_data_listener(self._recv_message) self._pservice.register_service(service) - def _recv_message(self, address, msg): - print msg + def _recv_message(self, address, message): + [nick, msg] = Chat.deserialize_message(message) + buddy = self._pservice.get_buddy_by_nick_name(nick) + if buddy: + if buddy == self._pservice.get_owner(): + return + service = buddy.get_service_of_type(BuddyChat.SERVICE_TYPE) + name = service.get_name() + if service: + if not self._chats.has_key(name): + self.open_chat(service) + self._chats[name].recv_message(message) + else: + logging.error('The buddy %s does not have a chat service.' % (nick)) + else: + logging.error('The buddy %s is not present.' % (nick)) + return - def open_chat(self, serialized_service): - service = Service.deserialize(serialized_service) - self._chat = ChatActivity(service) - self._chat.connect_to_shell() + def open_chat(self, service): + chat = ChatActivity(service) + self._chats[service.get_name()] = chat + gobject.idle_add(self._connect_chat, chat) + return chat + + def _connect_chat(self, chat): + chat.connect_to_shell() + return False log_writer = LogWriter("Chat") log_writer.start() diff --git a/shell/PresenceWindow.py b/shell/PresenceWindow.py index 6b529e66..63cc57ca 100644 --- a/shell/PresenceWindow.py +++ b/shell/PresenceWindow.py @@ -2,8 +2,10 @@ import pygtk pygtk.require('2.0') import gtk import gobject +import dbus from sugar.presence.PresenceService import PresenceService +from sugar.presence.Service import Service from sugar.chat.BuddyChat import BuddyChat class PresenceWindow(gtk.Window): @@ -23,6 +25,8 @@ class PresenceWindow(gtk.Window): self._pservice.connect("buddy-disappeared", self._on_buddy_disappeared_cb) self._pservice.start() + self._pservice.track_service_type(BuddyChat.SERVICE_TYPE) + self._setup_ui() def _is_buddy_visible(self, buddy): diff --git a/sugar/chat/BuddyChat.py b/sugar/chat/BuddyChat.py index 6d4633e5..35b440d1 100644 --- a/sugar/chat/BuddyChat.py +++ b/sugar/chat/BuddyChat.py @@ -1,15 +1,14 @@ -from sugar.activity.Activity import Activity +from sugar.chat.Chat import Chat +from sugar.p2p.Stream import Stream -class BuddyChat(Activity): +class BuddyChat(Chat): SERVICE_TYPE = "_olpc_buddy_chat._tcp" def __init__(self, service): Chat.__init__(self) - self._stream = Stream.new_from_service(service) - self._stream.set_data_listener(self._recv_message) - self._stream_writer = self._group_stream.new_writer() + self._stream = Stream.new_from_service(service, False) + self._stream_writer = self._stream.new_writer(service) - def recv_message(self, address, msg): - print msg -# Chat.recv_message(self, self._buddy, msg) + def _recv_message_cb(self, address, msg): + self.recv_message(msg) diff --git a/sugar/chat/Chat.py b/sugar/chat/Chat.py index ec51f2f3..325fa7f6 100644 --- a/sugar/chat/Chat.py +++ b/sugar/chat/Chat.py @@ -28,6 +28,9 @@ class Chat(gtk.VBox): def __init__(self): gtk.VBox.__init__(self, False, 6) + self._pservice = PresenceService.get_instance() + self._pservice.start() + self._stream_writer = None self.set_border_width(12) @@ -193,13 +196,16 @@ class Chat(gtk.VBox): return msg[desc_start:svg_last + len(tag_svg_end)] return None - def recv_message(self, buddy, msg): + def recv_message(self, message): """Insert a remote chat message into the chat buffer.""" + [nick, msg] = Chat.deserialize_message(message) + buddy = self._pservice.get_buddy_by_nick_name(nick) if not buddy: + logging.error('The buddy %s is not present.' % (nick)) return # FIXME a better way to compare buddies? - owner = PresenceService.get_instance().get_owner() + owner = self._pservice.get_owner() if buddy.get_nick_name() == owner.get_nick_name(): return @@ -236,5 +242,7 @@ class Chat(gtk.VBox): owner = PresenceService.get_instance().get_owner() return owner.get_nick_name() + '||' + message - def deserialize_message(self, message): + def deserialize_message(message): return message.split('||', 1) + + deserialize_message = staticmethod(deserialize_message) diff --git a/sugar/chat/GroupChat.py b/sugar/chat/GroupChat.py index a269552b..a2a33520 100644 --- a/sugar/chat/GroupChat.py +++ b/sugar/chat/GroupChat.py @@ -8,8 +8,6 @@ import sugar.env class GroupChat(Chat): def __init__(self): Chat.__init__(self) - self._pservice = PresenceService.get_instance() - self._pservice.start() self._group_stream = None def _setup_stream(self, service): @@ -18,10 +16,4 @@ class GroupChat(Chat): self._stream_writer = self._group_stream.new_writer() def _group_recv_message(self, address, msg): - pservice = PresenceService.get_instance() - [nick, msg] = self.deserialize_message(msg) - buddy = pservice.get_buddy_by_nick_name(nick) - if buddy: - self.recv_message(buddy, msg) - else: - logging.error('The buddy %s is not present.' % (nick)) + self.recv_message(msg) diff --git a/sugar/presence/Buddy.py b/sugar/presence/Buddy.py index 6bbd7879..c4dd0a53 100644 --- a/sugar/presence/Buddy.py +++ b/sugar/presence/Buddy.py @@ -142,8 +142,8 @@ class Buddy(gobject.GObject): for service in self._services.values(): if service.get_type() == stype and service.get_activity_id() == actid: return service - if self._services.has_key(short_stype): - return self._services[short_stype] + if self._services.has_key(stype): + return self._services[stype] return None def is_valid(self): diff --git a/sugar/presence/Service.py b/sugar/presence/Service.py index 56246bb0..c82d0191 100644 --- a/sugar/presence/Service.py +++ b/sugar/presence/Service.py @@ -69,9 +69,6 @@ def deserialize(sdict): stype = sdict['stype'] if type(stype) == type(u""): stype = stype.encode() - activity_id = sdict['activity_id'] - if type(activity_id) == type(u""): - activity_id = activity_id.encode() domain = sdict['domain'] if type(domain) == type(u""): domain = domain.encode() @@ -87,7 +84,18 @@ def deserialize(sdict): address = address.encode() except KeyError: pass - name = compose_service_name(name, activity_id) + + activity_id = None + try: + activity_id = sdict['activity_id'] + if type(activity_id) == type(u""): + activity_id = activity_id.encode() + except KeyError: + pass + + if activity_id is not None: + name = compose_service_name(name, activity_id) + return Service(name, stype, domain, address=address, port=port, properties=properties) @@ -152,7 +160,8 @@ class Service(object): else: sdict['name'] = dbus.Variant(self._name) sdict['stype'] = dbus.Variant(self._stype) - sdict['activity_id'] = dbus.Variant(self._activity_id) + if self._activity_id: + sdict['activity_id'] = dbus.Variant(self._activity_id) sdict['domain'] = dbus.Variant(self._domain) if self._address: sdict['address'] = dbus.Variant(self._address)