Refactor startup. In progress, give me a couple hours.

For now start sugar with "sugar-emulator shell/sugar-shell"
This commit is contained in:
Marco Pesenti Gritti 2006-10-16 13:34:43 +02:00
parent a3be4492b2
commit bc0ee6d34c
22 changed files with 108 additions and 428 deletions

View File

@ -73,7 +73,6 @@ sugar/chat/sketchpad/Makefile
sugar/graphics/Makefile sugar/graphics/Makefile
sugar/p2p/Makefile sugar/p2p/Makefile
sugar/presence/Makefile sugar/presence/Makefile
sugar/session/Makefile
po/Makefile.in po/Makefile.in
tools/Makefile tools/Makefile
tools/sugar-setup-activity tools/sugar-setup-activity

View File

@ -19,7 +19,7 @@ import logging
import gobject import gobject
import dbus, dbus.service import dbus, dbus.service
from sugar import env from sugar import profile
PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp" PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp"
@ -416,8 +416,8 @@ class Owner(Buddy):
portion of the Owner, paired with the server portion in Owner.py.""" portion of the Owner, paired with the server portion in Owner.py."""
def __init__(self, ps, bus_name, object_id, icon_cache): def __init__(self, ps, bus_name, object_id, icon_cache):
Buddy.__init__(self, bus_name, object_id, None, icon_cache) Buddy.__init__(self, bus_name, object_id, None, icon_cache)
self._nick_name = env.get_nick_name() self._nick_name = profile.get_nick_name()
self._color = env.get_color() self._color = profile.get_color()
self._ps = ps self._ps = ps
def add_service(self, service): def add_service(self, service):

View File

@ -22,6 +22,7 @@ import random
import logging import logging
from sugar import util from sugar import util
from sugar import env from sugar import env
from sugar import profile
import BuddyIconCache import BuddyIconCache
@ -293,6 +294,7 @@ class PresenceServiceDBusHelper(dbus.service.Object):
class PresenceService(object): class PresenceService(object):
def __init__(self): def __init__(self):
# interface -> IP address: interfaces we've gotten events on so far # interface -> IP address: interfaces we've gotten events on so far
self._started = False
self._local_addrs = {} self._local_addrs = {}
self._next_object_id = 0 self._next_object_id = 0
@ -319,7 +321,7 @@ class PresenceService(object):
self._icon_cache = BuddyIconCache.BuddyIconCache() self._icon_cache = BuddyIconCache.BuddyIconCache()
# Our owner object # Our owner object
if env.get_nick_name(): if profile.get_nick_name():
objid = self._get_next_object_id() objid = self._get_next_object_id()
self._owner = Buddy.Owner(self, self._bus_name, self._owner = Buddy.Owner(self, self._bus_name,
objid, self._icon_cache) objid, self._icon_cache)
@ -327,8 +329,6 @@ class PresenceService(object):
else: else:
self._owner = None self._owner = None
self._started = False
def start(self): def start(self):
if self._started: if self._started:
return return

View File

@ -1,7 +1,7 @@
SUBDIRS = conf data model view SUBDIRS = conf data model view
bin_SCRIPTS = \ bin_SCRIPTS = \
sugar \ sugar-shell \
sugar-activity \ sugar-activity \
sugar-activity-factory \ sugar-activity-factory \
sugar-console sugar-console

View File

@ -1,76 +0,0 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# 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 os
from ConfigParser import ConfigParser
from sugar.graphics import iconcolor
from sugar import env
class _Profile:
def __init__(self,):
self._path = env.get_profile_path()
self._nick_name = None
self._color = iconcolor.IconColor()
self._ensure_dirs()
cp = ConfigParser()
parsed = cp.read([self._get_config_path()])
if cp.has_option('Buddy', 'NickName'):
self._nick_name = cp.get('Buddy', 'NickName')
if cp.has_option('Buddy', 'Color'):
color = cp.get('Buddy', 'Color')
if iconcolor.is_valid(color):
self._color = iconcolor.IconColor(color)
def _ensure_dirs(self):
try:
os.makedirs(self._path)
except OSError, exc:
if exc[0] != 17: # file exists
print "Could not create user directory."
def get_color(self):
return self._color
def set_color(self, color):
self._color = color
def get_nick_name(self):
return self._nick_name
def set_nick_name(self, nick_name):
self._nick_name = nick_name
def get_path(self):
return self._path
def save(self):
cp = ConfigParser()
section = 'Buddy'
cp.add_section(section)
cp.set(section, 'NickName', self._nick_name)
cp.set(section, 'Color', self._color.to_string())
fileobject = open(self._get_config_path(), 'w')
cp.write(fileobject)
fileobject.close()
def _get_config_path(self):
return os.path.join(self._path, 'config')

