Merge branch 'master' of git+ssh://danw@dev.laptop.org/git/sugar

This commit is contained in:
Dan Winship 2007-08-08 13:13:31 -04:00
commit bdba2d149e
17 changed files with 157 additions and 113 deletions

View File

@ -45,7 +45,7 @@ data/Makefile
lib/Makefile lib/Makefile
lib/ui/Makefile lib/ui/Makefile
services/Makefile services/Makefile
services/clipboard/Makefile services/shell/Makefile
shell/Makefile shell/Makefile
shell/intro/Makefile shell/intro/Makefile
shell/hardware/Makefile shell/hardware/Makefile

View File

@ -1 +1 @@
SUBDIRS = clipboard console SUBDIRS = shell console

View File

@ -1,29 +1,37 @@
servicedir = $(datadir)/dbus-1/services servicedir = $(datadir)/dbus-1/services
service_in_files = \ service_in_files = \
org.laptop.ActivityRegistry.service.in \
org.laptop.Clipboard.service.in \ org.laptop.Clipboard.service.in \
org.laptop.ObjectTypeRegistry.service.in org.laptop.ObjectTypeRegistry.service.in
service_DATA = \ service_DATA = \
org.laptop.ActivityRegistry.service \
org.laptop.Clipboard.service \ org.laptop.Clipboard.service \
org.laptop.ObjectTypeRegistry.service org.laptop.ObjectTypeRegistry.service
org.laptop.ActivityRegistry.service: org.laptop.ActivityRegistry.service.in Makefile
@sed -e "s|\@bindir\@|$(bindir)|" $< > $@
org.laptop.Clipboard.service: org.laptop.Clipboard.service.in Makefile org.laptop.Clipboard.service: org.laptop.Clipboard.service.in Makefile
@sed -e "s|\@bindir\@|$(bindir)|" $< > $@ @sed -e "s|\@bindir\@|$(bindir)|" $< > $@
org.laptop.ObjectTypeRegistry.service: org.laptop.ObjectTypeRegistry.service.in Makefile org.laptop.ObjectTypeRegistry.service: org.laptop.ObjectTypeRegistry.service.in Makefile
@sed -e "s|\@bindir\@|$(bindir)|" $< > $@ @sed -e "s|\@bindir\@|$(bindir)|" $< > $@
sugardir = $(pkgdatadir)/services/clipboard sugardir = $(pkgdatadir)/services/shell
sugar_PYTHON = \ sugar_PYTHON = \
__init__.py \ __init__.py \
activityregistryservice.py \
bundleregistry.py \
clipboardobject.py \ clipboardobject.py \
clipboardservice.py \ clipboardservice.py \
objecttypeservice.py objecttypeservice.py
bin_SCRIPTS = sugar-clipboard bin_SCRIPTS = sugar-shell-service
DISTCLEANFILES = $(service_DATA) DISTCLEANFILES = $(service_DATA)
EXTRA_DIST = $(service_in_files) $(bin_SCRIPTS) EXTRA_DIST = $(service_in_files) $(bin_SCRIPTS)

View File

@ -0,0 +1,104 @@
# Copyright (C) 2006-2007 Red Hat, Inc.
# Copyright (C) 2007 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
# the Free Software Foundation; either version 2 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, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import dbus
import dbus.service
import bundleregistry
_ACTIVITY_REGISTRY_SERVICE_NAME = 'org.laptop.ActivityRegistry'
_ACTIVITY_REGISTRY_IFACE = 'org.laptop.ActivityRegistry'
_ACTIVITY_REGISTRY_PATH = '/org/laptop/ActivityRegistry'
class ActivityRegistry(dbus.service.Object):
def __init__(self):
bus = dbus.SessionBus()
bus_name = dbus.service.BusName(_ACTIVITY_REGISTRY_SERVICE_NAME, bus=bus)
dbus.service.Object.__init__(self, bus_name, _ACTIVITY_REGISTRY_PATH)
bundle_registry = bundleregistry.get_registry()
bundle_registry.connect('bundle-added', self._bundle_added_cb)
@dbus.service.method(_ACTIVITY_REGISTRY_IFACE,
in_signature='s', out_signature='b')
def AddBundle(self, bundle_path):
'''Register the activity bundle with the global registry
bundle_path -- path to the activity bundle's root directory,
that is, the directory with activity/activity.info as a
child of the directory.
The bundleregistry.BundleRegistry is responsible for setting
up a set of d-bus service mappings for each available activity.
'''
registry = bundleregistry.get_registry()
return registry.add_bundle(bundle_path)
@dbus.service.method(_ACTIVITY_REGISTRY_IFACE,
in_signature='s', out_signature='a{sv}')
def GetActivity(self, service_name):
registry = bundleregistry.get_registry()
bundle = registry.get_bundle(service_name)
if not bundle:
return {}
return self._bundle_to_dict(bundle)
@dbus.service.method(_ACTIVITY_REGISTRY_IFACE,
in_signature='s', out_signature='aa{sv}')
def FindActivity(self, name):
result = []
key = name.lower()
for bundle in bundleregistry.get_registry():
name = bundle.get_name().lower()
service_name = bundle.get_service_name().lower()
if name.find(key) != -1 or service_name.find(key) != -1:
result.append(self._bundle_to_dict(bundle))
return result
@dbus.service.method(_ACTIVITY_REGISTRY_IFACE,
in_signature='s', out_signature='aa{sv}')
def GetActivitiesForType(self, mime_type):
result = []
registry = bundleregistry.get_registry()
for bundle in registry.get_activities_for_type(mime_type):
result.append(self._bundle_to_dict(bundle))
return result
@dbus.service.signal(_ACTIVITY_REGISTRY_IFACE, signature='a{sv}')
def ActivityAdded(self, activity_info):
pass
def _bundle_to_dict(self, bundle):
return {'name': bundle.get_name(),
'icon': bundle.get_icon(),
'service_name': bundle.get_service_name(),
'path': bundle.get_path()}
def _bundle_added_cb(self, bundle_registry, bundle):
self.ActivityAdded(self._bundle_to_dict(bundle))
_instance = None
def get_instance():
global _instance
if not _instance:
_instance = ActivityRegistry()
return _instance

