diff --git a/configure.ac b/configure.ac index 81b760fb..585134f5 100644 --- a/configure.ac +++ b/configure.ac @@ -154,8 +154,6 @@ services/console/interface/logviewer/Makefile services/console/interface/terminal/Makefile sugar/Makefile sugar/activity/Makefile -sugar/chat/Makefile -sugar/chat/sketchpad/Makefile sugar/clipboard/Makefile sugar/graphics/Makefile sugar/p2p/Makefile diff --git a/po/sugar.pot b/po/sugar.pot deleted file mode 100644 index ba2477c5..00000000 --- a/po/sugar.pot +++ /dev/null @@ -1,109 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-03-23 14:50+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - -#: ../services/clipboard/typeregistry.py:29 -msgid "Text snippet" -msgstr "" - -#: ../services/clipboard/typeregistry.py:57 -msgid "Image" -msgstr "" - -#: ../services/clipboard/typeregistry.py:77 -msgid "Web Page" -msgstr "" - -#: ../services/clipboard/typeregistry.py:103 -msgid "PDF file" -msgstr "" - -#: ../services/clipboard/typeregistry.py:123 -msgid "MS Word file" -msgstr "" - -#: ../services/clipboard/typeregistry.py:143 -msgid "RTF file" -msgstr "" - -#: ../services/clipboard/typeregistry.py:154 -msgid "Abiword file" -msgstr "" - -#: ../services/clipboard/typeregistry.py:165 -msgid "Squeak project" -msgstr "" - -#: ../services/clipboard/typeregistry.py:185 -msgid "OpenOffice text file" -msgstr "" - -#: ../services/clipboard/typeregistry.py:202 -msgid "Object" -msgstr "" - -#: ../shell/intro/intro.py:78 -msgid "Pick a buddy picture" -msgstr "" - -#: ../shell/intro/intro.py:101 -msgid "My Picture:" -msgstr "" - -#: ../shell/intro/intro.py:181 -msgid "My Name:" -msgstr "" - -#: ../shell/intro/intro.py:203 -msgid "My Color:" -msgstr "" - -#: ../shell/view/BuddyMenu.py:89 -msgid "Remove friend" -msgstr "" - -#: ../shell/view/BuddyMenu.py:93 -msgid "Make friend" -msgstr "" - -#: ../shell/view/BuddyMenu.py:103 -msgid "Invite" -msgstr "" - -#: ../shell/view/clipboardmenu.py:63 ../shell/view/clipboardmenu.py:79 -msgid "Remove" -msgstr "" - -#: ../shell/view/clipboardmenu.py:69 -msgid "Open" -msgstr "" - -#: ../shell/view/clipboardmenu.py:93 -msgid "Stop download" -msgstr "" - -#: ../shell/view/frame/ZoomBox.py:41 -msgid "Close" -msgstr "" - -#: ../sugar/graphics/optionmenu.py:72 -msgid "No options" -msgstr "" - -#: ../sugar/chat/ChatEditor.py:56 -msgid "Send" -msgstr "" diff --git a/shell/view/ActivityHost.py b/shell/view/ActivityHost.py index 8d43bc24..de23d4e7 100644 --- a/shell/view/ActivityHost.py +++ b/shell/view/ActivityHost.py @@ -19,7 +19,6 @@ import dbus from sugar.p2p import Stream from sugar.p2p import network -from sugar.chat import ActivityChat import OverlayWindow class ActivityChatWindow(gtk.Window): @@ -51,8 +50,8 @@ class ActivityHost: self._overlay_window = None win = self._gdk_window - self._chat_widget = ActivityChat.ActivityChat(self) - self._chat_window = ActivityChatWindow(win, self._chat_widget) + #self._chat_widget = ActivityChat.ActivityChat(self) + #self._chat_window = ActivityChatWindow(win, self._chat_widget) self._frame_was_visible = False diff --git a/sugar/Makefile.am b/sugar/Makefile.am index 3e8aee2c..fa171861 100644 --- a/sugar/Makefile.am +++ b/sugar/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = activity chat clipboard graphics p2p presence datastore +SUBDIRS = activity clipboard graphics p2p presence datastore sugardir = $(pythondir)/sugar sugar_PYTHON = \ @@ -7,6 +7,5 @@ sugar_PYTHON = \ env.py \ logger.py \ profile.py \ - simulator.py \ TracebackUtils.py \ util.py diff --git a/sugar/chat/ActivityChat.py b/sugar/chat/ActivityChat.py deleted file mode 100644 index ecba9af7..00000000 --- a/sugar/chat/ActivityChat.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging - -from sugar.chat.GroupChat import GroupChat - -class ActivityChat(GroupChat): - SERVICE_TYPE = "_olpc_activity_chat._udp" - - def __init__(self, activity): - GroupChat.__init__(self) - self._chat_service = None - - self.connect('destroy', self._destroy_cb) - - self._activity = activity - self._pservice.register_service_type(ActivityChat.SERVICE_TYPE) - self._pservice.connect('service-appeared', self._service_appeared_cb) - - # Find an existing activity chat to latch onto - ps_activity = self._pservice.get_activity(activity.get_id()) - if ps_activity is not None: - services = ps_activity.get_services_of_type(ActivityChat.SERVICE_TYPE) - if len(services) > 0: - self._service_appeared_cb(self._pservice, services[0]) - - def _service_appeared_cb(self, pservice, service): - if service.get_activity_id() != self._activity.get_id(): - return - if service.get_type() != ActivityChat.SERVICE_TYPE: - return - if self._chat_service: - return - - logging.debug('Activity chat service appeared, setup the stream.') - # Ok, there's an existing chat service that we copy - # parameters and such from - addr = service.get_address() - port = service.get_port() - self._chat_service = self._pservice.share_activity(self._activity, - stype=ActivityChat.SERVICE_TYPE, address=addr, port=port) - self._setup_stream(self._chat_service) - - def share(self): - """Only called when we share the activity this chat is tied to.""" - self._chat_service = self._pservice.share_activity(self._activity, - stype=ActivityChat.SERVICE_TYPE) - self._setup_stream(self._chat_service) - - def _destroy_cb(self, widget): - if self._chat_service: - self._pservice.unregister_service(self._chat_service) diff --git a/sugar/chat/Chat.py b/sugar/chat/Chat.py deleted file mode 100644 index aae6450a..00000000 --- a/sugar/chat/Chat.py +++ /dev/null @@ -1,280 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -#!/usr/bin/env python - -import sha - -import dbus -import dbus.service -import dbus.glib - -import gtk -import gobject -import pango -import logging - -from sugar.chat.Emoticons import Emoticons -from sugar.chat.ChatToolbar import ChatToolbar -from sugar.chat.ChatEditor import ChatEditor -from sugar.presence import PresenceService -import richtext - -PANGO_SCALE = 1024 # Where is this defined? - -class Chat(gtk.VBox): - SERVICE_TYPE = "_olpc_chat._tcp" - SERVICE_PORT = 6100 - - TEXT_MODE = 0 - SKETCH_MODE = 1 - - def __init__(self): - gtk.VBox.__init__(self, False, 6) - - self._pservice = PresenceService.get_instance() - - self._stream_writer = None - self.set_border_width(12) - - chat_vbox = gtk.VBox() - chat_vbox.set_spacing(6) - - self._chat_sw = gtk.ScrolledWindow() - self._chat_sw.set_shadow_type(gtk.SHADOW_IN) - self._chat_sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) - self._chat_view = richtext.RichTextView() - self._chat_view.connect("link-clicked", self.__link_clicked_cb) - self._chat_view.set_editable(False) - self._chat_view.set_cursor_visible(False) - self._chat_view.set_pixels_above_lines(7) - self._chat_view.set_left_margin(5) - self._chat_sw.add(self._chat_view) - self._chat_view.show() - chat_vbox.pack_start(self._chat_sw) - self._chat_sw.show() - - self.pack_start(chat_vbox) - chat_vbox.show() - - self._mode = Chat.TEXT_MODE - self._editor = ChatEditor(self, ChatEditor.TEXT_MODE) - - toolbar = ChatToolbar(self._editor) - self.pack_start(toolbar, False) - toolbar.show() - - self.pack_start(self._editor, False) - self._editor.show() - - self.connect("key-press-event", self.__key_press_event_cb) - - def __key_press_event_cb(self, window, event): - if event.keyval == gtk.keysyms.s and \ - event.state & gtk.gdk.CONTROL_MASK: - if self.get_mode() == Chat.SKETCH_MODE: - self.set_mode(Chat.TEXT_MODE) - elif self.get_mode() == Chat.TEXT_MODE: - self.set_mode(Chat.SKETCH_MODE) - - def get_mode(self): - return self._mode - - def set_mode(self, mode): - self._mode = mode - if self._mode == Chat.TEXT_MODE: - self._editor.set_mode(ChatEditor.TEXT_MODE) - elif self._mode == Chat.SKETCH_MODE: - self._editor.set_mode(ChatEditor.SKETCH_MODE) - - def __get_browser_shell(self): - bus = dbus.SessionBus() - proxy_obj = bus.get_object('com.redhat.Sugar.Browser', '/com/redhat/Sugar/Browser') - self._browser_shell = dbus.Interface(proxy_obj, 'com.redhat.Sugar.BrowserShell') - - def __link_clicked_cb(self, view, address): - self.__get_browser_shell().open_browser(address) - - def _scroll_chat_view_to_bottom(self): - # Only scroll to bottom if the view is already close to the bottom - vadj = self._chat_sw.get_vadjustment() - if vadj.value + vadj.page_size > vadj.upper * 0.8: - vadj.value = vadj.upper - vadj.page_size - self._chat_sw.set_vadjustment(vadj) - - def _message_inserted(self): - gobject.idle_add(self._scroll_chat_view_to_bottom) - - def _insert_buddy(self, buf, buddy): - # Stuff in the buddy icon, if we have one for this buddy - icon = buddy.get_icon_pixbuf() - if icon: - rise = int(icon.get_height() / 4) * -1 - - hash_string = "%s-%s" % (buddy.get_name(), buddy.get_ip4_address()) - sha_hash = sha.new() - sha_hash.update(hash_string) - tagname = "buddyicon-%s" % sha_hash.hexdigest() - - if not buf.get_tag_table().lookup(tagname): - buf.create_tag(tagname, rise=(rise * PANGO_SCALE)) - - aniter = buf.get_end_iter() - buf.insert_pixbuf(aniter, icon) - aniter.backward_char() - enditer = buf.get_end_iter() - buf.apply_tag_by_name(tagname, aniter, enditer) - - # Stick in the buddy's nickname - if not buf.get_tag_table().lookup("nickname"): - buf.create_tag("nickname", weight=pango.WEIGHT_BOLD) - aniter = buf.get_end_iter() - offset = aniter.get_offset() - buf.insert(aniter, " " + buddy.get_name() + ": ") - enditer = buf.get_iter_at_offset(offset) - buf.apply_tag_by_name("nickname", aniter, enditer) - - def _insert_rich_message(self, buddy, msg): - msg = Emoticons.get_instance().replace(msg) - - buf = self._chat_view.get_buffer() - self._insert_buddy(buf, buddy) - - serializer = richtext.RichTextSerializer() - serializer.deserialize(msg, buf) - aniter = buf.get_end_iter() - buf.insert(aniter, "\n") - - self._message_inserted() - - def _insert_sketch(self, buddy, svgdata): - """Insert a sketch object into the chat buffer.""" - pbl = gtk.gdk.PixbufLoader("svg") - pbl.write(svgdata) - pbl.close() - pbuf = pbl.get_pixbuf() - - buf = self._chat_view.get_buffer() - - self._insert_buddy(buf, buddy) - - rise = int(pbuf.get_height() / 3) * -1 - sha_hash = sha.new() - sha_hash.update(svgdata) - tagname = "sketch-%s" % sha_hash.hexdigest() - if not buf.get_tag_table().lookup(tagname): - buf.create_tag(tagname, rise=(rise * PANGO_SCALE)) - - aniter = buf.get_end_iter() - buf.insert_pixbuf(aniter, pbuf) - aniter.backward_char() - enditer = buf.get_end_iter() - buf.apply_tag_by_name(tagname, aniter, enditer) - aniter = buf.get_end_iter() - buf.insert(aniter, "\n") - - self._message_inserted() - - def _get_first_richtext_chunk(self, msg): - """Scan the message for the first richtext-tagged chunk and return it.""" - rt_last = -1 - tag_rt_start = "" - tag_rt_end = "" - rt_first = msg.find(tag_rt_start) - length = -1 - if rt_first >= 0: - length = len(msg) - rt_last = msg.find(tag_rt_end, rt_first) - if rt_first >= 0 and rt_last >= (rt_first + len(tag_rt_start)) and length > 0: - return msg[rt_first:rt_last + len(tag_rt_end)] - return None - - def _get_first_sketch_chunk(self, msg): - """Scan the message for the first SVG-tagged chunk and return it.""" - svg_last = -1 - tag_svg_start = "") - if desc_start < 0: - return None - ignore = msg.find("= 0: - length = len(msg) - svg_last = msg.find(tag_svg_end, svg_first) - if svg_first >= 0 and svg_last >= (svg_first + len(tag_svg_start)) and length > 0: - return msg[desc_start:svg_last + len(tag_svg_end)] - return None - - 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_name(nick) - if not buddy: - logging.error('The buddy %s is not present.' % (nick)) - return - - # FIXME a better way to compare buddies? - owner = self._pservice.get_owner() - if buddy.get_name() == owner.get_name(): - return - - chunk = self._get_first_richtext_chunk(msg) - if chunk: - self._insert_rich_message(buddy, chunk) - return - - chunk = self._get_first_sketch_chunk(msg) - if chunk: - self._insert_sketch(buddy, chunk) - return - - def set_stream_writer(self, stream_writer): - self._stream_writer = stream_writer - - def send_sketch(self, svgdata): - if not svgdata or not len(svgdata): - return - if self._stream_writer: - self._stream_writer.write(self.serialize_message(svgdata)) - owner = self._pservice.get_owner() - if owner: - self._insert_sketch(owner, svgdata) - - def send_text_message(self, text): - """Send a chat message and insert it into the local buffer.""" - if len(text) <= 0: - return - if self._stream_writer: - self._stream_writer.write(self.serialize_message(text)) - else: - logging.warning("Cannot send message, there is no stream writer") - owner = self._pservice.get_owner() - if owner: - self._insert_rich_message(owner, text) - - def serialize_message(self, message): - owner = self._pservice.get_owner() - return owner.get_name() + '||' + message - - def deserialize_message(message): - return message.split('||', 1) - - deserialize_message = staticmethod(deserialize_message) diff --git a/sugar/chat/ChatEditor.py b/sugar/chat/ChatEditor.py deleted file mode 100644 index ee366888..00000000 --- a/sugar/chat/ChatEditor.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk -from gettext import gettext as _ - -from sugar.chat.sketchpad.SketchPad import SketchPad -import richtext - -class ChatEditor(gtk.HBox): - TEXT_MODE = 0 - SKETCH_MODE = 1 - - def __init__(self, chat, mode): - gtk.HBox.__init__(self, False, 6) - - self._chat = chat - - self._notebook = gtk.Notebook() - self._notebook.set_show_tabs(False) - self._notebook.set_show_border(False) - self._notebook.set_size_request(-1, 70) - - chat_view_sw = gtk.ScrolledWindow() - chat_view_sw.set_shadow_type(gtk.SHADOW_IN) - chat_view_sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self._text_view = richtext.RichTextView() - self._text_view.connect("key-press-event", self.__key_press_event_cb) - chat_view_sw.add(self._text_view) - self._text_view.show() - - self._notebook.append_page(chat_view_sw) - chat_view_sw.show() - - self._sketchpad = SketchPad() - self._notebook.append_page(self._sketchpad) - self._sketchpad.show() - - self.pack_start(self._notebook) - self._notebook.show() - - send_button = gtk.Button(_("Send")) - send_button.set_size_request(60, -1) - send_button.connect('clicked', self.__send_button_clicked_cb) - self.pack_start(send_button, False, True) - send_button.show() - - self.set_mode(mode) - - def set_color(self, color): - self._sketchpad.set_color(color) - - def get_buffer(self): - return self._text_view.get_buffer() - - def set_mode(self, mode): - self._mode = mode - if self._mode == ChatEditor.SKETCH_MODE: - self._notebook.set_current_page(1) - elif self._mode == ChatEditor.TEXT_MODE: - self._notebook.set_current_page(0) - - def __send_button_clicked_cb(self, button): - self._send() - - def _send(self): - if self._mode == ChatEditor.SKETCH_MODE: - self._send_sketch() - elif self._mode == ChatEditor.TEXT_MODE: - self._send_text() - - def _send_sketch(self): - self._chat.send_sketch(self._sketchpad.to_svg()) - self._sketchpad.clear() - - def _send_text(self): - buf = self._text_view.get_buffer() - text = buf.get_text(buf.get_start_iter(), buf.get_end_iter()) - if len(text.strip()) > 0: - serializer = richtext.RichTextSerializer() - text = serializer.serialize(buf) - self._chat.send_text_message(text) - - buf.set_text("") - buf.place_cursor(buf.get_start_iter()) - - def __key_press_event_cb(self, text_view, event): - if event.keyval == gtk.keysyms.Return: - self._send() - return True diff --git a/sugar/chat/ChatToolbar.py b/sugar/chat/ChatToolbar.py deleted file mode 100644 index d6331385..00000000 --- a/sugar/chat/ChatToolbar.py +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk, gobject - -from sugar.chat.Emoticons import Emoticons -from sugar.chat.sketchpad.Toolbox import Toolbox -import richtext - -class ChatToolbar(gtk.HBox): - def __init__(self, editor): - gtk.HBox.__init__(self, False, 24) - - self._editor = editor - self._emt_popup = None - - spring = gtk.Label('') - self.pack_start(spring, True) - spring.show() - - toolbox = richtext.RichTextToolbox(editor.get_buffer()) - self.pack_start(toolbox, False) - toolbox.show() - - item = gtk.Button() - item.unset_flags(gtk.CAN_FOCUS) - - e_hbox = gtk.HBox(False, 6) - - e_image = gtk.Image() - e_image.set_from_icon_name('stock_smiley-1', gtk.ICON_SIZE_SMALL_TOOLBAR) - e_hbox.pack_start(e_image) - e_image.show() - - arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_NONE) - e_hbox.pack_start(arrow) - arrow.show() - - item.set_image(e_hbox) - item.connect("clicked", self.__emoticons_button_clicked_cb) - toolbox.pack_start(item, False) - item.show() - -# separator = gtk.SeparatorToolItem() -# toolbar.insert(separator, -1) -# separator.show() - -# item = gtk.MenuToolButton(None, "Links") -# item.set_menu(gtk.Menu()) -# item.connect("show-menu", self.__show_link_menu_cb) -# toolbar.insert(item, -1) -# item.show() - - toolbox = Toolbox() - toolbox.connect('color-selected', self._color_selected) - self.pack_start(toolbox, False) - toolbox.show() - - spring = gtk.Label('') - self.pack_start(spring, True) - spring.show() - - def _color_selected(self, toolbox, color): - self._editor.set_color(color) - - def __link_activate_cb(self, item, link): - buf = self._editor.get_buffer() - buf.append_link(link['title'], link['address']) - - def __show_link_menu_cb(self, button): - menu = gtk.Menu() - - links = self.__get_browser_shell().get_links() - - for link in links: - item = gtk.MenuItem(link['title'], False) - item.connect("activate", self.__link_activate_cb, link) - menu.append(item) - item.show() - - button.set_menu(menu) - - def _create_emoticons_popup(self): - model = gtk.ListStore(gtk.gdk.Pixbuf, str) - - for name in Emoticons.get_instance().get_all(): - icon_theme = gtk.icon_theme_get_default() - try: - pixbuf = icon_theme.load_icon(name, 16, 0) - model.append([pixbuf, name]) - except gobject.GError: - pass - - icon_view = gtk.IconView(model) - icon_view.connect('selection-changed', self.__emoticon_selection_changed_cb) - icon_view.set_pixbuf_column(0) - icon_view.set_selection_mode(gtk.SELECTION_SINGLE) - - frame = gtk.Frame() - frame.set_shadow_type(gtk.SHADOW_ETCHED_IN) - frame.add(icon_view) - icon_view.show() - - window = gtk.Window(gtk.WINDOW_POPUP) - window.add(frame) - frame.show() - - return window - - def __emoticon_selection_changed_cb(self, icon_view): - items = icon_view.get_selected_items() - if items: - model = icon_view.get_model() - icon_name = model[items[0]][1] - self._editor.get_buffer().append_icon(icon_name) - self._emt_popup.hide() - - def __emoticons_button_clicked_cb(self, button): - # FIXME grabs... - if not self._emt_popup: - self._emt_popup = self._create_emoticons_popup() - - if self._emt_popup.get_property('visible'): - self._emt_popup.hide() - else: - width = 180 - height = 130 - - self._emt_popup.set_default_size(width, height) - - [x, y] = button.window.get_origin() - x += button.allocation.x - y += button.allocation.y - height - self._emt_popup.move(x, y) - - self._emt_popup.show() diff --git a/sugar/chat/Emoticons.py b/sugar/chat/Emoticons.py deleted file mode 100644 index 33e53eb7..00000000 --- a/sugar/chat/Emoticons.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -emoticons_table = [ \ -[ 'stock_smiley-10', [ ':P', ':p' ] ], \ -[ 'stock_smiley-19', None ], \ -[ 'stock_smiley-2', None ], \ -[ 'stock_smiley-11', None ], \ -[ 'stock_smiley-1', [ ':)' ] ], \ -[ 'stock_smiley-3', None ], \ -[ 'stock_smiley-12', None ], \ -[ 'stock_smiley-20', None ], \ -[ 'stock_smiley-4', [ ':(' ] ], \ -[ 'stock_smiley-13', None ], \ -[ 'stock_smiley-21', None ], \ -[ 'stock_smiley-5', None ], \ -[ 'stock_smiley-14', None ], \ -[ 'stock_smiley-22', None ], \ -[ 'stock_smiley-6', None ], \ -[ 'stock_smiley-15', None ], \ -[ 'stock_smiley-23', None ], \ -[ 'stock_smiley-7', None ], \ -[ 'stock_smiley-16', None ], \ -[ 'stock_smiley-24', None ], \ -[ 'stock_smiley-8', None ], \ -[ 'stock_smiley-17', None ], \ -[ 'stock_smiley-25', None ], \ -[ 'stock_smiley-9', None ], \ -[ 'stock_smiley-18', None ], \ -[ 'stock_smiley-26', None ], \ -] - -class Emoticons: - instance = None - - def get_instance(): - if not Emoticons.instance: - Emoticons.instance = Emoticons() - return Emoticons.instance - - get_instance = staticmethod(get_instance) - - def __init__(self): - self._table = {} - - for emoticon in emoticons_table: - [ name, text_emts ] = emoticon - self.add(name, text_emts) - - def add(self, icon_name, text=None): - self._table[icon_name] = text - - def get_all(self): - return self._table.keys() - - """Replace emoticons text with the icon name. - - Parse the provided text to find emoticons (in - textual form) and replace them with their xml - representation in the form: - - """ - def replace(self, text): - for icon_name in self._table.keys(): - text_emts = self._table[icon_name] - if text_emts: - for emoticon_text in text_emts: - xml = '' - text = text.replace(emoticon_text, xml) - return text diff --git a/sugar/chat/GroupChat.py b/sugar/chat/GroupChat.py deleted file mode 100644 index a1c6b651..00000000 --- a/sugar/chat/GroupChat.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging - -from sugar.chat.Chat import Chat -from sugar.p2p.Stream import Stream -from sugar.presence.PresenceService import PresenceService -import sugar.env - -class GroupChat(Chat): - def __init__(self): - Chat.__init__(self) - self._group_stream = None - - def _setup_stream(self, service): - self._group_stream = Stream.new_from_service(service) - self._group_stream.set_data_listener(self._group_recv_message) - self._stream_writer = self._group_stream.new_writer() - - def _group_recv_message(self, address, msg): - logging.debug('Group chat received from %s message %s' % (address, msg)) - self.recv_message(msg) diff --git a/sugar/chat/Makefile.am b/sugar/chat/Makefile.am deleted file mode 100644 index f7370cfb..00000000 --- a/sugar/chat/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -SUBDIRS = sketchpad - -sugardir = $(pythondir)/sugar/chat -sugar_PYTHON = \ - __init__.py \ - ActivityChat.py \ - Chat.py \ - ChatEditor.py \ - ChatToolbar.py \ - Emoticons.py \ - GroupChat.py \ - richtext.py - -EXTRA_DIST = \ - $(icon_DATA) diff --git a/sugar/chat/__init__.py b/sugar/chat/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/sugar/chat/richtext.py b/sugar/chat/richtext.py deleted file mode 100644 index ebd8b1c3..00000000 --- a/sugar/chat/richtext.py +++ /dev/null @@ -1,451 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gobject -import gtk -import pango -import xml.sax - -class RichTextView(gtk.TextView): - - __gsignals__ = { - 'link-clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_STRING])) - } - - def __init__(self): - gtk.TextView.__init__(self, RichTextBuffer()) - self.connect("motion-notify-event", self.__motion_notify_cb) - self.connect("button-press-event", self.__button_press_cb) - self.__hover_link = False - - def _set_hover_link(self, hover_link): - if hover_link != self.__hover_link: - self.__hover_link = hover_link - display = self.get_toplevel().get_display() - child_window = self.get_window(gtk.TEXT_WINDOW_TEXT) - - if hover_link: - cursor = gtk.gdk.Cursor(display, gtk.gdk.HAND2) - else: - cursor = gtk.gdk.Cursor(display, gtk.gdk.XTERM) - - child_window.set_cursor(cursor) - gtk.gdk.flush() - - def __iter_is_link(self, it): - item = self.get_buffer().get_tag_table().lookup("link") - if item: - return it.has_tag(item) - return False - - def __get_event_iter(self, event): - return self.get_iter_at_location(int(event.x), int(event.y)) - - def __motion_notify_cb(self, widget, event): - if event.is_hint: - event.window.get_pointer(); - - it = self.__get_event_iter(event) - if it: - hover_link = self.__iter_is_link(it) - else: - hover_link = False - - self._set_hover_link(hover_link) - - def __button_press_cb(self, widget, event): - it = self.__get_event_iter(event) - if it and self.__iter_is_link(it): - buf = self.get_buffer() - address_tag = buf.get_tag_table().lookup("object-id") - - address_end = it.copy() - address_end.backward_to_tag_toggle(address_tag) - - address_start = address_end.copy() - address_start.backward_to_tag_toggle(address_tag) - - address = buf.get_text(address_start, address_end) - self.emit("link-clicked", address) - -class RichTextBuffer(gtk.TextBuffer): - def __init__(self): - gtk.TextBuffer.__init__(self) - - self.connect_after("insert-text", self.__insert_text_cb) - - self.__create_tags() - self.active_tags = [] - - def append_link(self, title, address): - it = self.get_iter_at_mark(self.get_insert()) - self.insert_with_tags_by_name(it, address, "link", "object-id") - self.insert_with_tags_by_name(it, title, "link") - - def append_icon(self, name, it = None): - if not it: - it = self.get_iter_at_mark(self.get_insert()) - - self.insert_with_tags_by_name(it, name, "icon", "object-id") - icon_theme = gtk.icon_theme_get_default() - try: - pixbuf = icon_theme.load_icon(name, 16, 0) - self.insert_pixbuf(it, pixbuf) - except gobject.GError: - pass - - def apply_tag(self, tag_name): - self.active_tags.append(tag_name) - - bounds = self.get_selection_bounds() - if bounds: - [start, end] = bounds - self.apply_tag_by_name(tag_name, start, end) - - def unapply_tag(self, tag_name): - self.active_tags.remove(tag_name) - - bounds = self.get_selection_bounds() - if bounds: - [start, end] = bounds - self.remove_tag_by_name(tag_name, start, end) - - def __create_tags(self): - tag = self.create_tag("icon") - - tag = self.create_tag("link") - tag.set_property("underline", pango.UNDERLINE_SINGLE) - tag.set_property("foreground", "#0000FF") - - tag = self.create_tag("object-id") - tag.set_property("invisible", True) - - tag = self.create_tag("bold") - tag.set_property("weight", pango.WEIGHT_BOLD) - - tag = self.create_tag("italic") - tag.set_property("style", pango.STYLE_ITALIC) - - tag = self.create_tag("font-size-xx-small") - tag.set_property("scale", pango.SCALE_XX_SMALL) - - tag = self.create_tag("font-size-x-small") - tag.set_property("scale", pango.SCALE_X_SMALL) - - tag = self.create_tag("font-size-small") - tag.set_property("scale", pango.SCALE_SMALL) - - tag = self.create_tag("font-size-large") - tag.set_property("scale", pango.SCALE_LARGE) - - tag = self.create_tag("font-size-x-large") - tag.set_property("scale", pango.SCALE_X_LARGE) - - tag = self.create_tag("font-size-xx-large") - tag.set_property("scale", pango.SCALE_XX_LARGE) - - 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) - -class RichTextToolbox(gtk.HBox): - def __init__(self, buf): - gtk.HBox.__init__(self, False, 6) - - self.buf = buf - - self._font_size = "normal" - self._font_scales = [ "xx-small", "x-small", "small", \ - "normal", \ - "large", "x-large", "xx-large" ] - - image = gtk.Image() - image.set_from_stock(gtk.STOCK_BOLD, gtk.ICON_SIZE_SMALL_TOOLBAR) - - item = gtk.ToggleButton() - item.set_image(image) - item.connect("toggled", self.__toggle_style_cb, "bold") - item.unset_flags(gtk.CAN_FOCUS) - self.pack_start(item, False) - item.show() - - image.show() - - image = gtk.Image() - image.set_from_stock(gtk.STOCK_ITALIC, gtk.ICON_SIZE_SMALL_TOOLBAR) - - item = gtk.ToggleButton() - item.set_image(image) - item.unset_flags(gtk.CAN_FOCUS) - item.connect("toggled", self.__toggle_style_cb, "italic") - self.pack_start(item, False) - item.show() - - image = gtk.Image() - image.set_from_stock(gtk.STOCK_GO_UP, gtk.ICON_SIZE_SMALL_TOOLBAR) - - self._font_size_up = gtk.Button() - self._font_size_up.set_image(image) - self._font_size_up.unset_flags(gtk.CAN_FOCUS) - self._font_size_up.connect("clicked", self.__font_size_up_cb) - self.pack_start(self._font_size_up, False) - self._font_size_up.show() - - image.show() - - image = gtk.Image() - image.set_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_SMALL_TOOLBAR) - - self._font_size_down = gtk.Button() - self._font_size_down.set_image(image) - self._font_size_down.unset_flags(gtk.CAN_FOCUS) - self._font_size_down.connect("clicked", self.__font_size_down_cb) - self.pack_start(self._font_size_down, False) - self._font_size_down.show() - - image.show() - - def _get_font_size_index(self): - return self._font_scales.index(self._font_size); - - def __toggle_style_cb(self, toggle, tag_name): - if toggle.get_active(): - self.buf.apply_tag(tag_name) - else: - self.buf.unapply_tag(tag_name) - - def _set_font_size(self, font_size): - if self._font_size != "normal": - self.buf.unapply_tag("font-size-" + self._font_size) - if font_size != "normal": - self.buf.apply_tag("font-size-" + font_size) - - self._font_size = font_size - - can_up = self._get_font_size_index() < len(self._font_scales) - 1 - can_down = self._get_font_size_index() > 0 - self._font_size_up.set_sensitive(can_up) - self._font_size_down.set_sensitive(can_down) - - def __font_size_up_cb(self, button): - index = self._get_font_size_index() - if index + 1 < len(self._font_scales): - self._set_font_size(self._font_scales[index + 1]) - - def __font_size_down_cb(self, button): - index = self._get_font_size_index() - if index > 0: - self._set_font_size(self._font_scales[index - 1]) - -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 = [] - self._in_richtext = False - self._done = False - - def startElement(self, name, attrs): - # Look for, and only start parsing after 'richtext' - if not self._in_richtext and name == "richtext": - self._in_richtext = True - if not self._in_richtext: - return - - if name != "richtext": - tag = self.serializer.deserialize_element(name, attrs) - self.tags.append(tag) - if name == "link": - self.href = attrs['href'] - elif name == "icon": - self.buf.append_icon(attrs['name'], self.buf.get_end_iter()) - - def characters(self, data): - start_it = it = self.buf.get_end_iter() - mark = self.buf.create_mark(None, start_it, True) - self.buf.insert(it, data) - start_it = self.buf.get_iter_at_mark(mark) - - for tag in self.tags: - self.buf.apply_tag_by_name(tag, start_it, it) - if tag == "link": - self.buf.insert_with_tags_by_name(start_it, self.href, - "link", "object-id") - - def endElement(self, name): - if not self._done and self._in_richtext: - if name != "richtext": - self.tags.pop() - if name == "richtext": - self._done = True - self._in_richtext = False - -class RichTextSerializer: - def __init__(self): - self._open_tags = [] - - def deserialize_element(self, el_name, attributes): - if el_name == "bold": - return "bold" - elif el_name == "italic": - return "italic" - elif el_name == "font": - return "font-size-" + attributes["size"] - elif el_name == "link": - return "link" - elif el_name == "icon": - return "icon" - else: - return None - - def _parse_object_id(self, it): - object_id_tag = self.buf.get_tag_table().lookup("object-id") - end = it.copy() - end.forward_to_tag_toggle(object_id_tag) - return self.buf.get_text(it, end) - - def serialize_tag_start(self, tag, it): - name = tag.get_property("name") - if name == "bold": - return "" - elif name == "italic": - return "" - elif name == "link": - address = self._parse_object_id(it) - return "" - elif name == "icon": - name = self._parse_object_id(it) - return "" - elif name == "object-id": - return "" - elif name.startswith("font-size-"): - tag_name = name.replace("font-size-", "", 1) - return "" - else: - return "" - - def serialize_tag_end(self, tag): - name = tag.get_property("name") - if name == "bold": - return "" - elif name == "italic": - return "" - elif name == "link": - return "" - elif name == "icon": - return "" - elif name == "object-id": - return "" - elif name.startswith("font-size-"): - return "" - else: - return "" - - def serialize(self, buf): - self.buf = buf - - res = "" - - next_it = buf.get_start_iter() - while not next_it.is_end(): - it = next_it.copy() - if not next_it.forward_to_tag_toggle(None): - next_it = buf.get_end_iter() - - tags_to_reopen = [] - - for tag in it.get_toggled_tags(False): - while 1: - open_tag = self._open_tags.pop() - res += 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) - - for tag in it.get_toggled_tags(True): - self._open_tags.append(tag) - res += self.serialize_tag_start(tag, it) - - res += 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) - - res += "" - - return res - - def deserialize(self, xml_string, buf): - parser = xml.sax.make_parser() - handler = RichTextHandler(self, buf) - parser.setContentHandler(handler) - parser.feed(xml_string) - parser.close() - -def test_quit(w, rb): - print RichTextSerializer().serialize(rb) - gtk.main_quit() - -def link_clicked(v, address): - print "Link clicked " + address - -if __name__ == "__main__": - window = gtk.Window() - window.set_default_size(400, 300) - - vbox = gtk.VBox() - - view = RichTextView() - view.connect("link-clicked", link_clicked) - vbox.pack_start(view) - view.show() - - rich_buf = view.get_buffer() - - test_xml = "" - - test_xml += "Testone\n" - test_xml += "Test two" - test_xml += "Test three" - test_xml += "Test link" - test_xml += "" - test_xml += "" - - RichTextSerializer().deserialize(test_xml, rich_buf) - - toolbar = RichTextToolbar(rich_buf) - vbox.pack_start(toolbar, False) - toolbar.show() - - window.add(vbox) - vbox.show() - - window.show() - - window.connect("destroy", test_quit, rich_buf) - - gtk.main() diff --git a/sugar/chat/sketchpad/Makefile.am b/sugar/chat/sketchpad/Makefile.am deleted file mode 100644 index c8316922..00000000 --- a/sugar/chat/sketchpad/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -sugardir = $(pythondir)/sugar/chat/sketchpad -sugar_PYTHON = \ - __init__.py \ - Sketch.py \ - SketchPad.py \ - SVGdraw.py \ - Toolbox.py diff --git a/sugar/chat/sketchpad/SVGdraw.py b/sugar/chat/sketchpad/SVGdraw.py deleted file mode 100644 index 5dd24c80..00000000 --- a/sugar/chat/sketchpad/SVGdraw.py +++ /dev/null @@ -1,1545 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -#!/usr/bin/env python -##Copyright (c) 2002, Fedor Baart & Hans de Wit (Stichting Farmaceutische Kengetallen) -##All rights reserved. -## -##Redistribution and use in source and binary forms, with or without modification, -##are permitted provided that the following conditions are met: -## -##Redistributions of source code must retain the above copyright notice, this -##list of conditions and the following disclaimer. -## -##Redistributions in binary form must reproduce the above copyright notice, -##this list of conditions and the following disclaimer in the documentation and/or -##other materials provided with the distribution. -## -##Neither the name of the Stichting Farmaceutische Kengetallen nor the names of -##its contributors may be used to endorse or promote products derived from this -##software without specific prior written permission. -## -##THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -##AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -##IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -##DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -##FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -##DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -##SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -##CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -##OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -##OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -##Thanks to Gerald Rosennfellner for his help and useful comments. - -__doc__="""Use SVGdraw to generate your SVGdrawings. - -SVGdraw uses an object model drawing and a method toXML to create SVG graphics -by using easy to use classes and methods usualy you start by creating a drawing eg - - d=drawing() - #then you create a SVG root element - s=svg() - #then you add some elements eg a circle and add it to the svg root element - c=circle() - #you can supply attributes by using named arguments. - c=circle(fill='red',stroke='blue') - #or by updating the attributes attribute: - c.attributes['stroke-width']=1 - s.addElement(c) - #then you add the svg root element to the drawing - d.setSVG(s) - #and finaly you xmlify the drawing - d.toXml() - - -this results in the svg source of the drawing, which consists of a circle -on a white background. Its as easy as that;) -This module was created using the SVG specification of www.w3c.org and the -O'Reilly (www.oreilly.com) python books as information sources. A svg viewer -is available from www.adobe.com""" - -__version__="1.0" - -# there are two possibilities to generate svg: -# via a dom implementation and directly using text strings -# the latter is way faster (and shorter in coding) -# the former is only used in debugging svg programs -# maybe it will be removed alltogether after a while -# with the following variable you indicate whether to use the dom implementation -# Note that PyXML is required for using the dom implementation. -# It is also possible to use the standard minidom. But I didn't try that one. -# 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: - try: - from xml.dom import implementation - from xml.dom.ext import PrettyPrint - except: - raise exceptions.ImportError, "PyXML is required for using the dom implementation" -#The implementation is used for the creating the XML document. -#The prettyprint module is used for converting the xml document object to a xml file - -import sys -assert sys.version_info[0]>=2 -if sys.version_info[1]<2: - True=1 - False=0 - file=open - -sys.setrecursionlimit=50 -#The recursion limit is set conservative so mistakes like s=svg() s.addElement(s) -#won't eat up too much processor time. - -xlinkNSRef = "http://www.w3.org/1999/xlink" - -#the following code is pasted form xml.sax.saxutils -#it makes it possible to run the code without the xml sax package installed -#To make it possible to have in your text elements, it is necessary to escape the texts -def _escape(data, entities={}): - """Escape &, <, and > in a string of data. - - You can escape other strings of data by passing a dictionary as - the optional entities parameter. The keys and values must all be - strings; each key will be replaced with its corresponding value. - """ - data = data.replace("&", "&") - data = data.replace("<", "<") - data = data.replace(">", ">") - for chars, entity in entities.items(): - data = data.replace(chars, entity) - return data - -def _quoteattr(data, entities={}): - """Escape and quote an attribute value. - - Escape &, <, and > in a string of data, then quote it for use as - an attribute value. The \" character will be escaped as well, if - necessary. - - You can escape other strings of data by passing a dictionary as - the optional entities parameter. The keys and values must all be - strings; each key will be replaced with its corresponding value. - """ - data = _escape(data, entities) - if '"' in data: - if "'" in data: - data = '"%s"' % data.replace('"', """) - else: - data = "'%s'" % data - else: - data = '"%s"' % data - return data - - - -def _xypointlist(a): - """formats a list of xy pairs""" - s='' - for e in a: #this could be done more elegant - s+=str(e)[1:-1] +' ' - return s - -def _viewboxlist(a): - """formats a tuple""" - s='' - for e in a: - s+=str(e)+' ' - return s - -def _pointlist(a): - """formats a list of numbers""" - return str(a)[1:-1] - -class pathdata: - """class used to create a pathdata object which can be used for a path. - although most methods are pretty straightforward it might be useful to look at the SVG specification.""" - #I didn't test the methods below. - def __init__(self,x=None,y=None): - self.path=[] - if x is not None and y is not None: - self.path.append('M '+str(x)+' '+str(y)) - def closepath(self): - """ends the path""" - self.path.append('z') - def move(self,x,y): - """move to absolute""" - self.path.append('M '+str(x)+' '+str(y)) - def relmove(self,x,y): - """move to relative""" - self.path.append('m '+str(x)+' '+str(y)) - def line(self,x,y): - """line to absolute""" - self.path.append('L '+str(x)+' '+str(y)) - def relline(self,x,y): - """line to relative""" - self.path.append('l '+str(x)+' '+str(y)) - def hline(self,x): - """horizontal line to absolute""" - self.path.append('H'+str(x)) - def relhline(self,x): - """horizontal line to relative""" - self.path.append('h'+str(x)) - def vline(self,y): - """verical line to absolute""" - self.path.append('V'+str(y)) - def relvline(self,y): - """vertical line to relative""" - self.path.append('v'+str(y)) - def bezier(self,x1,y1,x2,y2,x,y): - """bezier with xy1 and xy2 to xy absolut""" - self.path.append('C'+str(x1)+','+str(y1)+' '+str(x2)+','+str(y2)+' '+str(x)+','+str(y)) - def relbezier(self,x1,y1,x2,y2,x,y): - """bezier with xy1 and xy2 to xy relative""" - self.path.append('c'+str(x1)+','+str(y1)+' '+str(x2)+','+str(y2)+' '+str(x)+','+str(y)) - def smbezier(self,x2,y2,x,y): - """smooth bezier with xy2 to xy absolut""" - self.path.append('S'+str(x2)+','+str(y2)+' '+str(x)+','+str(y)) - def relsmbezier(self,x2,y2,x,y): - """smooth bezier with xy2 to xy relative""" - self.path.append('s'+str(x2)+','+str(y2)+' '+str(x)+','+str(y)) - def qbezier(self,x1,y1,x,y): - """quadratic bezier with xy1 to xy absolut""" - self.path.append('Q'+str(x1)+','+str(y1)+' '+str(x)+','+str(y)) - def relqbezier(self,x1,y1,x,y): - """quadratic bezier with xy1 to xy relative""" - self.path.append('q'+str(x1)+','+str(y1)+' '+str(x)+','+str(y)) - def smqbezier(self,x,y): - """smooth quadratic bezier to xy absolut""" - self.path.append('T'+str(x)+','+str(y)) - def relsmqbezier(self,x,y): - """smooth quadratic bezier to xy relative""" - self.path.append('t'+str(x)+','+str(y)) - def ellarc(self,rx,ry,xrot,laf,sf,x,y): - """elliptival arc with rx and ry rotating with xrot using large-arc-flag and sweep-flag to xy absolut""" - self.path.append('A'+str(rx)+','+str(ry)+' '+str(xrot)+' '+str(laf)+' '+str(sf)+' '+str(x)+' '+str(y)) - def relellarc(self,rx,ry,xrot,laf,sf,x,y): - """elliptival arc with rx and ry rotating with xrot using large-arc-flag and sweep-flag to xy relative""" - self.path.append('a'+str(rx)+','+str(ry)+' '+str(xrot)+' '+str(laf)+' '+str(sf)+' '+str(x)+' '+str(y)) - def __repr__(self): - return ' '.join(self.path) - - -class Attribute: - def __init__(self, name, value, nsname=None, nsref=None): - self.name = name - self.value = value - self.nsname = nsname - self.nsref = nsref - def __repr__(self): - return "(%s=%s, ns: %s=%s)" % (self.name, self.value, self.nsname, self.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. - This element is the base of every svg element it defines a class which resembles - a xml-element. The main advantage of this kind of implementation is that you don't - have to create a toXML method for every different graph object. Every element - consists of a type, attribute, optional subelements, optional text and an optional - namespace. Note the elements==None, if elements = None:self.elements=[] construction. - This is done because if you default to elements=[] every object has a reference - to the same empty list.""" - def __init__(self,type='',attributes=None,elements=None,text='',namespace='',cdata=None,**args): - self.type=type - self._attributes={} - if attributes: - for key, value in attributes.items(): - attr = Attribute(key, value) - self._attributes[key] = attr - self.elements=[] - if elements: - self.elements=elements - self.text=text - self.namespace=namespace - self.cdata=cdata - for key, value in args.items(): - attr = Attribute(key, value) - self._attributes[key] = attr - self._parent = None - - def addElement(self,SVGelement): - """adds an element to a SVGelement - - SVGelement.addElement(SVGelement) - """ - self.elements.append(SVGelement) - SVGelement.setParent(self) - - def setParent(self, parent): - self._parent = parent - - def setAttribute(self, attribute, replace=True): - if not replace and self.hasAttribute(attribute.name): - return - 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 _get_namespace(attrname, nslist): - colon_idx = attrname.find(':') - if colon_idx <= 0: - return (attrname, None, None) - nsname = attrname[:colon_idx] - nsref = None - attrname = attrname[colon_idx+1:] - for (ns, val) in nslist: - if ns == nsname: - nsref = val - break - if not nsref: - nsname = None - return (attrname, nsname, nsref) - _get_namespace = staticmethod(_get_namespace) - - _XMLNS_TAG = "xmlns:" - def construct(name, attributes, text=None, cdata=None): - try: - eltClass = elementTable[name] - except KeyError, e: - print "Unknown SVG element %s." % e - return None - # Coalesce namespaces into the attributes themselves - attr_dict = {} - elt_namespace = None - namespaces = [] - tmp_attrs = [] - # Separate namespaces from actual attributes - for attrname, attrvalue in attributes.items(): - if attrname.startswith(SVGelement._XMLNS_TAG): - namespaces.append((attrname[len(SVGelement._XMLNS_TAG):], attrvalue)) - elif attrname.startswith("xmlns"): - # Element-wide attribute - elt_namespace = attrvalue - else: - tmp_attrs.append((attrname, attrvalue)) - - # Create attributes and assign namespaces to them - for (attrname, attrvalue) in tmp_attrs: - nsname = nsref = None - attr = None - # search for its namespace, if any - (attrname, nsname, nsref) = SVGelement._get_namespace(attrname, namespaces) - attr = Attribute(attrname, attrvalue, nsname, nsref) - attr_dict[attrname] = attr - - element = eltClass._construct(attr_dict) - if element: - for attr in attr_dict.values(): - element.setAttribute(attr, replace=False) - if text: - element.text = text - if cdata: - element.cdata = cdata - if not element.namespace and elt_namespace: - element.namespace = elt_namespace - return element - construct = staticmethod(construct) - - def toXml(self,level,f): - f.write('\t'*level) - f.write('<'+self.type) - if self.namespace: - f.write(' xmlns="'+ _escape(str(self.namespace))+'" ') - for attkey, attr in self._attributes.items(): - if attr.nsname: - f.write(' xmlns:'+_escape(str(attr.nsname))+'="'+_escape(str(attr.nsref))+'" ') - f.write(' '+_escape(str(attr.nsname))+':'+_escape(str(attkey))+'='+_quoteattr(str(attr.value))) - else: - f.write(' '+_escape(str(attkey))+'='+_quoteattr(str(attr.value))) - if self.elements or self.text or self.cdata: - f.write('>') - if self.elements: - f.write('\n') - for element in self.elements: - element.toXml(level+1,f) - if self.cdata: - f.write('\n'+'\t'*(level+1)+'\n') - if self.text: - if isinstance(self.text, str): #If the text is only text - f.write(_escape(str(self.text))) - else: #If the text is a spannedtext class - f.write(str(self.text)) - if self.elements: - f.write('\t'*level+'\n') - elif self.text: - f.write('\n') - elif self.cdata: - f.write('\t'*level+'\n') - else: - f.write('/>\n') - -class tspan(SVGelement): - """ts=tspan(text='',**args) - - a tspan element can be used for applying formatting to a textsection - usage: - ts=tspan('this text is bold') - ts.attributes['font-weight']='bold' - st=spannedtext() - st.addtspan(ts) - t=text(3,5,st) - """ - def __init__(self,text=None,**args): - SVGelement.__init__(self,'tspan',**args) - if self.text<>None: - self.text=text - def __repr__(self): - s="None: - raise ValueError, 'height is required' - if height<>None: - raise ValueError, 'width is required' - else: - raise ValueError, 'both height and width are required' - SVGelement.__init__(self,'rect',{'width':width,'height':height},**args) - if x<>None: - self.setAttribute(Attribute('x', x)) - if y<>None: - self.setAttribute(Attribute('y', y)) - if fill<>None: - self.setAttribute(Attribute('fill', fill)) - if stroke<>None: - self.setAttribute(Attribute('stroke', stroke)) - if stroke_width<>None: - 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.value, height=height.value) - _construct = staticmethod(_construct) - - -class ellipse(SVGelement): - """e=ellipse(rx,ry,x,y,fill,stroke,stroke_width,**args) - - an ellipse is defined as a center and a x and y radius. - """ - def __init__(self,cx=None,cy=None,rx=None,ry=None,fill=None,stroke=None,stroke_width=None,**args): - if rx==None or ry== None: - if rx<>None: - raise ValueError, 'rx is required' - if ry<>None: - raise ValueError, 'ry is required' - else: - raise ValueError, 'both rx and ry are required' - SVGelement.__init__(self,'ellipse',{'rx':rx,'ry':ry},**args) - if cx<>None: - self.setAttribute(Attribute('cx', cx)) - if cy<>None: - self.setAttribute(Attribute('cy', cy)) - if fill<>None: - self.setAttribute(Attribute('fill', fill)) - if stroke<>None: - self.setAttribute(Attribute('stroke', stroke)) - if stroke_width<>None: - 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.value, ry=ry.value) - _construct = staticmethod(_construct) - - -class circle(SVGelement): - """c=circle(x,y,radius,fill,stroke,stroke_width,**args) - - The circle creates an element using a x, y and radius values eg - """ - def __init__(self,cx=None,cy=None,r=None,fill=None,stroke=None,stroke_width=None,**args): - if r==None: - raise ValueError, 'r is required' - SVGelement.__init__(self,'circle',{'r':r},**args) - if cx<>None: - self.setAttribute(Attribute('cx', cx)) - if cy<>None: - self.setAttribute(Attribute('cy', cy)) - if fill<>None: - self.setAttribute(Attribute('fill', fill)) - if stroke<>None: - self.setAttribute(Attribute('stroke', stroke)) - if stroke_width<>None: - self.setAttribute(Attribute('stroke-width', stroke_width)) - - def _construct(attributes): - r = get_attr_value(attributes, 'r') - if int(r.value) == 1: - return point() - else: - return circle(r=r.value) - _construct = staticmethod(_construct) - - -class point(circle): - """p=point(x,y,color) - - 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=None,y=None,fill=None,**args): - circle.__init__(self,x,y,1,fill,**args) - -class line(SVGelement): - """l=line(x1,y1,x2,y2,stroke,stroke_width,**args) - - A line is defined by a begin x,y pair and an end x,y pair - """ - 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.setAttribute(Attribute('x1', x1)) - if y1<>None: - self.setAttribute(Attribute('y1', y1)) - if x2<>None: - self.setAttribute(Attribute('x2', x2)) - if y2<>None: - self.setAttribute(Attribute('y2', y2)) - if stroke_width<>None: - self.setAttribute(Attribute('stroke-width', stroke_width)) - if stroke<>None: - 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) - - a polyline is defined by a list of xy pairs - """ - def __init__(self,points,fill=None,stroke=None,stroke_width=None,**args): - SVGelement.__init__(self,'polyline',{'points':_xypointlist(points)},**args) - if fill<>None: - self.setAttribute(Attribute('fill', fill)) - if stroke_width<>None: - self.setAttribute(Attribute('stroke-width', stroke_width)) - if stroke<>None: - self.setAttribute(Attribute('stroke', stroke)) - - def _construct(attributes): - points = get_attr_value(attributes, 'points') - return polyline(points.value) - _construct = staticmethod(_construct) - - -class polygon(SVGelement): - """pl=polyline([[x1,y1],[x2,y2],...],fill,stroke,stroke_width,**args) - - a polygon is defined by a list of xy pairs - """ - def __init__(self,points,fill=None,stroke=None,stroke_width=None,**args): - SVGelement.__init__(self,'polygon',{'points':_xypointlist(points)},**args) - if fill<>None: - self.setAttribute(Attribute('fill', fill)) - if stroke_width<>None: - self.setAttribute(Attribute('stroke-width', stroke_width)) - if stroke<>None: - self.setAttribute(Attribute('stroke', stroke)) - - def _construct(attributes): - points = get_attr_value(attributes, 'points') - return polygon(points.value) - _construct = staticmethod(_construct) - - -class path(SVGelement): - """p=path(path,fill,stroke,stroke_width,**args) - - a path is defined by a path object and optional width, stroke and fillcolor - """ - 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.setAttribute(Attribute('stroke', stroke)) - if fill<>None: - self.setAttribute(Attribute('fill', fill)) - if stroke_width<>None: - self.setAttribute(Attribute('stroke-width', stroke_width)) - if id<>None: - self.setAttribute(Attribute('id', id)) - - def _construct(attributes): - pathdata = get_attr_value(attributes, 'd') - return path(pathdata.value) - _construct = staticmethod(_construct) - - -class text(SVGelement): - """t=text(x,y,text,font_size,font_family,**args) - - a text element can bge used for displaying text on the screen - """ - 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.setAttribute(Attribute('x', x)) - if y<>None: - self.setAttribute(Attribute('y', y)) - if font_size<>None: - self.setAttribute(Attribute('font-size', font_size)) - if font_family<>None: - self.setAttribute(Attribute('font-family', font_family)) - if text<>None: - self.text=text - if text_anchor<>None: - self.setAttribute(Attribute('text-anchor', text_anchor)) - - def _construct(attributes): - return text() - _construct = staticmethod(_construct) - - -class textpath(SVGelement): - """tp=textpath(text,link,**args) - - a textpath places a text on a path which is referenced by a link. - """ - def __init__(self,link,text=None,**args): - SVGelement.__init__(self,'textPath',**args) - self.setAttribute(Attribute('href', link, 'xlink', xlinkNSRef)) - if text<>None: - self.text=text - - def _construct(attributes): - href = get_attr_value(attributes, 'href') - if href and href.nsname == 'xlink': - return textpath(href.value) - return None - _construct = staticmethod(_construct) - - -class pattern(SVGelement): - """p=pattern(x,y,width,height,patternUnits,**args) - - A pattern is used to fill or stroke an object using a pre-defined - graphic object which can be replicated ("tiled") at fixed intervals - in x and y to cover the areas to be painted. - """ - def __init__(self,x=None,y=None,width=None,height=None,patternUnits=None,**args): - SVGelement.__init__(self,'pattern',**args) - if x<>None: - self.setAttribute(Attribute('x', x)) - if y<>None: - self.setAttribute(Attribute('y', y)) - if width<>None: - self.setAttribute(Attribute('width', width)) - if height<>None: - self.setAttribute(Attribute('height', height)) - if patternUnits<>None: - self.setAttribute(Attribute('patternUnits', patternUnits)) - - def _construct(attributes): - return pattern() - _construct = staticmethod(_construct) - - -class title(SVGelement): - """t=title(text,**args) - - a title is a text element. The text is displayed in the title bar - add at least one to the root svg element - """ - def __init__(self,text=None,**args): - SVGelement.__init__(self,'title',**args) - if text<>None: - self.text=text - - def _construct(attributes): - return title() - _construct = staticmethod(_construct) - - -class description(SVGelement): - """d=description(text,**args) - - a description can be added to any element and is used for a tooltip - Add this element before adding other elements. - """ - def __init__(self,text=None,**args): - SVGelement.__init__(self,'desc',**args) - 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) - - defines a lineargradient using two xy pairs. - stop elements van be added to define the gradient colors. - """ - def __init__(self,x1=None,y1=None,x2=None,y2=None,id=None,**args): - SVGelement.__init__(self,'linearGradient',**args) - if x1<>None: - self.setAttribute(Attribute('x1', x1)) - if y1<>None: - self.setAttribute(Attribute('y1', y1)) - if x2<>None: - self.setAttribute(Attribute('x2', x2)) - if y2<>None: - self.setAttribute(Attribute('y2', y2)) - if id<>None: - 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) - - defines a radial gradient using a outer circle which are defined by a cx,cy and r and by using a focalpoint. - stop elements van be added to define the gradient colors. - """ - 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.setAttribute(Attribute('cx', cx)) - if cy<>None: - self.setAttribute(Attribute('cy', cy)) - if r<>None: - self.setAttribute(Attribute('r', r)) - if fx<>None: - self.setAttribute(Attribute('fx', fx)) - if fy<>None: - self.setAttribute(Attribute('fy', fy)) - if id<>None: - self.setAttribute(Attribute('id', id)) - - def _construct(attributes): - return radialgradient() - _construct = staticmethod(_construct) - - -class stop(SVGelement): - """st=stop(offset,stop_color,**args) - - Puts a stop color at the specified radius - """ - def __init__(self,offset,stop_color=None,**args): - SVGelement.__init__(self,'stop',{'offset':offset},**args) - if stop_color<>None: - self.setAttribute(Attribute('stop-color', stop_color)) - - def _construct(attributes): - offset = get_attr_value(attributes, 'offset') - return stop(offset.value) - _construct = staticmethod(_construct) - -class style(SVGelement): - """st=style(type,cdata=None,**args) - - Add a CDATA element to this element for defing in line stylesheets etc.. - """ - 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.value) - _construct = staticmethod(_construct) - - -class image(SVGelement): - """im=image(url,width,height,x,y,**args) - - adds an image to the drawing. Supported formats are .png, .jpg and .svg. - """ - def __init__(self,url,x=None,y=None,width=None,height=None,**args): - if width==None or height==None: - if width<>None: - raise ValueError, 'height is required' - if height<>None: - raise ValueError, 'width is required' - else: - raise ValueError, 'both height and width are required' - SVGelement.__init__(self,'image',{'width':width,'height':height},**args) - self.setAttribute(Attribute('href', url, 'xlink', xlinkNSRef)) - if x<>None: - self.setAttribute(Attribute('x', x)) - if y<>None: - self.setAttribute(Attribute('y', y)) - - def _construct(attributes): - href = get_attr_value(attributes, 'href') - width = get_attr_value(attributes, 'width') - height = get_attr_value(attributes, 'height') - if href and href.nsname == 'xlink': - return image(href.value, width=width.value, height=height.value) - return None - _construct = staticmethod(_construct) - - -class cursor(SVGelement): - """c=cursor(url,**args) - - defines a custom cursor for a element or a drawing - """ - def __init__(self,url,**args): - SVGelement.__init__(self,'cursor',**args) - self.setAttribute(Attribute('href', url, 'xlink', xlinkNSRef)) - - def _construct(attributes): - href = get_attr_value(attributes, 'href') - if href and href.nsname == 'xlink': - return cursor(href.value) - return None - _construct = staticmethod(_construct) - - -class marker(SVGelement): - """m=marker(id,viewbox,refX,refY,markerWidth,markerHeight,**args) - - defines a marker which can be used as an endpoint for a line or other pathtypes - add an element to it which should be used as a marker. - """ - 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.setAttribute(Attribute('id', id)) - if viewBox<>None: - self.setAttribute(Attribute('viewBox', _viewboxlist(viewBox))) - if refx<>None: - self.setAttribute(Attribute('refX', refx)) - if refy<>None: - self.setAttribute(Attribute('refY', refy)) - if markerWidth<>None: - self.setAttribute(Attribute('markerWidth', markerWidth)) - if markerHeight<>None: - self.setAttribute(Attribute('markerHeight', markerHeight)) - - def _construct(attributes): - return marker() - _construct = staticmethod(_construct) - - -class group(SVGelement): - """g=group(id,**args) - - a group is defined by an id and is used to contain elements - g.addElement(SVGelement) - """ - def __init__(self,id=None,**args): - SVGelement.__init__(self,'g',**args) - if id<>None: - self.setAttribute(Attribute('id', id)) - - def _construct(attributes): - return group() - _construct = staticmethod(_construct) - -class symbol(SVGelement): - """sy=symbol(id,viewbox,**args) - - defines a symbol which can be used on different places in your graph using - the use element. A symbol is not rendered but you can use 'use' elements to - display it by referencing its id. - sy.addElement(SVGelement) - """ - - def __init__(self,id=None,viewBox=None,**args): - SVGelement.__init__(self,'symbol',**args) - if id<>None: - self.setAttribute(Attribute('id', id)) - if viewBox<>None: - self.setAttribute(Attribute('viewBox', _viewboxlist(viewBox))) - - def _construct(attributes): - return symbol() - _construct = staticmethod(_construct) - - -class defs(SVGelement): - """d=defs(**args) - - container for defining elements - """ - def __init__(self,**args): - SVGelement.__init__(self,'defs',**args) - - def _construct(attributes): - return defs() - _construct = staticmethod(_construct) - - -class switch(SVGelement): - """sw=switch(**args) - - Elements added to a switch element which are "switched" by the attributes - requiredFeatures, requiredExtensions and systemLanguage. - Refer to the SVG specification for details. - """ - 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) - - references a symbol by linking to its id and its position, height and width - """ - def __init__(self,link,x=None,y=None,width=None,height=None,**args): - SVGelement.__init__(self,'use',**args) - self.setAttribute(Attribute('href', link, 'xlink', xlinkNSRef)) - if x<>None: - self.setAttribute(Attribute('x', x)) - if y<>None: - self.setAttribute(Attribute('y', y)) - - if width<>None: - self.setAttribute(Attribute('width', width)) - if height<>None: - self.setAttribute(Attribute('height', height)) - - def _construct(attributes): - href = get_attr_value(attributes, 'href') - if href and href.nsname == 'xlink': - return use(href.value) - return None - _construct = staticmethod(_construct) - - -class link(SVGelement): - """a=link(url,**args) - - a link is defined by a hyperlink. add elements which have to be linked - a.addElement(SVGelement) - """ - def __init__(self,link='',**args): - SVGelement.__init__(self,'a',**args) - self.setAttribute(Attribute('href', link, 'xlink', xlinkNSRef)) - - def _construct(attributes): - href = get_attr_value(attributes, 'href') - if href and href.nsname == 'xlink': - return link(href.value) - return None - _construct = staticmethod(_construct) - - -class view(SVGelement): - """v=view(id,**args) - - a view can be used to create a view with different attributes""" - def __init__(self,id=None,**args): - SVGelement.__init__(self,'view',**args) - if id<>None: - self.setAttribute(Attribute('id', id)) - - def _construct(attributes): - return view() - _construct = staticmethod(_construct) - - -class script(SVGelement): - """sc=script(type,type,cdata,**args) - - adds a script element which contains CDATA to the SVG drawing - - """ - 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.value, cdata=cdata.value) - _construct = staticmethod(_construct) - - -class animate(SVGelement): - """an=animate(attribute,from,to,during,**args) - - animates an attribute. - """ - def __init__(self,attribute,fr=None,to=None,dur=None,**args): - SVGelement.__init__(self,'animate',{'attributeName':attribute},**args) - if fr<>None: - self.setAttribute(Attribute('from', fr)) - if to<>None: - self.setAttribute(Attribute('to', to)) - if dur<>None: - self.setAttribute(Attribute('dur', dur)) - - def _construct(attributes): - attribute = get_attr_value(attributes, 'attributeName') - return animate(attribute.value) - _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=None,dur=None,**args): - SVGelement.__init__(self,'animateMotion',**args) - if pathdata<>None: - self.setAttribute(Attribute('path', str(pathdata))) - if dur<>None: - self.setAttribute(Attribute('dur', dur)) - - def _construct(attributes): - return animateMotion() - _construct = staticmethod(_construct) - - -class animateTransform(SVGelement): - """antr=animateTransform(type,from,to,dur,**args) - - transform an element from and to a value. - """ - def __init__(self,type=None,fr=None,to=None,dur=None,**args): - SVGelement.__init__(self,'animateTransform',{'attributeName':'transform'},**args) - #As far as I know the attributeName is always transform - if type<>None: - self.setAttribute(Attribute('type', type)) - if fr<>None: - self.setAttribute(Attribute('from', fr)) - if to<>None: - self.setAttribute(Attribute('to', to)) - if dur<>None: - self.setAttribute(Attribute('dur', dur)) - - def _construct(attributes): - return animateTransform() - _construct = staticmethod(_construct) - - -class animateColor(SVGelement): - """ac=animateColor(attribute,type,from,to,dur,**args) - - Animates the color of a element - """ - def __init__(self,attribute,type=None,fr=None,to=None,dur=None,**args): - SVGelement.__init__(self,'animateColor',{'attributeName':attribute},**args) - if type<>None: - self.setAttribute(Attribute('type', type)) - if fr<>None: - self.setAttribute(Attribute('from', fr)) - if to<>None: - self.setAttribute(Attribute('to', to)) - if dur<>None: - self.setAttribute(Attribute('dur', dur)) - - def _construct(attributes): - attribute = get_attr_value(attributes, 'attributeName') - return animateColor(attribute.value) - _construct = staticmethod(_construct) - - -class set(SVGelement): - """st=set(attribute,to,during,**args) - - sets an attribute to a value for a - """ - def __init__(self,attribute,to=None,dur=None,**args): - SVGelement.__init__(self,'set',{'attributeName':attribute},**args) - if to<>None: - self.setAttribute(Attribute('to', to)) - if dur<>None: - self.setAttribute(Attribute('dur', dur)) - - def _construct(attributes): - attribute = get_attr_value(attributes, 'attributeName') - return set(attribute.value) - _construct = staticmethod(_construct) - - -class svg(SVGelement): - """s=svg(viewbox,width,height,**args) - - a svg or element is the root of a drawing add all elements to a svg element. - You can have different svg elements in one svg file - s.addElement(SVGelement) - - eg - d=drawing() - s=svg((0,0,100,100),'100%','100%') - c=circle(50,50,20) - s.addElement(c) - d.setSVG(s) - d.toXml() - """ - def __init__(self,viewBox=None, width=None, height=None,**args): - SVGelement.__init__(self,'svg',**args) - if viewBox<>None: - self.setAttribute(Attribute('viewBox', _viewboxlist(viewBox))) - if width<>None: - self.setAttribute(Attribute('width', width)) - if height<>None: - 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 - import copy - attrs = copy.deepcopy(attrs) - 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 and elt: - 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: - if not elt.text: - elt.text = "" - 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() - - this is the actual SVG document. It needs a svg element as a root. - Use the addSVG method to set the svg to the root. Use the toXml method to write the SVG - source to the screen or to a file - d=drawing() - d.addSVG(svg) - d.toXml(optionalfilename) - """ - - def __init__(self): - self.svg=None - - def setSVG(self,svg): - 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 - xml=cStringIO.StringIO() - xml.write("\n") - xml.write("\n") - self.svg.toXml(0,xml) - if not filename: - if compress: - import gzip - f=cStringIO.StringIO() - zf=gzip.GzipFile(fileobj=f,mode='wb') - zf.write(xml.getvalue()) - zf.close() - f.seek(0) - return f.read() - else: - return xml.getvalue() - else: - if filename[-4:]=='svgz': - import gzip - f=gzip.GzipFile(filename=filename,mode="wb", compresslevel=9) - f.write(xml.getvalue()) - f.close() - else: - f=file(filename,'w') - f.write(xml.getvalue()) - f.close() - - else: - def toXml(self,filename='',compress=False): - """drawing.toXml() ---->to the screen - drawing.toXml(filename)---->to the file - writes a svg drawing to the screen or to a file - compresses if filename ends with svgz or if compress is true - """ - doctype = implementation.createDocumentType('svg',"-//W3C//DTD SVG 1.0//EN""",'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd ') - - global root - #root is defined global so it can be used by the appender. Its also possible to use it as an arugument but - #that is a bit messy. - root=implementation.createDocument(None,None,doctype) - #Create the xml document. - global appender - def appender(element,elementroot): - """This recursive function appends elements to an element and sets the attributes - and type. It stops when alle elements have been appended""" - if element.namespace: - e=root.createElementNS(element.namespace,element.type) - else: - e=root.createElement(element.type) - if element.text: - textnode=root.createTextNode(element.text) - e.appendChild(textnode) - for attr in element.attributes.values(): #in element.attributes is supported from python 2.2 - if attr.nsname and attr.nsref: - e.setAttributeNS(attr.nsref, attr.nsname+":"+attr.name, str(attr.value)) - else: - e.setAttribute(attr.name,str(attr.value)) - if element.elements: - for el in element.elements: - e=appender(el,e) - elementroot.appendChild(e) - return elementroot - root=appender(self.svg,root) - if not filename: - import cStringIO - xml=cStringIO.StringIO() - PrettyPrint(root,xml) - if compress: - import gzip - f=cStringIO.StringIO() - zf=gzip.GzipFile(fileobj=f,mode='wb') - zf.write(xml.getvalue()) - zf.close() - f.seek(0) - return f.read() - else: - return xml.getvalue() - else: - try: - if filename[-4:]=='svgz': - import gzip - import cStringIO - xml=cStringIO.StringIO() - PrettyPrint(root,xml) - f=gzip.GzipFile(filename=filename,mode='wb',compresslevel=9) - f.write(xml.getvalue()) - f.close() - else: - f=open(filename,'w') - PrettyPrint(root,f) - f.close() - except: - print "Cannot write SVG file: " + filename - - def validate(self): - try: - import xml.parsers.xmlproc.xmlval - except: - raise exceptions.ImportError,'PyXml is required for validating SVG' - svg=self.toXml() - xv=xml.parsers.xmlproc.xmlval.XMLValidator() - try: - xv.feed(svg) - except: - raise "SVG is not well formed, see messages above" - else: - print "SVG well formed" - - -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 from_file(document): - import sys - f = open(sys.argv[1], "r") - fc = f.read() - document.fromXml(fc) - print document.toXml() - -def to_file(document): - 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) - g=group('animations') - e=ellipse(0,0,5,2) - g.addElement(e) - c=circle(0,0,1,'red') - g.addElement(c) - pd=pathdata(0,-10) - for i in range(6): - pd.relsmbezier(10,5,0,10) - pd.relsmbezier(-10,5,0,10) - an=animateMotion(pd,10) - an.setAttribute(Attribute('rotate', 'auto-reverse')) - an.setAttribute(Attribute('repeatCount', "indefinite")) - g.addElement(an) - s.addElement(g) - for i in range(20,120,20): - u=use('#animations',i,0) - s.addElement(u) - for i in range(0,120,20): - for j in range(5,105,10): - c=circle(i,j,1,'red','black',.5) - s.addElement(c) - document.setSVG(s) - - print document.toXml() - -def main(): - d=drawing() - from_file(d) -# to_file(d) - -if __name__=='__main__': - main() diff --git a/sugar/chat/sketchpad/Sketch.py b/sugar/chat/sketchpad/Sketch.py deleted file mode 100644 index ac0a865f..00000000 --- a/sugar/chat/sketchpad/Sketch.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -from SVGdraw import path - -class Sketch: - def __init__(self, rgb): - self._points = [] - self._rgb = (float(rgb[0]), float(rgb[1]), float(rgb[2])) - - def add_point(self, x, y): - self._points.append((x, y)) - - def get_points(self): - return self._points - - def draw(self, ctx): - start = True - for (x, y) in self._points: - if start: - ctx.move_to(x, y) - start = False - else: - ctx.line_to(x, y) - ctx.set_source_rgb(self._rgb[0], self._rgb[1], self._rgb[2]) - ctx.stroke() - - def draw_to_svg(self): - i = 0 - for (x, y) in self._points: - coords = str(x) + ' ' + str(y) + ' ' - if i == 0: - path_data = 'M ' + coords - elif i == 1: - path_data += 'L ' + coords - else: - path_data += coords - i += 1 - color = "#%02X%02X%02X" % (255 * self._rgb[0], 255 * self._rgb[1], 255 * self._rgb[2]) - return path(path_data, fill = 'none', stroke = color) diff --git a/sugar/chat/sketchpad/SketchPad.py b/sugar/chat/sketchpad/SketchPad.py deleted file mode 100644 index e15e4358..00000000 --- a/sugar/chat/sketchpad/SketchPad.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk, gobject - -from Sketch import Sketch - -from SVGdraw import drawing -from SVGdraw import svg - -class SketchPad(gtk.DrawingArea): - __gsignals__ = { - 'new-user-sketch':(gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) - } - - def __init__(self, bgcolor=(0.6, 1, 0.4)): - gtk.DrawingArea.__init__(self) - - self._active_sketch = None - self._rgb = (0.0, 0.0, 0.0) - self._bgcolor = bgcolor - self._sketches = [] - - self.add_events(gtk.gdk.BUTTON_PRESS_MASK | - gtk.gdk.BUTTON_RELEASE_MASK | - gtk.gdk.BUTTON1_MOTION_MASK) - self.connect("button-press-event", self._button_press_cb) - self.connect("button-release-event", self._button_release_cb) - self.connect("motion-notify-event", self._motion_notify_cb) - self.connect('expose_event', self.expose) - - def clear(self): - self._sketches = [] - self.window.invalidate_rect(None, False) - - def expose(self, widget, event): - """Draw the background of the sketchpad.""" - rect = self.get_allocation() - ctx = widget.window.cairo_create() - - ctx.set_source_rgb(self._bgcolor[0], self._bgcolor[1], self._bgcolor[2]) - ctx.rectangle(0, 0, rect.width, rect.height) - ctx.fill_preserve() - - ctx.set_source_rgb(0, 0.3, 0.2) - ctx.stroke() - - for sketch in self._sketches: - sketch.draw(ctx) - - return False - - def set_color(self, color): - """Sets the current drawing color of the sketchpad. - color agument should be 3-item tuple of rgb values between 0 and 1.""" - self._rgb = color - - def add_sketch(self, sketch): - """Add a sketch to the the pad. Mostly for subclasses and clients.""" - self._sketches.append(sketch) - self.window.invalidate_rect(None, False) - - def add_point(self, event): - if not self._active_sketch: - return - self._active_sketch.add_point(event.x, event.y) - self.window.invalidate_rect(None, False) - - def _button_press_cb(self, widget, event): - self._active_sketch = Sketch(self._rgb) - self._sketches.append(self._active_sketch) - self.add_point(event) - - def _button_release_cb(self, widget, event): - self.add_point(event) - self.emit('new-user-sketch', self._active_sketch) - self._active_sketch = None - - def _motion_notify_cb(self, widget, event): - self.add_point(event) - - def to_svg(self): - """Return a string containing an SVG representation of this sketch.""" - d = drawing() - s = svg() - for sketch in self._sketches: - s.addElement(sketch.draw_to_svg()) - d.setSVG(s) - return d.toXml() - -def test_quit(w, skpad): - print skpad.to_svg() - gtk.main_quit() - -if __name__ == "__main__": - window = gtk.Window() - window.set_default_size(400, 300) - window.connect("destroy", lambda w: gtk.main_quit()) - - sketchpad = SketchPad() - window.add(sketchpad) - sketchpad.show() - - window.show() - - window.connect("destroy", test_quit, sketchpad) - - gtk.main() diff --git a/sugar/chat/sketchpad/Toolbox.py b/sugar/chat/sketchpad/Toolbox.py deleted file mode 100644 index b142f988..00000000 --- a/sugar/chat/sketchpad/Toolbox.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk -import gobject - -class ColorButton(gtk.RadioButton): - def __init__(self, group, rgb): - gtk.RadioButton.__init__(self, group) - - self._rgb = rgb - - self.set_mode(False) - self.set_relief(gtk.RELIEF_NONE) - - drawing_area = gtk.DrawingArea() - drawing_area.set_size_request(24, 24) - drawing_area.connect_after('expose_event', self.expose) - self.add(drawing_area) - drawing_area.show() - - def color(self): - return self._rgb - - def expose(self, widget, event): - rect = widget.get_allocation() - ctx = widget.window.cairo_create() - - ctx.set_source_rgb(self._rgb[0], self._rgb[1] , self._rgb[2]) - ctx.rectangle(4, 4, rect.width - 8, rect.height - 8) - ctx.fill() - - return False - -class Toolbox(gtk.HBox): - __gsignals__ = { - 'color-selected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) - } - - def __init__(self): - gtk.HBox.__init__(self, False, 6) - - self._colors_group = None - - self._add_color([0, 0, 0]) - self._add_color([1, 0, 0]) - self._add_color([0, 1, 0]) - self._add_color([0, 0, 1]) - - def _add_color(self, rgb): - color = ColorButton(self._colors_group, rgb) - color.unset_flags(gtk.CAN_FOCUS) - color.connect('clicked', self.__color_clicked_cb, rgb) - self.pack_start(color, False) - - if self._colors_group == None: - self._colors_group = color - - color.show() - - def __color_clicked_cb(self, button, rgb): - self.emit("color-selected", button.color()) diff --git a/sugar/chat/sketchpad/__init__.py b/sugar/chat/sketchpad/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/sugar/simulator.py b/sugar/simulator.py deleted file mode 100644 index fd592ee4..00000000 --- a/sugar/simulator.py +++ /dev/null @@ -1,183 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import random -import copy - -import gobject -import dbus - -from sugar.presence import PresenceService -from sugar.graphics.xocolor import XoColor -from sugar.p2p import Stream -from sugar import util - -_nick_names = ['Aba', 'Abebe', 'Abebi', 'Abena', 'Abeni', 'Abeo', 'Abiba', 'Ada', 'Adah', 'Adana', 'Adanna', 'Adanya', 'Aissa', 'Akili', 'Alika', 'Ama', 'Amadi', 'Ameena', 'Ameenah', 'Ami', 'Amina', 'Aminah', 'Arziki', 'Asha', 'Ashia', 'Aziza', 'Baako', 'Binah', 'Binta', 'Bisa', 'Bolanle', 'Bunme', 'Caimile', 'Cataval', 'Chika', 'Chipo', 'Dalia', 'Dalila', 'Dayo', 'Deka', 'Delu', 'Denisha', 'Dore', 'Ebere', 'Fadhila', 'Faizah', 'Falala', 'Fayola', 'Feechi', 'Femi', 'Fisseha', 'Fola', 'Gamada', 'Ghalyela', 'Habika', 'Hada', 'Hadiya', 'Haiba', 'Halima', 'Hanzila', 'Hasina', 'Hija', 'Ilori', 'Iman', 'Imena', 'Iniko', 'Isabis', 'Isoke', 'Jahia', 'Jamelia', 'Jamila', 'Jamilah', 'Jamilia', 'Jamilla', 'Jamille', 'Jemila', 'Jendayi', 'Jina', 'Kabira', 'Kadija', 'Kafi', 'Kainda', 'Kali', 'Kalifa', 'Kanene', 'Kapera', 'Karimah', 'Kasinda', 'Keisha', 'Kesia', 'Lakeesha', 'Lateefah', 'Latrice', 'Latricia', 'Leal', 'Lehana', 'Limber', 'Lulu', 'Maha', 'Maizah', 'Malika', 'Mandisa', 'Mardea', 'Marjani', 'Marka', 'Nabelung', 'Nailah', 'Naima', 'Naja', 'Nakeisha', 'Narkeasha', 'Neda', 'Neema', 'Nichelle', 'Oba', 'Okoth', 'Ontibile', 'Orma', 'Pemba', 'Rabia', 'Rafiya', 'Ramla', 'Rashida', 'Raziya', 'Reta', 'Ridhaa', 'Saada', 'Sabra', 'Safara', 'Saidah', 'Salihah', 'Shasa', 'Shasmecka', 'Sibongile', 'Sika', 'Simbra', 'Sitembile', 'Siyanda', 'Sukutai', 'Tabita', 'Taifa', 'Taja', 'Takiyah', 'Tamala', 'Tamasha', 'Tanesha', 'Tanginika', 'Tanishia', 'Tapanga', 'Tarisai', 'Tayla', 'Tendai', 'Thandiwe', 'Tiesha', 'TinekaJawana', 'Tiombe', 'Wafa', 'Wangari', 'Waseme', 'Xhosa', 'Zabia', 'Zahara', 'Zahra', 'Zalika', 'Zanta', 'Zarina', 'Zina', 'Aba', 'Abebe', 'Abebi', 'Abena', 'Abeni', 'Abeo', 'Abiba', 'Ada', 'Adah', 'Adana', 'Adanna', 'Adanya', 'Aissa', 'Akili', 'Alika', 'Ama', 'Amadi', 'Ameena', 'Ameenah', 'Ami', 'Amina', 'Aminah', 'Amineh', 'Arziki', 'Asha', 'Ashia', 'Aziza', 'Baako', 'Binah', 'Binta', 'Bisa', 'Bolanle', 'Bunme', 'Caimile', 'Cataval', 'Chika', 'Chipo', 'Dalila', 'Dayo', 'Deka', 'Delu', 'Denisha', 'Dore', 'Ebere', 'Fadhila', 'Faizah', 'Falala', 'Fayola', 'Feechi', 'Femi', 'Fisseha', 'Fola', 'Gamada', 'Ghalyela', 'Habika', 'Hada', 'Hadiya', 'Haiba', 'Halima', 'Hanzila', 'Hasina', 'Hija', 'Ilori', 'Iman', 'Imena', 'Iniko', 'Isabis', 'Isoke', 'Jahia', 'Jamelia', 'Jamila', 'Jamilah', 'Jamilia', 'Jamilla', 'Jamille', 'Jemila', 'Jendayi', 'Jina', 'Kabira', 'Kadija', 'Kafi', 'Kainda', 'Kali', 'Kalifa', 'Kanene', 'Kapera', 'Karimah', 'Kasinda', 'Keisha', 'Kesia', 'Lakeesha', 'Lateefah', 'Latrice', 'Leal', 'Lehana', 'Limber', 'Lulu', 'Maha', 'Maizah', 'Malika', 'Mandisa', 'Mandisa', 'Mardea', 'Marjani', 'Marka', 'Nabelung', 'Nailah', 'Naima', 'Naja', 'Nakeisha', 'Narkeasha', 'Neda', 'Neema', 'Nichelle', 'Oba', 'Okoth', 'Ontibile', 'Orma', 'Pemba', 'Rabia', 'Rafiya', 'Ramla', 'Rashida', 'Raziya', 'Reta', 'Ridhaa', 'Saada', 'Sabra', 'Safara', 'Saidah', 'Salihah', 'Shasa', 'Shasmecka', 'Sibongile', 'Sika', 'Simbra', 'Sitembile', 'Siyanda', 'Sukutai', 'Tabita', 'Taifa', 'Taja', 'Takiyah', 'Tale', 'Tale green', 'Tamala', 'Tamasha', 'Tanesha', 'Tanginika', 'Tanishia', 'Tapanga', 'Tarisai', 'Tayla', 'Tendai', 'Thandiwe', 'Tiesha', 'TinekaJawana', 'Tiombe', 'Wafa', 'Wangari', 'Waseme', 'Xhosa', 'Zabia', 'Zahara', 'Zahra', 'Zalika', 'Zanta'] - -_PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp" - -_activity_refs = {} - -class _NameCollection(object): - def __init__(self): - self._names = copy.copy(_nick_names) - - def get_name(self): - i = random.randint(0, len(self._names)) - return self._names.pop(i) - -class _BotService(object): - def __init__(self, bot): - self._bot = bot - - def announce(self): - props = { 'color': self._bot.color.to_string() } - pservice = PresenceService.get_instance() - self._service = pservice.register_service(self._bot.name, - _PRESENCE_SERVICE_TYPE, properties=props) - - self._stream = Stream.Stream.new_from_service(self._service) - self._stream.register_reader_handler( - self._handle_buddy_icon_request, "get_buddy_icon") - self._stream.register_reader_handler( - self._handle_invite, "invite") - - def _handle_buddy_icon_request(self): - if self._bot.icon: - fd = open(self._bot.icon, "r") - icon_data = fd.read() - fd.close() - if icon_data: - return base64.b64encode(self._icon) - return '' - - def _handle_invite(self, issuer, bundle_id, activity_id): - return '' - - def set_current_activity(self, activity_id): - self._service.set_published_value('curact', dbus.String(activity_id)) - -class _JoinActivityAction(object): - def __init__(self, bot, named_ref): - self._bot = bot - self._named_ref = named_ref - - def execute(self): - activity_id = _activity_refs[self._named_ref] - - pservice = PresenceService.get_instance() - activity = pservice.get_activity(activity_id) - service = activity.get_services()[0] - - name = "%s [%s]" % (self._bot.name, activity_id) - properties = { 'title' : service.get_published_value('title'), - 'color' : service.get_published_value('color') } - - pservice.register_service(name, service.get_type(), - properties, service.get_address(), - service.get_port()) - - self._bot._service.set_current_activity(activity_id) - -class _ChangeActivityAction(object): - def __init__(self, bot, named_ref): - self._bot = bot - self._named_ref = named_ref - - def execute(self): - activity_id = _activity_refs[self._named_ref] - self._bot._service.set_current_activity(activity_id) - -class _ShareChatAction(object): - def __init__(self, bot, named_ref, title): - self._bot = bot - self._title = title - self._id = util.unique_id() - - _activity_refs[named_ref] = self._id - - def execute(self): - name = "%s [%s]" % (self._bot.name, self._id) - stype = '_GroupChatActivity_Sugar_redhat_com._udp' - properties = { 'title' : self._title, - 'color' : self._bot.color.to_string() } - address = u"232.%d.%d.%d" % (random.randint(0, 254), - random.randint(1, 254), - random.randint(1, 254)) - - pservice = PresenceService.get_instance() - pservice.register_service(name, stype, properties, address) - -class _WaitAction(object): - def __init__(self, bot, seconds): - self._bot = bot - self._seconds = seconds - - def execute(self): - self._bot._pause_queue(self._seconds) - -class Bot(object): - _name_collection = _NameCollection() - - def __init__(self): - self.name = Bot._name_collection.get_name() - self.color = XoColor() - self.icon = None - - self._queue = [] - - def wait(self, seconds): - action = _WaitAction(self, seconds) - self._queue.append(action) - - def share_chat(self, activity_id, title): - action = _ShareChatAction(self, activity_id, title) - self._queue.append(action) - - def change_activity(self, activity_id): - action = _ChangeActivityAction(self, activity_id) - self._queue.append(action) - - def join_activity(self, activity_id): - action = _JoinActivityAction(self, activity_id) - self._queue.append(action) - - def start(self): - self._service = _BotService(self) - self._service.announce() - - self._start_queue() - - def _idle_cb(self): - self._next_action() - return True - - def _pause_done_cb(self): - self._start_queue() - return False - - def _start_queue(self): - self._queue_sid = gobject.idle_add(self._idle_cb) - - def _pause_queue(self, seconds): - gobject.source_remove(self._queue_sid) - gobject.timeout_add(int(seconds * 1000), self._pause_done_cb) - - def _next_action(self): - if len(self._queue) > 0: - action = self._queue.pop(0) - action.execute() diff --git a/tests/simulator/data/LICENSE b/tests/simulator/data/LICENSE deleted file mode 100644 index e80f60b7..00000000 --- a/tests/simulator/data/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -This work is licensed under the Creative Commons Attribution 2.5 License. To view a copy of this license, visit http://creativecommons.org/licenses/by/2.5/ or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA. - -Attributions: - -chaitanya.jpg http://www.flickr.com/photos/meanestindian/166408558/ -penelope.jpg http://www.flickr.com/photos/gagah/9257515/ -kiu.jpg http://flickr.com/photos/31072589@N00/139234295/ diff --git a/tests/simulator/data/chaitanya.jpg b/tests/simulator/data/chaitanya.jpg deleted file mode 100644 index aecaf81e..00000000 Binary files a/tests/simulator/data/chaitanya.jpg and /dev/null differ diff --git a/tests/simulator/data/kiu.jpg b/tests/simulator/data/kiu.jpg deleted file mode 100644 index 1beca114..00000000 Binary files a/tests/simulator/data/kiu.jpg and /dev/null differ diff --git a/tests/simulator/data/penelope.jpg b/tests/simulator/data/penelope.jpg deleted file mode 100644 index 0d810977..00000000 Binary files a/tests/simulator/data/penelope.jpg and /dev/null differ diff --git a/tests/simulator/demo/chaitanya.py b/tests/simulator/demo/chaitanya.py deleted file mode 100644 index 7d374a3d..00000000 --- a/tests/simulator/demo/chaitanya.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from sugar.simulator import Bot - -bot = Bot() -bot.name = 'chaitanya' - -bot.share_chat('giraffes', 'All About Giraffes') - -bot.start() diff --git a/tests/simulator/demo/others.py b/tests/simulator/demo/others.py deleted file mode 100644 index 0b87c0c4..00000000 --- a/tests/simulator/demo/others.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import random - -from sugar.simulator import Bot - -for i in range(0, 8): - bot = Bot() - - bot.wait(random.randint(10, 20)) - bot.join_activity('giraffes') - bot.change_activity('giraffes') - - bot.start() - -for i in range(0, 6): - bot = Bot() - - bot.wait(random.randint(10, 20)) - bot.join_activity('nekkhamma') - bot.change_activity('nekkhamma') - - bot.start() diff --git a/tests/simulator/demo/penelope.py b/tests/simulator/demo/penelope.py deleted file mode 100644 index 60cc1fe3..00000000 --- a/tests/simulator/demo/penelope.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from sugar.simulator import Bot - -bot = Bot() -bot.name = 'penelope' - -bot.share_chat('nekkhamma', 'Nekkhamma') - -bot.start() diff --git a/tests/simulator/simulator b/tests/simulator/simulator deleted file mode 100755 index 838d645b..00000000 --- a/tests/simulator/simulator +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2006, Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import os - -import gobject - -from sugar.presence import PresenceService - -PresenceService.start() - -base_path = os.path.abspath(os.path.dirname(__file__)) - -stage_path = os.path.join(base_path, 'demo') -for bot_file in os.listdir(stage_path): - if bot_file.endswith('.py'): - execfile(os.path.join(stage_path, bot_file)) - -mainloop = gobject.MainLoop() -mainloop.run() diff --git a/tests/sketch/Makefile.am b/tests/sketch/Makefile.am deleted file mode 100644 index d8e3c428..00000000 --- a/tests/sketch/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pkgdatadir)/activities/sketch -sugar_PYTHON = \ - __init__.py \ - sketchactivity.py - -EXTRA_DIST = sketch.activity diff --git a/tests/sketch/__init__.py b/tests/sketch/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/sketch/sketch.activity b/tests/sketch/sketch.activity deleted file mode 100644 index 07223880..00000000 --- a/tests/sketch/sketch.activity +++ /dev/null @@ -1,6 +0,0 @@ -[Activity] -name = Sketch -id = org.laptop.Sketch -icon = activity-sketch -python_module = sketch.sketchactivity.SketchActivity -show_launcher = yes diff --git a/tests/sketch/sketchactivity.py b/tests/sketch/sketchactivity.py deleted file mode 100644 index 97db0c48..00000000 --- a/tests/sketch/sketchactivity.py +++ /dev/null @@ -1,234 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gtk -import gobject -import os -import logging - -from sugar.p2p import MostlyReliablePipe -from sugar.p2p.Stream import Stream - -from sugar.presence import PresenceService -from sugar.activity.Activity import Activity -from sugar.chat.sketchpad import SketchPad -from sugar.chat.sketchpad import Sketch -from sugar.graphics.xocolor import XoColor -from sugar import profile - -class NetworkController(gobject.GObject): - __gsignals__ = { - 'new-path':(gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), - } - - def __init__(self, parent, ps_owner): - gobject.GObject.__init__(self) - self._parent = parent - self._parent.connect('buddy-joined', self._buddy_joined) - self._parent.connect('buddy-left', self._buddy_left) - self._stream = None - self._stream_writer = None - self._joined_buddies = {} # IP address -> buddy - self._ps_owner = ps_owner - - def init_stream(self, service): - self._stream = Stream.new_from_service(service) - self._stream.set_data_listener(self._recv_message) - self._stream_writer = self._stream.new_writer() - - def _recv_message(self, address, msg): - # Ignore multicast messages from ourself - if self._ps_owner and address == self._ps_owner.get_ip4_address(): - return - - # Ensure the message comes from somebody in this activity - if not self._joined_buddies.has_key(address): - logging.debug("Message from unjoined buddy.") - return - - # Convert the points to an array and send to the sketchpad - points = [] - msg = msg.strip() - split_coords = msg.split(" ") - for item in split_coords: - x = 0 - y = 0 - try: - (x, y) = item.split(",") - x = float(x) - y = float(y) - except ValueError: - continue - if x < 0 or y < 0: - continue - points.append((x, y)) - - buddy = self._joined_buddies[address] - self.emit("new-path", buddy, points) - - def _buddy_joined(self, widget, activity, buddy, activity_type): - activity_service = buddy.get_service_of_type(activity_type, activity) - if not activity_service: - logging.debug("Buddy Joined, but could not get activity service " \ - "of %s" % activity_type) - return - - address = activity_service.get_source_address() - port = activity_service.get_port() - if not address or not port: - logging.debug("Buddy Joined, but could not get address/port from" \ - " activity service %s" % activity_type) - return - if not self._joined_buddies.has_key(address): - logging.debug("Buddy joined: %s (%s)" % (address, port)) - self._joined_buddies[address] = buddy - - def _buddy_left(self, widget, activity, buddy, activity_type): - buddy_key = None - for (key, value) in self._joined_buddies.items(): - if value == buddy: - buddy_key = key - break - if buddy_key: - del self._joined_buddies[buddy_key] - - def new_local_sketch(self, path): - """ Receive an array of point tuples the local user created """ - cmd = "" - # Convert points into the wire format - for point in path: - cmd = cmd + "%d,%d " % (point[0], point[1]) - - # If there were no points, or we aren't in a shared activity yet, - # don't send anything - if not len(cmd) or not self._stream_writer: - return - - # Send the points to other buddies - self._stream_writer.write(cmd) - -def _html_to_rgb_color(colorstring): - """ converts #RRGGBB to cairo-suitable floats""" - colorstring = colorstring.strip() - while colorstring[0] == '#': - colorstring = colorstring[1:] - r = int(colorstring[:2], 16) - g = int(colorstring[2:4], 16) - b = int(colorstring[4:6], 16) - color = ((float(r) / 255.0), (float(g) / 255.0), (float(b) / 255.0)) - return color - - -class SharedSketchPad(SketchPad.SketchPad): - def __init__(self, net_controller, color): - SketchPad.SketchPad.__init__(self, bgcolor=(1.0, 0.984313725, 0.560784314)) - self._net_controller = net_controller - self._user_color = _html_to_rgb_color(color) - self.set_color(self._user_color) - - # Receive notifications when our buddies send us new sketches - self._net_controller.connect('new-path', self._new_buddy_path) - - self.connect('new-user-sketch', self._new_local_sketch_cb) - - def _new_buddy_path(self, net_controller, buddy, path): - """ Called whenever a buddy on the mesh sends us a new sketch path """ - str_color = buddy.get_color() - if not str_color: - str_color = "#348798" # FIXME - color = XoColor(str_color) - stroke_color = _html_to_rgb_color(color.get_stroke_color()) - sketch = Sketch.Sketch(stroke_color) - for item in path: - sketch.add_point(item[0], item[1]) - self.add_sketch(sketch) - - def _new_local_sketch_cb(self, widget, sketch): - """ Send the sketch the user just made to the network """ - self._net_controller.new_local_sketch(sketch.get_points()) - - -class SketchActivity(Activity): - __gsignals__ = { - 'buddy-joined':(gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), - 'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])) - } - - def __init__(self): - Activity.__init__(self) - self.connect('destroy', self._cleanup_cb) - - self.set_title("Sketch") - - self._ps = PresenceService.get_instance() - self._ps_activity = None - self._owner = self._ps.get_owner() - - self._net_controller = NetworkController(self, self._owner) - self._sketchpad = SharedSketchPad(self._net_controller, - profile.get_color().get_stroke_color()) - self.add(self._sketchpad) - self.show_all() - - def get_ps(self): - return self._ps - - def _cleanup_cb(self): - del self._net_controller - - def share(self): - Activity.share(self) - self._net_controller.init_stream(self._service) - self._ps.connect('activity-appeared', self._activity_appeared_cb) - - def join(self, activity_ps): - Activity.join(self, activity_ps) - self._net_controller.init_stream(self._service) - self._ps.connect('activity-appeared', self._activity_appeared_cb) - self._activity_appeared_cb(self._ps, activity_ps) - - def _activity_appeared_cb(self, ps, activity): - # Only care about our own activity - if activity.get_id() != self.get_id(): - return - - # If we already have found our shared activity, do nothing - if self._ps_activity: - return - - self._ps_activity = activity - - # Connect signals to the shared activity so we are notified when - # buddies join and leave - self._ps_activity.connect('buddy-joined', self._add_buddy) - self._ps_activity.connect('buddy-left', self._remove_buddy) - - # Get the list of buddies already in this shared activity so we can - # connect to them - buddies = self._ps_activity.get_joined_buddies() - for buddy in buddies: - self._add_buddy(self._ps_activity, buddy) - - def _add_buddy(self, ps_activity, buddy): - service_type = self._ps_activity - self.emit('buddy-joined', ps_activity, buddy, self.get_default_type()) - - def _remove_buddy(self, ps_activity, buddy): - self.emit('buddy-left', ps_activity, buddy, self.get_default_type()) - diff --git a/tools/build-snapshot.sh b/tools/build-snapshot.sh index 0c35d365..55105232 100755 --- a/tools/build-snapshot.sh +++ b/tools/build-snapshot.sh @@ -1,6 +1,6 @@ VERSION=0.63 DATE=`date +%Y%m%d` -RELEASE=2.61 +RELEASE=2.62 TARBALL=sugar-$VERSION-$RELEASE.${DATE}git.tar.bz2 rm sugar-$VERSION.tar.bz2