View File

@ -1,11 +1,6 @@
from conf.ActivityRegistry import _ActivityRegistry from conf.ActivityRegistry import _ActivityRegistry
from conf.Profile import _Profile
__registry = _ActivityRegistry() _activity_registry = _ActivityRegistry()
__profile = _Profile()
def get_activity_registry(): def get_activity_registry():
return __registry return _activity_registry
def get_profile():
return __profile

View File

@ -18,15 +18,15 @@ import os
import random import random
import base64 import base64
import time import time
import conf
from sugar import env
import logging import logging
import dbus
from sugar import env
from sugar import profile
from sugar.p2p import Stream from sugar.p2p import Stream
from sugar.presence import PresenceService from sugar.presence import PresenceService
from sugar import util from sugar import util
from model.Invites import Invites from model.Invites import Invites
import dbus
PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp" PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp"
@ -35,10 +35,8 @@ class ShellOwner(object):
runs in the shell and serves up the buddy icon and other stuff. It's the runs in the shell and serves up the buddy icon and other stuff. It's the
server portion of the Owner, paired with the client portion in Buddy.py.""" server portion of the Owner, paired with the client portion in Buddy.py."""
def __init__(self): def __init__(self):
profile = conf.get_profile()
self._nick = profile.get_nick_name() self._nick = profile.get_nick_name()
user_dir = profile.get_path() user_dir = env.get_profile_path()
self._icon = None self._icon = None
self._icon_hash = "" self._icon_hash = ""
@ -71,7 +69,7 @@ class ShellOwner(object):
def announce(self): def announce(self):
# Create and announce our presence # Create and announce our presence
color = conf.get_profile().get_color() color = profile.get_color()
props = {'color': color.to_string(), 'icon-hash': self._icon_hash} props = {'color': color.to_string(), 'icon-hash': self._icon_hash}
self._service = self._pservice.register_service(self._nick, self._service = self._pservice.register_service(self._nick,
PRESENCE_SERVICE_TYPE, properties=props) PRESENCE_SERVICE_TYPE, properties=props)

View File

@ -16,33 +16,27 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import sys
import os
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
import gtk
curdir = os.path.abspath(os.path.dirname(__file__)) from sugar import profile
sourcedir = os.path.dirname(curdir) from sugar import TracebackUtils
from view.FirstTimeDialog import FirstTimeDialog
from view.Shell import Shell
from model.ShellModel import ShellModel
if os.path.isfile(os.path.join(sourcedir, 'sugar/__uninstalled__.py')): name = profile.get_nick_name()
print 'Running sugar from ' + sourcedir + ' ...' if not name or not len(name):
sys.path.insert(0, sourcedir) dialog = FirstTimeDialog()
else: dialog.run()
print 'Running the installed sugar...'
from sugar import env model = ShellModel()
shell = Shell(model)
env.setup_system() tbh = TracebackUtils.TracebackHelper()
try:
from sugar.session.Emulator import Emulator gtk.main()
except KeyboardInterrupt:
if os.environ.has_key('SUGAR_EMULATOR') and \ print 'Ctrl+C pressed, exiting...'
os.environ['SUGAR_EMULATOR'] == 'yes': del tbh
emulator = Emulator()
emulator.start()
from Session import Session
session = Session()
session.start()

View File

@ -18,6 +18,7 @@ import gtk
import dbus import dbus
import conf import conf
from sugar import profile
from sugar.activity import Activity from sugar.activity import Activity
from sugar.presence import PresenceService from sugar.presence import PresenceService
from sugar.graphics.iconcolor import IconColor from sugar.graphics.iconcolor import IconColor
@ -92,7 +93,7 @@ class ActivityHost:
if activity != None: if activity != None:
return IconColor(activity.get_color()) return IconColor(activity.get_color())
else: else:
return conf.get_profile().get_color() return profile.get_color()
def share(self): def share(self):
self._activity.share() self._activity.share()

View File