View File

@ -106,6 +106,13 @@ class BundleRegistry(gobject.GObject):
else: else:
return False return False
def get_activities_for_type(self, mime_type):
result = []
for bundle in self._bundles.values():
if bundle.get_mime_types() and mime_type in bundle.get_mime_types():
result.append(bundle)
return result
def get_registry(): def get_registry():
return _bundle_registry return _bundle_registry

View File

@ -19,9 +19,9 @@ import logging
import urlparse import urlparse
from sugar.objects import mime from sugar.objects import mime
from sugar import activity
import objecttypeservice import objecttypeservice
import bundleregistry
class ClipboardObject: class ClipboardObject:
@ -66,30 +66,15 @@ class ClipboardObject:
return '' return ''
def get_activity(self): def get_activity(self):
logging.debug('get_activity')
mapping = {'text/html' : 'org.laptop.WebActivity',
'image/jpeg' : 'org.laptop.WebActivity',
'image/gif' : 'org.laptop.WebActivity',
'image/png' : 'org.laptop.WebActivity',
'text/plain' : 'org.laptop.AbiWordActivity',
'text/rtf' : 'org.laptop.AbiWordActivity',
'text/richtext' : 'org.laptop.AbiWordActivity',
'application/pdf' : 'org.laptop.sugar.ReadActivity',
'application/x-squeak-project' : 'org.vpri.EtoysActivity'}
mime = self.get_mime_type() mime = self.get_mime_type()
if not mime: if not mime:
return '' return ''
"""
registry = activity.get_registry() registry = bundleregistry.get_registry()
activities = registry.get_activities_for_type(self.get_mime_type()) activities = registry.get_activities_for_type(self.get_mime_type())
# TODO: should we return several activities? # TODO: should we return several activities?
if activities: if activities:
return activities[0] return activities[0].get_service_name()
else:
return ''
"""
if mapping.has_key(mime):
return mapping[mime]
else: else:
return '' return ''
@ -101,8 +86,6 @@ class ClipboardObject:
def add_format(self, format): def add_format(self, format):
self._formats[format.get_type()] = format self._formats[format.get_type()] = format
# We want to get the activity early in order to prevent a DBus lockup.
activity = self.get_activity()
def get_formats(self): def get_formats(self):
return self._formats return self._formats

View File

@ -0,0 +1,4 @@
[D-BUS Service]
Name = org.laptop.ActivityRegistry
Exec = @bindir@/sugar-shell-service

View File

@ -1,4 +1,4 @@
[D-BUS Service] [D-BUS Service]
Name = org.laptop.Clipboard Name = org.laptop.Clipboard
Exec = @bindir@/sugar-clipboard Exec = @bindir@/sugar-shell-service

View File

@ -1,4 +1,4 @@
[D-BUS Service] [D-BUS Service]
Name = org.laptop.ObjectTypeRegistry Name = org.laptop.ObjectTypeRegistry
Exec = @bindir@/sugar-clipboard Exec = @bindir@/sugar-shell-service

View File

