diff --git a/shell/model/ShellModel.py b/shell/model/ShellModel.py index 95ed344d..f69003ab 100644 --- a/shell/model/ShellModel.py +++ b/shell/model/ShellModel.py @@ -20,6 +20,7 @@ from sugar.presence import PresenceService from sugar.activity.bundleregistry import BundleRegistry from model.Friends import Friends from model.MeshModel import MeshModel +from model.homemodel import HomeModel from model.Owner import ShellOwner from sugar import env @@ -37,6 +38,7 @@ class ShellModel: self._friends = Friends() self._mesh = MeshModel(self._bundle_registry) + self._home = HomeModel(self._bundle_registry) path = os.path.expanduser('~/Activities') self._bundle_registry.add_search_path(path) @@ -57,6 +59,9 @@ class ShellModel: def get_invites(self): return self._owner.get_invites() + def get_home(self): + return self._home + def get_owner(self): return self._owner diff --git a/shell/model/homeactivity.py b/shell/model/homeactivity.py index 8c4d2323..b38fc369 100644 --- a/shell/model/homeactivity.py +++ b/shell/model/homeactivity.py @@ -14,19 +14,42 @@ # 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.graphics.canvasicon import CanvasIcon +from sugar.presence import PresenceService +from sugar.activity import Activity +from sugar import profile class HomeActivity: - def __init__(self, activity): - self._icon_name = activity.get_icon_name() - self._icon_color = activity.get_icon_color() - self._id = activity.get_id() - + def __init__(self, registry, window): + self._window = window + + self._service = Activity.get_service(window.get_xid()) + self._id = self._service.get_id() + self._type = self._service.get_type() + + info = registry.get_bundle(self._type) + self._icon_name = info.get_icon() + + def get_title(self): + return self._window.get_name() + def get_icon_name(self): return self._icon_name def get_icon_color(self): - return self._icon_color + activity = PresenceService.get_instance().get_activity(self._id) + if activity != None: + return IconColor(activity.get_color()) + else: + return profile.get_color() def get_id(self): return self._id + + def get_window(self): + return self._window + + def get_type(self): + return self._type + + def get_shared(self): + return self._service.get_shared() diff --git a/shell/model/homemodel.py b/shell/model/homemodel.py index a5e2634d..c1eefe4e 100644 --- a/shell/model/homemodel.py +++ b/shell/model/homemodel.py @@ -15,9 +15,8 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import gobject +import wnck -from sugar.graphics.canvasicon import CanvasIcon -from sugar.graphics import style from model.homeactivity import HomeActivity class HomeModel(gobject.GObject): @@ -31,13 +30,15 @@ class HomeModel(gobject.GObject): ([gobject.TYPE_PYOBJECT])) } - def __init__(self, shell): + def __init__(self, bundle_registry): gobject.GObject.__init__(self) - self._activities = [] - self._shell = shell - - shell.connect('activity-opened', self.__activity_opened_cb) - shell.connect('activity-closed', self.__activity_closed_cb) + + self._activities = {} + self._bundle_registry = bundle_registry + + screen = wnck.screen_get_default() + screen.connect('window-opened', self._window_opened_cb) + screen.connect('window-closed', self._window_closed_cb) def __iter__(self): return iter(self._activities) @@ -47,23 +48,21 @@ class HomeModel(gobject.GObject): def __getitem__(self, i): return self._activities[i] - - def __activity_opened_cb(self, model, activity): - self._add_activity(activity) - def __activity_closed_cb(self, model, activity): - self._remove_activity(activity) - - def _add_activity(self, activity): - h_activity = HomeActivity(activity) - self._activities.append(h_activity) - self.emit('activity-added', h_activity) + def _window_opened_cb(self, screen, window): + if window.get_window_type() == wnck.WINDOW_NORMAL: + self._add_activity(window) - def _remove_activity(self, activity): - i = 0 - for h_activity in self._activities: - if h_activity.get_id() == activity.get_id(): - self.emit('activity-removed', self._activities[i]) - del self._activities[i] - return - i += 1 + def _window_closed_cb(self, screen, window): + if window.get_window_type() == wnck.WINDOW_NORMAL: + self._remove_activity(window.get_xid()) + + def _add_activity(self, window): + activity = HomeActivity(self._bundle_registry, window) + self._activities[window.get_xid()] = activity + self.emit('activity-added', activity) + + def _remove_activity(self, xid): + if self._activities.has_key(xid): + self.emit('activity-removed', self._activities[xid]) + del self._activities[xid] diff --git a/shell/view/ActivityHost.py b/shell/view/ActivityHost.py index 3da8e779..e91057e9 100644 --- a/shell/view/ActivityHost.py +++ b/shell/view/ActivityHost.py @@ -17,10 +17,7 @@ import gtk import dbus -from sugar import profile from sugar.activity import Activity -from sugar.presence import PresenceService -from sugar.graphics.iconcolor import IconColor from sugar.p2p import Stream from sugar.p2p import network from sugar.chat import ActivityChat @@ -41,23 +38,12 @@ class ActivityChatWindow(gtk.Window): self.add(chat_widget) class ActivityHost: - def __init__(self, shell_model, window): - self._window = window - self._xid = window.get_xid() - self._pservice = PresenceService.get_instance() - - bus = dbus.SessionBus() - proxy_obj = bus.get_object(Activity.get_service_name(self._xid), - Activity.get_object_path(self._xid)) - - self._activity = dbus.Interface(proxy_obj, Activity.ACTIVITY_INTERFACE) - self._id = self._activity.get_id() - self._type = self._activity.get_type() - self._gdk_window = gtk.gdk.window_foreign_new(self._xid) - - registry = shell_model.get_bundle_registry() - info = registry.get_bundle(self._type) - self._icon_name = info.get_icon() + def __init__(self, model): + self._model = model + self._id = model.get_id() + self._window = model.get_window() + self._activity = Activity.get_service(self.get_xid()) + self._gdk_window = gtk.gdk.window_foreign_new(self.get_xid()) try: self._overlay_window = OverlayWindow.OverlayWindow(self._gdk_window) @@ -74,21 +60,11 @@ class ActivityHost: def get_id(self): return self._id - def get_title(self): - return self._window.get_name() - def get_xid(self): - return self._xid + return self._window.get_xid() - def get_icon_name(self): - return self._icon_name - - def get_icon_color(self): - activity = self._pservice.get_activity(self._id) - if activity != None: - return IconColor(activity.get_color()) - else: - return profile.get_color() + def get_model(self): + return self._model def execute(self, command, args): self._activity.execute(command, args) @@ -108,12 +84,6 @@ class ActivityHost: writer.custom_request("invite", None, None, issuer, self._type, self._id) - def get_shared(self): - return self._activity.get_shared() - - def get_type(self): - return self._type - def present(self): self._window.activate(gtk.get_current_event_time()) diff --git a/shell/view/Shell.py b/shell/view/Shell.py index 8b0dee8a..684f4da7 100644 --- a/shell/view/Shell.py +++ b/shell/view/Shell.py @@ -35,12 +35,8 @@ import sugar class Shell(gobject.GObject): __gsignals__ = { - 'activity-opened': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), 'activity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), - 'activity-closed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])) } def __init__(self, model): @@ -66,8 +62,10 @@ class Shell(gobject.GObject): self._home_window.show() self.set_zoom_level(sugar.ZOOM_HOME) - self._screen.connect('window-opened', self.__window_opened_cb) - self._screen.connect('window-closed', self.__window_closed_cb) + home_model = self._model.get_home() + home_model.connect('activity-added', self._activity_added_cb) + home_model.connect('activity-removed', self._activity_removed_cb) + self._screen.connect('active-window-changed', self.__active_window_changed_cb) @@ -139,19 +137,9 @@ class Shell(gobject.GObject): elif key == '0x93': self._frame.notify_key_release() - def __window_opened_cb(self, screen, window): - logging.debug('Shell.__window_opened_cb') - if window.get_window_type() == wnck.WINDOW_NORMAL: - try: - activity_host = ActivityHost(self.get_model(), window) - except dbus.DBusException: - logging.debug('Shell.__window_opened_cb: opened unknown window ' + - window.get_name() + ' with xid ' + - str(window.get_xid())) - return - - self._hosts[activity_host.get_xid()] = activity_host - self.emit('activity-opened', activity_host) + def _activity_added_cb(self, home_model, home_activity): + activity_host = ActivityHost(home_activity) + self._hosts[activity_host.get_xid()] = activity_host def __active_window_changed_cb(self, screen): logging.debug('Shell.__active_window_changed_cb') @@ -168,19 +156,13 @@ class Shell(gobject.GObject): self._set_current_activity(activity_host) - def __window_closed_cb(self, screen, window): - logging.debug('Shell.__window_closed_cb') - if window.get_window_type() != wnck.WINDOW_NORMAL: + def _activity_removed_cb(self, home_model, home_activity): + xid = home_activity.get_window().get_xid() + if not self._hosts.has_key(xid): return - if not self._hosts.has_key(window.get_xid()): - return - - host = self._hosts[window.get_xid()] - host.destroy() - - self.emit('activity-closed', host) - del self._hosts[window.get_xid()] + self._hosts[xid].destroy() + del self._hosts[xid] if len(self._hosts) == 0: self._set_current_activity(None) diff --git a/shell/view/frame/ZoomBox.py b/shell/view/frame/ZoomBox.py index ed7e0a11..5f103c13 100644 --- a/shell/view/frame/ZoomBox.py +++ b/shell/view/frame/ZoomBox.py @@ -26,10 +26,10 @@ class ActivityMenu(Menu): ACTION_SHARE = 1 ACTION_CLOSE = 2 - def __init__(self, activity_host): - Menu.__init__(self, activity_host.get_title()) + def __init__(self, activity_model): + Menu.__init__(self, activity_model.get_title()) - if not activity_host.get_shared(): + if not activity_model.get_shared(): self._add_mesh_action() self._add_close_action() @@ -43,32 +43,29 @@ class ActivityMenu(Menu): self.add_action(icon, ActivityMenu.ACTION_CLOSE) class ActivityIcon(MenuIcon): - def __init__(self, shell, menu_shell, activity_host): + def __init__(self, shell, menu_shell, activity): self._shell = shell - self._activity_host = activity_host + self._activity = activity + self._activity_model = activity.get_model() - icon_name = activity_host.get_icon_name() - icon_color = activity_host.get_icon_color() + icon_name = self._activity_model.get_icon_name() + icon_color = self._activity_model.get_icon_color() MenuIcon.__init__(self, menu_shell, icon_name=icon_name, color=icon_color) def create_menu(self): - menu = ActivityMenu(self._activity_host) + menu = ActivityMenu(self._activity_model) menu.connect('action', self._action_cb) return menu def _action_cb(self, menu, action): self.popdown() - activity = self._shell.get_current_activity() - if activity == None: - return - if action == ActivityMenu.ACTION_SHARE: - activity.share() + self._activity.share() if action == ActivityMenu.ACTION_CLOSE: - activity.close() + self._activity.close() class ZoomBox(hippo.CanvasBox): def __init__(self, shell, menu_shell): diff --git a/shell/view/home/activitiesdonut.py b/shell/view/home/activitiesdonut.py index 7d1c3e5f..b4fe22ac 100644 --- a/shell/view/home/activitiesdonut.py +++ b/shell/view/home/activitiesdonut.py @@ -19,7 +19,6 @@ import math from sugar.graphics.canvasicon import CanvasIcon from sugar.graphics import style -from model.homemodel import HomeModel class ActivitiesDonut(hippo.CanvasBox, hippo.CanvasItem): __gtype_name__ = 'SugarActivitiesDonut' @@ -29,7 +28,7 @@ class ActivitiesDonut(hippo.CanvasBox, hippo.CanvasItem): self._activities = {} self._shell = shell - self._model = HomeModel(shell) + self._model = shell.get_model().get_home() self._model.connect('activity-added', self._activity_added_cb) self._model.connect('activity-removed', self._activity_removed_cb) diff --git a/sugar/activity/Activity.py b/sugar/activity/Activity.py index a10dc703..4ec29faa 100644 --- a/sugar/activity/Activity.py +++ b/sugar/activity/Activity.py @@ -40,6 +40,12 @@ def get_service_name(xid): def get_object_path(xid): return ACTIVITY_SERVICE_PATH + "/%s" % xid +def get_service(xid): + bus = dbus.SessionBus() + proxy_obj = bus.get_object(get_service_name(xid), get_object_path(xid)) + return dbus.Interface(proxy_obj, ACTIVITY_INTERFACE) + + class ActivityDbusService(dbus.service.Object): """Base dbus service object that each Activity uses to export dbus methods.