@ -14,11 +14,14 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import gtk import os
from ConfigParser import ConfigParser
import gtk
from gettext import gettext as _ from gettext import gettext as _
import conf from sugar.graphics.iconcolor import IconColor
from sugar import env
class FirstTimeDialog(gtk.Dialog): class FirstTimeDialog(gtk.Dialog):
def __init__(self): def __init__(self):
@ -37,22 +40,24 @@ class FirstTimeDialog(gtk.Dialog):
self._ok = gtk.Button(None, gtk.STOCK_OK) self._ok = gtk.Button(None, gtk.STOCK_OK)
self._ok.set_sensitive(False) self._ok.set_sensitive(False)
self.vbox.pack_start(self._ok) self.vbox.pack_start(self._ok)
self._ok.connect('clicked', self.__ok_button_clicked_cb) self._ok.connect('clicked', self._ok_button_clicked_cb)
self._ok.show() self._ok.show()
def _entry_changed_cb(self, entry): def _entry_changed_cb(self, entry):
valid = (len(entry.get_text()) > 0) valid = (len(entry.get_text()) > 0)
self._ok.set_sensitive(valid) self._ok.set_sensitive(valid)
def __ok_button_clicked_cb(self, button): def _ok_button_clicked_cb(self, button):
profile = conf.get_profile() cp = ConfigParser()
profile.set_nick_name(self._entry.get_text())
self.destroy()
def get_profile(): section = 'Buddy'
profile = conf.get_profile() cp.add_section(section)
if profile.get_nick_name() == None: cp.set(section, 'NickName', self._entry.get_text())
dialog = FirstTimeDialog() cp.set(section, 'Color', IconColor().to_string())
dialog.connect('destroy', self.__first_time_dialog_destroy_cb)
dialog.show() config_path = os.path.join(env.get_profile_path(), 'config')
return profile fileobject = open(config_path, 'w')
cp.write(fileobject)
fileobject.close()
self.destroy()

View File

@ -15,10 +15,9 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from sugar.graphics.canvasicon import CanvasIcon from sugar.graphics.canvasicon import CanvasIcon
import conf from sugar import profile
class MyIcon(CanvasIcon): class MyIcon(CanvasIcon):
def __init__(self): def __init__(self):
profile = conf.get_profile()
CanvasIcon.__init__(self, icon_name='stock-buddy', CanvasIcon.__init__(self, icon_name='stock-buddy',
color=profile.get_color()) color=profile.get_color())

View File

@ -1,9 +1,10 @@
SUBDIRS = activity chat graphics p2p presence session SUBDIRS = activity chat graphics p2p presence
sugardir = $(pythondir)/sugar sugardir = $(pythondir)/sugar
sugar_PYTHON = \ sugar_PYTHON = \
__init__.py \ __init__.py \
__installed__.py \ __installed__.py \
emulator.py \
env.py \ env.py \
logger.py \ logger.py \
setup.py \ setup.py \

View File

@ -26,25 +26,8 @@ except ImportError:
import sugar.setup import sugar.setup
def setup_user(profile):
os.environ['SUGAR_NICK_NAME'] = profile.get_nick_name()
os.environ['SUGAR_COLOR'] = profile.get_color().to_string()
def get_nick_name():
if os.environ.has_key('SUGAR_NICK_NAME'):
return os.environ['SUGAR_NICK_NAME']
else:
return None
def get_color():
if os.environ.has_key('SUGAR_COLOR'):
return os.environ['SUGAR_COLOR']
else:
return None
def setup_python_path(): def setup_python_path():
for path in sugar_python_path: for path in sugar_python_path:
sys.path.insert(0, path)
if os.environ.has_key('PYTHONPATH'): if os.environ.has_key('PYTHONPATH'):
old_path = os.environ['PYTHONPATH'] old_path = os.environ['PYTHONPATH']
os.environ['PYTHONPATH'] = path + ':' + old_path os.environ['PYTHONPATH'] = path + ':' + old_path
@ -76,9 +59,15 @@ def get_profile_path():
profile_id = os.environ['SUGAR_PROFILE'] profile_id = os.environ['SUGAR_PROFILE']
else: else:
profile_id = 'default' profile_id = 'default'
path = os.path.expanduser('~/.sugar')
return os.path.join(path, profile_id) path = os.path.join(os.path.expanduser('~/.sugar'), profile_id)
if not os.path.isdir(path):
try:
os.makedirs(path)
except OSError, exc:
print "Could not create user directory."
return path
def get_data_dir(): def get_data_dir():
return sugar_data_dir return sugar_data_dir

43
sugar/profile.py Normal file
View File

