diff --git a/configure.ac b/configure.ac index e31440d0..0828bda5 100644 --- a/configure.ac +++ b/configure.ac @@ -22,6 +22,5 @@ sugar/__installed__.py sugar/browser/Makefile sugar/chat/Makefile sugar/p2p/Makefile -sugar/p2p/model/Makefile sugar/shell/Makefile ]) diff --git a/pylint.sh b/pylint.sh deleted file mode 100755 index 4de5a507..00000000 --- a/pylint.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -# Errors that we may fix in the future -# -# C0301 Line length -# W0201 Attribute defined outside __init__ -# R0201 Method could be a function -TODO="C0301,W0201,R0201" - -# Errors we don't like -# -# W0613 Unused argument (glib signals) -# W0511 - FIXME/TODO/XXX -DISABLE="W0613,W0511" - -MSGS="$TODO,$DISABLE" -ARG="sugar" - -pylint \ - --disable-all \ - --include-ids=y \ - --enable-variables=y \ - --enable-exceptions=y \ - --enable-miscellaneous=y \ - --enable-format=y \ - --enable-classes=y \ - --disable-msg=$MSGS \ - --reports=n \ - --enable-metrics=n \ - --indent-string=" " \ - --ignore="SVGdraw.py" \ - $ARG diff --git a/sugar/browser/browser.py b/sugar/browser/browser.py index fc5ce0a1..633fa044 100755 --- a/sugar/browser/browser.py +++ b/sugar/browser/browser.py @@ -11,7 +11,6 @@ import gtk import geckoembed from sugar.shell import activity -from sugar.p2p.Group import LocalGroup import sugar.env class AddressToolbar(gtk.Toolbar): @@ -78,7 +77,7 @@ class AddressEntry(gtk.HBox): return self.folded def set_folded(self, folded): - self.folded = folded + self.folded = not self.folded self._update_folded_state() def __button_clicked_cb(self, button): @@ -89,12 +88,11 @@ class AddressEntry(gtk.HBox): self.set_folded(True) class NavigationToolbar(gtk.Toolbar): - def __init__(self, browser): + def __init__(self, embed): gtk.Toolbar.__init__(self) - self._browser = browser - self._embed = self._browser.get_embed() + self.embed = embed - self.set_style(gtk.TOOLBAR_BOTH_HORIZ) + self.set_style(gtk.TOOLBAR_ICONS) self.back = gtk.ToolButton(gtk.STOCK_GO_BACK) self.back.connect("clicked", self.__go_back_cb) @@ -115,9 +113,7 @@ class NavigationToolbar(gtk.Toolbar): self.insert(separator, -1) separator.show() - share = gtk.ToolButton(None, "Share") - share.set_icon_name('stock_shared-by-me') - share.set_is_important(True) + share = gtk.ToolButton("Share") share.connect("clicked", self.__share_cb) self.insert(share, -1) share.show() @@ -132,42 +128,34 @@ class NavigationToolbar(gtk.Toolbar): self._update_sensitivity() - self._embed.connect("location", self.__location_changed) + self.embed.connect("location", self.__location_changed) def _update_sensitivity(self): - self.back.set_sensitive(self._embed.can_go_back()) - self.forward.set_sensitive(self._embed.can_go_forward()) + self.back.set_sensitive(self.embed.can_go_back()) + self.forward.set_sensitive(self.embed.can_go_forward()) def __go_back_cb(self, button): - self._embed.go_back() + self.embed.go_back() def __go_forward_cb(self, button): - self._embed.go_forward() + self.embed.go_forward() def __reload_cb(self, button): - self._embed.reload() + self.embed.reload() def __share_cb(self, button): - self._browser.share() + pass def __location_changed(self, embed): self._update_sensitivity() def __open_address_cb(self, address): - self._embed.load_address(address) + self.embed.load_address(address) class BrowserActivity(activity.Activity): - def __init__(self, group, uri): + def __init__(self, uri): activity.Activity.__init__(self) - self.uri = uri - self._group = group - - def _setup_shared(self, uri): - self._model = self._group.get_store().get_model(uri) - if self._model: - self._load_shared_address() - self._model.add_listener(self.__shared_address_changed_cb) def activity_on_connected_to_shell(self): self.activity_set_ellipsize_tab(True) @@ -185,7 +173,7 @@ class BrowserActivity(activity.Activity): self.embed.show() self.embed.load_address(self.uri) - nav_toolbar = NavigationToolbar(self) + nav_toolbar = NavigationToolbar(self.embed) vbox.pack_start(nav_toolbar, False) nav_toolbar.show() @@ -194,36 +182,12 @@ class BrowserActivity(activity.Activity): plug.show() vbox.show() - - self._setup_shared(uri) def get_embed(self): return self.embed - def share(self): - address = self.embed.get_address() - self._model = self._group.get_store().create_model(address) - self._model.set_value('current_address', address) - self._model.add_listener(self.__shared_address_changed_cb) - - bus = dbus.SessionBus() - proxy_obj = bus.get_object('com.redhat.Sugar.Chat', '/com/redhat/Sugar/Chat') - chat_shell = dbus.Interface(proxy_obj, 'com.redhat.Sugar.ChatShell') - chat_shell.send_message('' + - self.embed.get_title() + '') - def __title_cb(self, embed): self.activity_set_tab_text(embed.get_title()) - # Temporary hack, we need an UI - self._model.set_value('current_address', self.embed.get_address()) - - def _load_shared_address(self): - address = self._model.get_value("current_address") - if address != self.embed.get_address(): - self.embed.load_address(address) - - def __shared_address_changed_cb(self, model, key): - self._load_shared_address() def activity_on_close_from_user(self): self.activity_shutdown() @@ -265,6 +229,7 @@ class WebActivity(activity.Activity): def activity_on_disconnected_from_shell(self): gtk.main_quit() + gc.collect() class BrowserShell(dbus.service.Object): instance = None @@ -284,7 +249,6 @@ class BrowserShell(dbus.service.Object): dbus.service.Object.__init__(self, bus_name, object_path) self.__browsers = [] - self._group = LocalGroup() def open_web_activity(self): web_activity = WebActivity() @@ -303,13 +267,17 @@ class BrowserShell(dbus.service.Object): @dbus.service.method('com.redhat.Sugar.BrowserShell') def open_browser(self, uri): - browser = BrowserActivity(self._group, uri) + browser = BrowserActivity(uri) self.__browsers.append(browser) browser.activity_connect_to_shell() def main(): BrowserShell.get_instance().open_web_activity() - gtk.main() + + try: + gtk.main() + except KeyboardInterrupt: + pass -if __name__ == "__main__": - main() +if __name__=="__main__": + main() diff --git a/sugar/chat/BuddyList.py b/sugar/chat/BuddyList.py new file mode 100644 index 00000000..d35fa847 --- /dev/null +++ b/sugar/chat/BuddyList.py @@ -0,0 +1,121 @@ +# -*- tab-width: 4; indent-tabs-mode: t -*- + +import presence +import avahi + +ACTION_BUDDY_ADDED = "added" +ACTION_BUDDY_REMOVED = "removed" + + +class Buddy(object): + def __init__(self, nick, realname, servicename, host, address, port, key=None): + self._nick = nick + self._realname = realname + self._servicename = servicename + self._key = key + self._host = host + self._address = str(address) + self._port = int(port) + self._chat = None + + def set_chat(self, chat): + self._chat = chat + + def chat(self): + return self._chat + + def nick(self): + return self._nick + + def realname(self): + return self._realname + + def servicename(self): + return self._servicename + + def host(self): + return self._host + + def address(self): + return self._address + + def port(self): + return self._port + + def key(self): + return self._key + +class BuddyList(object): + """ Manage a list of buddies """ + + def __init__(self, servicename): + self._listeners = [] + self._buddies = {} + self._servicename = servicename + self._pdiscovery = presence.PresenceDiscovery() + self._pdiscovery.add_service_listener(self._on_service_change) + + def start(self): + self._pdiscovery.start() + + def add_buddy_listener(self, listener): + self._listeners.append(listener) + + def _add_buddy(self, host, address, port, servicename, data): + # Ignore ourselves + if servicename == self._servicename: + return + + if len(data) > 0 and 'name' in data.keys(): + buddy = self._find_buddy_by_service_name(servicename) + if not buddy: + buddy = Buddy(data['name'], data['realname'], servicename, host, address, port) + self._buddies[data['name']] = buddy + self._notify_listeners(ACTION_BUDDY_ADDED, buddy) + + def _remove_buddy(self, buddy): + nick = buddy.nick() + self._notify_listeners(ACTION_BUDDY_REMOVED, buddy) + del self._buddies[nick] + + def _find_buddy_by_service_name(self, servicename): + for buddy in self._buddies.values(): + if buddy.servicename() == servicename: + return buddy + return None + + def find_buddy_by_address(self, address): + for buddy_name in self._buddies.keys(): + buddy = self._buddies[buddy_name] + if buddy.address() == address: + return buddy + return None + + def _notify_listeners(self, action, buddy): + for listener in self._listeners: + listener(action, buddy) + + def _on_service_change(self, action, interface, protocol, name, stype, domain, flags): + if stype != presence.OLPC_CHAT_SERVICE: + return + if action == presence.ACTION_SERVICE_NEW: + self._pdiscovery.resolve_service(interface, protocol, name, stype, domain, self._on_service_resolved) + elif action == presence.ACTION_SERVICE_REMOVED: + buddy = self._find_buddy_by_service_name(name) + if buddy: + self._remove_buddy(buddy) + + def _pair_to_dict(self, l): + res = {} + for el in l: + tmp = el.split('=', 1) + if len(tmp) > 1: + res[tmp[0]] = tmp[1] + else: + res[tmp[0]] = '' + return res + + def _on_service_resolved(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags): + data = self._pair_to_dict(avahi.txt_array_to_string_array(txt)) + self._add_buddy(host, address, port, name, data) + diff --git a/sugar/chat/SVGdraw.py b/sugar/chat/SVGdraw.py index abcda112..d2a12604 100644 --- a/sugar/chat/SVGdraw.py +++ b/sugar/chat/SVGdraw.py @@ -69,6 +69,7 @@ __version__="1.0" # Anyway the text based approach is about 60 times faster than using the full dom implementation. use_dom_implementation=0 +from xml.parsers import expat import exceptions if use_dom_implementation<>0: @@ -226,7 +227,11 @@ class Attribute: self.value = value self.nsname = nsname self.nsref = nsref - + +def get_attr_value(attrs, name): + return attrs[name] + + class SVGelement: """SVGelement(type,attributes,elements,text,namespace,**args) Creates a arbitrary svg element and is intended to be subclassed not used on its own. @@ -266,9 +271,38 @@ class SVGelement: def setParent(self, parent): self._parent = parent - def addAttribute(self, attribute): + def setAttribute(self, attribute): self._attributes[attribute.name] = attribute + def delAttribute(self, name): + if name in self._attributes.keys(): + del self._attributes[name] + + def hasAttribute(self, name): + if name in self._attributes.keys(): + return True + return False + + def _construct(attributes): + raise Exception("Can't construct a default object.") + _construct = staticmethod(_construct) + + def construct(name, attributes, text=None, cdata=None): + try: + eltClass = elementTable[name] + except KeyError, e: + print "Unknown SVG element %s." % e + return None + element = eltClass._construct(attributes) + for attrname, attrvalue in attributes.items(): + element.setAttribute(Attribute(attrname, attrvalue)) + if text: + element.text = text + if cdata: + element.cdata = cdata + return element + construct = staticmethod(construct) + def toXml(self,level,f): f.write('\t'*level) f.write('<'+self.type) @@ -323,11 +357,16 @@ class tspan(SVGelement): def __repr__(self): s="None: - self.addAttribute(Attribute('x', x)) + self.setAttribute(Attribute('x', x)) if y<>None: - self.addAttribute(Attribute('y', y)) + self.setAttribute(Attribute('y', y)) if fill<>None: - self.addAttribute(Attribute('fill', fill)) + self.setAttribute(Attribute('fill', fill)) if stroke<>None: - self.addAttribute(Attribute('stroke', stroke)) + self.setAttribute(Attribute('stroke', stroke)) if stroke_width<>None: - self.addAttribute(Attribute('stroke-width', stroke_width)) - + self.setAttribute(Attribute('stroke-width', stroke_width)) + + def _construct(attributes): + width = get_attr_value(attributes, 'width') + height = get_attr_value(attributes, 'height') + return rect(width=width, height=height) + _construct = staticmethod(_construct) + + class ellipse(SVGelement): """e=ellipse(rx,ry,x,y,fill,stroke,stroke_width,**args) @@ -425,17 +477,23 @@ class ellipse(SVGelement): raise ValueError, 'both rx and ry are required' SVGelement.__init__(self,'ellipse',{'rx':rx,'ry':ry},**args) if cx<>None: - self.addAttribute(Attribute('cx', cx)) + self.setAttribute(Attribute('cx', cx)) if cy<>None: - self.addAttribute(Attribute('cy', cy)) + self.setAttribute(Attribute('cy', cy)) if fill<>None: - self.addAttribute(Attribute('fill', fill)) + self.setAttribute(Attribute('fill', fill)) if stroke<>None: - self.addAttribute(Attribute('stroke', stroke)) + self.setAttribute(Attribute('stroke', stroke)) if stroke_width<>None: - self.addAttribute(Attribute('stroke-width', stroke_width)) + self.setAttribute(Attribute('stroke-width', stroke_width)) - + def _construct(attributes): + rx = get_attr_value(attributes, 'rx') + ry = get_attr_value(attributes, 'ry') + return ellipse(rx=rx, ry=ry) + _construct = staticmethod(_construct) + + class circle(SVGelement): """c=circle(x,y,radius,fill,stroke,stroke_width,**args) @@ -446,15 +504,24 @@ class circle(SVGelement): raise ValueError, 'r is required' SVGelement.__init__(self,'circle',{'r':r},**args) if cx<>None: - self.addAttribute(Attribute('cx', cx)) + self.setAttribute(Attribute('cx', cx)) if cy<>None: - self.addAttribute(Attribute('cy', cy)) + self.setAttribute(Attribute('cy', cy)) if fill<>None: - self.addAttribute(Attribute('fill', fill)) + self.setAttribute(Attribute('fill', fill)) if stroke<>None: - self.addAttribute(Attribute('stroke', stroke)) + self.setAttribute(Attribute('stroke', stroke)) if stroke_width<>None: - self.addAttribute(Attribute('stroke-width', stroke_width)) + self.setAttribute(Attribute('stroke-width', stroke_width)) + + def _construct(attributes): + r = get_attr_value(attributes, 'r') + if int(r) == 1: + return point() + else: + return circle(r=r) + _construct = staticmethod(_construct) + class point(circle): """p=point(x,y,color) @@ -462,7 +529,7 @@ class point(circle): A point is defined as a circle with a size 1 radius. It may be more efficient to use a very small rectangle if you use many points because a circle is difficult to render. """ - def __init__(self,x,y,fill='black',**args): + def __init__(self,x=None,y=None,fill='black',**args): circle.__init__(self,x,y,1,fill,**args) class line(SVGelement): @@ -473,17 +540,22 @@ class line(SVGelement): def __init__(self,x1=None,y1=None,x2=None,y2=None,stroke=None,stroke_width=None,**args): SVGelement.__init__(self,'line',**args) if x1<>None: - self.addAttribute(Attribute('x1', x1)) + self.setAttribute(Attribute('x1', x1)) if y1<>None: - self.addAttribute(Attribute('y1', y1)) + self.setAttribute(Attribute('y1', y1)) if x2<>None: - self.addAttribute(Attribute('x2', x2)) + self.setAttribute(Attribute('x2', x2)) if y2<>None: - self.addAttribute(Attribute('y2', y2)) + self.setAttribute(Attribute('y2', y2)) if stroke_width<>None: - self.addAttribute(Attribute('stroke-width', stroke_width)) + self.setAttribute(Attribute('stroke-width', stroke_width)) if stroke<>None: - self.addAttribute(Attribute('stroke', stroke)) + self.setAttribute(Attribute('stroke', stroke)) + + def _construct(attributes): + return line() + _construct = staticmethod(_construct) + class polyline(SVGelement): """pl=polyline([[x1,y1],[x2,y2],...],fill,stroke,stroke_width,**args) @@ -493,11 +565,17 @@ class polyline(SVGelement): def __init__(self,points,fill=None,stroke=None,stroke_width=None,**args): SVGelement.__init__(self,'polyline',{'points':_xypointlist(points)},**args) if fill<>None: - self.addAttribute(Attribute('fill', fill)) + self.setAttribute(Attribute('fill', fill)) if stroke_width<>None: - self.addAttribute(Attribute('stroke-width', stroke_width)) + self.setAttribute(Attribute('stroke-width', stroke_width)) if stroke<>None: - self.addAttribute(Attribute('stroke', stroke)) + self.setAttribute(Attribute('stroke', stroke)) + + def _construct(attributes): + points = get_attr_value(attributes, 'points') + return polyline(points) + _construct = staticmethod(_construct) + class polygon(SVGelement): """pl=polyline([[x1,y1],[x2,y2],...],fill,stroke,stroke_width,**args) @@ -507,11 +585,17 @@ class polygon(SVGelement): def __init__(self,points,fill=None,stroke=None,stroke_width=None,**args): SVGelement.__init__(self,'polygon',{'points':_xypointlist(points)},**args) if fill<>None: - self.addAttribute(Attribute('fill', fill)) + self.setAttribute(Attribute('fill', fill)) if stroke_width<>None: - self.addAttribute(Attribute('stroke-width', stroke_width)) + self.setAttribute(Attribute('stroke-width', stroke_width)) if stroke<>None: - self.addAttribute(Attribute('stroke', stroke)) + self.setAttribute(Attribute('stroke', stroke)) + + def _construct(attributes): + points = get_attr_value(attributes, 'points') + return polygon(points) + _construct = staticmethod(_construct) + class path(SVGelement): """p=path(path,fill,stroke,stroke_width,**args) @@ -521,14 +605,19 @@ class path(SVGelement): def __init__(self,pathdata,fill=None,stroke=None,stroke_width=None,id=None,**args): SVGelement.__init__(self,'path',{'d':str(pathdata)},**args) if stroke<>None: - self.addAttribute(Attribute('stroke', stroke)) + self.setAttribute(Attribute('stroke', stroke)) if fill<>None: - self.addAttribute(Attribute('fill', fill)) + self.setAttribute(Attribute('fill', fill)) if stroke_width<>None: - self.addAttribute(Attribute('stroke-width', stroke_width)) + self.setAttribute(Attribute('stroke-width', stroke_width)) if id<>None: - self.addAttribute(Attribute('id', id)) + self.setAttribute(Attribute('id', id)) + def _construct(attributes): + pathdata = get_attr_value(attributes, 'd') + return path(d) + _construct = staticmethod(_construct) + class text(SVGelement): """t=text(x,y,text,font_size,font_family,**args) @@ -538,17 +627,21 @@ class text(SVGelement): def __init__(self,x=None,y=None,text=None,font_size=None,font_family=None,text_anchor=None,**args): SVGelement.__init__(self,'text',**args) if x<>None: - self.addAttribute(Attribute('x', x)) + self.setAttribute(Attribute('x', x)) if y<>None: - self.addAttribute(Attribute('y', y)) + self.setAttribute(Attribute('y', y)) if font_size<>None: - self.addAttribute(Attribute('font-size', font_size)) + self.setAttribute(Attribute('font-size', font_size)) if font_family<>None: - self.addAttribute(Attribute('font-family', font_family)) + self.setAttribute(Attribute('font-family', font_family)) if text<>None: self.text=text if text_anchor<>None: - self.addAttribute(Attribute('text-anchor', text_anchor)) + self.setAttribute(Attribute('text-anchor', text_anchor)) + + def _construct(attributes): + return text() + _construct = staticmethod(_construct) class textpath(SVGelement): @@ -558,10 +651,18 @@ class textpath(SVGelement): """ def __init__(self,link,text=None,**args): SVGelement.__init__(self,'textPath',**args) - self.addAttribute(Attribute('href', link, 'xlink', xlinkNSRef)) + self.setAttribute(Attribute('href', link, 'xlink', xlinkNSRef)) if text<>None: self.text=text + def _construct(attributes): + href = get_attr_value(attributes, 'xlink:href') + if href and href.startswith("xlink:"): + href = href[len("xlink:"):] + return textpath(href) + _construct = staticmethod(_construct) + + class pattern(SVGelement): """p=pattern(x,y,width,height,patternUnits,**args) @@ -572,15 +673,20 @@ class pattern(SVGelement): def __init__(self,x=None,y=None,width=None,height=None,patternUnits=None,**args): SVGelement.__init__(self,'pattern',**args) if x<>None: - self.addAttribute(Attribute('x', x)) + self.setAttribute(Attribute('x', x)) if y<>None: - self.addAttribute(Attribute('y', y)) + self.setAttribute(Attribute('y', y)) if width<>None: - self.addAttribute(Attribute('width', width)) + self.setAttribute(Attribute('width', width)) if height<>None: - self.addAttribute(Attribute('height', height)) + self.setAttribute(Attribute('height', height)) if patternUnits<>None: - self.addAttribute(Attribute('patternUnits', patternUnits)) + self.setAttribute(Attribute('patternUnits', patternUnits)) + + def _construct(attributes): + return pattern() + _construct = staticmethod(_construct) + class title(SVGelement): """t=title(text,**args) @@ -593,6 +699,11 @@ class title(SVGelement): if text<>None: self.text=text + def _construct(attributes): + return title() + _construct = staticmethod(_construct) + + class description(SVGelement): """d=description(text,**args) @@ -604,6 +715,11 @@ class description(SVGelement): if text<>None: self.text=text + def _construct(attributes): + return description() + _construct = staticmethod(_construct) + + class lineargradient(SVGelement): """lg=lineargradient(x1,y1,x2,y2,id,**args) @@ -613,15 +729,20 @@ class lineargradient(SVGelement): def __init__(self,x1=None,y1=None,x2=None,y2=None,id=None,**args): SVGelement.__init__(self,'linearGradient',**args) if x1<>None: - self.addAttribute(Attribute('x1', x1)) + self.setAttribute(Attribute('x1', x1)) if y1<>None: - self.addAttribute(Attribute('y1', y1)) + self.setAttribute(Attribute('y1', y1)) if x2<>None: - self.addAttribute(Attribute('x2', x2)) + self.setAttribute(Attribute('x2', x2)) if y2<>None: - self.addAttribute(Attribute('y2', y2)) + self.setAttribute(Attribute('y2', y2)) if id<>None: - self.addAttribute(Attribute('id', id)) + self.setAttribute(Attribute('id', id)) + + def _construct(attributes): + return lineargradient() + _construct = staticmethod(_construct) + class radialgradient(SVGelement): """rg=radialgradient(cx,cy,r,fx,fy,id,**args) @@ -632,17 +753,22 @@ class radialgradient(SVGelement): def __init__(self,cx=None,cy=None,r=None,fx=None,fy=None,id=None,**args): SVGelement.__init__(self,'radialGradient',**args) if cx<>None: - self.addAttribute(Attribute('cx', cx)) + self.setAttribute(Attribute('cx', cx)) if cy<>None: - self.addAttribute(Attribute('cy', cy)) + self.setAttribute(Attribute('cy', cy)) if r<>None: - self.addAttribute(Attribute('r', r)) + self.setAttribute(Attribute('r', r)) if fx<>None: - self.addAttribute(Attribute('fx', fx)) + self.setAttribute(Attribute('fx', fx)) if fy<>None: - self.addAttribute(Attribute('fy', fy)) + self.setAttribute(Attribute('fy', fy)) if id<>None: - self.addAttribute(Attribute('id', id)) + self.setAttribute(Attribute('id', id)) + + def _construct(attributes): + return radialgradient() + _construct = staticmethod(_construct) + class stop(SVGelement): """st=stop(offset,stop_color,**args) @@ -652,7 +778,12 @@ class stop(SVGelement): def __init__(self,offset,stop_color=None,**args): SVGelement.__init__(self,'stop',{'offset':offset},**args) if stop_color<>None: - self.addAttribute(Attribute('stop-color', stop_color)) + self.setAttribute(Attribute('stop-color', stop_color)) + + def _construct(attributes): + offset = get_attr_value(attributes, 'offset') + return stop(offset) + _construct = staticmethod(_construct) class style(SVGelement): """st=style(type,cdata=None,**args) @@ -661,6 +792,11 @@ class style(SVGelement): """ def __init__(self,type,cdata=None,**args): SVGelement.__init__(self,'style',{'type':type},cdata=cdata, **args) + + def _construct(attributes): + type = get_attr_value(attributes, 'type') + return style(type) + _construct = staticmethod(_construct) class image(SVGelement): @@ -677,12 +813,22 @@ class image(SVGelement): else: raise ValueError, 'both height and width are required' SVGelement.__init__(self,'image',{'width':width,'height':height},**args) - self.addAttribute(Attribute('href', url, 'xlink', xlinkNSRef)) + self.setAttribute(Attribute('href', url, 'xlink', xlinkNSRef)) if x<>None: - self.addAttribute(Attribute('x', x)) + self.setAttribute(Attribute('x', x)) if y<>None: - self.addAttribute(Attribute('y', y)) + self.setAttribute(Attribute('y', y)) + def _construct(attributes): + href = get_attr_value(attributes, 'xlink:href') + if href and href.startswith("xlink:"): + href = href[len("xlink:"):] + width = get_attr_value(attributes, 'width') + height = get_attr_value(attributes, 'height') + return image(href, width=width, height=height) + _construct = staticmethod(_construct) + + class cursor(SVGelement): """c=cursor(url,**args) @@ -690,7 +836,14 @@ class cursor(SVGelement): """ def __init__(self,url,**args): SVGelement.__init__(self,'cursor',**args) - self.addAttribute(Attribute('href', url, 'xlink', xlinkNSRef)) + self.setAttribute(Attribute('href', url, 'xlink', xlinkNSRef)) + + def _construct(attributes): + href = get_attr_value(attributes, 'xlink:href') + if href and href.startswith("xlink:"): + href = href[len("xlink:"):] + return cursor(href) + _construct = staticmethod(_construct) class marker(SVGelement): @@ -702,17 +855,22 @@ class marker(SVGelement): def __init__(self,id=None,viewBox=None,refx=None,refy=None,markerWidth=None,markerHeight=None,**args): SVGelement.__init__(self,'marker',**args) if id<>None: - self.addAttribute(Attribute('id', id)) + self.setAttribute(Attribute('id', id)) if viewBox<>None: - self.addAttribute(Attribute('viewBox', _viewboxlist(viewBox))) + self.setAttribute(Attribute('viewBox', _viewboxlist(viewBox))) if refx<>None: - self.addAttribute(Attribute('refX', refx)) + self.setAttribute(Attribute('refX', refx)) if refy<>None: - self.addAttribute(Attribute('refY', refy)) + self.setAttribute(Attribute('refY', refy)) if markerWidth<>None: - self.addAttribute(Attribute('markerWidth', markerWidth)) + self.setAttribute(Attribute('markerWidth', markerWidth)) if markerHeight<>None: - self.addAttribute(Attribute('markerHeight', markerHeight)) + self.setAttribute(Attribute('markerHeight', markerHeight)) + + def _construct(attributes): + return marker() + _construct = staticmethod(_construct) + class group(SVGelement): """g=group(id,**args) @@ -723,7 +881,11 @@ class group(SVGelement): def __init__(self,id=None,**args): SVGelement.__init__(self,'g',**args) if id<>None: - self.addAttribute(Attribute('id', id)) + self.setAttribute(Attribute('id', id)) + + def _construct(attributes): + return group() + _construct = staticmethod(_construct) class symbol(SVGelement): """sy=symbol(id,viewbox,**args) @@ -737,9 +899,14 @@ class symbol(SVGelement): def __init__(self,id=None,viewBox=None,**args): SVGelement.__init__(self,'symbol',**args) if id<>None: - self.addAttribute(Attribute('id', id)) + self.setAttribute(Attribute('id', id)) if viewBox<>None: - self.addAttribute(Attribute('viewBox', _viewboxlist(viewBox))) + self.setAttribute(Attribute('viewBox', _viewboxlist(viewBox))) + + def _construct(attributes): + return symbol() + _construct = staticmethod(_construct) + class defs(SVGelement): """d=defs(**args) @@ -749,6 +916,11 @@ class defs(SVGelement): def __init__(self,**args): SVGelement.__init__(self,'defs',**args) + def _construct(attributes): + return defs() + _construct = staticmethod(_construct) + + class switch(SVGelement): """sw=switch(**args) @@ -759,7 +931,11 @@ class switch(SVGelement): def __init__(self,**args): SVGelement.__init__(self,'switch',**args) - + def _construct(attributes): + return switch() + _construct = staticmethod(_construct) + + class use(SVGelement): """u=use(link,x,y,width,height,**args) @@ -767,18 +943,25 @@ class use(SVGelement): """ def __init__(self,link,x=None,y=None,width=None,height=None,**args): SVGelement.__init__(self,'use',**args) - self.addAttribute(Attribute('href', link, 'xlink', xlinkNSRef)) + self.setAttribute(Attribute('href', link, 'xlink', xlinkNSRef)) if x<>None: - self.addAttribute(Attribute('x', x)) + self.setAttribute(Attribute('x', x)) if y<>None: - self.addAttribute(Attribute('y', y)) + self.setAttribute(Attribute('y', y)) if width<>None: - self.addAttribute(Attribute('width', width)) + self.setAttribute(Attribute('width', width)) if height<>None: - self.addAttribute(Attribute('height', height)) - - + self.setAttribute(Attribute('height', height)) + + def _construct(attributes): + href = get_attr_value(attributes, 'xlink:href') + if href and href.startswith("xlink:"): + href = href[len("xlink:"):] + return use(href) + _construct = staticmethod(_construct) + + class link(SVGelement): """a=link(url,**args) @@ -787,7 +970,15 @@ class link(SVGelement): """ def __init__(self,link='',**args): SVGelement.__init__(self,'a',**args) - self.addAttribute(Attribute('href', link, 'xlink', xlinkNSRef)) + self.setAttribute(Attribute('href', link, 'xlink', xlinkNSRef)) + + def _construct(attributes): + href = get_attr_value(attributes, 'xlink:href') + if href and href.startswith("xlink:"): + href = href[len("xlink:"):] + return link(href) + _construct = staticmethod(_construct) + class view(SVGelement): """v=view(id,**args) @@ -796,7 +987,12 @@ class view(SVGelement): def __init__(self,id=None,**args): SVGelement.__init__(self,'view',**args) if id<>None: - self.addAttribute(Attribute('id', id)) + self.setAttribute(Attribute('id', id)) + + def _construct(attributes): + return view() + _construct = staticmethod(_construct) + class script(SVGelement): """sc=script(type,type,cdata,**args) @@ -806,6 +1002,12 @@ class script(SVGelement): """ def __init__(self,type,cdata=None,**args): SVGelement.__init__(self,'script',{'type':type},cdata=cdata,**args) + + def _construct(attributes): + type = get_attr_value(attributes, 'type') + return script(type, cdata=cdata) + _construct = staticmethod(_construct) + class animate(SVGelement): """an=animate(attribute,from,to,during,**args) @@ -815,23 +1017,34 @@ class animate(SVGelement): def __init__(self,attribute,fr=None,to=None,dur=None,**args): SVGelement.__init__(self,'animate',{'attributeName':attribute},**args) if fr<>None: - self.addAttribute(Attribute('from', fr)) + self.setAttribute(Attribute('from', fr)) if to<>None: - self.addAttribute(Attribute('to', to)) + self.setAttribute(Attribute('to', to)) if dur<>None: - self.addAttribute(Attribute('dur', dur)) + self.setAttribute(Attribute('dur', dur)) + + def _construct(attributes): + attribute = get_attr_value(attributes, 'attributeName') + return animate(attribute) + _construct = staticmethod(_construct) + class animateMotion(SVGelement): """an=animateMotion(pathdata,dur,**args) animates a SVGelement over the given path in dur seconds """ - def __init__(self,pathdata,dur,**args): + def __init__(self,pathdata=None,dur=None,**args): SVGelement.__init__(self,'animateMotion',**args) if pathdata<>None: - self.addAttribute(Attribute('path', str(pathdata))) + self.setAttribute(Attribute('path', str(pathdata))) if dur<>None: - self.addAttribute(Attribute('dur', dur)) + self.setAttribute(Attribute('dur', dur)) + + def _construct(attributes): + return animateMotion() + _construct = staticmethod(_construct) + class animateTransform(SVGelement): """antr=animateTransform(type,from,to,dur,**args) @@ -842,13 +1055,19 @@ class animateTransform(SVGelement): SVGelement.__init__(self,'animateTransform',{'attributeName':'transform'},**args) #As far as I know the attributeName is always transform if type<>None: - self.addAttribute(Attribute('type', type)) + self.setAttribute(Attribute('type', type)) if fr<>None: - self.addAttribute(Attribute('from', fr)) + self.setAttribute(Attribute('from', fr)) if to<>None: - self.addAttribute(Attribute('to', to)) + self.setAttribute(Attribute('to', to)) if dur<>None: - self.addAttribute(Attribute('dur', dur)) + self.setAttribute(Attribute('dur', dur)) + + def _construct(attributes): + return animateTransform() + _construct = staticmethod(_construct) + + class animateColor(SVGelement): """ac=animateColor(attribute,type,from,to,dur,**args) @@ -857,13 +1076,20 @@ class animateColor(SVGelement): def __init__(self,attribute,type=None,fr=None,to=None,dur=None,**args): SVGelement.__init__(self,'animateColor',{'attributeName':attribute},**args) if type<>None: - self.addAttribute(Attribute('type', type)) + self.setAttribute(Attribute('type', type)) if fr<>None: - self.addAttribute(Attribute('from', fr)) + self.setAttribute(Attribute('from', fr)) if to<>None: - self.addAttribute(Attribute('to', to)) + self.setAttribute(Attribute('to', to)) if dur<>None: - self.addAttribute(Attribute('dur', dur)) + self.setAttribute(Attribute('dur', dur)) + + def _construct(attributes): + attribute = get_attr_value(attributes, 'attributeName') + return animateColor(attribute) + _construct = staticmethod(_construct) + + class set(SVGelement): """st=set(attribute,to,during,**args) @@ -872,12 +1098,16 @@ class set(SVGelement): def __init__(self,attribute,to=None,dur=None,**args): SVGelement.__init__(self,'set',{'attributeName':attribute},**args) if to<>None: - self.addAttribute(Attribute('to', to)) + self.setAttribute(Attribute('to', to)) if dur<>None: - self.addAttribute(Attribute('dur', dur)) + self.setAttribute(Attribute('dur', dur)) + + def _construct(attributes): + attribute = get_attr_value(attributes, 'attributeName') + return set(attribute) + _construct = staticmethod(_construct) - class svg(SVGelement): """s=svg(viewbox,width,height,**args) @@ -896,12 +1126,113 @@ class svg(SVGelement): def __init__(self,viewBox=None, width=None, height=None,**args): SVGelement.__init__(self,'svg',**args) if viewBox<>None: - self.addAttribute(Attribute('viewBox', _viewboxlist(viewBox))) + self.setAttribute(Attribute('viewBox', _viewboxlist(viewBox))) if width<>None: - self.addAttribute(Attribute('width', width)) + self.setAttribute(Attribute('width', width)) if height<>None: - self.addAttribute(Attribute('height', height_)) + self.setAttribute(Attribute('height', height_)) self.namespace="http://www.w3.org/2000/svg" + + def _construct(attributes): + return svg() + _construct = staticmethod(_construct) + + +class ElementHelper(object): + def __init__(self, name, attrs): + self.name = name + self.attrs = attrs + self.cdata = None + self.text = None + +class Stack(object): + def __init__(self): + self._stack = [] + + def push(self, obj): + self._stack.append(obj) + + def pop(self): + if len(self._stack) == 0: + return None + obj = self._stack[-1] + del self._stack[-1] + return obj + + def peek(self): + if len(self._stack) == 0: + return None + return self._stack[-1] + + def is_empty(self): + if len(self._stack) == 0: + return True + return False + + def size(self): + return len(self._stack) + +class SVGImportParser(object): + def __init__(self): + self._indent = 0 + self._cdata = 0 + self._stack = Stack() + self._base = None + self._debug = False + + def getBaseElement(self): + return self._base + + def log(self, msg): + if self._debug: + print " " * self._indent + msg + + def StartElementHandler(self, name, attrs): + self.log("<%s>" % name) + self._indent = self._indent + 1 + for attrname, attrvalue in attrs.items(): + self.log("%s = %s" % (attrname, attrvalue)) + parent = self._stack.peek() + elt = SVGelement.construct(name, attrs) + if not self._base: + self._base = elt + if parent: + parent.addElement(elt) + self._stack.push(elt) + + def StartCdataSectionHandler(self): + self._cdata = 1 + + def CharacterDataHandler(self, content): + if self._cdata: + self.log("CDATA = '%s'" % content) + elt = self._stack.peek() + if elt: + elt.cdata = elt.cdata + content + else: + if len(content) and not content.isspace(): + self.log("Text = '%s'" % content.strip()) + elt = self._stack.peek() + if elt: + elt.text = elt.text + content.strip() + + def EndCdataSectionHandler(self): + self._cdata = 0 + + def EndElementHandler(self, name): + self._indent = self._indent - 1 + self.log("" % name) + self._stack.pop() + + def CommentHandler(self, comment): + self.log("Comment = '%s'" % comment) + + def StartNamespaceDeclHandler(self, prefix, uri): + self.log("Namespace = '%s' -> '%s'" % (prefix, uri)) + + def EndNamespaceDeclHandler(self, prefix): + self.log("Namespace = '%s'" % prefix) + class drawing: """d=drawing() @@ -921,6 +1252,30 @@ class drawing: self.svg=svg #Voeg een element toe aan de grafiek toe. + def fromXml(self, xml): + HANDLER_NAMES = [ + 'StartElementHandler', 'EndElementHandler', + 'CharacterDataHandler', + 'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler', + 'CommentHandler', + 'StartCdataSectionHandler', 'EndCdataSectionHandler', + ] + + # Create a parser + parser = expat.ParserCreate() + + handler = SVGImportParser() + for name in HANDLER_NAMES: + setattr(parser, name, getattr(handler, name)) + parser.returns_unicode = 0 + + # Parse the XML + parser.Parse(xml) + base_element = handler.getBaseElement() + if not base_element or not isinstance(base_element, svg): + raise Exception("Base element was not SVG.") + self.setSVG(base_element) + if use_dom_implementation==0: def toXml(self, filename='',compress=False): import cStringIO @@ -1032,13 +1387,60 @@ class drawing: print "SVG well formed" -if __name__=='__main__': +elementTable = { + 'tspan': tspan, + 'tref': tref, + 'rect': rect, + 'ellipse': ellipse, + 'circle': circle, + 'line': line, + 'polyline': polyline, + 'polygon': polygon, + 'path': path, + 'text': text, + 'textPath': textpath, + 'pattern': pattern, + 'title': title, + 'desc': description, + 'linearGradient': lineargradient, + 'radialGradient': radialgradient, + 'stop': stop, + 'style': style, + 'image': image, + 'cursor': cursor, + 'marker': marker, + 'g': group, + 'symbol': symbol, + 'defs': defs, + 'switch': switch, + 'use': use, + 'a': link, + 'view': view, + 'script': script, + 'animate': animate, + 'animateMotion': animateMotion, + 'animateTransform': animateTransform, + 'animateColor': animateColor, + 'set': set, + 'svg': svg +} - +def main(): d=drawing() + import sys + f = open(sys.argv[1], "r") + fc = f.read() + d.fromXml(fc) + print d.toXml() + return + + s=svg((0,0,100,100)) r=rect(-100,-100,300,300,'cyan') s.addElement(r) + + text = tspan("Foobar") + s.addElement(text) t=title('SVGdraw Demo') s.addElement(t) @@ -1052,8 +1454,8 @@ if __name__=='__main__': pd.relsmbezier(10,5,0,10) pd.relsmbezier(-10,5,0,10) an=animateMotion(pd,10) - an.addAttribute(Attribute('rotate', 'auto-reverse')) - an.addAttribute(Attribute('repeatCount', "indefinite")) + an.setAttribute(Attribute('rotate', 'auto-reverse')) + an.setAttribute(Attribute('repeatCount', "indefinite")) g.addElement(an) s.addElement(g) for i in range(20,120,20): @@ -1067,3 +1469,6 @@ if __name__=='__main__': print d.toXml() + +if __name__=='__main__': + main() diff --git a/sugar/chat/chat.py b/sugar/chat/chat.py index fef2c838..2bc72305 100755 --- a/sugar/chat/chat.py +++ b/sugar/chat/chat.py @@ -10,11 +10,9 @@ pygtk.require('2.0') import gtk, gobject from sugar.shell import activity -from sugar.p2p.Group import Group -from sugar.p2p.Group import LocalGroup -from sugar.p2p.Service import Service -from sugar.p2p.StreamReader import StreamReader -from sugar.p2p.StreamWriter import StreamWriter +from sugar.p2p.Group import * +from sugar.p2p.StreamReader import * +from sugar.p2p.StreamWriter import * import sugar.env import richtext @@ -73,14 +71,14 @@ class Chat(activity.Activity): self._hbox = gtk.HBox(False, 12) self._hbox.set_border_width(12) - [chat_vbox, buf] = self._create_chat() + [chat_vbox, buffer] = self._create_chat() self._hbox.pack_start(chat_vbox) chat_vbox.show() vbox.pack_start(self._hbox) self._hbox.show() - toolbar = self._create_toolbar(buf) + toolbar = self._create_toolbar(buffer) vbox.pack_start(toolbar, False) toolbar.show() @@ -132,37 +130,37 @@ class Chat(activity.Activity): button.set_menu(menu) def activity_on_close_from_user(self): - print "act %d: in activity_on_close_from_user" % self.activity_get_id() + print "act %d: in activity_on_close_from_user"%self.activity_get_id() self.activity_shutdown() def activity_on_lost_focus(self): - print "act %d: in activity_on_lost_focus" % self.activity_get_id() + print "act %d: in activity_on_lost_focus"%self.activity_get_id() def activity_on_got_focus(self): - print "act %d: in activity_on_got_focus" % self.activity_get_id() - # FIXME self._controller.notify_activate(self) + print "act %d: in activity_on_got_focus"%self.activity_get_id() + self._controller.notify_activate(self) def recv_message(self, buddy, msg): self._insert_rich_message(buddy.get_nick_name(), msg) self._controller.notify_new_message(self, buddy) def _insert_rich_message(self, nick, msg): - buf = self._chat_view.get_buffer() - aniter = buf.get_end_iter() - buf.insert(aniter, nick + ": ") + buffer = self._chat_view.get_buffer() + aniter = buffer.get_end_iter() + buffer.insert(aniter, nick + ": ") serializer = richtext.RichTextSerializer() - serializer.deserialize(msg, buf) + serializer.deserialize(msg, buffer) - aniter = buf.get_end_iter() - buf.insert(aniter, "\n") + aniter = buffer.get_end_iter() + buffer.insert(aniter, "\n") def _local_message(self, success, text): if not success: message = "Error: %s\n" % text - buf = self._chat_view.get_buffer() - aniter = buf.get_end_iter() - buf.insert(aniter, message) + buffer = self._chat_view.get_buffer() + aniter = buffer.get_end_iter() + buffer.insert(aniter, message) else: owner = self._controller.get_group().get_owner() self._insert_rich_message(owner.get_nick_name(), text) @@ -327,11 +325,11 @@ class GroupChat(Chat): if buddy.get_nick_name() == self._group.get_owner().get_nick_name(): # Do not show ourself in the buddy list pass - elif action == Group.BUDDY_JOIN: + elif action == BUDDY_JOIN: aniter = self._buddy_list_model.append(None) self._buddy_list_model.set(aniter, self._MODEL_COL_NICK, buddy.get_nick_name(), self._MODEL_COL_ICON, None, self._MODEL_COL_BUDDY, buddy) - elif action == Group.BUDDY_LEAVE: + elif action == BUDDY_LEAVE: aniter = self._get_iter_for_buddy(buddy) if aniter: self._buddy_list_model.remove(aniter) @@ -348,7 +346,7 @@ class GroupChat(Chat): aniter = self._get_iter_for_buddy(buddy) self._buddy_list_model.set(aniter, self._MODEL_COL_ICON, self._pixbuf_new_message) - def notify_activate(self, chat, buddy): + def notify_activate(self, chat): aniter = self._get_iter_for_buddy(buddy) self._buddy_list_model.set(aniter, self._MODEL_COL_ICON, self._pixbuf_active_chat) @@ -389,16 +387,19 @@ class ChatShell(dbus.service.Object): dbus.service.Object.__init__(self, bus_name, object_path) def open_group_chat(self): - self._group_chat = GroupChat() - self._group_chat.activity_connect_to_shell() + group_chat = GroupChat() + group_chat.activity_connect_to_shell() @dbus.service.method('com.redhat.Sugar.ChatShell') def send_message(self, message): - self._group_chat.send_message(message) + pass def main(): ChatShell.get_instance().open_group_chat() - gtk.main() + try: + gtk.main() + except KeyboardInterrupt: + pass if __name__ == "__main__": main() diff --git a/sugar/chat/richtext.py b/sugar/chat/richtext.py index ecb15c2e..0ac70b16 100644 --- a/sugar/chat/richtext.py +++ b/sugar/chat/richtext.py @@ -45,7 +45,7 @@ class RichTextView(gtk.TextView): def __motion_notify_cb(self, widget, event): if event.is_hint: - event.window.get_pointer(); + [x, y, state] = event.window.get_pointer(); it = self.__get_event_iter(event) if it: @@ -134,9 +134,9 @@ class RichTextBuffer(gtk.TextBuffer): def __insert_text_cb(self, widget, pos, text, length): for tag in self.active_tags: - pos_end = pos.copy() - pos_end.backward_chars(length) - self.apply_tag_by_name(tag, pos, pos_end) + pos_end = pos.copy() + pos_end.backward_chars(length) + self.apply_tag_by_name(tag, pos, pos_end) class RichTextToolbar(gtk.Toolbar): def __init__(self, buf): @@ -205,7 +205,6 @@ class RichTextToolbar(gtk.Toolbar): class RichTextHandler(xml.sax.handler.ContentHandler): def __init__(self, serializer, buf): - xml.sax.handler.ContentHandler.__init__(self) self.buf = buf self.serializer = serializer self.tags = [] @@ -287,7 +286,7 @@ class RichTextSerializer: def serialize(self, buf): self.buf = buf - res = "" + xml = "" next_it = buf.get_start_iter() while not next_it.is_end(): @@ -300,29 +299,29 @@ class RichTextSerializer: for tag in it.get_toggled_tags(False): while 1: open_tag = self._open_tags.pop() - res += self.serialize_tag_end(tag) + xml += self.serialize_tag_end(tag) if open_tag == tag: break tags_to_reopen.append(open_tag) for tag in tags_to_reopen: self._open_tags.append(tag) - res += self.serialize_tag_start(tag, it) + xml += self.serialize_tag_start(tag, it) for tag in it.get_toggled_tags(True): self._open_tags.append(tag) - res += self.serialize_tag_start(tag, it) + xml += self.serialize_tag_start(tag, it) - res += buf.get_text(it, next_it, False) + xml += buf.get_text(it, next_it, False) if next_it.is_end(): self._open_tags.reverse() for tag in self._open_tags: - res += self.serialize_tag_end(tag) + xml += self.serialize_tag_end(tag) - res += "" + xml += "" - return res + return xml def deserialize(self, xml_string, buf): parser = xml.sax.make_parser() @@ -331,11 +330,11 @@ class RichTextSerializer: parser.feed(xml_string) parser.close() -def test_quit(w, rb): - print RichTextSerializer().serialize(rb) +def test_quit(window, rich_buf): + print RichTextSerializer().serialize(rich_buf) gtk.main_quit() -def link_clicked(v, address): +def link_clicked(view, address): print "Link clicked " + address if __name__ == "__main__": @@ -351,15 +350,15 @@ if __name__ == "__main__": rich_buf = view.get_buffer() - test_xml = "" + xml_string = "" - test_xml += "Testone\n" - test_xml += "Test two" - test_xml += "Test three" - test_xml += "Test link" - test_xml += "" + xml_string += "Testone\n" + xml_string += "Test two" + xml_string += "Test three" + xml_string += "Test link" + xml_string += "" - RichTextSerializer().deserialize(test_xml, rich_buf) + RichTextSerializer().deserialize(xml_string, rich_buf) toolbar = RichTextToolbar(rich_buf) vbox.pack_start(toolbar, False) diff --git a/sugar/env.py b/sugar/env.py index 3b812d32..e30daa2d 100644 --- a/sugar/env.py +++ b/sugar/env.py @@ -1,7 +1,9 @@ +import os + try: - from sugar.__uninstalled__ import internal_get_data_file + from sugar.__uninstalled__ import * except ImportError: - from sugar.__installed__ import internal_get_data_file + from sugar.__installed__ import * def get_data_file(filename): return internal_get_data_file(filename) diff --git a/sugar/p2p/Buddy.py b/sugar/p2p/Buddy.py index 8263a8e3..19d7c0ef 100644 --- a/sugar/p2p/Buddy.py +++ b/sugar/p2p/Buddy.py @@ -1,7 +1,7 @@ import pwd import os -from Service import Service +from Service import * PRESENCE_SERVICE_TYPE = "_olpc_presence._tcp" PRESENCE_SERVICE_PORT = 6000 diff --git a/sugar/p2p/Group.py b/sugar/p2p/Group.py index faa6041c..dedbc1ed 100644 --- a/sugar/p2p/Group.py +++ b/sugar/p2p/Group.py @@ -1,26 +1,21 @@ -from Buddy import Buddy -from Buddy import Owner -from Buddy import PRESENCE_SERVICE_TYPE -from Service import Service -from sugar.p2p.model.Store import Store +import avahi + import presence +from Buddy import * +from Service import * + +SERVICE_ADDED = "service_added" +SERVICE_REMOVED = "service_removed" + +BUDDY_JOIN = "buddy_join" +BUDDY_LEAVE = "buddy_leave" class Group: - SERVICE_ADDED = "service_added" - SERVICE_REMOVED = "service_removed" - - BUDDY_JOIN = "buddy_join" - BUDDY_LEAVE = "buddy_leave" - def __init__(self): self._service_listeners = [] self._presence_listeners = [] - self._store = Store(self) - def get_store(self): - return self._store - - def join(self): + def join(self, buddy): pass def add_service_listener(self, listener): @@ -31,19 +26,19 @@ class Group: def _notify_service_added(self, service): for listener in self._service_listeners: - listener(Group.SERVICE_ADDED, service) + listener(SERVICE_ADDED, buddy) - def _notify_service_removed(self, service_id): + def _notify_service_removed(self, service): for listener in self._service_listeners: - listener(Group.SERVICE_REMOVED, service_id) + listener(SERVICE_REMOVED,buddy) def _notify_buddy_join(self, buddy): for listener in self._presence_listeners: - listener(Group.BUDDY_JOIN, buddy) + listener(BUDDY_JOIN, buddy) def _notify_buddy_leave(self, buddy): for listener in self._presence_listeners: - listener(Group.BUDDY_LEAVE, buddy) + listener(BUDDY_LEAVE, buddy) class LocalGroup(Group): def __init__(self): @@ -64,19 +59,16 @@ class LocalGroup(Group): self._services[sid] = service self._notify_service_added(service) - def remove_service(self, service_id): - self._notify_service_removed(service_id) - del self._services[service_id] + def remove_service(self, sid): + self._notify_service_removed(service) + del self._services[sid] def join(self): self._owner = Owner(self) self._owner.register() def get_service(self, name, stype): - if self._services.has_key((name, stype)): - return self._services[(name, stype)] - else: - return None + return self._services[(name, stype)] def get_buddy(self, name): return self._buddies[name] @@ -103,8 +95,8 @@ class LocalGroup(Group): def _on_service_resolved(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags): - service = Service(name, stype, address, port) - if stype == PRESENCE_SERVICE_TYPE: - self._add_buddy(Buddy(service, name)) - elif stype.startswith("_olpc"): - self.add_service(service) + service = Service(name, stype, address, port) + if stype == PRESENCE_SERVICE_TYPE: + self._add_buddy(Buddy(service, name)) + elif stype.startswith("_olpc"): + self.add_service(service) diff --git a/sugar/p2p/NotificationListener.py b/sugar/p2p/NotificationListener.py deleted file mode 100644 index e490f390..00000000 --- a/sugar/p2p/NotificationListener.py +++ /dev/null @@ -1,27 +0,0 @@ -from Service import Service -import network - -class NotificationListener: - TYPE = "_olpc_model_notification._udp" - ADDRESS = "224.0.0.222" - PORT = 6300 - - def __init__(self, group, name): - server = network.GroupServer(NotificationListener.TYPE, - NotificationListener.PORT, - self._recv_multicast) - server.start() - - service = Service(name, NotificationListener.TYPE, - NotificationListener.ADDRESS, - NotificationListener.PORT, True) - service.register(group) - - self._listeners = {} - - def add_listener(self, listener): - self._listeners.add(listener) - - def _recv_multicast(self, msg): - for listener in self._listeners: - listener(msg) diff --git a/sugar/p2p/Notifier.py b/sugar/p2p/Notifier.py deleted file mode 100644 index 017183c9..00000000 --- a/sugar/p2p/Notifier.py +++ /dev/null @@ -1,11 +0,0 @@ -import network - -class Notifier: - def __init__(self, group, name): - service = group.get_service(name) - address = service.get_address() - port = service.get_port() - self._client = network.GroupClient(address, port) - - def notify(self, msg): - self._client.send_msg(msg) diff --git a/sugar/p2p/StreamReader.py b/sugar/p2p/StreamReader.py index d3dbf83e..c108547b 100644 --- a/sugar/p2p/StreamReader.py +++ b/sugar/p2p/StreamReader.py @@ -1,5 +1,3 @@ -import socket - import network class StreamReaderRequestHandler(object): @@ -7,6 +5,7 @@ class StreamReaderRequestHandler(object): self._reader = reader def message(self, nick_name, message): + address = network.get_authinfo() self._reader.recv(nick_name, message) return True @@ -38,7 +37,7 @@ class StreamReader: p2p_server = network.GlibXMLRPCServer(("", port)) p2p_server.register_instance(StreamReaderRequestHandler(self)) started = True - except(socket.error): + except: port = port + 1 tries = tries - 1 self._service.set_port(port) diff --git a/sugar/p2p/StreamWriter.py b/sugar/p2p/StreamWriter.py index 6007a934..f30801ea 100644 --- a/sugar/p2p/StreamWriter.py +++ b/sugar/p2p/StreamWriter.py @@ -31,7 +31,7 @@ class StreamWriter: nick_name = self._group.get_owner().get_nick_name() self._uclient.message(nick_name, data) return True - except (socket.error, xmlrpclib.Fault, xmlrpclib.ProtocolError): + except (socket.error, xmlrpclib.Fault, xmlrpclib.ProtocolError), e: traceback.print_exc() return False diff --git a/sugar/p2p/model/AbstractModel.py b/sugar/p2p/model/AbstractModel.py deleted file mode 100644 index a5fbe493..00000000 --- a/sugar/p2p/model/AbstractModel.py +++ /dev/null @@ -1,10 +0,0 @@ -class AbstractModel: - def __init__(self): - self._listeners = [] - - def add_listener(self, listener): - self._listeners.append(listener) - - def _notify_model_change(self, key): - for listener in self._listeners: - listener(self, key) diff --git a/sugar/p2p/model/LocalModel.py b/sugar/p2p/model/LocalModel.py deleted file mode 100644 index 89171924..00000000 --- a/sugar/p2p/model/LocalModel.py +++ /dev/null @@ -1,55 +0,0 @@ -import socket - -from sugar.p2p.Service import Service -from sugar.p2p.model.AbstractModel import AbstractModel -from sugar.p2p import network - -class ModelRequestHandler(object): - def __init__(self, model): - self._model = model - - def get_value(self, key): - return self._model.get_value(key) - - def set_value(self, key, value): - return self._model.set_value(key, value) - -class LocalModel(AbstractModel): - SERVICE_TYPE = "_olpc_model._tcp" - SERVICE_PORT = 6300 - - def __init__(self, group, model_id): - AbstractModel.__init__(self) - self._group = group - self._model_id = model_id - self._values = {} - - self._setup_service() - - def get_value(self, key): - return self._values[key] - - def set_value(self, key, value): - self._values[key] = value - self._notify_model_change(key) - - def _setup_service(self): - service = Service(self._model_id, LocalModel.SERVICE_TYPE, '', - LocalModel.SERVICE_PORT) - self._setup_server(service) - service.register(self._group) - - # FIXME this is duplicated with StreamReader - def _setup_server(self, service): - started = False - tries = 10 - port = service.get_port() - while not started and tries > 0: - try: - p2p_server = network.GlibXMLRPCServer(("", port)) - p2p_server.register_instance(ModelRequestHandler(self)) - started = True - except(socket.error): - port = port + 1 - tries = tries - 1 - service.set_port(port) diff --git a/sugar/p2p/model/Makefile.am b/sugar/p2p/model/Makefile.am deleted file mode 100644 index c828a086..00000000 --- a/sugar/p2p/model/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pythondir)/sugar/p2p/model -sugar_PYTHON = \ - __init__.py \ - LocalModel.py \ - RemoteModel.py \ - Store.py diff --git a/sugar/p2p/model/RemoteModel.py b/sugar/p2p/model/RemoteModel.py deleted file mode 100644 index b966b435..00000000 --- a/sugar/p2p/model/RemoteModel.py +++ /dev/null @@ -1,26 +0,0 @@ -import xmlrpclib - -from sugar.p2p.NotificationListener import NotificationListener -from sugar.p2p.model.AbstractModel import AbstractModel - -class RemoteModel(AbstractModel): - def __init__(self, service): - AbstractModel.__init__(self) - - self._service = service - - addr = "http://%s:%d" % (service.get_address(), service.get_port()) - self._client = xmlrpclib.ServerProxy(addr) - - self._setup_notification_listener() - - def get_value(self, key): - return self._client.get_value(key) - - def set_value(self, key, value): - self._client.set_value(key, value) - - def _setup_notification_listener(self): - name = self._service.get_name() - self._notification = NotificationListener(self._group, name) - self._notification.add_listener(self._notify_model_change) diff --git a/sugar/p2p/model/Store.py b/sugar/p2p/model/Store.py deleted file mode 100644 index d39783f4..00000000 --- a/sugar/p2p/model/Store.py +++ /dev/null @@ -1,22 +0,0 @@ -from sugar.p2p.model.RemoteModel import RemoteModel -from sugar.p2p.model.LocalModel import LocalModel - -class Store: - def __init__(self, group): - self._group = group - self._local_models = {} - - def create_model(self, model_id): - model = LocalModel(self._group, model_id) - self._local_models[model_id] = model - return model - - def get_model(self, model_id): - if self._local_models.has_key(model_id): - return self._local_models(model_id) - else: - service = self._group.get_service(model_id, LocalModel.SERVICE_TYPE) - if service: - return RemoteModel(service) - else: - return None diff --git a/sugar/p2p/model/__init__.py b/sugar/p2p/model/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/sugar/p2p/network.py b/sugar/p2p/network.py index 4c054fea..c88ede6c 100644 --- a/sugar/p2p/network.py +++ b/sugar/p2p/network.py @@ -1,6 +1,10 @@ +# -*- tab-width: 4; indent-tabs-mode: t -*- + import socket import threading import traceback +import select +import time import xmlrpclib import sys @@ -129,6 +133,10 @@ class GroupServer(object): # Set some options to make it multicast-friendly self._listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + self._listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + except: + pass self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 20) self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1) diff --git a/sugar/p2p/presence.py b/sugar/p2p/presence.py index 4c5c086f..e16fc928 100644 --- a/sugar/p2p/presence.py +++ b/sugar/p2p/presence.py @@ -65,7 +65,7 @@ class PresenceDiscovery(object): self._service_type_browsers[(interface, protocol, domain)] = b - def new_domain(self, interface, protocol, domain, flags): + def new_domain(self,interface, protocol, domain, flags): if domain != "local": return self.browse_domain(interface, protocol, domain) @@ -84,7 +84,7 @@ class PresenceAnnounce(object): self._hostname = "%s:%s" % (self.server.GetHostName(), rs_port) rs_name = self._hostname - info = ["%s=%s" % (k, v) for k, v in kwargs.items()] + info = ["%s=%s" % (k,v) for k,v in kwargs.items()] g.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, 0, rs_name, rs_service, "", "", # domain, host (let the system figure it out) dbus.UInt16(rs_port), info,) diff --git a/sugar/shell/activity.py b/sugar/shell/activity.py index 4678a9c0..6f1f3fc1 100644 --- a/sugar/shell/activity.py +++ b/sugar/shell/activity.py @@ -1,11 +1,15 @@ # -*- tab-width: 4; indent-tabs-mode: t -*- +import string + +import gc import dbus import dbus.service import dbus.glib +import gobject import pygtk pygtk.require('2.0') -import gtk +import gtk,sys class Activity(dbus.service.Object): @@ -32,21 +36,21 @@ class Activity(dbus.service.Object): "com.redhat.Sugar.Shell.ActivityContainer") self.__activity_id = self.__activity_container.add_activity("") - self.__object_path = "/com/redhat/Sugar/Shell/Activities/%d" % self.__activity_id + self.__object_path = "/com/redhat/Sugar/Shell/Activities/%d"%self.__activity_id - print "object_path = %s" % self.__object_path + print "object_path = %s"%self.__object_path self.__activity_object = dbus.Interface(self.__bus.get_object("com.redhat.Sugar.Shell", self.__object_path), \ "com.redhat.Sugar.Shell.ActivityHost") self.__window_id = self.__activity_object.get_host_xembed_id() - print "XEMBED window_id = %d" % self.__window_id + print "XEMBED window_id = %d"%self.__window_id self.__plug = gtk.Plug(self.__window_id) # Now let the Activity register a peer service so the Shell can poke it - self.__peer_service_name = "com.redhat.Sugar.Activity%d" % self.__activity_id - self.__peer_object_name = "/com/redhat/Sugar/Activity/%d" % self.__activity_id + self.__peer_service_name = "com.redhat.Sugar.Activity%d"%self.__activity_id + self.__peer_object_name = "/com/redhat/Sugar/Activity/%d"%self.__activity_id self.__service = dbus.service.BusName(self.__peer_service_name, bus=self.__bus) dbus.service.Object.__init__(self, self.__service, self.__peer_object_name) @@ -82,7 +86,7 @@ class Activity(dbus.service.Object): pixarray = [] pixstr = pixbuf.get_pixels(); for c in pixstr: - pixarray.append(c) + pixarray.append(c) self.__activity_object.set_tab_icon(pixarray, \ pixbuf.get_colorspace(), \ pixbuf.get_has_alpha(), \ @@ -159,16 +163,16 @@ class Activity(dbus.service.Object): # pure virtual methods def activity_on_connected_to_shell(self): - print "act %d: you need to override activity_on_connected_to_shell" % self.activity_get_id() + print "act %d: you need to override activity_on_connected_to_shell"%self.activity_get_id() def activity_on_disconnected_from_shell(self): - print "act %d: you need to override activity_on_disconnected_from_shell" % self.activity_get_id() - + print "act %d: you need to override activity_on_disconnected_from_shell"%self.activity_get_id() + def activity_on_close_from_user(self): - print "act %d: you need to override activity_on_close_from_user" % self.activity_get_id() + print "act %d: you need to override activity_on_close_from_user"%self.activity_get_id() def activity_on_lost_focus(self): - print "act %d: you need to override activity_on_lost_focus" % self.activity_get_id() + print "act %d: you need to override activity_on_lost_focus"%self.activity_get_id() def activity_on_got_focus(self): - print "act %d: you need to override activity_on_got_focus" % self.activity_get_id() + print "act %d: you need to override activity_on_got_focus"%self.activity_get_id() diff --git a/sugar/shell/shell.py b/sugar/shell/shell.py index 0dd3ea95..d5423079 100755 --- a/sugar/shell/shell.py +++ b/sugar/shell/shell.py @@ -1,9 +1,12 @@ #!/usr/bin/python # -*- tab-width: 4; indent-tabs-mode: t -*- +import string + import dbus import dbus.service import dbus.glib +import gobject import pygtk pygtk.require('2.0') import gtk @@ -24,7 +27,7 @@ class ActivityHost(dbus.service.Object): self.activity_id = activity_counter activity_counter += 1 - self.dbus_object_name = "/com/redhat/Sugar/Shell/Activities/%d" % self.activity_id + self.dbus_object_name = "/com/redhat/Sugar/Shell/Activities/%d"%self.activity_id #print "object name = %s"%self.dbus_object_name dbus.service.Object.__init__(self, activity_container.service, self.dbus_object_name) @@ -140,7 +143,7 @@ class ActivityHost(dbus.service.Object): #print " data = ", data pixstr = "" for c in data: - pixstr += chr(c) + pixstr += chr(c) pixbuf = gtk.gdk.pixbuf_new_from_data(pixstr, colorspace, has_alpha, bits_per_sample, width, height, rowstride) #print pixbuf @@ -222,11 +225,10 @@ class ActivityContainer(dbus.service.Object): self.window.add(self.notebook) self.window.connect("destroy", lambda w: gtk.main_quit()) + self.window.show() self.current_activity = None - def show(self): - self.window.show() def __focus_reply_cb(self): pass @@ -281,10 +283,10 @@ class ActivityContainer(dbus.service.Object): return activity.get_host_activity_id() def __print_activities(self): - print "__print_activities: %d activities registered" % len(self.activities) + print "__print_activities: %d activities registered"%len(self.activities) i = 0 for owner, activity in self.activities: - print " %d: owner=%s activity_object_name=%s" % (i, owner, activity.dbus_object_name) + print " %d: owner=%s activity_object_name=%s"%(i, owner, activity.dbus_object_name) i += 1 @@ -293,9 +295,11 @@ def main(): service = dbus.service.BusName("com.redhat.Sugar.Shell", bus=session_bus) activityContainer = ActivityContainer(service, session_bus) - activityContainer.show() - gtk.main() + try: + gtk.main() + except KeyboardInterrupt: + pass -if __name__ == "__main__": - main() +if __name__=="__main__": + main()