From 9a36a9f05ca6352cc53da0920491ff7451d87089 Mon Sep 17 00:00:00 2001 From: Simon Schampijer Date: Fri, 09 May 2008 17:03:20 +0000 Subject: controlpanel - modularize model --- diff --git a/bin/sugar-control-panel.in b/bin/sugar-control-panel.in index 922f95c..e70764b 100644 --- a/bin/sugar-control-panel.in +++ b/bin/sugar-control-panel.in @@ -17,10 +17,12 @@ import sys -sys.path.insert(0, '@prefix@/share/sugar/shell') +path = '@prefix@/share/sugar/shell' + +sys.path.insert(0, path) from controlpanel.cmd import main -main() +main(path) diff --git a/configure.ac b/configure.ac index a99fdf0..d6e8b12 100644 --- a/configure.ac +++ b/configure.ac @@ -43,6 +43,7 @@ data/Makefile service/Makefile src/Makefile src/controlpanel/Makefile +src/controlpanel/model/Makefile src/intro/Makefile src/hardware/Makefile src/view/Makefile diff --git a/src/controlpanel/Makefile.am b/src/controlpanel/Makefile.am index f89132c..d50559d 100644 --- a/src/controlpanel/Makefile.am +++ b/src/controlpanel/Makefile.am @@ -1,5 +1,4 @@ sugardir = $(pkgdatadir)/shell/controlpanel sugar_PYTHON = \ __init__.py \ - cmd.py \ - control.py + cmd.py diff --git a/src/controlpanel/cmd.py b/src/controlpanel/cmd.py index 24653b2..da89cda 100644 --- a/src/controlpanel/cmd.py +++ b/src/controlpanel/cmd.py @@ -1,4 +1,4 @@ -# Copyright (C) 2007, One Laptop Per Child +# Copyright (C) 2007, 2008 One Laptop Per Child # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,11 +16,12 @@ import sys import getopt +import os from gettext import gettext as _ -from controlpanel import control - + def cmd_help(): + '''Print the help for to the screen''' print _('Usage: sugar-control-panel [ option ] key [ args ... ] \n\ Control for the sugar environment. \n\ Options: \n\ @@ -31,7 +32,28 @@ def cmd_help(): -s key set the current value for the key \n\ ') -def main(): +def note_restart(): + '''Instructions how to restart sugar''' + print _('To apply your changes you have to restart sugar.\n' + + 'Hit ctrl+alt+erase on the keyboard to trigger a restart.') + +def load_modules(path): + '''Build a list of pointers to available modules in the model directory + and load them. + ''' + subpath = ['controlpanel', 'model'] + names = os.listdir(os.path.join(path, '/'.join(subpath))) + + modules = [] + for name in names: + if name.endswith('.py') and name != '__init__.py': + tmp = name.strip('.py') + mod = __import__('.'.join(subpath) + '.' + + tmp, globals(), locals(), [tmp]) + modules.append(mod) + return modules + +def main(path): try: opts, args = getopt.getopt(sys.argv[1:], "h:s:g:l", []) except getopt.GetoptError: @@ -41,37 +63,49 @@ def main(): if not opts: cmd_help() sys.exit() - + + modules = load_modules(path) + for opt, key in opts: - if opt in ("-h"): - method = getattr(control, 'set_' + key, None) - if method is None: - print _("sugar-control-panel: key=%s not an available option" - % key) - sys.exit() - else: - print method.__doc__ - if opt in ("-l"): - elems = dir(control) - for elem in elems: - if elem.startswith('set_'): - print elem[4:] + if opt in ("-h"): + for module in modules: + method = getattr(module, 'set_' + key, None) + if method: + print method.__doc__ + sys.exit() + print _("sugar-control-panel: key=%s not an available option" + % key) + if opt in ("-l"): + for module in modules: + methods = dir(module) + print '%s:' % module.__name__.split('.')[-1] + for method in methods: + if method.startswith('get_'): + print ' %s' % method[4:] if opt in ("-g"): - method = getattr(control, 'print_' + key, None) - if method is None: - print _("sugar-control-panel: key=%s not an available option" - % key) - sys.exit() - else: - method() + for module in modules: + method = getattr(module, 'print_' + key, None) + if method: + try: + method() + except Exception, detail: + print _("sugar-control-panel: %s" + % detail) + sys.exit() + print _("sugar-control-panel: key=%s not an available option" + % key) if opt in ("-s"): - method = getattr(control, 'set_' + key, None) - if method is None: - print _("sugar-control-panel: key=%s not an available option" - % key) - sys.exit() - else: - try: - method(*args) - except Exception, e: - print _("sugar-control-panel: %s"% e) + for module in modules: + method = getattr(module, 'set_' + key, None) + if method: + note = 0 + try: + note = method(*args) + except Exception, detail: + print _("sugar-control-panel: %s" + % detail) + if note == 'RESTART': + note_restart() + sys.exit() + print _("sugar-control-panel: key=%s not an available option" + % key) diff --git a/src/controlpanel/model/Makefile.am b/src/controlpanel/model/Makefile.am new file mode 100644 index 0000000..4bc3264 --- /dev/null +++ b/src/controlpanel/model/Makefile.am @@ -0,0 +1,8 @@ +sugardir = $(pkgdatadir)/shell/controlpanel/model +sugar_PYTHON = \ + __init__.py \ + network.py \ + aboutme.py \ + language.py \ + timezone.py \ + aboutxo.py diff --git a/src/controlpanel/model/__init__.py b/src/controlpanel/model/__init__.py new file mode 100644 index 0000000..2b0f269 --- /dev/null +++ b/src/controlpanel/model/__init__.py @@ -0,0 +1,17 @@ +# Copyright (C) 2008 One Laptop Per Child +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + diff --git a/src/controlpanel/model/aboutme.py b/src/controlpanel/model/aboutme.py new file mode 100644 index 0000000..98726c6 --- /dev/null +++ b/src/controlpanel/model/aboutme.py @@ -0,0 +1,108 @@ +# Copyright (C) 2008 One Laptop Per Child +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +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') + +def get_nick(): + return profile.get_nick_name() + +def print_nick(): + print get_nick() + +def set_nick(nick): + """Set the nickname. + nick : e.g. 'walter' + """ + if not nick: + raise ValueError(_("You must enter a name.")) + pro = profile.get_profile() + pro.nick_name = nick + pro.save() + return 'RESTART' + +def get_color(): + return profile.get_color() + +def print_color(): + color = get_color().to_string() + tmp = color.split(',') + + stroke = None + fill = None + for color in _COLORS: + for hue in _COLORS[color]: + if _COLORS[color][hue] == tmp[0]: + stroke = (color, hue) + if _COLORS[color][hue] == tmp[1]: + fill = (color, hue) + + if stroke is not None: + print 'stroke: color=%s hue=%s' % (stroke[0], stroke[1]) + else: + print 'stroke: %s' % (tmp[0]) + if fill is not None: + print 'fill: color=%s hue=%s' % (fill[0], fill[1]) + else: + print 'fill: %s' % (tmp[1]) + +def set_color(stroke, fill, modstroke='medium', modfill='medium'): + """Set the system color by setting a fill and stroke color. + fill : [red, orange, yellow, blue, purple] + stroke : [red, orange, yellow, blue, purple] + hue stroke : [dark, medium, light] (optional) + hue fill : [dark, medium, light] (optional) + """ + + 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() + return "RESTART" + +def set_color_xo(color): + """Set a color with an XoColor + """ + pro = profile.get_profile() + pro.color = color + pro.save() + return "RESTART" diff --git a/src/controlpanel/model/aboutxo.py b/src/controlpanel/model/aboutxo.py new file mode 100644 index 0000000..1a63f32 --- /dev/null +++ b/src/controlpanel/model/aboutxo.py @@ -0,0 +1,22 @@ +# Copyright (C) 2008 One Laptop Per Child +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +def get_aboutxo(): + return 'TODO: make info available here as well for the cml interface' + +def print_aboutxo(): + print get_aboutxo() diff --git a/src/controlpanel/model/language.py b/src/controlpanel/model/language.py new file mode 100644 index 0000000..49bac07 --- /dev/null +++ b/src/controlpanel/model/language.py @@ -0,0 +1,123 @@ +# Copyright (C) 2007, 2008 One Laptop Per Child +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# +# The language config is based on the system-config-language +# (http://fedoraproject.org/wiki/SystemConfig/language) tool +# Parts of the code were reused. +# + +import os +from gettext import gettext as _ +import subprocess + +def readlocale(): + fdp = subprocess.Popen(['locale', '-av'], stdout=subprocess.PIPE) + lines = fdp.stdout.read().split('\n') + locales = [] + try: + for line in lines: + if line.find('locale:') != -1: + loc = line.lstrip('locale: ') + loc = loc.split('archive:')[0].strip() + elif line.find('language |') != -1: + lang = line.lstrip('language |') + elif line.find('territory |') != -1: + ter = line.lstrip('territory |') + if loc.endswith('utf8') and len(lang): + locales.append((lang, ter, loc)) + except Exception, error: + print "Error reading locale: %s" % error + locales.sort() + return locales + +def _initialize(): + languages = readlocale() + set_language.__doc__ += '\n' + for lang in languages: + set_language.__doc__ += '%s \n' % (lang[0].replace(' ', '_') + '/' + + lang[1].replace(' ', '_')) + +def _write_i18n(lang): + path = os.path.join(os.environ.get("HOME"), '.i18n') + if os.access(path, os.W_OK) == 0: + print(_("Could not access %s. Create standard settings.") % path) + fd = open(path, 'w') + fd.write('LANG="en_US.utf8"\n') + fd.close() + else: + fd = open(path, 'r') + lines = fd.readlines() + fd.close() + for i in range(len(lines)): + if lines[i][:5] == "LANG=": + lines[i] = 'LANG="' + lang + '"\n' + fd = open(path, 'w') + fd.writelines(lines) + fd.close() + +def get_language(): + path = os.path.join(os.environ.get("HOME"), '.i18n') + if os.access(path, os.R_OK) == 0: + print(_("Could not access %s. Create standard settings.") % path) + fd = open(path, 'w') + default = 'en_US.utf8' + fd.write('LANG="%s"\n' % default) + fd.close() + return default + + fd = open(path, "r") + lines = fd.readlines() + fd.close() + + lang = None + + for line in lines: + if line[:5] == "LANG=": + lang = line[5:].replace('"', '') + lang = lang.strip() + + return lang + +def print_language(): + code = get_language() + + languages = readlocale() + for lang in languages: + if lang[2] == code: + print lang[0].replace(' ', '_') + '/' + lang[1].replace(' ', '_') + return + print (_("Language for code=%s could not be determined.") % code) + +def set_language(language): + """Set the system language. + languages : + """ + if language.endswith('utf8'): + _write_i18n(language) + return "RESTART" + else: + languages = readlocale() + for lang in languages: + code = lang[0].replace(' ', '_') + '/' + lang[1].replace(' ', '_') + if code == language: + _write_i18n(lang[2]) + return "RESTART" + print (_("Sorry I do not speak \'%s\'.") % language) + +# inilialize the docstrings for the language +_initialize() + diff --git a/src/controlpanel/model/network.py b/src/controlpanel/model/network.py new file mode 100644 index 0000000..6190a4d --- /dev/null +++ b/src/controlpanel/model/network.py @@ -0,0 +1,86 @@ +# Copyright (C) 2008 One Laptop Per Child +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +import dbus +from gettext import gettext as _ + +from sugar import profile + +NM_SERVICE_NAME = 'org.freedesktop.NetworkManager' +NM_SERVICE_PATH = '/org/freedesktop/NetworkManager' +NM_SERVICE_IFACE = 'org.freedesktop.NetworkManager' +NM_ASLEEP = 1 + +KEYWORDS = ['network', 'jabber', 'radio', 'server'] + +class ReadError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + +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 : e.g. 'olpc.collabora.co.uk' + """ + if not server: + raise ValueError(_("You must enter a server.")) + pro = profile.get_profile() + pro.jabber_server = server + pro.jabber_registered = False + pro.save() + return "RESTART" + +def get_radio(): + bus = dbus.SystemBus() + proxy = bus.get_object(NM_SERVICE_NAME, NM_SERVICE_PATH) + nm = dbus.Interface(proxy, NM_SERVICE_IFACE) + state = nm.getWirelessEnabled() + if state == 0: + return _('off') + elif state == 1: + return _('on') + else: + raise ReadError(_('State is unknown.')) + +def print_radio(): + print get_radio() + +def set_radio(state): + """Turn Radio 'on' or 'off' + state : 'on/off' + """ + if state == 'on': + bus = dbus.SystemBus() + proxy = bus.get_object(NM_SERVICE_NAME, NM_SERVICE_PATH) + nm = dbus.Interface(proxy, NM_SERVICE_IFACE) + nm.setWirelessEnabled(True) + elif state == 'off': + bus = dbus.SystemBus() + proxy = bus.get_object(NM_SERVICE_NAME, NM_SERVICE_PATH) + nm = dbus.Interface(proxy, NM_SERVICE_IFACE) + nm.setWirelessEnabled(False) + else: + raise ValueError(_("Error in specified radio argument use on/off.")) + diff --git a/src/controlpanel/model/timezone.py b/src/controlpanel/model/timezone.py new file mode 100644 index 0000000..5ebb9df --- /dev/null +++ b/src/controlpanel/model/timezone.py @@ -0,0 +1,80 @@ +# Copyright (C) 2007, 2008 One Laptop Per Child +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# +# The timezone config is based on the system-config-date +# (http://fedoraproject.org/wiki/SystemConfig/date) tool. +# Parts of the code were reused. +# + +import os +from gettext import gettext as _ + +from sugar import profile + +def _initialize(): + '''Initialize the docstring of the set function''' + timezones = read_timezones() + for timezone in timezones: + set_timezone.__doc__ += timezone + '\n' + +def read_timezones(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() + + for offset in xrange(-14, 13): + if offset < 0: + tz = 'GMT%d' % offset + elif offset > 0: + tz = 'GMT+%d' % offset + else: + tz = 'GMT' + timezones.append(tz) + return timezones + +def get_timezone(): + pro = profile.get_profile() + return pro.timezone + +def print_timezone(): + print get_timezone() + +def set_timezone(timezone): + """Set the system timezone + server : e.g. 'America/Los_Angeles' + """ + timezones = read_timezones() + if timezone in timezones: + os.environ['TZ'] = timezone + pro = profile.get_profile() + pro.timezone = timezone + pro.save() + else: + raise ValueError(_("Error timezone does not exist.")) + return 'RESTART' + +# inilialize the docstrings for the timezone +_initialize() + diff --git a/src/main.py b/src/main.py index 76d753f..3a88a37 100644 --- a/src/main.py +++ b/src/main.py @@ -110,6 +110,9 @@ def main(): win.show_all() gtk.main() + # set timezone + os.environ['TZ'] = get_profile().timezone + if os.environ.has_key("SUGAR_TP_DEBUG"): # Allow the user time to start up telepathy connection managers # using the Sugar DBus bus address -- cgit v0.9.1