From f4e2791c897651d52980d35b84115e7c7f85a249 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Wed, 21 Jun 2006 18:23:18 +0000 Subject: Big refactor of the directory structure and packages to reflect private/public --- (limited to 'activities') diff --git a/activities/browser/AddressItem.py b/activities/browser/AddressItem.py new file mode 100644 index 0000000..df5e71c --- /dev/null +++ b/activities/browser/AddressItem.py @@ -0,0 +1,66 @@ +import pygtk +pygtk.require('2.0') +import gtk + +class AddressEntry(gtk.HBox): + def __init__(self, callback): + gtk.HBox.__init__(self) + + self.callback = callback + self.folded = True + + label = gtk.Label("Open") + self.pack_start(label, False) + label.show() + + self.button = gtk.Button() + self.button.set_relief(gtk.RELIEF_NONE) + self.button.connect("clicked", self.__button_clicked_cb) + self.pack_start(self.button, False) + self.button.show() + + self.entry = gtk.Entry() + self.entry.connect("activate", self.__activate_cb) + self.pack_start(self.entry, False) + self.entry.show() + + self._update_folded_state() + + def _update_folded_state(self): + if self.folded: + image = gtk.Image() + image.set_from_icon_name('expand', gtk.ICON_SIZE_SMALL_TOOLBAR) + self.button.set_image(image) + image.show() + + self.entry.hide() + else: + image = gtk.Image() + image.set_from_icon_name('unexpand', gtk.ICON_SIZE_SMALL_TOOLBAR) + self.button.set_image(image) + image.show() + + self.entry.show() + self.entry.grab_focus() + + def get_folded(self): + return self.folded + + def set_folded(self, folded): + self.folded = folded + self._update_folded_state() + + def __button_clicked_cb(self, button): + self.set_folded(not self.get_folded()) + + def __activate_cb(self, entry): + self.callback(entry.get_text()) + self.set_folded(True) + +class AddressItem(gtk.ToolItem): + def __init__(self, callback): + gtk.ToolItem.__init__(self) + + address_entry = AddressEntry(callback) + self.add(address_entry) + address_entry.show() diff --git a/activities/browser/BrowserActivity.py b/activities/browser/BrowserActivity.py new file mode 100644 index 0000000..662313f --- /dev/null +++ b/activities/browser/BrowserActivity.py @@ -0,0 +1,156 @@ +import logging +import xml.sax.saxutils + +import pygtk +pygtk.require('2.0') +import gtk +import geckoembed + +from sugar.activity import activity +from sugar.presence.PresenceService import PresenceService +from sugar.p2p.model.LocalModel import LocalModel +from sugar.p2p.model.RemoteModel import RemoteModel + +from NotificationBar import NotificationBar +from NavigationToolbar import NavigationToolbar + +_BROWSER_ACTIVITY_TYPE = "_web_olpc._udp" +_SERVICE_URI_TAG = "URI" +_SERVICE_TITLE_TAG = "Title" + +class BrowserActivity(activity.Activity): + SOLO = 1 + FOLLOWING = 2 + LEADING = 3 + + def __init__(self, uri, mode = SOLO): + activity.Activity.__init__(self, _BROWSER_ACTIVITY_TYPE) + self.uri = uri + self._mode = mode + + self._share_service = None + self._model_service = None + self._notif_service = None + self._model = None + + def _service_appeared_cb(self, pservice, buddy, service): + # Make sure the service is for our activity + if service.get_activity_uid() != self._activity_id: + return + + if service.get_type() == _BROWSER_ACTIVITY_TYPE: + self._notif_service = service + elif service.get_type() == LocalModel.SERVICE_TYPE: + if self._mode != BrowserActivity.LEADING: + self._model_service = service + + if self._notif_service and self._model_service: + self._model = RemoteModel(self._model_service, self._notif_service) + self._model.add_listener(self.__shared_location_changed_cb) + + def get_default_type(self): + return _BROWSER_ACTIVITY_TYPE + + def _update_shared_location(self): + address = self.embed.get_address() + self._model.set_value('address', address) + title = self.embed.get_title() + self._model.set_value('title', title) + + def __notif_bar_action_cb(self, bar, action_id): + print action_id + if action_id == 'set_shared_location': + self._update_shared_location() + elif action_id == 'goto_shared_location': + address = self._model.get_value("address") + print address + self.embed.load_address(address) + self._notif_bar.hide() + + def set_mode(self, mode): + self._mode = mode + if mode == BrowserActivity.LEADING: + self._notif_bar.set_text('Share this page with the group.') + self._notif_bar.set_action('set_shared_location', 'Share') + self._notif_bar.set_icon('stock_shared-by-me') + self._notif_bar.show() + + def on_connected_to_shell(self): + self.set_ellipsize_tab(True) + self.set_can_close(True) + self.set_tab_text("Web Page") + self.set_tab_icon(name="web-browser") + self.set_show_tab_icon(True) + + vbox = gtk.VBox() + + self._notif_bar = NotificationBar() + vbox.pack_start(self._notif_bar, False) + self._notif_bar.connect('action', self.__notif_bar_action_cb) + + self.embed = geckoembed.Embed() + self.embed.connect("title", self.__title_cb) + vbox.pack_start(self.embed) + + self.embed.show() + self.embed.load_address(self.uri) + + nav_toolbar = NavigationToolbar(self) + vbox.pack_start(nav_toolbar, False) + nav_toolbar.show() + + plug = self.gtk_plug() + plug.add(vbox) + plug.show() + + vbox.show() + + logging.debug('Start presence service') + self._pservice = PresenceService.get_instance() + self._pservice.start() + + logging.debug('Track browser activities') + self._pservice.connect('service-appeared', self._service_appeared_cb) + self._pservice.track_service_type(_BROWSER_ACTIVITY_TYPE) + self._pservice.track_service_type(LocalModel.SERVICE_TYPE) + + # Join the shared activity if we were started from one + if self._initial_service: + logging.debug("BrowserActivity joining shared activity %s" % self._initial_service.get_activity_uid()) + self._pservice.join_shared_activity(self._initial_service) + + def get_embed(self): + return self.embed + + def publish(self): + escaped_title = xml.sax.saxutils.escape(self.embed.get_title()) + escaped_url = xml.sax.saxutils.escape(self.embed.get_address()) + + # Publish ourselves on the network + properties = {_SERVICE_URI_TAG: escaped_url, _SERVICE_TITLE_TAG: escaped_title} + self._share_service = self._pservice.share_activity(self, + stype=_BROWSER_ACTIVITY_TYPE, properties=properties) + + # Create our activity-specific browser sharing service + self._model = LocalModel(self, self._pservice, self._share_service) + self._model.set_value('owner', self._pservice.get_owner().get_nick_name()) + self._update_shared_location() + + self.set_mode(BrowserActivity.LEADING) + + def __title_cb(self, embed): + self.set_tab_text(embed.get_title()) + + def __shared_location_changed_cb(self, model, key): + self.set_has_changes(True) + self._notify_shared_location_change() + + def _notify_shared_location_change(self): + owner = self._model.get_value('owner') + title = self._model.get_value('title') + + text = '' + owner + ' is reading ' + title + '' + self._notif_bar.set_text(text) + self._notif_bar.set_action('goto_shared_location', 'Go There') + self._notif_bar.set_icon('stock_right') + self._notif_bar.show() diff --git a/activities/browser/BrowserShell.py b/activities/browser/BrowserShell.py new file mode 100644 index 0000000..c1e0c44 --- /dev/null +++ b/activities/browser/BrowserShell.py @@ -0,0 +1,51 @@ +import dbus +import geckoembed +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +import sugar.env +from sugar.presence import Service + +from BrowserActivity import BrowserActivity + +class BrowserShell(dbus.service.Object): + def __init__(self, bus_name, object_path = '/com/redhat/Sugar/Browser'): + dbus.service.Object.__init__(self, bus_name, object_path) + + geckoembed.set_profile_path(sugar.env.get_user_dir()) + self.__browsers = [] + + def start(self): + gtk.main() + + @dbus.service.method('com.redhat.Sugar.BrowserShell') + def get_links(self): + links = [] + for browser in self.__browsers: + embed = browser.get_embed() + link = {} + link['title'] = embed.get_title() + link['address'] = embed.get_address() + links.append(link) + return links + + def _start_browser_cb(self, browser, service): + browser.connect_to_shell(service) + + @dbus.service.method('com.redhat.Sugar.BrowserShell') + def open_browser(self, uri, serialized_service=None): + service = None + if serialized_service is not None: + service = Service.deserialize(serialized_service) + browser = BrowserActivity(uri) + self.__browsers.append(browser) + gobject.idle_add(self._start_browser_cb, browser, service) + + @dbus.service.method('com.redhat.Sugar.BrowserShell') + def open_browser_from_service_foobar(self, uri, serialized_service): + service = Service.deserialize(serialized_service) + browser = BrowserActivity(uri) + self.__browsers.append(browser) + gobject.idle_add(self._start_browser_cb, browser, service) diff --git a/activities/browser/Makefile.am b/activities/browser/Makefile.am new file mode 100644 index 0000000..2c66e22 --- /dev/null +++ b/activities/browser/Makefile.am @@ -0,0 +1,25 @@ +sugardir = $(pythondir)/sugar/browser +sugar_PYTHON = \ + __init__.py \ + browser.py \ + NotificationBar.py \ + BrowserShell.py \ + AddressItem.py \ + BrowserActivity.py \ + NavigationToolbar.py + +icondir = $(pkgdatadir) +icon_DATA = \ + fold.png \ + unfold.png + +rcdir = $(pkgdatadir) +rc_DATA = browser.rc + +activitydir = $(pkgdatadir)/activities +activity_DATA = browser.activity + +EXTRA_DIST = \ + $(rc_DATA) \ + $(activity_DATA) \ + $(icon_DATA) diff --git a/activities/browser/NavigationToolbar.py b/activities/browser/NavigationToolbar.py new file mode 100644 index 0000000..bf8c96b --- /dev/null +++ b/activities/browser/NavigationToolbar.py @@ -0,0 +1,62 @@ +import pygtk +pygtk.require('2.0') +import gtk + +from AddressItem import AddressItem + +class NavigationToolbar(gtk.Toolbar): + def __init__(self, browser): + gtk.Toolbar.__init__(self) + self._browser = browser + self._embed = self._browser.get_embed() + + self.set_style(gtk.TOOLBAR_BOTH_HORIZ) + + self.back = gtk.ToolButton(None, 'Back') + self.back.set_icon_name('back') + self.back.connect("clicked", self.__go_back_cb) + self.insert(self.back, -1) + self.back.show() + + self.forward = gtk.ToolButton(None, 'Forward') + self.forward.set_icon_name('forward') + self.forward.connect("clicked", self.__go_forward_cb) + self.insert(self.forward, -1) + self.forward.show() + + self.reload = gtk.ToolButton(None, 'Reload') + self.reload.set_icon_name('reload') + self.reload.connect("clicked", self.__reload_cb) + self.insert(self.reload, -1) + self.reload.show() + + separator = gtk.SeparatorToolItem() + self.insert(separator, -1) + separator.show() + + address_item = AddressItem(self.__open_address_cb) + self.insert(address_item, -1) + address_item.show() + + self._update_sensitivity() + + self._embed.connect("location", self.__location_changed) + + def _update_sensitivity(self): + self.back.set_sensitive(self._embed.can_go_back()) + self.forward.set_sensitive(self._embed.can_go_forward()) + + def __go_back_cb(self, button): + self._embed.go_back() + + def __go_forward_cb(self, button): + self._embed.go_forward() + + def __reload_cb(self, button): + self._embed.reload() + + def __location_changed(self, embed): + self._update_sensitivity() + + def __open_address_cb(self, address): + self._embed.load_address(address) diff --git a/activities/browser/NotificationBar.py b/activities/browser/NotificationBar.py new file mode 100644 index 0000000..c9b3b8a --- /dev/null +++ b/activities/browser/NotificationBar.py @@ -0,0 +1,58 @@ +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +class NotificationBar(gtk.HBox): + __gsignals__ = { + 'action': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_STRING])) + } + + def __init__(self): + gtk.HBox.__init__(self, False, 12) + + self.set_name("notif bar") + self.set_border_width(3) + + self._icon = gtk.Image() + self.pack_start(self._icon, False) + + self._text_label = gtk.Label() + self._text_label.set_alignment(0.0, 0.5) + self.pack_start(self._text_label) + self._text_label.show() + + self._action_button = gtk.Button() + self._action_button.connect('clicked', self.__button_clicked) + self.pack_start(self._action_button, False) + self._action_button.show() + + self.connect('expose_event', self.expose) + + def expose(self, widget, event): + rect = self.get_allocation() + ctx = widget.window.cairo_create() + + ctx.new_path() + ctx.rectangle(rect.x, rect.y, rect.width, rect.height) + ctx.set_source_rgb(0.56 , 0.75 , 1) + ctx.fill_preserve() + ctx.set_source_rgb(0.16 , 0.35 , 0.6) + ctx.stroke() + + return False + + def set_icon(self, icon_name): + self._icon.set_from_icon_name(icon_name, gtk.ICON_SIZE_BUTTON) + self._icon.show() + + def set_text(self, text): + self._text_label.set_markup(text) + + def set_action(self, action_id, action_text): + self._action_id = action_id + self._action_button.set_label(action_text) + + def __button_clicked(self, button): + self.emit("action", self._action_id) diff --git a/activities/browser/__init__.py b/activities/browser/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/activities/browser/__init__.py diff --git a/activities/browser/browser.activity b/activities/browser/browser.activity new file mode 100644 index 0000000..7aba61f --- /dev/null +++ b/activities/browser/browser.activity @@ -0,0 +1,2 @@ +[Activity] +python_class = browser diff --git a/activities/browser/browser.py b/activities/browser/browser.py new file mode 100755 index 0000000..bdfa2bd --- /dev/null +++ b/activities/browser/browser.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +import pygtk +pygtk.require('2.0') +import gtk +import dbus + +import sugar.env +from sugar.session.LogWriter import LogWriter + +from BrowserShell import BrowserShell + +log_writer = LogWriter("Web") +log_writer.start() + +gtk.rc_parse(sugar.env.get_data_file('browser.rc')) + +session_bus = dbus.SessionBus() +bus_name = dbus.service.BusName('com.redhat.Sugar.Browser', bus=session_bus) +shell = BrowserShell(bus_name) +shell.start() diff --git a/activities/browser/browser.rc b/activities/browser/browser.rc new file mode 100644 index 0000000..69f1320 --- /dev/null +++ b/activities/browser/browser.rc @@ -0,0 +1,7 @@ +style "NotificationBarButton" = "button" +{ + xthickness = 0 + ythickness = 0 +} + +widget "*.notif bar.*GtkButton*" style "NotificationBarButton" diff --git a/activities/browser/fold.png b/activities/browser/fold.png new file mode 100644 index 0000000..cd4169b --- /dev/null +++ b/activities/browser/fold.png Binary files differ diff --git a/activities/browser/unfold.png b/activities/browser/unfold.png new file mode 100644 index 0000000..f3f82fa --- /dev/null +++ b/activities/browser/unfold.png Binary files differ -- cgit v0.9.1