Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu@tomeuvizoso.net>2008-04-01 19:18:34 (GMT)
committer Tomeu Vizoso <tomeu@tomeuvizoso.net>2008-04-01 19:18:34 (GMT)
commit4094a96d0c52ce56c02e42d2524f5ae425e9c6e8 (patch)
treeae5a46cfcd6f1798c1ad4943ffe6b54b80a10183 /src
parent6f92d9077eefc81a4bffd5f451ea5c5cfe34b4f7 (diff)
New activities tray
Diffstat (limited to 'src')
-rw-r--r--src/view/frame/activitiestray.py303
-rw-r--r--src/view/frame/frame.py14
2 files changed, 187 insertions, 130 deletions
diff --git a/src/view/frame/activitiestray.py b/src/view/frame/activitiestray.py
index 11e812c..2060783 100644
--- a/src/view/frame/activitiestray.py
+++ b/src/view/frame/activitiestray.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2007 Red Hat, Inc.
+# Copyright (C) 2008 One Laptop Per Child
#
# 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
@@ -15,145 +15,194 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import os
+import statvfs
import logging
+from gettext import gettext as _
-import hippo
+import gtk
-from sugar.graphics.tray import TrayButton
+from sugar import env
+from sugar import profile
+from sugar.graphics import style
from sugar.graphics.tray import HTray
+from sugar.graphics.radiotoolbutton import RadioToolButton
from sugar.graphics.icon import Icon
-from sugar.graphics import style
-from sugar import profile
-from sugar import activity
-from sugar import env
+from sugar.graphics.palette import Palette
+from sugar.graphics.menuitem import MenuItem
+
+from view.frame.frameinvoker import FrameWidgetInvoker
+
+class _Palette(Palette):
+ def __init__(self, widget, home_activity):
+ Palette.__init__(self, '', menu_after_content=True)
+
+ self.props.invoker = FrameWidgetInvoker(widget)
+ self.set_group_id('frame')
+
+ if home_activity.props.launching:
+ home_activity.connect('notify::launching', self._launching_changed_cb)
+ self.set_primary_text(_('Starting...'))
+ else:
+ self.setup_palette()
+
+ def _launching_changed_cb(self, home_activity, pspec):
+ if not home_activity.props.launching:
+ self.setup_palette()
+
+ def setup_palette(self):
+ raise NotImplementedError
+
+class ActivityPalette(_Palette):
+ def __init__(self, widget, home_activity):
+ _Palette.__init__(self, widget, home_activity)
+ self._home_activity = home_activity
+
+ def setup_palette(self):
+ self.set_primary_text(self._home_activity.get_title())
+
+ menu_item = MenuItem(_('Resume'), 'activity-start')
+ menu_item.connect('activate', self.__resume_activate_cb)
+ self.menu.append(menu_item)
+ menu_item.show()
+
+ """ Not implemented yet
+ menu_item = MenuItem(_('Share with'), 'zoom-neighborhood')
+ #menu_item.connect('activate', self.__share_activate_cb)
+ self.menu.append(menu_item)
+ menu_item.show()
+
+ menu_item = MenuItem(_('Keep'))
+ icon = Icon(icon_name='document-save', icon_size=gtk.ICON_SIZE_MENU,
+ xo_color=profile.get_color())
+ menu_item.set_image(icon)
+ icon.show()
+ #menu_item.connect('activate', self.__keep_activate_cb)
+ self.menu.append(menu_item)
+ menu_item.show()
+ """
+
+ separator = gtk.SeparatorMenuItem()
+ self.menu.append(separator)
+ separator.show()
+
+ menu_item = MenuItem(_('Stop'), 'activity-stop')
+ menu_item.connect('activate', self.__stop_activate_cb)
+ self.menu.append(menu_item)
+ menu_item.show()
+
+ def __resume_activate_cb(self, menu_item):
+ self._home_activity.get_window().activate(1)
+
+ def __stop_activate_cb(self, menu_item):
+ self._home_activity.get_window().close(1)
+
+class JournalPalette(_Palette):
+ def __init__(self, widget, home_activity):
+ _Palette.__init__(self, widget, home_activity)
+ self._home_activity = home_activity
+ self._progress_bar = None
+ self._free_space_label = None
+
+ def setup_palette(self):
+ self.set_primary_text(self._home_activity.get_title())
+
+ vbox = gtk.VBox()
+ self.set_content(vbox)
+ vbox.show()
+
+ self._progress_bar = gtk.ProgressBar()
+ vbox.add(self._progress_bar)
+ self._progress_bar.show()
+
+ self._free_space_label = gtk.Label()
+ self._free_space_label.set_alignment(0.5, 0.5)
+ vbox.add(self._free_space_label)
+ self._free_space_label.show()
+
+ self.connect('popup', self.__popup_cb)
+
+ menu_item = MenuItem(_('Show contents'))
+
+ icon = Icon(file=self._home_activity.get_icon_path(),
+ icon_size=gtk.ICON_SIZE_MENU,
+ xo_color=self._home_activity.get_icon_color())
+ menu_item.set_image(icon)
+ icon.show()
-from activitybutton import ActivityButton
-import config
+ menu_item.connect('activate', self.__open_activate_cb)
+ self.menu.append(menu_item)
+ menu_item.show()
-class InviteButton(TrayButton):
- def __init__(self, activity_model, invite):
- TrayButton.__init__(self)
+ def __open_activate_cb(self, menu_item):
+ self._home_activity.get_window().activate(1)
- icon = Icon(file=activity_model.get_icon_name(),
- xo_color=activity_model.get_color())
- self.set_icon_widget(icon)
- icon.show()
+ def __popup_cb(self, palette):
+ # TODO: we should be able to ask the datastore this info, as that's the
+ # component that knows about mount points.
+ stat = os.statvfs(env.get_profile_path())
+ free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]
+ total_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BLOCKS]
- self._invite = invite
+ fraction = (total_space - free_space) / float(total_space)
+ self._progress_bar.props.fraction = fraction
+ self._free_space_label.props.label = _('%(free_space)d MB Free') % \
+ {'free_space': free_space / (1024 * 1024)}
- def get_activity_id(self):
- return self._invite.get_activity_id()
+class ActivityButton(RadioToolButton):
+ def __init__(self, home_activity, group):
+ RadioToolButton.__init__(self, group=group)
- def get_bundle_id(self):
- return self._invite.get_bundle_id()
+ self._home_activity = home_activity
- def get_invite(self):
- return self._invite
+ icon = Icon(xo_color=home_activity.get_icon_color())
+ if home_activity.get_icon_path():
+ icon.props.file = home_activity.get_icon_path()
+ else:
+ icon.props.icon_name = 'image-missing'
+ self.set_icon_widget(icon)
+ icon.show()
+
+ if self._home_activity.get_type() == "org.laptop.JournalActivity":
+ palette = JournalPalette(self, self._home_activity)
+ else:
+ palette = ActivityPalette(self, self._home_activity)
+ self.set_palette(palette)
-class ActivitiesTray(hippo.CanvasBox):
+class ActivitiesTray(HTray):
def __init__(self, shell):
- hippo.CanvasBox.__init__(self, orientation=hippo.ORIENTATION_HORIZONTAL)
+ HTray.__init__(self)
+ self._buttons = {}
self._shell = shell
- self._shell_model = self._shell.get_model()
- self._invite_to_item = {}
- self._invites = self._shell_model.get_invites()
- self._config = self._load_config()
-
- self._tray = HTray()
- self.append(hippo.CanvasWidget(widget=self._tray), hippo.PACK_EXPAND)
- self._tray.show()
-
- registry = activity.get_registry()
- registry.get_activities_async(reply_handler=self._get_activities_cb)
-
- registry.connect('activity-added', self._activity_added_cb)
- registry.connect('activity-removed', self._activity_removed_cb)
-
- for invite in self._invites:
- self.add_invite(invite)
- self._invites.connect('invite-added', self._invite_added_cb)
- self._invites.connect('invite-removed', self._invite_removed_cb)
-
- def _load_config(self):
- cfg = []
-
- f = open(os.path.join(config.data_path, 'activities.defaults'), 'r')
- for line in f.readlines():
- line = line.strip()
- if line and not line.startswith('#'):
- cfg.append(line)
- f.close()
-
- return cfg
-
- def _get_activities_cb(self, activity_list):
- known_activities = []
- unknown_activities = []
- name_to_activity = {}
-
- while activity_list:
- info = activity_list.pop()
- name_to_activity[info.bundle_id] = info
-
- if info.bundle_id in self._config:
- known_activities.append(info)
- else:
- unknown_activities.append(info)
-
- sorted_activities = []
- for name in self._config:
- if name in name_to_activity:
- sorted_activities.append(name_to_activity[name])
-
- for info in sorted_activities + unknown_activities:
- if info.show_launcher:
- self.add_activity(info)
-
- def _activity_clicked_cb(self, icon):
- self._shell.start_activity(icon.get_bundle_id())
-
- def _invite_clicked_cb(self, icon):
- self._invites.remove_invite(icon.get_invite())
- self._shell.join_activity(icon.get_bundle_id(),
- icon.get_activity_id())
-
- def _invite_added_cb(self, invites, invite):
- self.add_invite(invite)
-
- def _invite_removed_cb(self, invites, invite):
- self.remove_invite(invite)
-
- def _remove_activity_cb(self, item):
- self._tray.remove_item(item)
-
- def _activity_added_cb(self, activity_registry, activity_info):
- self.add_activity(activity_info)
-
- def _activity_removed_cb(self, activity_registry, activity_info):
- for item in self._tray.get_children():
- if item.get_bundle_id() == activity_info.bundle_id:
- self._tray.remove_item(item)
- return
-
- def add_activity(self, activity_info):
- item = ActivityButton(activity_info)
- item.connect('clicked', self._activity_clicked_cb)
- item.connect('remove_activity', self._remove_activity_cb)
- self._tray.add_item(item, -1)
- item.show()
-
- def add_invite(self, invite):
- mesh = self._shell_model.get_mesh()
- activity_model = mesh.get_activity(invite.get_activity_id())
- if activity:
- item = InviteButton(activity_model, invite)
- item.connect('clicked', self._invite_clicked_cb)
- self._tray.add_item(item, 0)
- item.show()
-
- self._invite_to_item[invite] = item
-
- def remove_invite(self, invite):
- self._tray.remove_item(self._invite_to_item[invite])
- del self._invite_to_item[invite]
+ self._home_model = shell.get_model().get_home()
+ self._home_model.connect('activity-added', self.__activity_added_cb)
+ self._home_model.connect('activity-removed', self.__activity_removed_cb)
+ self._home_model.connect('pending-activity-changed', self.__activity_changed_cb)
+
+ def __activity_added_cb(self, home_model, home_activity):
+ logging.debug('__activity_added_cb: %r' % home_activity)
+ if self.get_children():
+ group = self.get_children()[0]
+ else:
+ group = None
+
+ button = ActivityButton(home_activity, group)
+ self.add_item(button)
+ self._buttons[home_activity.get_activity_id()] = button
+ button.connect('toggled', self.__activity_toggled_cb, home_activity)
+ button.show()
+
+ def __activity_removed_cb(self, home_model, home_activity):
+ logging.debug('__activity_removed_cb: %r' % home_activity)
+ button = self._buttons[home_activity.get_activity_id()]
+ self.remove_item(button)
+ del self._buttons[home_activity.get_activity_id()]
+
+ def __activity_changed_cb(self, home_model, home_activity):
+ logging.debug('__activity_changed_cb: %r' % home_activity)
+ button = self._buttons[home_activity.get_activity_id()]
+ button.props.active = True
+
+ def __activity_toggled_cb(self, button, home_activity):
+ home_activity.get_window().activate(1)
+
diff --git a/src/view/frame/frame.py b/src/view/frame/frame.py
index e0230ee..5fea0d1 100644
--- a/src/view/frame/frame.py
+++ b/src/view/frame/frame.py
@@ -166,17 +166,25 @@ class Frame(object):
def _create_top_panel(self):
panel = self._create_panel(gtk.POS_TOP)
+ # TODO: setting box_width and hippo.PACK_EXPAND looks like a hack to me.
+ # Why hippo isn't respecting the request size of these controls?
+
zoom_toolbar = ZoomToolbar(self._shell)
- panel.append(hippo.CanvasWidget(widget=zoom_toolbar), hippo.PACK_EXPAND)
+ panel.append(hippo.CanvasWidget(widget=zoom_toolbar,
+ box_width=4*style.GRID_CELL_SIZE))
zoom_toolbar.show()
+ activities_tray = ActivitiesTray(self._shell)
+ panel.append(hippo.CanvasWidget(widget=activities_tray),
+ hippo.PACK_EXPAND)
+ activities_tray.show()
+
return panel
def _create_bottom_panel(self):
panel = self._create_panel(gtk.POS_BOTTOM)
- box = ActivitiesTray(self._shell)
- panel.append(box, hippo.PACK_EXPAND)
+ # Append devices tray.
return panel