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:
parent
b27257fadb
commit
8cea4c5fc6
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user