Get one-to-one chat to actually work...

This commit is contained in:
Marco Pesenti Gritti 2006-06-22 18:07:54 -04:00
parent c234b7b4a3
commit 59f25b0741
7 changed files with 87 additions and 45 deletions

View File

@ -1,13 +1,16 @@
import dbus import dbus
import random import random
import logging
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
import gtk import gtk
import gobject
from sugar.activity.Activity import Activity from sugar.activity.Activity import Activity
from sugar.LogWriter import LogWriter 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.chat.BuddyChat import BuddyChat
from sugar.p2p.Stream import Stream from sugar.p2p.Stream import Stream
from sugar.presence.PresenceService import PresenceService from sugar.presence.PresenceService import PresenceService
@ -17,22 +20,25 @@ _CHAT_ACTIVITY_TYPE = "_chat_activity_type._tcp"
class ChatActivity(Activity): class ChatActivity(Activity):
def __init__(self, service): def __init__(self, service):
Activity.__init__(self, _GMAIL_ACTIVITY_TYPE) Activity.__init__(self, _CHAT_ACTIVITY_TYPE)
self._service = service self._service = service
self._chat = BuddyChat(self._service)
def on_connected_to_shell(self): def on_connected_to_shell(self):
self.set_tab_text(self._service.get_name())
self.set_can_close(True) self.set_can_close(True)
self.set_tab_icon(icon_name="im") self.set_tab_icon(name = "im")
self.set_show_tab_icon(True) self.set_show_tab_icon(True)
plug = self.gtk_plug() plug = self.gtk_plug()
plug.add(self._chat)
chat = BuddyChat(self._service) self._chat.show()
plug.add(chat)
chat.show()
plug.show() plug.show()
def recv_message(self, message):
self._chat.recv_message(message)
class ChatShellDbusService(dbus.service.Object): class ChatShellDbusService(dbus.service.Object):
def __init__(self, parent): def __init__(self, parent):
self._parent = parent self._parent = parent
@ -42,8 +48,8 @@ class ChatShellDbusService(dbus.service.Object):
dbus.service.Object.__init__(self, bus_name, object_path) dbus.service.Object.__init__(self, bus_name, object_path)
@dbus.service.method('com.redhat.Sugar.ChatShell') @dbus.service.method('com.redhat.Sugar.ChatShell')
def open_chat(self, message): def open_chat(self, serialized_service):
self._parent.send_text_message(message) self._parent.open_chat(Service.deserialize(serialized_service))
class ChatShell: class ChatShell:
instance = None instance = None
@ -55,25 +61,49 @@ class ChatShell:
get_instance = staticmethod(get_instance) get_instance = staticmethod(get_instance)
def __init__(self): def __init__(self):
ChatShellDbusService(self)
self._chats = {}
self._pservice = PresenceService.get_instance() self._pservice = PresenceService.get_instance()
self._pservice.start() self._pservice.start()
self._pservice.track_service_type(BuddyChat.SERVICE_TYPE) self._pservice.track_service_type(BuddyChat.SERVICE_TYPE)
def start(self): def start(self):
port = random.randint(5000, 65535) port = random.randint(5000, 65535)
service = Service(sugar.env.get_nick_name(), BuddyChat.SERVICE_TYPE, service = Service.Service(sugar.env.get_nick_name(), BuddyChat.SERVICE_TYPE,
'local', '', port) 'local', '', port)
self._buddy_stream = Stream.new_from_service(service) 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) self._pservice.register_service(service)
def _recv_message(self, address, msg): def _recv_message(self, address, message):
print msg [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): def open_chat(self, service):
service = Service.deserialize(serialized_service) chat = ChatActivity(service)
self._chat = ChatActivity(service) self._chats[service.get_name()] = chat
self._chat.connect_to_shell() 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 = LogWriter("Chat")
log_writer.start() log_writer.start()

View File

@ -2,8 +2,10 @@ import pygtk
pygtk.require('2.0') pygtk.require('2.0')
import gtk import gtk
import gobject import gobject
import dbus
from sugar.presence.PresenceService import PresenceService from sugar.presence.PresenceService import PresenceService
from sugar.presence.Service import Service
from sugar.chat.BuddyChat import BuddyChat from sugar.chat.BuddyChat import BuddyChat
class PresenceWindow(gtk.Window): class PresenceWindow(gtk.Window):
@ -23,6 +25,8 @@ class PresenceWindow(gtk.Window):
self._pservice.connect("buddy-disappeared", self._on_buddy_disappeared_cb) self._pservice.connect("buddy-disappeared", self._on_buddy_disappeared_cb)
self._pservice.start() self._pservice.start()
self._pservice.track_service_type(BuddyChat.SERVICE_TYPE)
self._setup_ui() self._setup_ui()
def _is_buddy_visible(self, buddy): def _is_buddy_visible(self, buddy):

