# Copyright (C) 2012 Aleksey Lim # # 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 # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import logging from gi.repository import Gtk from gi.repository import Gdk from gi.repository import Wnck from gi.repository import GConf from sugar3 import wm from sugar3.graphics.xocolor import XoColor from sugar3.activity.activityfactory import create_activity_id from jarabe.view.launcher import LaunchWindow from jarabe.journal import model from jarabe.model import shell from jarabe.plugins.sn import get_client, get_registry, get_browser from jarabe.plugins.sn.bundleregistry import stub_icon _logger = logging.getLogger('plugins.sn.launcher') class Launcher(object): def __init__(self): self._launches = {} self._screen = Wnck.Screen.get_default() self._screen.connect('window-opened', self.__window_opened_cb) get_client().connect('event', self.__Event_cb) def launch(self, bundle, activity_id=None, object_id=None, uri=None, color=None, invited=None, args=None): if activity_id: activity = shell.get_model().get_activity_by_id(activity_id) if activity is not None: _logger.debug('Resume %r activity', activity_id) activity.get_window().activate(Gtk.get_current_event_time()) return def found_jobjects(jobjects, total): if not jobjects: props = {} else: props = jobjects[0] self._launch(bundle, props.get('activity_id') or activity_id, props.get('object_id') or object_id, props.get('icon-color') or color, uri, args) def not_found_jobjects(error): _logger.exception('Failed to launch %r: %s', bundle.get_bundle_id(), error) if activity_id and not object_id: _logger.debug('Look for jobject for %r activity_id', activity_id) # pylint: disable-msg=W0212 model._get_datastore().find({'activity_id': activity_id}, ['uid'], reply_handler=found_jobjects, error_handler=not_found_jobjects, byte_arrays=True) else: self._launch(bundle, activity_id, object_id, color, uri, args) def _launch(self, bundle, activity_id, object_id, color, uri, extra_args): if not activity_id: activity_id = create_activity_id() _logger.info('Starting %r: activity_id=%r object_id=%r uri=%r', bundle.get_bundle_id(), activity_id, object_id, uri) self._start_launcher(bundle.get_bundle_id(), bundle.get_icon(), activity_id, color) get_client().get(['context', bundle.get_bundle_id()], cmd='launch', mountpoint=bundle.mountpoint, args=extra_args, activity_id=activity_id, object_id=object_id, uri=uri, color=None if color is None else color.to_string()) def _start_launcher(self, bundle_id, icon, activity_id, color): if color is None: gc = GConf.Client.get_default() color = XoColor(gc.get_string('/desktop/sugar/user/color')) window = LaunchWindow(activity_id, icon, color) window.connect('realize', self.__window_realize_cb, bundle_id, activity_id) window.show() self._launches[activity_id] = window def _stop_launcher(self, activity_id): if activity_id not in self._launches: return _logger.debug('Stop %r launcher', activity_id) window = self._launches.pop(activity_id) window.destroy() def _failure_report(self, event): kwargs = {'context': event.get('context')} if 'implementation' in event: kwargs['implementation'] = event['implementation'] if 'log_path' in event: kwargs['filename'] = event['log_path'] get_browser().open_report(**kwargs) def __window_opened_cb(self, screen, window): if window.get_window_type() != Wnck.WindowType.NORMAL or \ wm.get_sugar_window_type(window) == 'launcher': return activity_id = wm.get_activity_id(window) if activity_id: self._stop_launcher(activity_id) def __window_realize_cb(self, widget, bundle_id, activity_id): wm.set_activity_id(widget.window, str(activity_id)) widget.window.property_change('_SUGAR_WINDOW_TYPE', 'STRING', 8, Gdk.PropMode.REPLACE, 'launcher') wm.set_bundle_id(widget.window, str(bundle_id)) def __Event_cb(self, event, data): if event != 'launch': return if data['state'] == 'fork': if data['activity_id'] not in self._launches: bundle = get_registry().get_bundle( data['context'], data.get('mountpoint') or '/') if bundle is None: icon = stub_icon() else: icon = bundle.get_icon() color = data.get('color') if color: color = XoColor(color) self._start_launcher(data['context'], icon, data['activity_id'], color) elif event['state'] == 'failure': _logger.warning('Activity %r failed', data['activity_id']) self._stop_launcher(data['activity_id']) self._failure_report(event)