@ -23,28 +23,31 @@ import os
import logging import logging
from sugar import logger from sugar import logger
logger.start('clipboard') logger.start('shellservice')
import gobject import gobject
import dbus.glib import dbus.glib
from sugar import env from sugar import env
sys.path.append(env.get_service_path('clipboard')) sys.path.append(env.get_service_path('shell'))
import clipboardservice import clipboardservice
import objecttypeservice import objecttypeservice
import activityregistryservice
logging.info('Starting clipboard service.') logging.info('Starting shell service.')
gobject.threads_init() gobject.threads_init()
dbus.glib.threads_init() dbus.glib.threads_init()
clipboard_service = clipboardservice.get_instance() clipboard_service = clipboardservice.get_instance()
object_type_registry = objecttypeservice.get_instance() object_type_registry = objecttypeservice.get_instance()
activity_registry = activityregistryservice.get_instance()
loop = gobject.MainLoop() loop = gobject.MainLoop()
try: try:
loop.run() loop.run()
except KeyboardInterrupt: except KeyboardInterrupt:
print 'Ctrl+C pressed, exiting...' print 'Ctrl+C pressed, exiting...'

View File

@ -4,7 +4,6 @@ sugardir = $(pkgdatadir)/shell/model
sugar_PYTHON = \ sugar_PYTHON = \
__init__.py \ __init__.py \
accesspointmodel.py \ accesspointmodel.py \
bundleregistry.py \
BuddyModel.py \ BuddyModel.py \
Friends.py \ Friends.py \
Invites.py \ Invites.py \

View File

@ -17,10 +17,7 @@
"""D-bus service providing access to the shell's functionality""" """D-bus service providing access to the shell's functionality"""
import dbus import dbus
from model import bundleregistry
_DBUS_SERVICE = "org.laptop.Shell" _DBUS_SERVICE = "org.laptop.Shell"
_DBUS_ACTIVITY_REGISTRY_IFACE = "org.laptop.Shell.ActivityRegistry"
_DBUS_SHELL_IFACE = "org.laptop.Shell" _DBUS_SHELL_IFACE = "org.laptop.Shell"
_DBUS_OWNER_IFACE = "org.laptop.Shell.Owner" _DBUS_OWNER_IFACE = "org.laptop.Shell.Owner"
_DBUS_PATH = "/org/laptop/Shell" _DBUS_PATH = "/org/laptop/Shell"
@ -56,9 +53,6 @@ class ShellService(dbus.service.Object):
self._home_model.connect('active-activity-changed', self._home_model.connect('active-activity-changed',
self._cur_activity_changed_cb) self._cur_activity_changed_cb)
bundle_registry = bundleregistry.get_registry()
bundle_registry.connect('bundle-added', self._bundle_added_cb)
bus = dbus.SessionBus() bus = dbus.SessionBus()
bus_name = dbus.service.BusName(_DBUS_SERVICE, bus=bus) bus_name = dbus.service.BusName(_DBUS_SERVICE, bus=bus)
dbus.service.Object.__init__(self, bus_name, _DBUS_PATH) dbus.service.Object.__init__(self, bus_name, _DBUS_PATH)
@ -83,60 +77,6 @@ class ShellService(dbus.service.Object):
def NotifyLaunchFailure(self, activity_id): def NotifyLaunchFailure(self, activity_id):
self._shell.notify_launch_failure(activity_id) self._shell.notify_launch_failure(activity_id)
@dbus.service.method(_DBUS_ACTIVITY_REGISTRY_IFACE,
in_signature="s", out_signature="b")
def AddBundle(self, bundle_path):
"""Register the activity bundle with the global registry
bundle_path -- path to the activity bundle's root directory,
that is, the directory with activity/activity.info as a
child of the directory.
The bundleregistry.BundleRegistry is responsible for setting
up a set of d-bus service mappings for each available activity.
"""
registry = bundleregistry.get_registry()
return registry.add_bundle(bundle_path)
@dbus.service.method(_DBUS_ACTIVITY_REGISTRY_IFACE,
in_signature="s", out_signature="a{sv}")
def GetActivity(self, service_name):
registry = bundleregistry.get_registry()
bundle = registry.get_bundle(service_name)
if not bundle:
return {}
return self._bundle_to_dict(bundle)
@dbus.service.method(_DBUS_ACTIVITY_REGISTRY_IFACE,
in_signature="s", out_signature="aa{sv}")
def FindActivity(self, name):
result = []
key = name.lower()
for bundle in bundleregistry.get_registry():
name = bundle.get_name().lower()
service_name = bundle.get_service_name().lower()
if name.find(key) != -1 or service_name.find(key) != -1:
result.append(self._bundle_to_dict(bundle))
return result
@dbus.service.method(_DBUS_ACTIVITY_REGISTRY_IFACE,
in_signature="s", out_signature="aa{sv}")
def GetActivitiesForType(self, mime_type):
result = []
for bundle in bundleregistry.get_registry():
if bundle.get_mime_types() and mime_type in bundle.get_mime_types():
result.append(self._bundle_to_dict(bundle))
return result
@dbus.service.signal(_DBUS_ACTIVITY_REGISTRY_IFACE, signature="a{sv}")
def ActivityAdded(self, activity_info):
pass
@dbus.service.signal(_DBUS_OWNER_IFACE, signature="s") @dbus.service.signal(_DBUS_OWNER_IFACE, signature="s")
def ColorChanged(self, color): def ColorChanged(self, color):
pass pass
@ -169,12 +109,3 @@ class ShellService(dbus.service.Object):
if new_id: if new_id:
self.CurrentActivityChanged(new_id) self.CurrentActivityChanged(new_id)
def _bundle_to_dict(self, bundle):
return {'name': bundle.get_name(),
'icon': bundle.get_icon(),
'service_name': bundle.get_service_name(),
'path': bundle.get_path()}
def _bundle_added_cb(self, bundle_registry, bundle):
self.ActivityAdded(self._bundle_to_dict(bundle))