@ -0,0 +1,43 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# 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 os
from ConfigParser import ConfigParser
from sugar import env
from sugar.graphics.iconcolor import IconColor
def get_nick_name():
return _nick_name
def get_color():
return _color
cp = ConfigParser()
config_path = os.path.join(env.get_profile_path(), 'config')
parsed = cp.read([config_path])
if cp.has_option('Buddy', 'NickName'):
_nick_name = cp.get('Buddy', 'NickName')
else:
_nick_name = None
if cp.has_option('Buddy', 'Color'):
_color = IconColor(cp.get('Buddy', 'Color'))
else:
_color = None
del cp

View File

@ -1,37 +0,0 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import os
from sugar.session.Process import Process
from sugar import env
class DbusProcess(Process):
def __init__(self):
config = env.get_dbus_config()
cmd = "dbus-daemon --print-address --config-file %s" % config
Process.__init__(self, cmd)
def get_name(self):
return 'Dbus'
def start(self):
Process.start(self, True)
dbus_file = os.fdopen(self._stdout)
addr = dbus_file.readline().strip()
dbus_file.close()
os.environ["DBUS_SESSION_BUS_ADDRESS"] = addr

View File

@ -1,87 +0,0 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import os
import socket
import sys
from sugar.session.Process import Process
import sugar.env
def get_display_number():
"""Find a free display number trying to connect to 6000+ ports"""
retries = 20
display_number = 1
display_is_free = False
while not display_is_free and retries > 0:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect(('127.0.0.1', 6000 + display_number))
s.close()
display_number += 1
retries -= 1
except:
display_is_free = True
if display_is_free:
return display_number
else:
logging.error('Cannot find a free display.')
sys.exit(0)
class XephyrProcess(Process):
def __init__(self):
self._display = get_display_number()
cmd = 'Xephyr :%d -ac -screen 800x600' % (self._display)
Process.__init__(self, cmd)
def get_name(self):
return 'Xephyr'
def start(self):
Process.start(self)
os.environ['DISPLAY'] = ":%d" % (self._display)
class XnestProcess(Process):
def __init__(self):
self._display = get_display_number()
cmd = 'Xnest :%d -ac -geometry 800x600' % (self._display)
Process.__init__(self, cmd)
def get_name(self):
return 'Xnest'
def start(self):
Process.start(self)
os.environ['DISPLAY'] = ":%d" % (self._display)
class Emulator:
"""The OLPC emulator"""
def start(self):
try:
process = XephyrProcess()
process.start()
except:
try:
process = XnestProcess()
process.start()
except:
print 'Cannot run the emulator. You need to install \
Xephyr or Xnest.'
sys.exit(0)

View File

@ -1,9 +0,0 @@
sugardir = $(pythondir)/sugar/session
sugar_PYTHON = \
__init__.py \
DbusProcess.py \
Emulator.py \
MatchboxProcess.py \
Process.py \
TestSession.py \
UITestSession.py

View File

@ -1,35 +0,0 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import os
from sugar.session.Process import Process
from sugar import env
class MatchboxProcess(Process):
def __init__(self):
kbd_config = os.path.join(env.get_data_dir(), 'kbdconfig')
options = '-kbdconfig %s ' % kbd_config
options += '-use_titlebar no '
options += '-theme olpc '
command = 'matchbox-window-manager %s ' % options
Process.__init__(self, command)
def get_name(self):
return 'Matchbox'

View File

@ -1,36 +0,0 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import logging
import gobject
class Process:
"""Object representing one of the session processes"""
def __init__(self, command):
self._command = command
def get_name(self):
return self._command
def start(self, standard_output=False):
args = self._command.split()
flags = gobject.SPAWN_SEARCH_PATH
result = gobject.spawn_async(args, flags=flags,
standard_output=standard_output)
self._stdout = result[2]

View File

@ -1,26 +0,0 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
from sugar.session.DbusProcess import DbusProcess
from sugar import env
class TestSession:
def start(self):
env.setup_python_path()
process = DbusProcess()
process.start()

View File

@ -1,38 +0,0 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import os
from sugar.session.DbusProcess import DbusProcess
from sugar.session.MatchboxProcess import MatchboxProcess
from sugar.session.Emulator import Emulator
from sugar import env
class UITestSession:
def start(self):
env.setup_python_path()
if os.environ.has_key('SUGAR_EMULATOR') and \
os.environ['SUGAR_EMULATOR'] == 'yes':
emulator = Emulator()
emulator.start()
process = MatchboxProcess()
process.start()
process = DbusProcess()
process.start()