View File

@ -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" SERVICE_TYPE = "_olpc_buddy_chat._tcp"
def __init__(self, service): def __init__(self, service):
Chat.__init__(self) Chat.__init__(self)
self._stream = Stream.new_from_service(service) self._stream = Stream.new_from_service(service, False)
self._stream.set_data_listener(self._recv_message) self._stream_writer = self._stream.new_writer(service)
self._stream_writer = self._group_stream.new_writer()
def recv_message(self, address, msg): def _recv_message_cb(self, address, msg):
print msg self.recv_message(msg)
# Chat.recv_message(self, self._buddy, msg)

View File

@ -28,6 +28,9 @@ class Chat(gtk.VBox):
def __init__(self): def __init__(self):
gtk.VBox.__init__(self, False, 6) gtk.VBox.__init__(self, False, 6)
self._pservice = PresenceService.get_instance()
self._pservice.start()
self._stream_writer = None self._stream_writer = None
self.set_border_width(12) self.set_border_width(12)
@ -193,13 +196,16 @@ class Chat(gtk.VBox):
return msg[desc_start:svg_last + len(tag_svg_end)] return msg[desc_start:svg_last + len(tag_svg_end)]
return None return None
def recv_message(self, buddy, msg): def recv_message(self, message):
"""Insert a remote chat message into the chat buffer.""" """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: if not buddy:
logging.error('The buddy %s is not present.' % (nick))
return return
# FIXME a better way to compare buddies? # 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(): if buddy.get_nick_name() == owner.get_nick_name():
return return
@ -236,5 +242,7 @@ class Chat(gtk.VBox):
owner = PresenceService.get_instance().get_owner() owner = PresenceService.get_instance().get_owner()
return owner.get_nick_name() + '||' + message return owner.get_nick_name() + '||' + message
def deserialize_message(self, message): def deserialize_message(message):
return message.split('||', 1) return message.split('||', 1)
deserialize_message = staticmethod(deserialize_message)

View File

@ -8,8 +8,6 @@ import sugar.env
class GroupChat(Chat): class GroupChat(Chat):
def __init__(self): def __init__(self):
Chat.__init__(self) Chat.__init__(self)
self._pservice = PresenceService.get_instance()
self._pservice.start()
self._group_stream = None self._group_stream = None
def _setup_stream(self, service): def _setup_stream(self, service):
@ -18,10 +16,4 @@ class GroupChat(Chat):
self._stream_writer = self._group_stream.new_writer() self._stream_writer = self._group_stream.new_writer()
def _group_recv_message(self, address, msg): def _group_recv_message(self, address, msg):
pservice = PresenceService.get_instance() self.recv_message(msg)
[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))

View File

@ -142,8 +142,8 @@ class Buddy(gobject.GObject):
for service in self._services.values(): for service in self._services.values():
if service.get_type() == stype and service.get_activity_id() == actid: if service.get_type() == stype and service.get_activity_id() == actid:
return service return service
if self._services.has_key(short_stype): if self._services.has_key(stype):
return self._services[short_stype] return self._services[stype]
return None return None
def is_valid(self): def is_valid(self):

View File

@ -69,9 +69,6 @@ def deserialize(sdict):
stype = sdict['stype'] stype = sdict['stype']
if type(stype) == type(u""): if type(stype) == type(u""):
stype = stype.encode() stype = stype.encode()
activity_id = sdict['activity_id']
if type(activity_id) == type(u""):
activity_id = activity_id.encode()
domain = sdict['domain'] domain = sdict['domain']
if type(domain) == type(u""): if type(domain) == type(u""):
domain = domain.encode() domain = domain.encode()
@ -87,7 +84,18 @@ def deserialize(sdict):
address = address.encode() address = address.encode()
except KeyError: except KeyError:
pass pass
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) name = compose_service_name(name, activity_id)
return Service(name, stype, domain, address=address, return Service(name, stype, domain, address=address,
port=port, properties=properties) port=port, properties=properties)
@ -152,6 +160,7 @@ class Service(object):
else: else:
sdict['name'] = dbus.Variant(self._name) sdict['name'] = dbus.Variant(self._name)
sdict['stype'] = dbus.Variant(self._stype) sdict['stype'] = dbus.Variant(self._stype)
if self._activity_id:
sdict['activity_id'] = dbus.Variant(self._activity_id) sdict['activity_id'] = dbus.Variant(self._activity_id)
sdict['domain'] = dbus.Variant(self._domain) sdict['domain'] = dbus.Variant(self._domain)
if self._address: if self._address: