Make activity launching asynchronous

The ActivityFactory create() method now returns a handler GObject,
which callers may attach signals to to receive success and error
signals from the result of the activity launch request.
This commit is contained in:
Dan Williams 2007-01-07 00:04:30 -05:00
parent 8cea4c5fc6
commit fb716ae046
5 changed files with 119 additions and 69 deletions

View File

@ -127,7 +127,7 @@ class HomeModel(gobject.GObject):
del self._activities[act_id] del self._activities[act_id]
def _remove_activity(self, xid): def _remove_activity(self, xid):
activity = self._get_activity_by_xid(window.get_xid()) activity = self._get_activity_by_xid(xid)
if activity: if activity:
self._internal_remove_activity(activity) self._internal_remove_activity(activity)
else: else:

View File

@ -18,11 +18,19 @@
import sys import sys
import os import os
import gobject
from sugar.activity import ActivityFactory from sugar.activity import ActivityFactory
from sugar import env from sugar import env
from sugar import util from sugar import util
def _success_cb(handler, activity, loop):
activity.start(util.unique_id())
loop.quit()
def _error_cb(handler, err, loop):
loop.quit()
ppath = env.get_profile_path() ppath = env.get_profile_path()
bus_file = os.path.join(ppath, "session_bus_address") bus_file = os.path.join(ppath, "session_bus_address")
f = open(bus_file, "r") f = open(bus_file, "r")
@ -30,5 +38,10 @@ bus_name = f.read()
f.close() f.close()
os.environ['DBUS_SESSION_BUS_ADDRESS'] = bus_name os.environ['DBUS_SESSION_BUS_ADDRESS'] = bus_name
activity = ActivityFactory.create(sys.argv[1]) loop = gobject.MainLoop()
activity.start(util.unique_id())
handler = ActivityFactory.create(sys.argv[1])
handler.connect('success', _success_cb, loop)
handler.connect('error', _error_cb, loop)
loop.run()

View File

@ -191,35 +191,41 @@ class Shell(gobject.GObject):
def get_model(self): def get_model(self):
return self._model return self._model
def _join_success_cb(self, handler, activity, activity_ps, activity_id, activity_type):
logging.debug("Joining activity %s (%s)" % (activity_id, activity_type))
activity.join(activity_ps.object_path())
def _join_error_cb(self, handler, err, home_model, activity_id, activity_type):
logging.error("Couldn't launch activity %s (%s):\n%s" % (activity_id, activity_type, err))
home_mode.notify_activity_launch_failed(activity_id)
def join_activity(self, bundle_id, activity_id): def join_activity(self, bundle_id, activity_id):
activity = self.get_activity(activity_id) activity = self.get_activity(activity_id)
if activity: if activity:
activity.present() activity.present()
else: return
activity_ps = self._pservice.get_activity(activity_id)
if activity_ps: activity_ps = self._pservice.get_activity(activity_id)
# Get the service name for this activity, if if not activity_ps:
# we have a bundle on the system capable of handling logging.error("Couldn't find shared activity for %s" % activity_id)
# this activity type return
breg = self._model.get_bundle_registry()
bundle = breg.find_by_default_type(bundle_id) # Get the service name for this activity, if
if bundle: # we have a bundle on the system capable of handling
act_type = bundle.get_service_name() # this activity type
home_model = self._model.get_home() breg = self._model.get_bundle_registry()
home_model.notify_activity_launch(activity_id, act_type) bundle = breg.find_by_default_type(bundle_id)
try: if not bundle:
activity = ActivityFactory.create(act_type) logging.error("Couldn't find activity for type %s" % bundle_id)
except DBusException, e: return
logging.error("Couldn't launch activity %s:\n%s" % (act_type, e))
home_mode.notify_activity_launch_failed(activity_id) act_type = bundle.get_service_name()
else: home_model = self._model.get_home()
logging.debug("Joining activity type %s id %s" % (act_type, activity_id)) home_model.notify_activity_launch(activity_id, act_type)
activity.join(activity_ps.object_path())
else: handler = ActivityFactory.create(act_type)
logging.error("Couldn't find activity for type %s" % bundle_id) handler.connect('success', self._join_success_cb, activity_ps, activity_id, act_type)
else: handler.connect('error', self._join_error_cb, home_model, activity_id, act_type)
logging.error('Cannot start activity.')
def _find_unique_activity_id(self): def _find_unique_activity_id(self):
# create a new unique activity ID # create a new unique activity ID
@ -251,6 +257,14 @@ class Shell(gobject.GObject):
return act_id return act_id
def _start_success_cb(self, handler, activity, activity_id, activity_type):
logging.debug("Started activity %s (%s)" % (activity_id, activity_type))
activity.start(activity_id)
def _start_error_cb(self, handler, err, home_model, activity_id, activity_type):
logging.error("Couldn't launch activity %s (%s):\n%s" % (activity_id, activity_type, err))
home_mode.notify_activity_launch_failed(activity_id)
def start_activity(self, activity_type): def start_activity(self, activity_type):
logging.debug('Shell.start_activity') logging.debug('Shell.start_activity')
act_id = self._find_unique_activity_id() act_id = self._find_unique_activity_id()
@ -261,16 +275,10 @@ class Shell(gobject.GObject):
home_model = self._model.get_home() home_model = self._model.get_home()
home_model.notify_activity_launch(act_id, activity_type) home_model.notify_activity_launch(act_id, activity_type)
try: logging.debug("Shell.start_activity will start %s (%s)" % (act_id, activity_type))
logging.debug("Shell.start_activity will start %s:%s" % (activity_type, act_id)) handler = ActivityFactory.create(activity_type)
activity = ActivityFactory.create(activity_type) handler.connect('success', self._start_success_cb, act_id, activity_type)
except dbus.DBusException, e: handler.connect('error', self._start_error_cb, home_model, act_id, activity_type)
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)
return activity
def set_zoom_level(self, level): def set_zoom_level(self, level):
if level == sugar.ZOOM_ACTIVITY: if level == sugar.ZOOM_ACTIVITY:

