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) | ||||
| * Initial push for the sugar control panel (erikos) | ||||
| * #4358: pydoc strings for sugar.activity.Activity | ||||
| 
 | ||||
| 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. | ||||
| 
 | ||||
|    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. | ||||
| # | ||||
| @ -49,6 +73,11 @@ SCOPE_INVITE_ONLY = "invite"  # shouldn't be shown in UI, it's implicit when you | ||||
| SCOPE_NEIGHBORHOOD = "public" | ||||
| 
 | ||||
| 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): | ||||
|         gtk.Toolbar.__init__(self) | ||||
| 
 | ||||
| @ -169,6 +198,38 @@ class ActivityToolbar(gtk.Toolbar): | ||||
|         self._update_share() | ||||
| 
 | ||||
| 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): | ||||
|         gtk.Toolbar.__init__(self) | ||||
| 
 | ||||
| @ -198,6 +259,23 @@ class EditToolbar(gtk.Toolbar): | ||||
|         self.paste.show() | ||||
| 
 | ||||
| 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): | ||||
|         Toolbox.__init__(self) | ||||
|          | ||||
| @ -209,7 +287,71 @@ class ActivityToolbox(Toolbox): | ||||
|         return self._activity_toolbar | ||||
| 
 | ||||
| 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' | ||||
| 
 | ||||
|     __gsignals__ = { | ||||
| @ -248,6 +390,11 @@ class Activity(Window, gtk.Container): | ||||
|              | ||||
|             Creates an ActivityService (self._bus) servicing | ||||
|             this application. | ||||
|          | ||||
|         Usage:         | ||||
|             If your Activity implements __init__(), it should call | ||||
|             the base class __init()__ before doing Activity specific things. | ||||
|              | ||||
|         """ | ||||
|         Window.__init__(self) | ||||
| 
 | ||||
| @ -360,12 +507,25 @@ class Activity(Window, gtk.Container): | ||||
|             return self._max_participants | ||||
| 
 | ||||
|     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 | ||||
| 
 | ||||
|     def get_bundle_id(self): | ||||
|         """Returns the bundle_id from the activity.info file""" | ||||
|         return os.environ['SUGAR_BUNDLE_ID'] | ||||
| 
 | ||||
|     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) | ||||
|         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) | ||||
| 
 | ||||
|     def get_activity_root(self): | ||||
|         """ | ||||
|         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 | ||||
|         thus cannot go into the DataStore. | ||||
|         """Returns a path for saving Activity specific preferences, etc. | ||||
|          | ||||
|         Returns a path to the location in the filesystem where the activity can | ||||
|         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 \ | ||||
|            os.environ['SUGAR_ACTIVITY_ROOT']: | ||||
| @ -395,6 +562,17 @@ class Activity(Window, gtk.Container): | ||||
|         """ | ||||
|         Subclasses implement this method if they support resuming objects 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 | ||||
| 
 | ||||
| @ -402,6 +580,17 @@ class Activity(Window, gtk.Container): | ||||
|         """ | ||||
|         Subclasses implement this method if they support saving data to objects | ||||
|         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 | ||||
| 
 | ||||
| @ -466,7 +655,13 @@ class Activity(Window, gtk.Container): | ||||
|         self._preview = self._get_preview() | ||||
| 
 | ||||
|     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) | ||||
| 
 | ||||
| @ -507,6 +702,11 @@ class Activity(Window, gtk.Container): | ||||
|                     error_handler=self.__save_error_cb) | ||||
| 
 | ||||
|     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) | ||||
|         self._preview = self._get_preview() | ||||
|         self.save() | ||||
| @ -570,6 +770,12 @@ class Activity(Window, gtk.Container): | ||||
|                 logging.error('Cannot invite %s, no such buddy.' % 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) | ||||
| 
 | ||||
|         if (self._shared_activity is None | ||||
| @ -598,6 +804,11 @@ class Activity(Window, gtk.Container): | ||||
|         self._pservice.share_activity(self, private=private) | ||||
| 
 | ||||
|     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() | ||||
| 
 | ||||
|         if self._shared_activity: | ||||
| @ -617,6 +828,17 @@ class Activity(Window, gtk.Container): | ||||
|         return True | ||||
| 
 | ||||
|     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: | ||||
|             return self._jobject.metadata | ||||
|         else: | ||||
| @ -625,12 +847,10 @@ class Activity(Window, gtk.Container): | ||||
|     metadata = property(get_metadata, None) | ||||
| 
 | ||||
| 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'] | ||||
|      | ||||
| 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'] | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										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
	 Marco Pesenti Gritti
						Marco Pesenti Gritti