Track activities while they launch

HomeModel now uses the activity ID to track activities, and creates
the HomeActivity object when the activity is launched, not when
its window appears.
This commit is contained in:
Dan Williams 2007-01-06 19:31:19 -05:00
parent b27257fadb
commit 8cea4c5fc6
3 changed files with 146 additions and 18 deletions

View File

@ -14,23 +14,73 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import time
import gobject
import logging
from sugar.presence import PresenceService
from sugar.activity import Activity
from sugar import profile
class HomeActivity:
def __init__(self, registry, window):
class HomeActivity(gobject.GObject):
__gsignals__ = {
'launch-timeout': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([])),
}
def __init__(self, bundle, activity_id):
gobject.GObject.__init__(self)
self._window = None
self._xid = None
self._service = None
self._id = activity_id
self._type = bundle.get_service_name()
self._icon_name = bundle.get_icon()
self._launch_time = time.time()
self._launched = False
self._launch_timeout_id = gobject.timeout_add(10000, self._launch_timeout_cb)
logging.debug("Activity %s (%s) launching..." % (self._id, self._type))
def __del__(self):
gobject.source_remove(self._launch_timeout_id)
self._launch_timeout_id = 0
def _launch_timeout_cb(self, user_data=None):
logging.debug("Activity %s (%s) launch timed out" % (self._id, self._type))
self._launch_timeout_id = 0
self.emit('launch-timeout')
return False
def set_window(self, window):
"""An activity is 'launched' once we get its window."""
logging.debug("Activity %s (%s) finished launching" % (self._id, self._type))
self._launched = True
gobject.source_remove(self._launch_timeout_id)
self._launch_timeout_id = 0
if self._window or self._xid:
raise RuntimeError("Activity is already launched!")
if not window:
raise ValueError("window must be valid")
self._window = window
self._xid = window.get_xid()
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()
# verify id and type details
act_id = self._service.get_id()
if act_id != self._id:
raise RuntimeError("Activity's real ID (%s) didn't match expected (%s)." % (act_id, self._id))
act_type = self._service.get_type()
if act_type != self._type:
raise RuntimeError("Activity's real type (%s) didn't match expected (%s)." % (act_type, self._type))
def get_title(self):
if not self._launched:
raise RuntimeError("Activity is still launching.")
return self._window.get_name()
def get_icon_name(self):
@ -47,13 +97,25 @@ class HomeActivity:
return self._id
def get_xid(self):
if not self._launched:
raise RuntimeError("Activity is still launching.")
return self._xid
def get_window(self):
if not self._launched:
raise RuntimeError("Activity is still launching.")
return self._window
def get_type(self):
return self._type
def get_shared(self):
if not self._launched:
raise RuntimeError("Activity is still launching.")
return self._service.get_shared()
def get_launch_time(self):
return self._launch_time
def get_launched(self):
return self._launched

View File

@ -20,10 +20,14 @@ import gobject
import wnck
from model.homeactivity import HomeActivity
from sugar.activity import Activity
class HomeModel(gobject.GObject):
__gsignals__ = {
'activity-launched': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'activity-added': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
@ -68,6 +72,12 @@ class HomeModel(gobject.GObject):
if window.get_window_type() == wnck.WINDOW_NORMAL:
self._remove_activity(window.get_xid())
def _get_activity_by_xid(self, xid):
for act in self._activities.values():
if act.get_xid() == xid:
return act
return None
def _active_window_changed_cb(self, screen):
window = screen.get_active_window()
if window == None:
@ -77,8 +87,13 @@ class HomeModel(gobject.GObject):
return
xid = window.get_xid()
if self._activities.has_key(xid):
self._current_activity = self._activities[xid]
act = self._get_activity_by_xid(window.get_xid())
if act:
if act.get_launched() == True:
self._current_activity = act
else:
self._current_activity = None
logging.error('Actiivty for window %d was not yet launched.' % xid)
else:
self._current_activity = None
logging.error('Model for window %d does not exist.' % xid)
@ -86,13 +101,57 @@ class HomeModel(gobject.GObject):
self.emit('active-activity-changed', self._current_activity)
def _add_activity(self, window):
activity = HomeActivity(self._bundle_registry, window)
self._activities[window.get_xid()] = activity
act_service = Activity.get_service(window.get_xid())
act_id = act_service.get_id()
activity = None
if self._activities.has_key(act_id):
activity = self._activities[act_id]
else:
# activity got lost, took longer to launch than we allow,
# or it was launched by something other than the shell
act_type = act_service.get_type()
bundle = self._bundle_registry.get_bundle(act_type)
if not bundle:
raise RuntimeError("No bundle for activity type '%s'." % act_type)
return
activity = HomeActivity(bundle, act_id)
self._activities[act_id] = activity
activity.set_window(window)
self.emit('activity-added', activity)
def _internal_remove_activity(self, activity):
self.emit('activity-removed', activity)
act_id = activity.get_id()
del self._activities[act_id]
def _remove_activity(self, xid):
if self._activities.has_key(xid):
self.emit('activity-removed', self._activities[xid])
del self._activities[xid]
activity = self._get_activity_by_xid(window.get_xid())
if activity:
self._internal_remove_activity(activity)
else:
logging.error('Model for window %d does not exist.' % xid)
def _activity_launch_timeout_cb(self, activity):
act_id = activity.get_id()
if not act_id in self._activities.keys():
return
self._internal_remove_activity(activity)
def notify_activity_launch(self, activity_id, service_name):
bundle = self._bundle_registry.get_bundle(service_name)
if not bundle:
raise ValueError("Activity service name '%s' was not found in the bundle registry." % service_name)
activity = HomeActivity(bundle, activity_id)
activity.connect('launch-timeout', self._activity_launch_timeout_cb)
self._activities[activity_id] = activity
self.emit('activity-launched', activity)
def notify_activity_launch_failed(self, activity_id):
if self._activities.has_key(activity_id):
activity = self._activities[activity_id]
logging.debug("Activity %s (%s) launch failed" % (activity_id, activity.get_type()))
self._internal_remove_activity(activity)
else:
logging.error('Model for activity id %s does not exist.' % activity_id)

View File

@ -205,13 +205,16 @@ class Shell(gobject.GObject):
breg = self._model.get_bundle_registry()
bundle = breg.find_by_default_type(bundle_id)
if bundle:
serv_name = bundle.get_service_name()
act_type = bundle.get_service_name()
home_model = self._model.get_home()
home_model.notify_activity_launch(activity_id, act_type)
try:
activity = ActivityFactory.create(serv_name)
activity = ActivityFactory.create(act_type)
except DBusException, e:
logging.error("Couldn't launch activity %s:\n%s" % (serv_name, e))
logging.error("Couldn't launch activity %s:\n%s" % (act_type, e))
home_mode.notify_activity_launch_failed(activity_id)
else:
logging.debug("Joining activity type %s id %s" % (serv_name, activity_id))
logging.debug("Joining activity type %s id %s" % (act_type, activity_id))
activity.join(activity_ps.object_path())
else:
logging.error("Couldn't find activity for type %s" % bundle_id)
@ -255,11 +258,15 @@ class Shell(gobject.GObject):
logging.error("Couldn't find available activity ID.")
return None
home_model = self._model.get_home()
home_model.notify_activity_launch(act_id, activity_type)
try:
logging.debug("Shell.start_activity will start %s:%s" % (activity_type, act_id))
activity = ActivityFactory.create(activity_type)
except dbus.DBusException, e:
logging.debug("Couldn't start activity '%s':\n %s" % (activity_type, e))
home_mode.notify_activity_launch_failed(act_id)
return None
activity.start(act_id)