View File

@ -40,22 +40,32 @@ class ClipboardIcon(MenuIcon):
else: else:
return None return None
def _activity_create_success_cb(self, handler, activity):
activity.start(util.unique_id())
activity.execute("open_document", [self._object_id])
def _activity_create_error_cb(self, handler, err):
pass
def _icon_activated_cb(self, icon): def _icon_activated_cb(self, icon):
if self._percent == 100: if self._percent < 100:
cb_service = clipboardservice.get_instance() return
(name, percent, icon, preview, format_types) = \ cb_service = clipboardservice.get_instance()
cb_service.get_object(self._object_id) (name, percent, icon, preview, format_types) = \
cb_service.get_object(self._object_id)
if not format_types:
return
if format_types: logging.debug("_icon_activated_cb: " + self._object_id)
logging.debug("_icon_activated_cb: " + self._object_id) activity_type = self._get_activity_for_mime_type(format_types[0])
if not activity_type:
return
activity_id = self._get_activity_for_mime_type(format_types[0]) # Launch the activity to handle this item
handler = ActivityFactory.create(activity_type)
if activity_id: handler.connect('success', self._activity_create_success_cb)
activity = ActivityFactory.create(activity_id) handler.connect('error', self._activity_create_error_cb)
activity.start(util.unique_id())
activity.execute("open_document", [self._object_id])
def _popup_action_cb(self, popup, action): def _popup_action_cb(self, popup, action):
self.popdown() self.popdown()

View File

@ -76,24 +76,43 @@ class ActivityFactory(dbus.service.Object):
if len(self._activities) == 0: if len(self._activities) == 0:
gtk.main_quit() gtk.main_quit()
class ActivityCreationHandler(gobject.GObject):
__gsignals__ = {
'error': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'success': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
}
def __init__(self, activity_name):
gobject.GObject.__init__(self)
bus = dbus.SessionBus()
factory_name = activity_name
factory_path = get_path(factory_name)
proxy_obj = bus.get_object(factory_name, factory_path)
factory = dbus.Interface(proxy_obj, "com.redhat.Sugar.ActivityFactory")
factory.create(reply_handler=self._reply_handler, error_handler=self._error_handler)
def _reply_handler(self, xid):
bus = dbus.SessionBus()
proxy_obj = bus.get_object(Activity.get_service_name(xid),
Activity.get_object_path(xid))
activity = dbus.Interface(proxy_obj, Activity.ACTIVITY_INTERFACE)
self.emit('success', activity)
def _error_handler(self, err):
logging.debug("Couldn't create activity: %s" % err)
self.emit('error', err)
def create(activity_name): def create(activity_name):
"""Create a new activity from his name.""" """Create a new activity from its name."""
bus = dbus.SessionBus() return ActivityCreationHandler(activity_name)
factory_name = activity_name
factory_path = get_path(factory_name)
proxy_obj = bus.get_object(factory_name, factory_path)
factory = dbus.Interface(proxy_obj, "com.redhat.Sugar.ActivityFactory")
xid = factory.create()
bus = dbus.SessionBus()
proxy_obj = bus.get_object(Activity.get_service_name(xid),
Activity.get_object_path(xid))
activity = dbus.Interface(proxy_obj, Activity.ACTIVITY_INTERFACE)
return activity
def start_factory(activity_class, bundle_path): def start_factory(activity_class, bundle_path):
"""Start the activity factory.""" """Start the activity factory."""