View File

@ -64,11 +64,13 @@ class ClipboardMenu(Palette):
self._remove_item = MenuItem(_('Remove'), 'stock-remove') self._remove_item = MenuItem(_('Remove'), 'stock-remove')
self._remove_item.connect('activate', self._remove_item_activate_cb) self._remove_item.connect('activate', self._remove_item_activate_cb)
self.append_menu_item(self._remove_item) self.menu.append(self._remove_item)
self._remove_item.show()
self._open_item = MenuItem(_('Open'), 'stock-keep') self._open_item = MenuItem(_('Open'), 'stock-keep')
self._open_item.connect('activate', self._open_item_activate_cb) self._open_item.connect('activate', self._open_item_activate_cb)
self.append_menu_item(self._open_item) self.menu.append(self._open_item)
self._open_item.show()
#self._stop_item = MenuItem(_('Stop download'), 'stock-close') #self._stop_item = MenuItem(_('Stop download'), 'stock-close')
# TODO: Implement stopping downloads # TODO: Implement stopping downloads
@ -77,7 +79,8 @@ class ClipboardMenu(Palette):
self._journal_item = MenuItem(_('Add to journal'), 'document-save') self._journal_item = MenuItem(_('Add to journal'), 'document-save')
self._journal_item.connect('activate', self._journal_item_activate_cb) self._journal_item.connect('activate', self._journal_item_activate_cb)
self.append_menu_item(self._journal_item) self.menu.append(self._journal_item)
self._journal_item.show()
self._update_items_visibility(installable) self._update_items_visibility(installable)

View File

@ -1,4 +1,5 @@
# Copyright (C) 2006-2007 Red Hat, Inc. # Copyright (C) 2006-2007 Red Hat, Inc.
# Copyright (C) 2007 One Laptop Per Child
# #
# This library is free software; you can redistribute it and/or # This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public # modify it under the terms of the GNU Lesser General Public
@ -19,9 +20,9 @@ import logging
import dbus import dbus
_SHELL_SERVICE = "org.laptop.Shell" _ACTIVITY_REGISTRY_SERVICE_NAME = 'org.laptop.ActivityRegistry'
_SHELL_PATH = "/org/laptop/Shell" _ACTIVITY_REGISTRY_IFACE = 'org.laptop.ActivityRegistry'
_REGISTRY_IFACE = "org.laptop.Shell.ActivityRegistry" _ACTIVITY_REGISTRY_PATH = '/org/laptop/ActivityRegistry'
def _activity_info_from_dict(info_dict): def _activity_info_from_dict(info_dict):
if not info_dict: if not info_dict:
@ -39,8 +40,9 @@ class ActivityInfo(object):
class ActivityRegistry(object): class ActivityRegistry(object):
def __init__(self): def __init__(self):
bus = dbus.SessionBus() bus = dbus.SessionBus()
bus_object = bus.get_object(_SHELL_SERVICE, _SHELL_PATH) bus_object = bus.get_object(_ACTIVITY_REGISTRY_SERVICE_NAME,
self._registry = dbus.Interface(bus_object, _REGISTRY_IFACE) _ACTIVITY_REGISTRY_PATH)
self._registry = dbus.Interface(bus_object, _ACTIVITY_REGISTRY_IFACE)
self._registry.connect_to_signal('ActivityAdded', self._activity_added_cb) self._registry.connect_to_signal('ActivityAdded', self._activity_added_cb)
# Two caches fo saving some travel across dbus. # Two caches fo saving some travel across dbus.