Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
Conflicts: NEWS
This commit is contained in:
commit
15210f4cc4
2
NEWS
2
NEWS
@ -1,4 +1,6 @@
|
|||||||
* #4428 Revert to the trial-3 frame behavior (marco)
|
* #4428 Revert to the trial-3 frame behavior (marco)
|
||||||
|
* Initial push for the sugar control panel (erikos)
|
||||||
|
* #4358: pydoc strings for sugar.activity.Activity
|
||||||
|
|
||||||
Snapshot 176262f2e9
|
Snapshot 176262f2e9
|
||||||
|
|
||||||
|
@ -1,7 +1,31 @@
|
|||||||
"""Base class for Python-coded activities
|
"""Base class for activities written in Python
|
||||||
|
|
||||||
This is currently the only reference for what an
|
This is currently the only definitive reference for what an
|
||||||
activity must do to participate in the Sugar desktop.
|
activity must do to participate in the Sugar desktop.
|
||||||
|
|
||||||
|
A Basic Activity
|
||||||
|
|
||||||
|
All activities must implement a class derived from 'Activity' in this class.
|
||||||
|
The convention is to call it ActivitynameActivity, but this is not required as
|
||||||
|
the activity.info file associated with your activity will tell the sugar-shell
|
||||||
|
which class to start.
|
||||||
|
|
||||||
|
For example the most minimal Activity:
|
||||||
|
|
||||||
|
|
||||||
|
from sugar.activity import activity
|
||||||
|
|
||||||
|
class ReadActivity(activity.Activity):
|
||||||
|
pass
|
||||||
|
|
||||||
|
To get a real, working activity, you will at least have to implement:
|
||||||
|
__init__(), read_file() and write_file()
|
||||||
|
|
||||||
|
Aditionally, you will probably need a at least a Toolbar so you can have some
|
||||||
|
interesting buttons for the user, like for example 'exit activity'
|
||||||
|
|
||||||
|
See the methods of the Activity class below for more information on what you
|
||||||
|
will need for a real activity.
|
||||||
"""
|
"""
|
||||||
# Copyright (C) 2006-2007 Red Hat, Inc.
|
# Copyright (C) 2006-2007 Red Hat, Inc.
|
||||||
#
|
#
|
||||||
@ -49,6 +73,11 @@ SCOPE_INVITE_ONLY = "invite" # shouldn't be shown in UI, it's implicit when you
|
|||||||
SCOPE_NEIGHBORHOOD = "public"
|
SCOPE_NEIGHBORHOOD = "public"
|
||||||
|
|
||||||
class ActivityToolbar(gtk.Toolbar):
|
class ActivityToolbar(gtk.Toolbar):
|
||||||
|
"""The Activity toolbar with the Journal entry title, sharing, Keep and Stop buttons
|
||||||
|
|
||||||
|
All activities should have this toolbar. It is easiest to add it to your
|
||||||
|
Activity by using the ActivityToolbox.
|
||||||
|
"""
|
||||||
def __init__(self, activity):
|
def __init__(self, activity):
|
||||||
gtk.Toolbar.__init__(self)
|
gtk.Toolbar.__init__(self)
|
||||||
|
|
||||||
@ -169,6 +198,38 @@ class ActivityToolbar(gtk.Toolbar):
|
|||||||
self._update_share()
|
self._update_share()
|
||||||
|
|
||||||
class EditToolbar(gtk.Toolbar):
|
class EditToolbar(gtk.Toolbar):
|
||||||
|
"""Provides the standard edit toolbar for Activities.
|
||||||
|
|
||||||
|
Members:
|
||||||
|
undo -- the undo button
|
||||||
|
redo -- the redo button
|
||||||
|
copy -- the copy button
|
||||||
|
paste -- the paste button
|
||||||
|
separator -- A separator between undo/redo and copy/paste
|
||||||
|
|
||||||
|
This class only provides the 'edit' buttons in a standard layout, your activity
|
||||||
|
will need to either hide buttons which make no sense for your Activity, or you
|
||||||
|
need to connect the button events to your own callbacks:
|
||||||
|
|
||||||
|
## Example from Read.activity:
|
||||||
|
# Create the edit toolbar:
|
||||||
|
self._edit_toolbar = EditToolbar(self._view)
|
||||||
|
# Hide undo and redo, they're not needed
|
||||||
|
self._edit_toolbar.undo.props.visible = False
|
||||||
|
self._edit_toolbar.redo.props.visible = False
|
||||||
|
# Hide the separator too:
|
||||||
|
self._edit_toolbar.separator.props.visible = False
|
||||||
|
|
||||||
|
# As long as nothing is selected, copy needs to be insensitive:
|
||||||
|
self._edit_toolbar.copy.set_sensitive(False)
|
||||||
|
# When the user clicks the button, call _edit_toolbar_copy_cb()
|
||||||
|
self._edit_toolbar.copy.connect('clicked', self._edit_toolbar_copy_cb)
|
||||||
|
|
||||||
|
# Add the edit toolbar:
|
||||||
|
toolbox.add_toolbar(_('Edit'), self._edit_toolbar)
|
||||||
|
# And make it visible:
|
||||||
|
self._edit_toolbar.show()
|
||||||
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
gtk.Toolbar.__init__(self)
|
gtk.Toolbar.__init__(self)
|
||||||
|
|
||||||
@ -198,6 +259,23 @@ class EditToolbar(gtk.Toolbar):
|
|||||||
self.paste.show()
|
self.paste.show()
|
||||||
|
|
||||||
class ActivityToolbox(Toolbox):
|
class ActivityToolbox(Toolbox):
|
||||||
|
"""Creates the Toolbox for the Activity
|
||||||
|
|
||||||
|
By default, the toolbox contains only the ActivityToolbar. After creating the
|
||||||
|
toolbox, you can add your activity specific toolbars, for example the
|
||||||
|
EditToolbar.
|
||||||
|
|
||||||
|
To add the ActivityToolbox to your Activity in MyActivity.__init__() do:
|
||||||
|
|
||||||
|
# Create the Toolbar with the ActivityToolbar:
|
||||||
|
toolbox = activity.ActivityToolbox(self)
|
||||||
|
... your code, inserting all other toolbars you need, like EditToolbar ...
|
||||||
|
|
||||||
|
# Add the toolbox to the activity frame:
|
||||||
|
self.set_toolbox(toolbox)
|
||||||
|
# And make it visible:
|
||||||
|
toolbox.show()
|
||||||
|
"""
|
||||||
def __init__(self, activity):
|
def __init__(self, activity):
|
||||||
Toolbox.__init__(self)
|
Toolbox.__init__(self)
|
||||||
|
|
||||||
@ -209,7 +287,71 @@ class ActivityToolbox(Toolbox):
|
|||||||
return self._activity_toolbar
|
return self._activity_toolbar
|
||||||
|
|
||||||
class Activity(Window, gtk.Container):
|
class Activity(Window, gtk.Container):
|
||||||
"""Base Activity class that all other Activities derive from."""
|
"""This is the base Activity class that all other Activities derive from. This is where your activity starts.
|
||||||
|
|
||||||
|
To get a working Activity:
|
||||||
|
0. Derive your Activity from this class:
|
||||||
|
class MyActivity(activity.Activity):
|
||||||
|
...
|
||||||
|
|
||||||
|
1. implement an __init__() method for your Activity class.
|
||||||
|
|
||||||
|
Use your init method to create your own ActivityToolbar which will
|
||||||
|
contain some standard buttons:
|
||||||
|
toolbox = activity.ActivityToolbox(self)
|
||||||
|
|
||||||
|
Add extra Toolbars to your toolbox.
|
||||||
|
|
||||||
|
You should setup Activity sharing here too.
|
||||||
|
|
||||||
|
Finaly, your Activity may need some resources which you can claim
|
||||||
|
here too.
|
||||||
|
|
||||||
|
The __init__() method is also used to make the distinction between
|
||||||
|
being resumed from the Journal, or starting with a blank document.
|
||||||
|
|
||||||
|
2. Implement read_file() and write_file()
|
||||||
|
Most activities revolve around creating and storing Journal entries.
|
||||||
|
For example, Write: You create a document, it is saved to the Journal
|
||||||
|
and then later you resume working on the document.
|
||||||
|
|
||||||
|
read_file() and write_file() will be called by sugar to tell your
|
||||||
|
Activity that it should load or save the document the user is working
|
||||||
|
on.
|
||||||
|
|
||||||
|
3. Implement our Activity Toolbars.
|
||||||
|
The Toolbars are added to your Activity in step 1 (the toolbox), but
|
||||||
|
you need to implement them somewhere. Now is a good time.
|
||||||
|
|
||||||
|
There are a number of standard Toolbars. The most basic one, the one
|
||||||
|
your almost absolutely MUST have is the ActivityToolbar. Without
|
||||||
|
this, you're not really making a proper Sugar Activity (which may be
|
||||||
|
okay, but you should really stop and think about why not!) You do
|
||||||
|
this with the ActivityToolbox(self) call in step 1.
|
||||||
|
|
||||||
|
Usually, you will also need the standard EditToolbar. This is the one
|
||||||
|
which has the standard copy and paste buttons. You need to derive
|
||||||
|
your own EditToolbar class from sugar.EditToolbar:
|
||||||
|
class EditToolbar(activity.EditToolbar):
|
||||||
|
...
|
||||||
|
|
||||||
|
See EditToolbar for the methods you should implement in your class.
|
||||||
|
|
||||||
|
Finaly, your Activity will very likely need some activity specific
|
||||||
|
buttons and options you can create your own toolbars by deriving a
|
||||||
|
class from gtk.Toolbar:
|
||||||
|
class MySpecialToolbar(gtk.Toolbar):
|
||||||
|
...
|
||||||
|
|
||||||
|
4. Use your creativity. Make your Activity something special and share
|
||||||
|
it with your friends!
|
||||||
|
|
||||||
|
Read through the methods of the Activity class below, to learn more about
|
||||||
|
how to make an Activity work.
|
||||||
|
|
||||||
|
Hint: A good and simple Activity to learn from is the Read activity. To
|
||||||
|
create your own activity, you may want to copy it and use it as a template.
|
||||||
|
"""
|
||||||
__gtype_name__ = 'SugarActivity'
|
__gtype_name__ = 'SugarActivity'
|
||||||
|
|
||||||
__gsignals__ = {
|
__gsignals__ = {
|
||||||
@ -248,6 +390,11 @@ class Activity(Window, gtk.Container):
|
|||||||
|
|
||||||
Creates an ActivityService (self._bus) servicing
|
Creates an ActivityService (self._bus) servicing
|
||||||
this application.
|
this application.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
If your Activity implements __init__(), it should call
|
||||||
|
the base class __init()__ before doing Activity specific things.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Window.__init__(self)
|
Window.__init__(self)
|
||||||
|
|
||||||
@ -360,12 +507,25 @@ class Activity(Window, gtk.Container):
|
|||||||
return self._max_participants
|
return self._max_participants
|
||||||
|
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
|
"""Returns the activity id of the current instance of your activity.
|
||||||
|
|
||||||
|
The activity id is sort-of-like the unix process id (PID). However,
|
||||||
|
unlike PIDs it is only different for each new instance (with
|
||||||
|
create_jobject = True set) and stays the same everytime a user
|
||||||
|
resumes an activity. This is also the identity of your Activity to other
|
||||||
|
XOs for use when sharing.
|
||||||
|
"""
|
||||||
return self._activity_id
|
return self._activity_id
|
||||||
|
|
||||||
def get_bundle_id(self):
|
def get_bundle_id(self):
|
||||||
|
"""Returns the bundle_id from the activity.info file"""
|
||||||
return os.environ['SUGAR_BUNDLE_ID']
|
return os.environ['SUGAR_BUNDLE_ID']
|
||||||
|
|
||||||
def set_canvas(self, canvas):
|
def set_canvas(self, canvas):
|
||||||
|
"""Sets the 'work area' of your activity with the canvas of your choice.
|
||||||
|
|
||||||
|
One commonly used canvas is gtk.ScrolledWindow
|
||||||
|
"""
|
||||||
Window.set_canvas(self, canvas)
|
Window.set_canvas(self, canvas)
|
||||||
canvas.connect('map', self.__canvas_map_cb)
|
canvas.connect('map', self.__canvas_map_cb)
|
||||||
|
|
||||||
@ -380,10 +540,17 @@ class Activity(Window, gtk.Container):
|
|||||||
logging.debug("Error creating activity datastore object: %s" % err)
|
logging.debug("Error creating activity datastore object: %s" % err)
|
||||||
|
|
||||||
def get_activity_root(self):
|
def get_activity_root(self):
|
||||||
"""
|
"""Returns a path for saving Activity specific preferences, etc.
|
||||||
Return the appropriate location in the fs where to store activity related
|
|
||||||
data that doesn't pertain to the current execution of the activity and
|
Returns a path to the location in the filesystem where the activity can
|
||||||
thus cannot go into the DataStore.
|
store activity related data that doesn't pertain to the current
|
||||||
|
execution of the activity and thus cannot go into the DataStore.
|
||||||
|
|
||||||
|
Currently, this will return something like ~/.sugar/default/MyActivityName/
|
||||||
|
|
||||||
|
Activities should ONLY save settings, user preferences and other data
|
||||||
|
which isn't specific to a journal item here. If (meta-)data is in anyway
|
||||||
|
specific to a journal entry, it MUST be stored in the DataStore.
|
||||||
"""
|
"""
|
||||||
if os.environ.has_key('SUGAR_ACTIVITY_ROOT') and \
|
if os.environ.has_key('SUGAR_ACTIVITY_ROOT') and \
|
||||||
os.environ['SUGAR_ACTIVITY_ROOT']:
|
os.environ['SUGAR_ACTIVITY_ROOT']:
|
||||||
@ -395,6 +562,17 @@ class Activity(Window, gtk.Container):
|
|||||||
"""
|
"""
|
||||||
Subclasses implement this method if they support resuming objects from
|
Subclasses implement this method if they support resuming objects from
|
||||||
the journal. 'file_path' is the file to read from.
|
the journal. 'file_path' is the file to read from.
|
||||||
|
|
||||||
|
You should immediately open the file from the file_path, because the
|
||||||
|
file_name will be deleted immediately after returning from read_file().
|
||||||
|
Once the file has been opened, you do not have to read it immediately:
|
||||||
|
After you have opened it, the file will only be really gone when you
|
||||||
|
close it.
|
||||||
|
|
||||||
|
Although not required, this is also a good time to read all meta-data:
|
||||||
|
the file itself cannot be changed externally, but the title, description
|
||||||
|
and other metadata['tags'] may change. So if it is important for you to
|
||||||
|
notice changes, this is the time to record the originals.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@ -402,6 +580,17 @@ class Activity(Window, gtk.Container):
|
|||||||
"""
|
"""
|
||||||
Subclasses implement this method if they support saving data to objects
|
Subclasses implement this method if they support saving data to objects
|
||||||
in the journal. 'file_path' is the file to write to.
|
in the journal. 'file_path' is the file to write to.
|
||||||
|
|
||||||
|
If the user did make changes, you should create the file_path and save
|
||||||
|
all document data to it.
|
||||||
|
|
||||||
|
Additionally, you should also write any metadata needed to resume your
|
||||||
|
activity. For example, the Read activity saves the current page and zoom
|
||||||
|
level, so it can display the page.
|
||||||
|
|
||||||
|
Note: Currently, the file_path *WILL* be different from the one you
|
||||||
|
received in file_read(). Even if you kept the file_path from file_read()
|
||||||
|
open until now, you must still write the entire file to this file_path.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@ -466,7 +655,13 @@ class Activity(Window, gtk.Container):
|
|||||||
self._preview = self._get_preview()
|
self._preview = self._get_preview()
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""Request that the activity is saved to the Journal."""
|
"""Request that the activity is saved to the Journal.
|
||||||
|
|
||||||
|
This method is called by the close() method below. In general,
|
||||||
|
activities should not override this method. This method is part of the
|
||||||
|
public API of an Acivity, and should behave in standard ways. Use your
|
||||||
|
own implementation of write_file() to save your Activity specific data.
|
||||||
|
"""
|
||||||
|
|
||||||
logging.debug('Activity.save: %r' % self._jobject.object_id)
|
logging.debug('Activity.save: %r' % self._jobject.object_id)
|
||||||
|
|
||||||
@ -507,6 +702,11 @@ class Activity(Window, gtk.Container):
|
|||||||
error_handler=self.__save_error_cb)
|
error_handler=self.__save_error_cb)
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
|
"""Request that the activity 'Keep in Journal' the current state of the activity.
|
||||||
|
|
||||||
|
Activities should not override this method. Instead, like save() do any
|
||||||
|
copy work that needs to be done in write_file()
|
||||||
|
"""
|
||||||
logging.debug('Activity.copy: %r' % self._jobject.object_id)
|
logging.debug('Activity.copy: %r' % self._jobject.object_id)
|
||||||
self._preview = self._get_preview()
|
self._preview = self._get_preview()
|
||||||
self.save()
|
self.save()
|
||||||
@ -570,6 +770,12 @@ class Activity(Window, gtk.Container):
|
|||||||
logging.error('Cannot invite %s, no such buddy.' % buddy_key)
|
logging.error('Cannot invite %s, no such buddy.' % buddy_key)
|
||||||
|
|
||||||
def invite(self, buddy_key):
|
def invite(self, buddy_key):
|
||||||
|
"""Invite a buddy to join this Activity.
|
||||||
|
|
||||||
|
Side Effects:
|
||||||
|
Calls self.share(True) to privately share the activity if it wasn't
|
||||||
|
shared before.
|
||||||
|
"""
|
||||||
self._invites_queue.append(buddy_key)
|
self._invites_queue.append(buddy_key)
|
||||||
|
|
||||||
if (self._shared_activity is None
|
if (self._shared_activity is None
|
||||||
@ -598,6 +804,11 @@ class Activity(Window, gtk.Container):
|
|||||||
self._pservice.share_activity(self, private=private)
|
self._pservice.share_activity(self, private=private)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
"""Request that the activity be stopped and saved to the Journal
|
||||||
|
|
||||||
|
Activities should not override this method, but should implement write_file() to
|
||||||
|
do any state saving instead.
|
||||||
|
"""
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
if self._shared_activity:
|
if self._shared_activity:
|
||||||
@ -617,6 +828,17 @@ class Activity(Window, gtk.Container):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def get_metadata(self):
|
def get_metadata(self):
|
||||||
|
"""Returns the jobject metadata or None if there is no jobject.
|
||||||
|
|
||||||
|
Activities can set metadata in write_file() using:
|
||||||
|
self.metadata['MyKey'] = "Something"
|
||||||
|
|
||||||
|
and retrieve metadata in read_file() using:
|
||||||
|
self.metadata.get('MyKey', 'aDefaultValue')
|
||||||
|
|
||||||
|
Note: Make sure your activity works properly if one or more of the
|
||||||
|
metadata items is missing. Never assume they will all be present.
|
||||||
|
"""
|
||||||
if self._jobject:
|
if self._jobject:
|
||||||
return self._jobject.metadata
|
return self._jobject.metadata
|
||||||
else:
|
else:
|
||||||
@ -625,12 +847,10 @@ class Activity(Window, gtk.Container):
|
|||||||
metadata = property(get_metadata, None)
|
metadata = property(get_metadata, None)
|
||||||
|
|
||||||
def get_bundle_name():
|
def get_bundle_name():
|
||||||
"""Return the bundle name for the current process' bundle
|
"""Return the bundle name for the current process' bundle"""
|
||||||
"""
|
|
||||||
return os.environ['SUGAR_BUNDLE_NAME']
|
return os.environ['SUGAR_BUNDLE_NAME']
|
||||||
|
|
||||||
def get_bundle_path():
|
def get_bundle_path():
|
||||||
"""Return the bundle path for the current process' bundle
|
"""Return the bundle path for the current process' bundle"""
|
||||||
"""
|
|
||||||
return os.environ['SUGAR_BUNDLE_PATH']
|
return os.environ['SUGAR_BUNDLE_PATH']
|
||||||
|
|
||||||
|
425
shell/controlpanel/control.py
Normal file
425
shell/controlpanel/control.py
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
# Copyright (C) 2007, One Laptop Per Child
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The language config is based on the system-config-language
|
||||||
|
# (http://fedoraproject.org/wiki/SystemConfig/language) tool
|
||||||
|
# and the timezone config on the system-config-date
|
||||||
|
# (http://fedoraproject.org/wiki/SystemConfig/date) tool.
|
||||||
|
# Parts of the code were reused.
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import string
|
||||||
|
import shutil
|
||||||
|
from gettext import gettext as _
|
||||||
|
|
||||||
|
from sugar import profile
|
||||||
|
from sugar.graphics.xocolor import XoColor
|
||||||
|
|
||||||
|
|
||||||
|
_COLORS = {'red': {'dark':'#b20008', 'medium':'#e6000a', 'light':'#ffadce'},
|
||||||
|
'orange': {'dark':'#9a5200', 'medium':'#c97e00', 'light':'#ffc169'},
|
||||||
|
'yellow': {'dark':'#807500', 'medium':'#be9e00', 'light':'#fffa00'},
|
||||||
|
'green': {'dark':'#008009', 'medium':'#00b20d', 'light':'#8bff7a'},
|
||||||
|
'blue': {'dark':'#00588c', 'medium':'#005fe4', 'light':'#bccdff'},
|
||||||
|
'purple': {'dark':'#5e008c', 'medium':'#7f00bf', 'light':'#d1a3ff'}
|
||||||
|
}
|
||||||
|
|
||||||
|
_MODIFIERS = ('dark', 'medium', 'light')
|
||||||
|
|
||||||
|
_TIMEZONE_CONFIG = '/etc/sysconfig/clock'
|
||||||
|
|
||||||
|
_LANGUAGES = {
|
||||||
|
'Afrikaans/South_Africa': ('af_ZA', 'lat0-sun16'),
|
||||||
|
'Albanian': ('sq_AL.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Algeria': ('ar_DZ.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Bahrain': ('ar_BH.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Egypt': ('ar_EG.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/India': ('ar_IN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Iraq': ('ar_IQ.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Jordan': ('ar_JO.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Kuwait': ('ar_KW.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Lebanon': ('ar_LB.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Libyan_Arab_Jamahiriya': ('ar_LY.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Morocco': ('ar_MA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Oman': ('ar_OM.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Qatar': ('ar_QA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Saudi_Arabia': ('ar_SA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Sudan': ('ar_SD.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Syrian_Arab_Republic': ('ar_SY.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Tunisia': ('ar_TN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/United_Arab_Emirates': ('ar_AE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Arabic/Yemen': ('ar_YE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Basque/Spain': ('eu_ES.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Belarusian': ('be_BY.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Bengali/BD': ('bn_BD.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Bengali/India': ('bn_IN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Bosnian/Bosnia_and_Herzegowina': ('bs_BA', 'lat2-sun16'),
|
||||||
|
'Breton/France': ('br_FR', 'lat0-sun16'),
|
||||||
|
'Bulgarian': ('bg_BG.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Catalan/Spain': ('ca_ES.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Chinese/Hong_Kong': ('zh_HK.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Chinese/P.R._of_China': ('zh_CN.UTF-8', 'lat0-sun16'),
|
||||||
|
'Chinese/Taiwan': ('zh_TW.UTF-8', 'lat0-sun16'),
|
||||||
|
'Cornish/Britain': ('kw_GB.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Croatian': ('hr_HR.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Czech': ('cs_CZ.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Danish': ('da_DK.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Dutch/Belgium': ('nl_BE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Dutch/Netherlands': ('nl_NL.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/Australia': ('en_AU.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/Botswana': ('en_BW.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/Canada': ('en_CA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/Denmark': ('en_DK.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/Great_Britain': ('en_GB.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/Hong_Kong': ('en_HK.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/India': ('en_IN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/Ireland': ('en_IE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/New_Zealand': ('en_NZ.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/Philippines': ('en_PH.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/Singapore': ('en_SG.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/South_Africa': ('en_ZA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/USA': ('en_US.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'English/Zimbabwe': ('en_ZW.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Estonian': ('et_EE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Faroese/Faroe_Islands': ('fo_FO.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Finnish': ('fi_FI.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'French/Belgium': ('fr_BE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'French/Canada': ('fr_CA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'French/France': ('fr_FR.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'French/Luxemburg': ('fr_LU.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'French/Switzerland': ('fr_CH.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Galician/Spain': ('gl_ES.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'German/Austria': ('de_AT.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'German/Belgium': ('de_BE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'German/Germany': ('de_DE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'German/Luxemburg': ('de_LU.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'German/Switzerland': ('de_CH.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Greek': ('el_GR.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Greenlandic/Greenland': ('kl_GL.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Gujarati/India': ('gu_IN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Hebrew/Israel': ('he_IL.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Hindi/India': ('hi_IN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Hungarian': ('hu_HU.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Icelandic': ('is_IS.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Indonesian': ('id_ID.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Irish': ('ga_IE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Italian/Italy': ('it_IT.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Italian/Switzerland': ('it_CH.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Japanese': ('ja_JP.UTF-8', 'lat0-sun16'),
|
||||||
|
'Korean/Republic_of_Korea': ('ko_KR.UTF-8', 'lat0-sun16'),
|
||||||
|
'Lao/Laos': ('lo_LA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Latvian/Latvia': ('lv_LV.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Lithuanian': ('lt_LT.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Macedonian': ('mk_MK.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Malay/Malaysia': ('ms_MY.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Maltese/malta': ('mt_MT.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Manx/Britain': ('gv_GB.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Marathi/India': ('mr_IN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Northern/Norway': ('se_NO', 'latarcyrheb-sun16'),
|
||||||
|
'Norwegian': ('nb_NO.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Norwegian,/Norway': ('nn_NO.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Occitan/France': ('oc_FR', 'lat0-sun16'),
|
||||||
|
'Oriya/India': ('or_IN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Persian/Iran': ('fa_IR.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Polish': ('pl_PL.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Portuguese/Brasil': ('pt_BR.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Portuguese/Portugal': ('pt_PT.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Punjabi/India': ('pa_IN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Romanian': ('ro_RO.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Russian': ('ru_RU.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Russian/Ukraine': ('ru_UA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Serbian': ('sr_CS.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Serbian/Latin': ('sr_CS.UTF-8@Latn', 'latarcyrheb-sun16'),
|
||||||
|
'Slovak': ('sk_SK.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Slovenian/Slovenia': ('sl_SI.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Argentina': ('es_AR.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Bolivia': ('es_BO.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Chile': ('es_CL.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Colombia': ('es_CO.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Costa_Rica': ('es_CR.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Dominican_Republic': ('es_DO.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/El_Salvador': ('es_SV.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Equador': ('es_EC.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Guatemala': ('es_GT.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Honduras': ('es_HN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Mexico': ('es_MX.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Nicaragua': ('es_NI.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Panama': ('es_PA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Paraguay': ('es_PY.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Peru': ('es_PE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Puerto_Rico': ('es_PR.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Spain': ('es_ES.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/USA': ('es_US.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Uruguay': ('es_UY.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Spanish/Venezuela': ('es_VE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Swedish/Finland': ('sv_FI.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Swedish/Sweden': ('sv_SE.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Tagalog/Philippines': ('tl_PH', 'lat0-sun16'),
|
||||||
|
'Tamil/India': ('ta_IN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Telugu/India': ('te_IN.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Thai': ('th_TH.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Turkish': ('tr_TR.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Ukrainian': ('uk_UA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Urdu/Pakistan': ('ur_PK', 'latarcyrheb-sun16'),
|
||||||
|
'Uzbek/Uzbekistan': ('uz_UZ', 'lat0-sun16'),
|
||||||
|
'Walloon/Belgium': ('wa_BE@euro', 'lat0-sun16'),
|
||||||
|
'Welsh/Great_Britain': ('cy_GB.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Xhosa/South_Africa': ('xh_ZA.UTF-8', 'latarcyrheb-sun16'),
|
||||||
|
'Zulu/South_Africa': ('zu_ZA.UTF-8', 'latarcyrheb-sun16')
|
||||||
|
}
|
||||||
|
|
||||||
|
_timezones = []
|
||||||
|
|
||||||
|
def _initialize():
|
||||||
|
_timezones = _read_zonetab()
|
||||||
|
j=0
|
||||||
|
for timezone in _timezones:
|
||||||
|
set_timezone.__doc__ += timezone+', '
|
||||||
|
j+=1
|
||||||
|
if j%3 == 0:
|
||||||
|
set_timezone.__doc__ += '\n'
|
||||||
|
|
||||||
|
if not os.access(_TIMEZONE_CONFIG, os.R_OK):
|
||||||
|
#Theres no /etc/sysconfig/clock file, so make one
|
||||||
|
fd = open(_TIMEZONE_CONFIG, 'w')
|
||||||
|
f.write(' The ZONE parameter is only evaluated by sugarcontrol.\n')
|
||||||
|
f.write('The timezone of the system' +
|
||||||
|
' is defined by the contents of /etc/localtime.\n')
|
||||||
|
f.write('ZONE="America/NEW_York"\n')
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
keys = _LANGUAGES.keys()
|
||||||
|
keys.sort()
|
||||||
|
i = 0
|
||||||
|
for key in keys:
|
||||||
|
set_language.__doc__ += key+', '
|
||||||
|
i+=1
|
||||||
|
if i%3 == 0:
|
||||||
|
set_language.__doc__ += '\n'
|
||||||
|
|
||||||
|
def get_jabber():
|
||||||
|
pro = profile.get_profile()
|
||||||
|
return pro.jabber_server
|
||||||
|
|
||||||
|
def print_jabber():
|
||||||
|
print get_jabber()
|
||||||
|
|
||||||
|
def set_jabber(server):
|
||||||
|
"""Set the jabber server
|
||||||
|
server : 'olpc.collabora.co.uk'
|
||||||
|
"""
|
||||||
|
pro = profile.get_profile()
|
||||||
|
pro.jabber_server = server
|
||||||
|
pro.save()
|
||||||
|
|
||||||
|
def get_color():
|
||||||
|
return profile.get_color()
|
||||||
|
|
||||||
|
def print_color():
|
||||||
|
print get_color().to_string()
|
||||||
|
|
||||||
|
def set_color(stroke, fill, modstroke='medium', modfill='medium'):
|
||||||
|
"""Set the system color.
|
||||||
|
fill : 'red, orange, yellow, blue, purple'
|
||||||
|
stroke : 'red, orange, yellow, blue, purple'
|
||||||
|
modstroke : 'dark, medium, light'
|
||||||
|
modfill : ''dark, medium, light'
|
||||||
|
"""
|
||||||
|
|
||||||
|
if modstroke not in _MODIFIERS or modfill not in _MODIFIERS:
|
||||||
|
print (_("Error in specified color modifiers."))
|
||||||
|
return
|
||||||
|
if stroke not in _COLORS or fill not in _COLORS:
|
||||||
|
print (_("Error in specified colors."))
|
||||||
|
return
|
||||||
|
|
||||||
|
if modstroke == modfill:
|
||||||
|
if modfill == medium:
|
||||||
|
modfill = light
|
||||||
|
else:
|
||||||
|
modfill = medium
|
||||||
|
|
||||||
|
color = _COLORS[stroke][modstroke] + ',' + _COLORS[fill][modfill]
|
||||||
|
pro = profile.get_profile()
|
||||||
|
pro.color = XoColor(color)
|
||||||
|
pro.save()
|
||||||
|
|
||||||
|
def get_nick():
|
||||||
|
return profile.get_nick_name()
|
||||||
|
|
||||||
|
def print_nick():
|
||||||
|
print get_nick()
|
||||||
|
|
||||||
|
def set_nick(nick):
|
||||||
|
"""Set the nickname.
|
||||||
|
nick : 'erikos'
|
||||||
|
"""
|
||||||
|
pro = profile.get_profile()
|
||||||
|
pro.nick_name = nick
|
||||||
|
pro.save()
|
||||||
|
|
||||||
|
def get_radio(state):
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def print_radio(self):
|
||||||
|
print get_radio()
|
||||||
|
|
||||||
|
def set_radio(state):
|
||||||
|
"""Turn Radio off
|
||||||
|
state : 'on/off'
|
||||||
|
"""
|
||||||
|
if state == 'on':
|
||||||
|
cmd = '/sbin/iwconfig eth0 txpower on'
|
||||||
|
handle = os.popen(cmd, 'r')
|
||||||
|
print string.join(handle.readlines())
|
||||||
|
handle.close()
|
||||||
|
elif state == 'off':
|
||||||
|
cmd = '/sbin/iwconfig eth0 txpower off'
|
||||||
|
handle = os.popen(cmd, 'r')
|
||||||
|
print string.join(handle.readlines())
|
||||||
|
handle.close()
|
||||||
|
else:
|
||||||
|
print (_("Error in specified radio argument use on/off."))
|
||||||
|
|
||||||
|
def get_timezone():
|
||||||
|
fd = open(_TIMEZONE_CONFIG, "r")
|
||||||
|
lines = fd.readlines()
|
||||||
|
fd.close()
|
||||||
|
try:
|
||||||
|
for line in lines:
|
||||||
|
line = string.strip(line)
|
||||||
|
if len (line) and line[0] == '#':
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
tokens = string.split(line, "=")
|
||||||
|
if tokens[0] == "ZONE":
|
||||||
|
timezone = string.replace(tokens[1], '"', '')
|
||||||
|
return timezone
|
||||||
|
except Exception, e:
|
||||||
|
print (_("get_timezone: %s") % e)
|
||||||
|
except Exception, e:
|
||||||
|
print (_("get_timezone: %s") % e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def print_timezone():
|
||||||
|
timezone = get_timezone()
|
||||||
|
if timezone is None:
|
||||||
|
print (_("Error in reading timezone"))
|
||||||
|
else:
|
||||||
|
print timezone
|
||||||
|
|
||||||
|
def set_timezone(timezone):
|
||||||
|
"""Set the system timezone
|
||||||
|
timezone :
|
||||||
|
"""
|
||||||
|
if timezone in _timezones:
|
||||||
|
fromfile = os.path.join("/usr/share/zoneinfo/", timezone)
|
||||||
|
try:
|
||||||
|
shutil.copyfile(fromfile, "/etc/localtime")
|
||||||
|
except OSError, (errno, msg):
|
||||||
|
print (_("Error copying timezone (from %s): %s")%(fromfile, msg))
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
os.chmod("/etc/localtime", 0644)
|
||||||
|
except OSError, (errno, msg):
|
||||||
|
print (_("Changing permission of timezone: %s") % (msg))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Write info to the /etc/sysconfig/clock file
|
||||||
|
fd = open(_TIMEZONE_CONFIG, "w")
|
||||||
|
fd.write('# The ZONE parameter is only evaluated by sugarcontrol.\n')
|
||||||
|
fd.write('# The timezone of the system ' +
|
||||||
|
'is defined by the contents of /etc/localtime.\n')
|
||||||
|
fd.write('ZONE="%s"\n' % timezone)
|
||||||
|
fd.close()
|
||||||
|
else:
|
||||||
|
print (_("Error timezone does not exist."))
|
||||||
|
|
||||||
|
def _read_zonetab(fn='/usr/share/zoneinfo/zone.tab'):
|
||||||
|
fd = open (fn, 'r')
|
||||||
|
lines = fd.readlines()
|
||||||
|
fd.close()
|
||||||
|
timezones = []
|
||||||
|
for line in lines:
|
||||||
|
if line.startswith('#'):
|
||||||
|
continue
|
||||||
|
line = line.split()
|
||||||
|
if len(line) > 1:
|
||||||
|
timezones.append(line[2])
|
||||||
|
timezones.sort()
|
||||||
|
return timezones
|
||||||
|
|
||||||
|
def _remove_encoding(lang):
|
||||||
|
if '.' in lang:
|
||||||
|
langBase = lang.split('.')
|
||||||
|
return langBase[0]
|
||||||
|
elif '@' in lang:
|
||||||
|
langBase = lang.split('@')
|
||||||
|
return langBase[0]
|
||||||
|
else:
|
||||||
|
return lang
|
||||||
|
|
||||||
|
def _writeI18N(lang, sysfont):
|
||||||
|
path = '/etc/sysconfig/i18n'
|
||||||
|
if os.access(path, os.R_OK) == 0:
|
||||||
|
print(_("Could not access %s")%path)
|
||||||
|
else:
|
||||||
|
fd = open(path, 'w')
|
||||||
|
fd.write('LANG="' + lang + '"\n')
|
||||||
|
fd.write('SYSFONT="' + sysfont + '"\n')
|
||||||
|
fd.close()
|
||||||
|
|
||||||
|
def get_language():
|
||||||
|
originalFile = None
|
||||||
|
path = '/etc/sysconfig/i18n'
|
||||||
|
if os.access(path, os.R_OK) == 0:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
fd = open(path, "r")
|
||||||
|
originalFile = fd.readlines()
|
||||||
|
fd.close()
|
||||||
|
|
||||||
|
lang = None
|
||||||
|
|
||||||
|
for line in originalFile:
|
||||||
|
if line[:5] == "LANG=":
|
||||||
|
lang = line[5:].replace('"', '')
|
||||||
|
lang = lang.strip()
|
||||||
|
|
||||||
|
if lang:
|
||||||
|
lang = _remove_encoding(lang)
|
||||||
|
else:
|
||||||
|
lang = "en_US"
|
||||||
|
return lang
|
||||||
|
|
||||||
|
def print_language():
|
||||||
|
print get_language()
|
||||||
|
|
||||||
|
def set_language(language):
|
||||||
|
"""Set the system language.
|
||||||
|
languages :
|
||||||
|
"""
|
||||||
|
if language in _LANGUAGES:
|
||||||
|
_writeI18N(_LANGUAGES[language][0], _LANGUAGES[language][1])
|
||||||
|
else:
|
||||||
|
print (_("Sorry I do not speak \'%s\'.")%language)
|
||||||
|
|
||||||
|
|
||||||
|
# inilialize the docstrings for the timezone and language
|
||||||
|
_initialize()
|
71
shell/controlpanel/sugar-control
Executable file
71
shell/controlpanel/sugar-control
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Copyright (C) 2007, One Laptop Per Child
|
||||||
|
#
|
||||||
|
# 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 getopt, sys
|
||||||
|
|
||||||
|
import control
|
||||||
|
|
||||||
|
def cmd_help():
|
||||||
|
print 'Usage: sugar-control [ option ] key [ args ... ] \n\
|
||||||
|
Control for the sugar environment. \n\
|
||||||
|
Options: \n\
|
||||||
|
-h, --help show this help message and exit \n\
|
||||||
|
-h key show information about this key \n\
|
||||||
|
-g key get the current value of the key \n\
|
||||||
|
-s key set the current value for the key \n\
|
||||||
|
'
|
||||||
|
|
||||||
|
def main():
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:], "h:s:g:", ["help"])
|
||||||
|
except getopt.GetoptError:
|
||||||
|
cmd_help()
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
output = None
|
||||||
|
verbose = False
|
||||||
|
|
||||||
|
for opt, key in opts:
|
||||||
|
if opt in ("-h"):
|
||||||
|
method = getattr(control, 'set_' + key, None)
|
||||||
|
if method is None:
|
||||||
|
cmd_help()
|
||||||
|
sys.exit()
|
||||||
|
else:
|
||||||
|
print method.__doc__
|
||||||
|
if opt in ("-g"):
|
||||||
|
method = getattr(control, 'print_' + key, None)
|
||||||
|
if method is None:
|
||||||
|
cmd_help()
|
||||||
|
sys.exit()
|
||||||
|
else:
|
||||||
|
method()
|
||||||
|
if opt in ("-s"):
|
||||||
|
method = getattr(control, 'set_' + key, None)
|
||||||
|
if method is None:
|
||||||
|
cmd_help()
|
||||||
|
sys.exit()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
method(*args)
|
||||||
|
except Exception, e:
|
||||||
|
print "sugar-control: %s"% e
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user