diff --git a/activities/web/linkscontroller.py b/activities/web/linkscontroller.py new file mode 100644 index 00000000..e9d4cab9 --- /dev/null +++ b/activities/web/linkscontroller.py @@ -0,0 +1,19 @@ +from sugar.presence import PresenceService + +class LinksController(object): + def __init__(self, service, model): + self._model = model + + self._pservice = PresenceService.get_instance() + + self._stream = Stream.new_from_service(service) + self._stream.set_data_listener(self._recv_message) + self._stream_writer = self._stream.new_writer() + + def post_link(self, title, address): + self._stream_writer.write('test') + + def _recv_message(self, address, msg): + buddy = self._pservice.get_buddy_by_address(address) + if buddy: + self._model.add_link(buddy, 'Test title', 'Test address') diff --git a/activities/web/linksmodel.py b/activities/web/linksmodel.py new file mode 100644 index 00000000..db9e411d --- /dev/null +++ b/activities/web/linksmodel.py @@ -0,0 +1,35 @@ +import gobject + +class Link(object): + def __init__(self, buddy, title, url): + self.buddy = buddy + self.title = title + self.url = url + +class LinksModel(gobject.GObject): + __gsignals__ = { + 'link-added': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), + 'link-removed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), + } + + def __init__(self): + gobject.GObject.__init__(self) + self._links = {} + + def add_link(buddy, title, url): + link = Link(buddy, title, url) + self._links[(buddy.get_name(), url)] = link + + self.emit('link-added', link) + + def remove_link(buddy, url): + key = (buddy.get_name(), url) + if self._links.haskey(key): + link = self._links[key] + del self._links[key] + self.emit('link-removed', link) + + def __iter__(self): + return self._links.values().__iter__() diff --git a/activities/web/linksview.py b/activities/web/linksview.py new file mode 100644 index 00000000..fde11566 --- /dev/null +++ b/activities/web/linksview.py @@ -0,0 +1,36 @@ +import hippo + +from sugar.graphics.bubble import Bubble + +class LinksView(hippo.Canvas): + def __init__(self, model): + hippo.Canvas.__init__(self) + + self._bubbles = {} + + self._box = hippo.CanvasBox(background_color=0x414141ff) + self.set_root(self._box) + + for link in model: + self._add_link(link) + + model.connect('link_added', self._link_added_cb) + model.connect('link_removed', self._link_removed_cb) + + def _add_link(self, link): + bubble = Bubble(color=link.buddy.get_color()) + self._box.append(link) + + self._bubbles[link] = bubble + + def _remove_link(self, link): + bubble = self._bubbles[link] + self._box.remove(bubble) + + del self._bubbles[link] + + def _link_added_cb(self, model, link): + self._add_link(link) + + def _link_removed_cb(self, model, link): + self._removed_link(link) diff --git a/activities/web/toolbar.py b/activities/web/toolbar.py index a820b8f4..a1911433 100644 --- a/activities/web/toolbar.py +++ b/activities/web/toolbar.py @@ -43,6 +43,18 @@ class Toolbar(gtk.Toolbar): self.insert(address_item, -1) address_item.show() + separator = gtk.SeparatorToolItem() + separator.set_draw(False) + self.insert(separator, -1) + separator.show() + + self._post = gtk.ToolButton() + self._post.props.sensitive = False + self._post.set_icon_name('stock-add') + self._post.connect("clicked", self._post_cb) + self.insert(self._post, -1) + self._post.show() + self._insert_spring() self._embed = embed @@ -53,6 +65,10 @@ class Toolbar(gtk.Toolbar): self._embed.connect("notify::can-go-forward", self._can_go_forward_changed_cb) + def set_links_controller(self, links_controller): + self._links_controller = links_controller + self._post.props.sensitive = False + def _progress_changed_cb(self, embed, spec): self._entry.props.progress = embed.props.progress @@ -74,6 +90,11 @@ class Toolbar(gtk.Toolbar): def _go_forward_cb(self, button): self._embed.go_forward() + def _post_cb(self, button): + title = self._embed.get_title() + address = self._embed.get_location() + self._links_controller.post_link(title, address) + def _insert_spring(self): separator = gtk.SeparatorToolItem() separator.set_draw(False) diff --git a/activities/web/webactivity.py b/activities/web/webactivity.py index 452fcae5..518d8bb7 100644 --- a/activities/web/webactivity.py +++ b/activities/web/webactivity.py @@ -6,6 +6,9 @@ from sugar.activity.Activity import Activity from sugar import env from webbrowser import WebBrowser from toolbar import Toolbar +from linksmodel import LinksModel +from linksview import LinksView +from linkscontroller import LinksController _HOMEPAGE = 'http://www.google.com' @@ -20,13 +23,24 @@ class WebActivity(Activity): self._browser = WebBrowser() self._browser.connect('notify::title', self._title_changed_cb) - toolbar = Toolbar(self._browser) - vbox.pack_start(toolbar, False) - toolbar.show() + links_model = LinksModel() + links_view = LinksView(links_model) - vbox.pack_start(self._browser) + self._toolbar = Toolbar(self._browser) + vbox.pack_start(self._toolbar, False) + self._toolbar.show() + + hbox = gtk.HBox() + + hbox.pack_start(links_view, False) + links_view.show() + + hbox.pack_start(self._browser) self._browser.show() + vbox.pack_start(hbox) + hbox.show() + self.add(vbox) vbox.show() @@ -35,6 +49,9 @@ class WebActivity(Activity): def join(self, activity_ps): Activity.join(self, activity_ps) + links_controller = LinksController(service, links_model) + self._toolbar.set_links_controller(links_controller) + url = self._service.get_published_value('URL') if url: self._browser.load_url(url) diff --git a/sugar/graphics/bubble.py b/sugar/graphics/bubble.py new file mode 100644 index 00000000..dc7c6352 --- /dev/null +++ b/sugar/graphics/bubble.py @@ -0,0 +1,48 @@ +import gobject +import hippo + +class Bubble(hippo.CanvasBox, hippo.CanvasItem): + __gtype_name__ = 'SugarBubble' + + __gproperties__ = { + 'color' : (object, None, None, + gobject.PARAM_READWRITE), + } + + def __init__(self, **kwargs): + self._color = None + self._radius = 12 + + hippo.CanvasBox.__init__(self, **kwargs) + + def do_set_property(self, pspec, value): + if pspec.name == 'color': + self._color = value + self.emit_paint_needed(0, 0, -1, -1) + + def do_get_property(self, pspec): + if pspec.name == 'color': + return self._color + + def _color_string_to_rgb(self, color_string): + col = gtk.gdk.color_parse(color_string) + return (col.red / 65535, col.green / 65535, col.blue / 65535) + + def do_paint_below_children(self, cr, damaged_box): + cairo_move_to(self._radius, 0); + cr.arc(width - self._radius, self._radius, + self._radius, math.pi * 1.5, math.pi * 2); + cr.arc(width - self._radius, height - self._radius, + self._radius, 0, math.pi * 0.5); + cr.arc(self._radius, height - self._radius, + self._radius, math.pi * 0.5, math.pi); + cr.arc(cr, self._radius, self._radius, self._radius, + math.pi, math.pi * 1.5); + + color = self._color.get_fill_color() + cr.set_source_rgb(cr, self._color_string_to_rgb(color)); + cairo_fill_preserve(cr); + + color = self._color.get_stroke_color() + cr.set_source_rgb(cr, self._color_string_to_rgb(color)); + cairo_stroke(cr);