diff options
Diffstat (limited to 'extensions')
36 files changed, 728 insertions, 553 deletions
diff --git a/extensions/cpsection/aboutcomputer/__init__.py b/extensions/cpsection/aboutcomputer/__init__.py index ceb515a..faf814d 100644 --- a/extensions/cpsection/aboutcomputer/__init__.py +++ b/extensions/cpsection/aboutcomputer/__init__.py @@ -19,4 +19,3 @@ from gettext import gettext as _ CLASS = 'AboutComputer' ICON = 'module-about_my_computer' TITLE = _('About my Computer') - diff --git a/extensions/cpsection/aboutcomputer/model.py b/extensions/cpsection/aboutcomputer/model.py index 898d79c..3219dd1 100644 --- a/extensions/cpsection/aboutcomputer/model.py +++ b/extensions/cpsection/aboutcomputer/model.py @@ -22,31 +22,45 @@ import subprocess from gettext import gettext as _ import errno +import dbus + from jarabe import config + +_NM_SERVICE = 'org.freedesktop.NetworkManager' +_NM_PATH = '/org/freedesktop/NetworkManager' +_NM_IFACE = 'org.freedesktop.NetworkManager' +_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' +_NM_DEVICE_TYPE_WIFI = 2 + _logger = logging.getLogger('ControlPanel - AboutComputer') _not_available = _('Not available') + def get_aboutcomputer(): msg = 'Serial Number: %s \nBuild Number: %s \nFirmware Number: %s \n' \ % (get_serial_number(), get_build_number(), get_firmware_number()) return msg + def print_aboutcomputer(): print get_aboutcomputer() + def get_serial_number(): serial_no = _read_file('/ofw/serial-number') if serial_no is None: serial_no = _not_available return serial_no - + + def print_serial_number(): serial_no = get_serial_number() if serial_no is None: serial_no = _not_available print serial_no + def get_build_number(): build_no = _read_file('/boot/olpc_build') @@ -68,38 +82,88 @@ def get_build_number(): return build_no + def print_build_number(): print get_build_number() -def get_firmware_number(): + +def get_firmware_number(): firmware_no = _read_file('/ofw/openprom/model') if firmware_no is None: firmware_no = _not_available else: - firmware_no = re.split(" +", firmware_no) + firmware_no = re.split(' +', firmware_no) if len(firmware_no) == 3: firmware_no = firmware_no[1] - return firmware_no + return firmware_no + -def print_firmware_number(): +def print_firmware_number(): print get_firmware_number() -def get_wireless_firmware(): + +def _get_wireless_interfaces(): try: - info = subprocess.Popen(["/usr/sbin/ethtool", "-i", "eth0"], - stdout=subprocess.PIPE).stdout.readlines() - except OSError: + bus = dbus.SystemBus() + manager_object = bus.get_object(_NM_SERVICE, _NM_PATH) + network_manager = dbus.Interface(manager_object, _NM_IFACE) + except dbus.DBusException: + _logger.warning('Cannot connect to NetworkManager, falling back to' + ' static list of devices') + return ['wlan0', 'eth0'] + + interfaces = [] + for device_path in network_manager.GetDevices(): + device_object = bus.get_object(_NM_SERVICE, device_path) + properties = dbus.Interface(device_object, + 'org.freedesktop.DBus.Properties') + device_type = properties.Get(_NM_DEVICE_IFACE, 'DeviceType') + if device_type != _NM_DEVICE_TYPE_WIFI: + continue + + interfaces.append(properties.Get(_NM_DEVICE_IFACE, 'Interface')) + + return interfaces + + +def get_wireless_firmware(): + environment = os.environ.copy() + environment['PATH'] = '%s:/usr/sbin' % (environment['PATH'], ) + firmware_info = {} + for interface in _get_wireless_interfaces(): + try: + output = subprocess.Popen(['ethtool', '-i', interface], + stdout=subprocess.PIPE, + env=environment).stdout.readlines() + except OSError: + _logger.exception('Error running ethtool for %r', interface) + continue + + try: + version = ([line for line in output + if line.startswith('firmware')][0].split()[1]) + except IndexError: + _logger.exception('Error parsing ethtool output for %r', + interface) + continue + + firmware_info[interface] = version + + if not firmware_info: return _not_available - try: - wireless_firmware = [line for line in info - if line.startswith('firmware')][0].split()[1] - except IndexError: - wireless_firmware = _not_available - return wireless_firmware + + if len(firmware_info) == 1: + return firmware_info.values()[0] + + return ', '.join([_('%(interface)s: %(version)s') % + {'interface': interface, 'version': version} + for interface, version in firmware_info.items()]) + def print_wireless_firmware(): print get_wireless_firmware() + def _read_file(path): if os.access(path, os.R_OK) == 0: return None @@ -114,17 +178,18 @@ def _read_file(path): _logger.debug('No information in file or directory: %s', path) return None + def get_license(): license_file = os.path.join(config.data_path, 'GPLv2') lang = os.environ['LANG'] - if lang.endswith("UTF-8"): + if lang.endswith('UTF-8'): lang = lang[:-6] - try_file = license_file + "." + lang + try_file = license_file + '.' + lang if os.path.isfile(try_file): license_file = try_file else: - try_file = license_file + "." + lang.split("_")[0] + try_file = license_file + '.' + lang.split('_')[0] if os.path.isfile(try_file): license_file = try_file diff --git a/extensions/cpsection/aboutcomputer/view.py b/extensions/cpsection/aboutcomputer/view.py index b6ff43f..e5f2f32 100644 --- a/extensions/cpsection/aboutcomputer/view.py +++ b/extensions/cpsection/aboutcomputer/view.py @@ -26,6 +26,7 @@ from sugar.graphics import style from jarabe import config from jarabe.controlpanel.sectionview import SectionView + class AboutComputer(SectionView): def __init__(self, model, alerts=None): SectionView.__init__(self) @@ -68,7 +69,7 @@ class AboutComputer(SectionView): box_identity = gtk.HBox(spacing=style.DEFAULT_SPACING) label_serial = gtk.Label(_('Serial Number:')) label_serial.set_alignment(1, 0) - label_serial.modify_fg(gtk.STATE_NORMAL, + label_serial.modify_fg(gtk.STATE_NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) box_identity.pack_start(label_serial, expand=False) self._group.add_widget(label_serial) @@ -83,7 +84,7 @@ class AboutComputer(SectionView): self._vbox.pack_start(vbox_identity, expand=False) vbox_identity.show() - def _setup_software(self): + def _setup_software(self): separator_software = gtk.HSeparator() self._vbox.pack_start(separator_software, expand=False) separator_software.show() @@ -99,7 +100,7 @@ class AboutComputer(SectionView): box_build = gtk.HBox(spacing=style.DEFAULT_SPACING) label_build = gtk.Label(_('Build:')) label_build.set_alignment(1, 0) - label_build.modify_fg(gtk.STATE_NORMAL, + label_build.modify_fg(gtk.STATE_NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) box_build.pack_start(label_build, expand=False) self._group.add_widget(label_build) @@ -130,7 +131,7 @@ class AboutComputer(SectionView): box_firmware = gtk.HBox(spacing=style.DEFAULT_SPACING) label_firmware = gtk.Label(_('Firmware:')) label_firmware.set_alignment(1, 0) - label_firmware.modify_fg(gtk.STATE_NORMAL, + label_firmware.modify_fg(gtk.STATE_NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) box_firmware.pack_start(label_firmware, expand=False) self._group.add_widget(label_firmware) @@ -174,30 +175,30 @@ class AboutComputer(SectionView): vbox_copyright.set_border_width(style.DEFAULT_SPACING * 2) vbox_copyright.set_spacing(style.DEFAULT_SPACING) - label_copyright = gtk.Label("© 2006-2010 One Laptop per Child " - "Association Inc, Sugar Labs Inc, " - "Red Hat Inc, Collabora Ltd " - "and Contributors.") + copyright_text = '© 2006-2011 One Laptop per Child Association Inc,' \ + ' Sugar Labs Inc, Red Hat Inc, Collabora Ltd and' \ + ' Contributors.' + label_copyright = gtk.Label(copyright_text) label_copyright.set_alignment(0, 0) label_copyright.set_size_request(gtk.gdk.screen_width() / 2, -1) label_copyright.set_line_wrap(True) label_copyright.show() vbox_copyright.pack_start(label_copyright, expand=False) - label_info = gtk.Label(_("Sugar is the graphical user interface that " - "you are looking at. Sugar is free software, " - "covered by the GNU General Public License, " - "and you are welcome to change it and/or " - "distribute copies of it under certain " - "conditions described therein.")) + info_text = _('Sugar is the graphical user interface that you are' + ' looking at. Sugar is free software, covered by the' + ' GNU General Public License, and you are welcome to' + ' change it and/or distribute copies of it under' + ' certain conditions described therein.') + label_info = gtk.Label(info_text) label_info.set_alignment(0, 0) label_info.set_line_wrap(True) label_info.set_size_request(gtk.gdk.screen_width() / 2, -1) label_info.show() vbox_copyright.pack_start(label_info, expand=False) - expander = gtk.Expander(_("Full license:")) - expander.connect("notify::expanded", self.license_expander_cb) + expander = gtk.Expander(_('Full license:')) + expander.connect('notify::expanded', self.license_expander_cb) expander.show() vbox_copyright.pack_start(expander, expand=True) diff --git a/extensions/cpsection/aboutme/__init__.py b/extensions/cpsection/aboutme/__init__.py index 98843e1..7ded428 100644 --- a/extensions/cpsection/aboutme/__init__.py +++ b/extensions/cpsection/aboutme/__init__.py @@ -24,5 +24,3 @@ ICON = 'module-about_me' TITLE = _('About Me') client = gconf.client_get_default() COLOR = XoColor(client.get_string('/desktop/sugar/user/color')) - - diff --git a/extensions/cpsection/aboutme/model.py b/extensions/cpsection/aboutme/model.py index 8500799..fb4c2f1 100644 --- a/extensions/cpsection/aboutme/model.py +++ b/extensions/cpsection/aboutme/model.py @@ -18,38 +18,45 @@ from gettext import gettext as _ import gconf -_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'} - } + +_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(): client = gconf.client_get_default() - return client.get_string("/desktop/sugar/user/nick") + return client.get_string('/desktop/sugar/user/nick') + 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.")) + raise ValueError(_('You must enter a name.')) if not isinstance(nick, unicode): nick = unicode(nick, 'utf-8') client = gconf.client_get_default() - client.set_string("/desktop/sugar/user/nick", nick) + client.set_string('/desktop/sugar/user/nick', nick) return 1 + def get_color(): client = gconf.client_get_default() - return client.get_string("/desktop/sugar/user/color") + return client.get_string('/desktop/sugar/user/color') + def print_color(): color_string = get_color() @@ -64,16 +71,17 @@ def print_color(): if _COLORS[color][hue] == tmp[1]: fill_tuple = (color, hue) - if stroke_tuple is not None: - print _('stroke: color=%s hue=%s') % (stroke_tuple[0], + if stroke_tuple is not None: + print _('stroke: color=%s hue=%s') % (stroke_tuple[0], stroke_tuple[1]) else: - print _('stroke: %s') % (tmp[0]) - if fill_tuple is not None: + print _('stroke: %s') % (tmp[0]) + if fill_tuple is not None: print _('fill: color=%s hue=%s') % (fill_tuple[0], fill_tuple[1]) else: print _('fill: %s') % (tmp[1]) - + + def set_color(stroke, fill, stroke_modifier='medium', fill_modifier='medium'): """Set the system color by setting a fill and stroke color. fill : [red, orange, yellow, blue, green, purple] @@ -81,35 +89,37 @@ def set_color(stroke, fill, stroke_modifier='medium', fill_modifier='medium'): hue stroke : [dark, medium, light] (optional) hue fill : [dark, medium, light] (optional) """ - + if stroke_modifier not in _MODIFIERS or fill_modifier not in _MODIFIERS: - print (_("Error in specified color modifiers.")) + print (_('Error in specified color modifiers.')) return if stroke not in _COLORS or fill not in _COLORS: - print (_("Error in specified colors.")) + print (_('Error in specified colors.')) return - + if stroke_modifier == fill_modifier: if fill_modifier == 'medium': fill_modifier = 'light' else: fill_modifier = 'medium' - + color = _COLORS[stroke][stroke_modifier] + ',' \ + _COLORS[fill][fill_modifier] client = gconf.client_get_default() - client.set_string("/desktop/sugar/user/color", color) + client.set_string('/desktop/sugar/user/color', color) return 1 + def get_color_xo(): client = gconf.client_get_default() - return client.get_string("/desktop/sugar/user/color") + return client.get_string('/desktop/sugar/user/color') + def set_color_xo(color): - """Set a color with an XoColor + """Set a color with an XoColor This method is used by the graphical user interface """ client = gconf.client_get_default() - client.set_string("/desktop/sugar/user/color", color) + client.set_string('/desktop/sugar/user/color', color) return 1 diff --git a/extensions/cpsection/aboutme/view.py b/extensions/cpsection/aboutme/view.py index 95314a1..84daec7 100644 --- a/extensions/cpsection/aboutme/view.py +++ b/extensions/cpsection/aboutme/view.py @@ -35,12 +35,12 @@ def _get_next_stroke_color(color): as color. """ current_index = _get_current_index(color) if current_index == -1: - return "%s,%s" % (color.stroke, color.fill) + return '%s,%s' % (color.stroke, color.fill) next_index = _next_index(current_index) while(colors[next_index][_FILL_COLOR] != \ colors[current_index][_FILL_COLOR]): next_index = _next_index(next_index) - return "%s,%s" % (colors[next_index][_STROKE_COLOR], + return '%s,%s' % (colors[next_index][_STROKE_COLOR], colors[next_index][_FILL_COLOR]) @@ -49,12 +49,12 @@ def _get_previous_stroke_color(color): as color. """ current_index = _get_current_index(color) if current_index == -1: - return "%s,%s" % (color.stroke, color.fill) + return '%s,%s' % (color.stroke, color.fill) previous_index = _previous_index(current_index) while (colors[previous_index][_FILL_COLOR] != \ colors[current_index][_FILL_COLOR]): previous_index = _previous_index(previous_index) - return "%s,%s" % (colors[previous_index][_STROKE_COLOR], + return '%s,%s' % (colors[previous_index][_STROKE_COLOR], colors[previous_index][_FILL_COLOR]) @@ -63,12 +63,12 @@ def _get_next_fill_color(color): as color. """ current_index = _get_current_index(color) if current_index == -1: - return "%s,%s" % (color.stroke, color.fill) + return '%s,%s' % (color.stroke, color.fill) next_index = _next_index(current_index) while (colors[next_index][_STROKE_COLOR] != \ colors[current_index][_STROKE_COLOR]): next_index = _next_index(next_index) - return "%s,%s" % (colors[next_index][_STROKE_COLOR], + return '%s,%s' % (colors[next_index][_STROKE_COLOR], colors[next_index][_FILL_COLOR]) @@ -77,12 +77,12 @@ def _get_previous_fill_color(color): as color. """ current_index = _get_current_index(color) if current_index == -1: - return "%s,%s" % (color.stroke, color.fill) + return '%s,%s' % (color.stroke, color.fill) previous_index = _previous_index(current_index) while (colors[previous_index][_STROKE_COLOR] != \ colors[current_index][_STROKE_COLOR]): previous_index = _previous_index(previous_index) - return "%s,%s" % (colors[previous_index][_STROKE_COLOR], + return '%s,%s' % (colors[previous_index][_STROKE_COLOR], colors[previous_index][_FILL_COLOR]) @@ -96,7 +96,7 @@ def _next_index(current_index): def _previous_index(current_index): previous_index = current_index - 1 if previous_index < 0: - previous_index = len(colors)-1 + previous_index = len(colors) - 1 return previous_index @@ -112,7 +112,7 @@ _PREVIOUS_STROKE_COLOR = 4 class EventIcon(gtk.EventBox): - __gtype_name__ = "SugarEventIcon" + __gtype_name__ = 'SugarEventIcon' def __init__(self, **kwargs): gtk.EventBox.__init__(self) @@ -131,7 +131,7 @@ class ColorPicker(EventIcon): __gsignals__ = { 'color-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([object])) + ([object])), } def __init__(self, picker): @@ -184,12 +184,12 @@ class AboutMe(SectionView): self._color_alert = None self._pickers = { - _PREVIOUS_FILL_COLOR: ColorPicker(_PREVIOUS_FILL_COLOR), - _NEXT_FILL_COLOR: ColorPicker(_NEXT_FILL_COLOR), - _CURRENT_COLOR: ColorPicker(_CURRENT_COLOR), - _NEXT_STROKE_COLOR: ColorPicker(_NEXT_STROKE_COLOR), - _PREVIOUS_STROKE_COLOR: ColorPicker(_PREVIOUS_STROKE_COLOR) - } + _PREVIOUS_FILL_COLOR: ColorPicker(_PREVIOUS_FILL_COLOR), + _NEXT_FILL_COLOR: ColorPicker(_NEXT_FILL_COLOR), + _CURRENT_COLOR: ColorPicker(_CURRENT_COLOR), + _NEXT_STROKE_COLOR: ColorPicker(_NEXT_STROKE_COLOR), + _PREVIOUS_STROKE_COLOR: ColorPicker(_PREVIOUS_STROKE_COLOR), + } self._setup_color() initial_color = XoColor(self._model.get_color_xo()) diff --git a/extensions/cpsection/datetime/model.py b/extensions/cpsection/datetime/model.py index 76064e4..84e1259 100644 --- a/extensions/cpsection/datetime/model.py +++ b/extensions/cpsection/datetime/model.py @@ -26,18 +26,20 @@ import gconf _zone_tab = '/usr/share/zoneinfo/zone.tab' + def _initialize(): - '''Initialize the docstring of the set function''' + """Initialize the docstring of the set function""" if set_timezone.__doc__ is None: # when running under 'python -OO', all __doc__ fields are None, # so += would fail -- and this function would be unnecessary anyway. return - timezones = read_all_timezones() + timezones = read_all_timezones() for timezone in timezones: - set_timezone.__doc__ += timezone + '\n' - + set_timezone.__doc__ += timezone + '\n' + + def read_all_timezones(fn=_zone_tab): - fd = open (fn, 'r') + fd = open(fn, 'r') lines = fd.readlines() fd.close() timezones = [] @@ -48,7 +50,7 @@ def read_all_timezones(fn=_zone_tab): if len(line) > 1: timezones.append(line[2]) timezones.sort() - + for offset in xrange(-12, 13): if offset < 0: tz = 'GMT%d' % offset @@ -56,7 +58,7 @@ def read_all_timezones(fn=_zone_tab): tz = 'GMT+%d' % offset else: tz = 'GMT' - timezones.append(tz) + timezones.append(tz) for offset in xrange(-12, 13): if offset < 0: tz = 'UTC%d' % offset @@ -64,16 +66,19 @@ def read_all_timezones(fn=_zone_tab): tz = 'UTC+%d' % offset else: tz = 'UTC' - timezones.append(tz) + timezones.append(tz) return timezones + def get_timezone(): client = gconf.client_get_default() return client.get_string('/desktop/sugar/date/timezone') + def print_timezone(): print get_timezone() + def set_timezone(timezone): """Set the system timezone timezone : e.g. 'America/Los_Angeles' @@ -84,9 +89,8 @@ def set_timezone(timezone): client = gconf.client_get_default() client.set_string('/desktop/sugar/date/timezone', timezone) else: - raise ValueError(_("Error timezone does not exist.")) + raise ValueError(_('Error timezone does not exist.')) return 1 -# inilialize the docstrings for the timezone +# inilialize the docstrings for the timezone _initialize() - diff --git a/extensions/cpsection/datetime/view.py b/extensions/cpsection/datetime/view.py index 58719b4..1cef78f 100644 --- a/extensions/cpsection/datetime/view.py +++ b/extensions/cpsection/datetime/view.py @@ -24,36 +24,38 @@ from sugar.graphics import iconentry from jarabe.controlpanel.sectionview import SectionView from jarabe.controlpanel.inlinealert import InlineAlert + class TimeZone(SectionView): def __init__(self, model, alerts): SectionView.__init__(self) self._model = model self.restart_alerts = alerts - self._zone_sid = 0 + self._zone_sid = 0 self._cursor_change_handler = None self.set_border_width(style.DEFAULT_SPACING * 2) self.set_spacing(style.DEFAULT_SPACING) - self.connect("realize", self.__realize_cb) + self.connect('realize', self.__realize_cb) self._entry = iconentry.IconEntry() self._entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, 'system-search') self._entry.add_clear_button() - self._entry.modify_bg(gtk.STATE_INSENSITIVE, + self._entry.modify_bg(gtk.STATE_INSENSITIVE, style.COLOR_WHITE.get_gdk_color()) - self._entry.modify_base(gtk.STATE_INSENSITIVE, - style.COLOR_WHITE.get_gdk_color()) + self._entry.modify_base(gtk.STATE_INSENSITIVE, + style.COLOR_WHITE.get_gdk_color()) self.pack_start(self._entry, False) - self._entry.show() + self._entry.show() self._scrolled_window = gtk.ScrolledWindow() - self._scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + self._scrolled_window.set_policy(gtk.POLICY_NEVER, + gtk.POLICY_AUTOMATIC) self._scrolled_window.set_shadow_type(gtk.SHADOW_IN) - self._store = gtk.ListStore(gobject.TYPE_STRING) + self._store = gtk.ListStore(gobject.TYPE_STRING) zones = model.read_all_timezones() for zone in zones: self._store.append([zone]) @@ -91,16 +93,16 @@ class TimeZone(SectionView): zone = self._model.get_timezone() for row in self._store: if zone == row[0]: - self._treeview.set_cursor(row.path, self._timezone_column, + self._treeview.set_cursor(row.path, self._timezone_column, False) - self._treeview.scroll_to_cell(row.path, self._timezone_column, - True, 0.5, 0.5) + self._treeview.scroll_to_cell(row.path, self._timezone_column, + True, 0.5, 0.5) break - - self.needs_restart = False + + self.needs_restart = False self._cursor_change_handler = self._treeview.connect( \ - "cursor-changed", self.__zone_changed_cd) - + 'cursor-changed', self.__zone_changed_cd) + def undo(self): self._treeview.disconnect(self._cursor_change_handler) self._model.undo() @@ -121,18 +123,18 @@ class TimeZone(SectionView): return False if self._model.get_timezone() == self._store.get_value(row, 0): return False - + if self._zone_sid: gobject.source_remove(self._zone_sid) - self._zone_sid = gobject.timeout_add(self._APPLY_TIMEOUT, + self._zone_sid = gobject.timeout_add(self._APPLY_TIMEOUT, self.__zone_timeout_cb, row) return True - def __zone_timeout_cb(self, row): - self._zone_sid = 0 + def __zone_timeout_cb(self, row): + self._zone_sid = 0 self._model.set_timezone(self._store.get_value(row, 0)) self.restart_alerts.append('zone') - self.needs_restart = True + self.needs_restart = True self._zone_alert.props.msg = self.restart_msg self._zone_alert.show() return False diff --git a/extensions/cpsection/frame/model.py b/extensions/cpsection/frame/model.py index 9eea9ad..4796062 100644 --- a/extensions/cpsection/frame/model.py +++ b/extensions/cpsection/frame/model.py @@ -17,47 +17,53 @@ from gettext import gettext as _ import gconf - + + def get_corner_delay(): client = gconf.client_get_default() corner_delay = client.get_int('/desktop/sugar/frame/corner_delay') return corner_delay + def print_corner_delay(): print get_corner_delay() - + + def set_corner_delay(delay): """Set a delay for the activation of the frame using hot corners. instantaneous: 0 (0 milliseconds) - delay: 100 (100 milliseconds) + delay: 100 (100 milliseconds) never: 1000 (disable activation) """ try: int(delay) - except ValueError: - raise ValueError(_("Value must be an integer.")) + except ValueError: + raise ValueError(_('Value must be an integer.')) client = gconf.client_get_default() client.set_int('/desktop/sugar/frame/corner_delay', int(delay)) return 0 - + + def get_edge_delay(): client = gconf.client_get_default() edge_delay = client.get_int('/desktop/sugar/frame/edge_delay') return edge_delay + def print_edge_delay(): print get_edge_delay() - + + def set_edge_delay(delay): - """Set a delay for the activation of the frame using warm edges. + """Set a delay for the activation of the frame using warm edges. instantaneous: 0 (0 milliseconds) - delay: 100 (100 milliseconds) + delay: 100 (100 milliseconds) never: 1000 (disable activation) """ try: int(delay) - except ValueError: - raise ValueError(_("Value must be an integer.")) + except ValueError: + raise ValueError(_('Value must be an integer.')) client = gconf.client_get_default() client.set_int('/desktop/sugar/frame/edge_delay', int(delay)) return 0 diff --git a/extensions/cpsection/frame/view.py b/extensions/cpsection/frame/view.py index cbe43bb..8b4ab83 100644 --- a/extensions/cpsection/frame/view.py +++ b/extensions/cpsection/frame/view.py @@ -23,11 +23,13 @@ from sugar.graphics import style from jarabe.controlpanel.sectionview import SectionView from jarabe.controlpanel.inlinealert import InlineAlert -_never = _('never') + +_never = _('never') _instantaneous = _('instantaneous') _seconds_label = _('%s seconds') _MAX_DELAY = 1000 + class Frame(SectionView): def __init__(self, model, alerts): SectionView.__init__(self) @@ -43,7 +45,7 @@ class Frame(SectionView): self.set_border_width(style.DEFAULT_SPACING * 2) self.set_spacing(style.DEFAULT_SPACING) - self._group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) + self._group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) separator = gtk.HSeparator() self.pack_start(separator, expand=False) @@ -67,25 +69,25 @@ class Frame(SectionView): self._setup_edge() self.pack_start(self._box_sliders, expand=False) - self._box_sliders.show() + self._box_sliders.show() self.setup() - def _setup_corner(self): + def _setup_corner(self): box_delay = gtk.HBox(spacing=style.DEFAULT_SPACING) label_delay = gtk.Label(_('Corner')) label_delay.set_alignment(1, 0.75) - label_delay.modify_fg(gtk.STATE_NORMAL, + label_delay.modify_fg(gtk.STATE_NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) box_delay.pack_start(label_delay, expand=False) self._group.add_widget(label_delay) - label_delay.show() - - adj = gtk.Adjustment(value=100, lower=0, upper=_MAX_DELAY, + label_delay.show() + + adj = gtk.Adjustment(value=100, lower=0, upper=_MAX_DELAY, step_incr=100, page_incr=100, page_size=0) self._corner_delay_slider = gtk.HScale(adj) self._corner_delay_slider.set_digits(0) - self._corner_delay_slider.connect('format-value', + self._corner_delay_slider.connect('format-value', self.__corner_delay_format_cb) box_delay.pack_start(self._corner_delay_slider) self._corner_delay_slider.show() @@ -105,22 +107,22 @@ class Frame(SectionView): if 'corner_delay' in self.restart_alerts: self._corner_delay_alert.props.msg = self.restart_msg self._corner_delay_alert.show() - - def _setup_edge(self): + + def _setup_edge(self): box_delay = gtk.HBox(spacing=style.DEFAULT_SPACING) label_delay = gtk.Label(_('Edge')) label_delay.set_alignment(1, 0.75) - label_delay.modify_fg(gtk.STATE_NORMAL, + label_delay.modify_fg(gtk.STATE_NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) box_delay.pack_start(label_delay, expand=False) self._group.add_widget(label_delay) - label_delay.show() - - adj = gtk.Adjustment(value=100, lower=0, upper=_MAX_DELAY, + label_delay.show() + + adj = gtk.Adjustment(value=100, lower=0, upper=_MAX_DELAY, step_incr=100, page_incr=100, page_size=0) self._edge_delay_slider = gtk.HScale(adj) self._edge_delay_slider.set_digits(0) - self._edge_delay_slider.connect('format-value', + self._edge_delay_slider.connect('format-value', self.__edge_delay_format_cb) box_delay.pack_start(self._edge_delay_slider) self._edge_delay_slider.show() @@ -140,24 +142,24 @@ class Frame(SectionView): if 'edge_delay' in self.restart_alerts: self._edge_delay_alert.props.msg = self.restart_msg self._edge_delay_alert.show() - + def setup(self): self._corner_delay_slider.set_value(self._model.get_corner_delay()) self._edge_delay_slider.set_value(self._model.get_edge_delay()) self._corner_delay_is_valid = True self._edge_delay_is_valid = True self.needs_restart = False - self._corner_delay_change_handler = self._corner_delay_slider.connect( \ + self._corner_delay_change_handler = self._corner_delay_slider.connect( 'value-changed', self.__corner_delay_changed_cb) - self._edge_delay_change_handler = self._edge_delay_slider.connect( \ + self._edge_delay_change_handler = self._edge_delay_slider.connect( 'value-changed', self.__edge_delay_changed_cb) - - def undo(self): + + def undo(self): self._corner_delay_slider.disconnect(self._corner_delay_change_handler) self._edge_delay_slider.disconnect(self._edge_delay_change_handler) self._model.undo() - self._corner_delay_alert.hide() - self._edge_delay_alert.hide() + self._corner_delay_alert.hide() + self._edge_delay_alert.hide() def _validate(self): if self._edge_delay_is_valid and self._corner_delay_is_valid: @@ -165,15 +167,15 @@ class Frame(SectionView): else: self.props.is_valid = False - def __corner_delay_changed_cb(self, scale, data=None): + def __corner_delay_changed_cb(self, scale, data=None): if self._corner_delay_sid: gobject.source_remove(self._corner_delay_sid) self._corner_delay_sid = gobject.timeout_add( \ self._APPLY_TIMEOUT, self.__corner_delay_timeout_cb, scale) - - def __corner_delay_timeout_cb(self, scale): + + def __corner_delay_timeout_cb(self, scale): self._corner_delay_sid = 0 - if scale.get_value() == self._model.get_corner_delay(): + if scale.get_value() == self._model.get_corner_delay(): return try: self._model.set_corner_delay(scale.get_value()) @@ -182,12 +184,12 @@ class Frame(SectionView): self._corner_delay_is_valid = False else: self._corner_delay_alert.props.msg = self.restart_msg - self._corner_delay_is_valid = True + self._corner_delay_is_valid = True self.needs_restart = True self.restart_alerts.append('corner_delay') - + self._validate() - self._corner_delay_alert.show() + self._corner_delay_alert.show() return False def __corner_delay_format_cb(self, scale, value): @@ -198,15 +200,15 @@ class Frame(SectionView): else: return _seconds_label % (value / _MAX_DELAY) - def __edge_delay_changed_cb(self, scale, data=None): + def __edge_delay_changed_cb(self, scale, data=None): if self._edge_delay_sid: gobject.source_remove(self._edge_delay_sid) self._edge_delay_sid = gobject.timeout_add( \ self._APPLY_TIMEOUT, self.__edge_delay_timeout_cb, scale) - - def __edge_delay_timeout_cb(self, scale): + + def __edge_delay_timeout_cb(self, scale): self._edge_delay_sid = 0 - if scale.get_value() == self._model.get_edge_delay(): + if scale.get_value() == self._model.get_edge_delay(): return try: self._model.set_edge_delay(scale.get_value()) @@ -215,12 +217,12 @@ class Frame(SectionView): self._edge_delay_is_valid = False else: self._edge_delay_alert.props.msg = self.restart_msg - self._edge_delay_is_valid = True + self._edge_delay_is_valid = True self.needs_restart = True self.restart_alerts.append('edge_delay') - + self._validate() - self._edge_delay_alert.show() + self._edge_delay_alert.show() return False def __edge_delay_format_cb(self, scale, value): diff --git a/extensions/cpsection/keyboard/__init__.py b/extensions/cpsection/keyboard/__init__.py index 568e7a5..065086c 100644 --- a/extensions/cpsection/keyboard/__init__.py +++ b/extensions/cpsection/keyboard/__init__.py @@ -19,4 +19,3 @@ from gettext import gettext as _ CLASS = 'Keyboard' ICON = 'module-keyboard' TITLE = _('Keyboard') - diff --git a/extensions/cpsection/keyboard/model.py b/extensions/cpsection/keyboard/model.py index 089c2ea..1f92973 100644 --- a/extensions/cpsection/keyboard/model.py +++ b/extensions/cpsection/keyboard/model.py @@ -20,12 +20,13 @@ import xklavier import gconf -_GROUP_NAME = 'grp' # The XKB name for group switch options +_GROUP_NAME = 'grp' # The XKB name for group switch options _LAYOUTS_KEY = '/desktop/sugar/peripherals/keyboard/layouts' _OPTIONS_KEY = '/desktop/sugar/peripherals/keyboard/options' _MODEL_KEY = '/desktop/sugar/peripherals/keyboard/model' + class KeyboardManager(object): def __init__(self, display): self._engine = xklavier.Engine(display) @@ -33,7 +34,7 @@ class KeyboardManager(object): self._configregistry.load(False) self._configrec = xklavier.ConfigRec() self._configrec.get_from_server(self._engine) - + self._gconf_client = gconf.client_get_default() def _populate_one(self, config_registry, item, store): @@ -48,7 +49,7 @@ class KeyboardManager(object): else: description = 'Default layout, %s' % item.get_description() variant = '' - + store.append([description, ('%s(%s)' % (layout, variant))]) def get_models(self): @@ -76,8 +77,8 @@ class KeyboardManager(object): def get_options_group(self): """Return list of supported options for switching keyboard group""" options = [] - self._configregistry.foreach_option(_GROUP_NAME, self._populate_one, \ - options) + self._configregistry.foreach_option(_GROUP_NAME, self._populate_one, + options) options.sort() return options @@ -96,7 +97,7 @@ class KeyboardManager(object): layouts = self._gconf_client.get_list(_LAYOUTS_KEY, gconf.VALUE_STRING) if layouts: return layouts - + layouts = self._configrec.get_layouts() variants = self._configrec.get_variants() @@ -126,7 +127,7 @@ class KeyboardManager(object): return option return None - + def get_max_layouts(self): """Return the maximum number of layouts supported simultaneously""" return self._engine.get_max_num_groups() @@ -162,8 +163,7 @@ class KeyboardManager(object): for layout in layouts: layouts_list.append(layout.split('(')[0]) variants_list.append(layout.split('(')[1][:-1]) - + self._configrec.set_layouts(layouts_list) self._configrec.set_variants(variants_list) - self._configrec.activate(self._engine) - + self._configrec.activate(self._engine) diff --git a/extensions/cpsection/keyboard/view.py b/extensions/cpsection/keyboard/view.py index dd62a85..e349255 100644 --- a/extensions/cpsection/keyboard/view.py +++ b/extensions/cpsection/keyboard/view.py @@ -26,6 +26,7 @@ from sugar.graphics.icon import Icon from jarabe.controlpanel.sectionview import SectionView + CLASS = 'Language' ICON = 'module-keyboard' TITLE = _('Keyboard') @@ -37,6 +38,7 @@ _APPLY_TIMEOUT = 500 # once python-xklavier has been packaged for all major distributions # For more information, see: http://dev.sugarlabs.org/ticket/407 + class LayoutCombo(gtk.HBox): """ @@ -45,8 +47,8 @@ class LayoutCombo(gtk.HBox): """ __gsignals__ = { - 'selection-changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_INT)) + 'selection-changed': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, + (gobject.TYPE_STRING, gobject.TYPE_INT)), } def __init__(self, keyboard_manager, n): @@ -57,7 +59,7 @@ class LayoutCombo(gtk.HBox): self.set_border_width(style.DEFAULT_SPACING) self.set_spacing(style.DEFAULT_SPACING) - label = gtk.Label(' <b>%s</b> ' % str(n+1)) + label = gtk.Label(' <b>%s</b> ' % str(n + 1)) label.set_use_markup(True) label.modify_fg(gtk.STATE_NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) @@ -69,7 +71,7 @@ class LayoutCombo(gtk.HBox): for description, name in self._keyboard_manager.get_languages(): self._klang_store.append([name, description]) - self._klang_combo = gtk.ComboBox(model = self._klang_store) + self._klang_combo = gtk.ComboBox(model=self._klang_store) self._klang_combo_changed_id = \ self._klang_combo.connect('changed', self._klang_combo_changed_cb) cell = gtk.CellRendererText() @@ -77,10 +79,10 @@ class LayoutCombo(gtk.HBox): cell.props.ellipsize_set = True self._klang_combo.pack_start(cell) self._klang_combo.add_attribute(cell, 'text', 1) - self.pack_start(self._klang_combo, expand=True, fill = True) + self.pack_start(self._klang_combo, expand=True, fill=True) self._kvariant_store = None - self._kvariant_combo = gtk.ComboBox(model = None) + self._kvariant_combo = gtk.ComboBox(model=None) self._kvariant_combo_changed_id = \ self._kvariant_combo.connect('changed', \ self._kvariant_combo_changed_cb) @@ -89,7 +91,7 @@ class LayoutCombo(gtk.HBox): cell.props.ellipsize_set = True self._kvariant_combo.pack_start(cell) self._kvariant_combo.add_attribute(cell, 'text', 1) - self.pack_start(self._kvariant_combo, expand=True, fill = True) + self.pack_start(self._kvariant_combo, expand=True, fill=True) self._klang_combo.set_active(self._index) @@ -129,7 +131,7 @@ class LayoutCombo(gtk.HBox): model = combobox.get_model() lang = model.get(it, 0)[0] self._set_kvariant_store(lang) - + def _kvariant_combo_changed_cb(self, combobox): it = combobox.get_active_iter() model = combobox.get_model() @@ -145,18 +147,17 @@ class Keyboard(SectionView): self._kmodel = None self._selected_kmodel = None - + self._klayouts = [] self._selected_klayouts = [] - + self._group_switch_option = None self._selected_group_switch_option = None self.set_border_width(style.DEFAULT_SPACING * 2) self.set_spacing(style.DEFAULT_SPACING) - - self._layout_table = gtk.Table(rows = 4, columns = 2, \ - homogeneous = False) + + self._layout_table = gtk.Table(rows=4, columns=2, homogeneous=False) self._keyboard_manager = model.KeyboardManager(self.get_display()) self._layout_combo_list = [] @@ -169,7 +170,7 @@ class Keyboard(SectionView): self._vbox = gtk.VBox() scrollwindow.add_with_viewport(self._vbox) - + self.__kmodel_sid = None self.__layout_sid = None self.__group_switch_sid = None @@ -177,7 +178,7 @@ class Keyboard(SectionView): self._setup_kmodel() self._setup_layouts() self._setup_group_switch_option() - + self._vbox.show() def _setup_kmodel(self): @@ -200,7 +201,7 @@ class Keyboard(SectionView): for description, name in self._keyboard_manager.get_models(): kmodel_store.append([name, description]) - kmodel_combo = gtk.ComboBox(model = kmodel_store) + kmodel_combo = gtk.ComboBox(model=kmodel_store) cell = gtk.CellRendererText() cell.props.ellipsize = pango.ELLIPSIZE_MIDDLE cell.props.ellipsize_set = True @@ -214,7 +215,7 @@ class Keyboard(SectionView): kmodel_combo.set_active_iter(row.iter) break - box_kmodel.pack_start(kmodel_combo, expand = False) + box_kmodel.pack_start(kmodel_combo, expand=False) self._vbox.pack_start(box_kmodel, expand=False) box_kmodel.show_all() @@ -223,7 +224,7 @@ class Keyboard(SectionView): def __kmodel_changed_cb(self, combobox): if self.__kmodel_sid is not None: gobject.source_remove(self.__kmodel_sid) - self.__kmodel_sid = gobject.timeout_add(_APPLY_TIMEOUT, + self.__kmodel_sid = gobject.timeout_add(_APPLY_TIMEOUT, self.__kmodel_timeout_cb, combobox) def __kmodel_timeout_cb(self, combobox): @@ -240,7 +241,8 @@ class Keyboard(SectionView): return False def _setup_group_switch_option(self): - """Adds the controls for changing the group switch option of keyboard""" + """Adds the controls for changing the group switch option of keyboard + """ separator_group_option = gtk.HSeparator() self._vbox.pack_start(separator_group_option, expand=False) separator_group_option.show_all() @@ -259,7 +261,7 @@ class Keyboard(SectionView): for description, name in self._keyboard_manager.get_options_group(): group_option_store.append([name, description]) - group_option_combo = gtk.ComboBox(model = group_option_store) + group_option_combo = gtk.ComboBox(model=group_option_store) cell = gtk.CellRendererText() cell.props.ellipsize = pango.ELLIPSIZE_MIDDLE cell.props.ellipsize_set = True @@ -280,7 +282,7 @@ class Keyboard(SectionView): if not found: group_option_combo.set_active(0) - box_group_option.pack_start(group_option_combo, expand = False) + box_group_option.pack_start(group_option_combo, expand=False) self._vbox.pack_start(box_group_option, expand=False) box_group_option.show_all() @@ -290,7 +292,7 @@ class Keyboard(SectionView): def __group_switch_changed_cb(self, combobox): if self.__group_switch_sid is not None: gobject.source_remove(self.__group_switch_sid) - self.__group_switch_sid = gobject.timeout_add(_APPLY_TIMEOUT, + self.__group_switch_sid = gobject.timeout_add(_APPLY_TIMEOUT, self.__group_switch_timeout_cb, combobox) def __group_switch_timeout_cb(self, combobox): @@ -306,7 +308,6 @@ class Keyboard(SectionView): except Exception: logging.exception('Could not set new keyboard group switch option') - return False def _setup_layouts(self): @@ -324,18 +325,18 @@ class Keyboard(SectionView): for i in range(0, self._keyboard_manager.get_max_layouts()): add_remove_box = self.__create_add_remove_box() self._layout_addremovebox_list.append(add_remove_box) - self._layout_table.attach(add_remove_box, 1, 2, i, i+1) + self._layout_table.attach(add_remove_box, 1, 2, i, i + 1) layout_combo = LayoutCombo(self._keyboard_manager, i) layout_combo.connect('selection-changed', \ self.__layout_combo_selection_changed_cb) self._layout_combo_list.append(layout_combo) - self._layout_table.attach(layout_combo, 0, 1, i, i+1) + self._layout_table.attach(layout_combo, 0, 1, i, i + 1) if i < len(self._klayouts): layout_combo.show_all() layout_combo.select_layout(self._klayouts[i]) - + self._vbox.pack_start(self._layout_table, expand=False) self._layout_table.set_size_request(self._vbox.size_request()[0], -1) self._layout_table.show() @@ -359,15 +360,15 @@ class Keyboard(SectionView): i += 1 def __create_add_remove_box(self): - '''Creates gtk.Hbox with add/remove buttons''' - add_icon = Icon(icon_name='list-add') + """Creates gtk.Hbox with add/remove buttons""" + add_icon = Icon(icon_name='list-add') add_button = gtk.Button() add_button.set_image(add_icon) add_button.connect('clicked', self.__add_button_clicked_cb) - remove_icon = Icon(icon_name='list-remove') + remove_icon = Icon(icon_name='list-remove') remove_button = gtk.Button() remove_button.set_image(remove_icon) remove_button.connect('clicked', @@ -387,7 +388,7 @@ class Keyboard(SectionView): def __add_button_clicked_cb(self, button): self._layout_combo_list[len(self._selected_klayouts)].show_all() self._update_klayouts() - + def __remove_button_clicked_cb(self, button): self._layout_combo_list[len(self._selected_klayouts) - 1].hide() self._update_klayouts() @@ -403,7 +404,7 @@ class Keyboard(SectionView): if self.__layout_sid is not None: gobject.source_remove(self.__layout_sid) - self.__layout_sid = gobject.timeout_add(_APPLY_TIMEOUT, + self.__layout_sid = gobject.timeout_add(_APPLY_TIMEOUT, self.__layout_timeout_cb) def __layout_timeout_cb(self): @@ -417,10 +418,8 @@ class Keyboard(SectionView): return False - def undo(self): """Reverts back to the original keyboard configuration""" self._keyboard_manager.set_model(self._kmodel) self._keyboard_manager.set_layouts(self._klayouts) self._keyboard_manager.set_option_group(self._group_switch_option) - diff --git a/extensions/cpsection/language/__init__.py b/extensions/cpsection/language/__init__.py index a8f9f08..c93b7d1 100644 --- a/extensions/cpsection/language/__init__.py +++ b/extensions/cpsection/language/__init__.py @@ -19,4 +19,3 @@ from gettext import gettext as _ CLASS = 'Language' ICON = 'module-language' TITLE = _('Language') - diff --git a/extensions/cpsection/language/model.py b/extensions/cpsection/language/model.py index 4f3686f..240e562 100644 --- a/extensions/cpsection/language/model.py +++ b/extensions/cpsection/language/model.py @@ -25,8 +25,10 @@ import locale from gettext import gettext as _ import subprocess + _default_lang = '%s.%s' % locale.getdefaultlocale() -_standard_msg = _("Could not access ~/.i18n. Create standard settings.") +_standard_msg = _('Could not access ~/.i18n. Create standard settings.') + def read_all_languages(): fdp = subprocess.Popen(['locale', '-av'], stdout=subprocess.PIPE) @@ -43,7 +45,7 @@ def read_all_languages(): if locale.endswith('utf8') and len(lang): locales.append((lang, territory, locale)) - #FIXME: This is a temporary workaround for locales that are essential to + #FIXME: This is a temporary workaround for locales that are essential to # OLPC, but are not in Glibc yet. locales.append(('Kreyol', 'Haiti', 'ht_HT.utf8')) locales.append(('Dari', 'Afghanistan', 'fa_AF.utf8')) @@ -52,7 +54,8 @@ def read_all_languages(): locales.sort() return locales -def _initialize(): + +def _initialize(): if set_languages.__doc__ is None: # when running under 'python -OO', all __doc__ fields are None, # so += would fail -- and this function would be unnecessary anyway. @@ -60,13 +63,12 @@ def _initialize(): languages = read_all_languages() set_languages.__doc__ += '\n' for lang in languages: - set_languages.__doc__ += '%s \n' % (lang[0].replace(' ', '_') + '/' + + set_languages.__doc__ += '%s \n' % (lang[0].replace(' ', '_') + '/' + lang[1].replace(' ', '_')) - -def _write_i18n(langs): - colon = ':' - langstr = colon.join(langs) - path = os.path.join(os.environ.get("HOME"), '.i18n') + + +def _write_i18n(lang_env, language_env): + path = os.path.join(os.environ.get('HOME'), '.i18n') if not os.access(path, os.W_OK): print _standard_msg fd = open(path, 'w') @@ -75,32 +77,33 @@ def _write_i18n(langs): fd.close() else: fd = open(path, 'w') - fd.write('LANG="%s"\n' % langs[0].strip("\n")) - fd.write('LANGUAGE="%s"\n' % langstr) + fd.write('LANG="%s"\n' % lang_env) + fd.write('LANGUAGE="%s"\n' % language_env) fd.close() + def get_languages(): - path = os.path.join(os.environ.get("HOME"), '.i18n') + path = os.path.join(os.environ.get('HOME', ''), '.i18n') if not os.access(path, os.R_OK): - print _standard_msg + print _standard_msg fd = open(path, 'w') fd.write('LANG="%s"\n' % _default_lang) fd.write('LANGUAGE="%s"\n' % _default_lang) fd.close() return [_default_lang] - - fd = open(path, "r") + + fd = open(path, 'r') lines = fd.readlines() fd.close() langlist = None for line in lines: - if line.startswith("LANGUAGE="): + if line.startswith('LANGUAGE='): lang = line[9:].replace('"', '') lang = lang.strip() langlist = lang.split(':') - elif line.startswith("LANG="): + elif line.startswith('LANG='): lang = line[5:].replace('"', '') # There might be cases where .i18n may not contain a LANGUAGE field @@ -109,6 +112,7 @@ def get_languages(): else: return langlist + def print_languages(): codes = get_languages() @@ -122,30 +126,35 @@ def print_languages(): found_lang = True break if not found_lang: - print (_("Language for code=%s could not be determined.") % code) - + print (_('Language for code=%s could not be determined.') % code) + + def set_languages(languages): """Set the system language. - languages : + languages : """ - if isinstance(languages, str): - # This came from the commandline - #TODO: Support multiple languages from the command line - if languages.endswith('utf8'): - _write_i18n(languages) - return 1 - else: - langs = read_all_languages() - for lang, territory, locale in langs: - code = lang.replace(' ', '_') + '/' \ - + territory.replace(' ', '_') - if code == languages: - _write_i18n(locale) - return 1 - print (_("Sorry I do not speak \'%s\'.") % languages) + + if languages.endswith('utf8'): + set_languages_list([languages]) + return 1 else: - _write_i18n(languages) + langs = read_all_languages() + for lang, territory, locale in langs: + code = lang.replace(' ', '_') + '/' \ + + territory.replace(' ', '_') + if code == languages: + set_languages_list([locale]) + return 1 + print (_("Sorry I do not speak \'%s\'.") % languages) + + +def set_languages_list(languages): + """Set the system language using a list of preferred languages""" + colon = ':' + language_env = colon.join(languages) + lang_env = languages[0].strip('\n') + _write_i18n(lang_env, language_env) + # inilialize the docstrings for the language _initialize() - diff --git a/extensions/cpsection/language/view.py b/extensions/cpsection/language/view.py index d1a49cf..1553959 100644 --- a/extensions/cpsection/language/view.py +++ b/extensions/cpsection/language/view.py @@ -25,13 +25,14 @@ from sugar.graphics.icon import Icon from jarabe.controlpanel.sectionview import SectionView from jarabe.controlpanel.inlinealert import InlineAlert -_translate_language = lambda msg: gettext.dgettext('iso_639', msg) +_translate_language = lambda msg: gettext.dgettext('iso_639', msg) _translate_country = lambda msg: gettext.dgettext('iso_3166', msg) CLASS = 'Language' ICON = 'module-language' TITLE = gettext.gettext('Language') + class Language(SectionView): def __init__(self, model, alerts): SectionView.__init__(self) @@ -53,9 +54,9 @@ class Language(SectionView): self.set_border_width(style.DEFAULT_SPACING * 2) self.set_spacing(style.DEFAULT_SPACING) - explanation = gettext.gettext("Add languages in the order you prefer." \ - " If a translation is not available,"\ - " the next in the list will be used.") + explanation = gettext.gettext('Add languages in the order you prefer.' + ' If a translation is not available,' + ' the next in the list will be used.') self._text = gtk.Label(explanation) self._text.set_width_chars(100) self._text.set_line_wrap(True) @@ -69,14 +70,14 @@ class Language(SectionView): self.pack_start(scrolled, expand=True) self._table = gtk.Table(rows=1, columns=3, homogeneous=False) - self._table.set_border_width(style.DEFAULT_SPACING * 2) + self._table.set_border_width(style.DEFAULT_SPACING * 2) self._table.show() scrolled.add_with_viewport(self._table) self._lang_alert_box = gtk.HBox(spacing=style.DEFAULT_SPACING) self.pack_start(self._lang_alert_box, False) - self._lang_alert = InlineAlert() + self._lang_alert = InlineAlert() self._lang_alert_box.pack_start(self._lang_alert) if 'lang' in self.restart_alerts: self._lang_alert.props.msg = self.restart_msg @@ -86,10 +87,10 @@ class Language(SectionView): self.setup() def _add_row(self, locale_code=None): - '''Adds a row to the table''' + """Adds a row to the table""" self._selected_lang_count += 1 - + self._table.resize(self._selected_lang_count, 3) label = gtk.Label(str=str(self._selected_lang_count)) @@ -98,8 +99,7 @@ class Language(SectionView): self._labels.append(label) self._attach_to_table(label, 0, 1, padding=1) label.show() - - + store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) for language, country, code in self._available_locales: description = '%s (%s)' % (_translate_language(language), \ @@ -115,7 +115,7 @@ class Language(SectionView): for row in store: lang = locale_code.split('.')[0] lang_column = row[0].split('.')[0] - if lang in lang_column: + if lang in lang_column: combobox.set_active_iter(row.iter) break else: @@ -132,7 +132,7 @@ class Language(SectionView): self._attach_to_table(add_remove_box, 2, 3) add_remove_box.show_all() - + if self._selected_lang_count > 1: previous_add_removes = self._add_remove_boxes[-2] previous_add_removes.hide_all() @@ -149,12 +149,12 @@ class Language(SectionView): ypadding=padding) def _delete_last_row(self): - '''Deletes the last row of the table''' + """Deletes the last row of the table""" self._selected_lang_count -= 1 label, add_remove_box, combobox, store_ = self._get_last_row() - + label.destroy() add_remove_box.destroy() combobox.destroy() @@ -180,15 +180,15 @@ class Language(SectionView): self._lang_alert.hide() def _create_add_remove_box(self): - '''Creates gtk.Hbox with add/remove buttons''' - add_icon = Icon(icon_name='list-add') + """Creates gtk.Hbox with add/remove buttons""" + add_icon = Icon(icon_name='list-add') add_button = gtk.Button() add_button.set_image(add_icon) add_button.connect('clicked', self.__add_button_clicked_cb) - remove_icon = Icon(icon_name='list-remove') + remove_icon = Icon(icon_name='list-remove') remove_button = gtk.Button() remove_button.set_image(remove_icon) remove_button.connect('clicked', @@ -217,8 +217,8 @@ class Language(SectionView): selected_langs = self._get_selected_langs() last_lang = selected_langs[-1] - self._determine_add_remove_visibility(last_lang = last_lang) - + self._determine_add_remove_visibility(last_lang=last_lang) + self._changed = (selected_langs != self._selected_locales) if self._changed == False: @@ -245,10 +245,10 @@ class Language(SectionView): model = combobox.get_model() lang_code = model.get(it, 0)[0] new_codes.append(lang_code) - + return new_codes - def _determine_add_remove_visibility(self, last_lang = None): + def _determine_add_remove_visibility(self, last_lang=None): # We should not let users add fallback languages for English (USA) # This is because the software is not usually _translated_ into English # which means that the fallback gets selected automatically @@ -256,11 +256,11 @@ class Language(SectionView): if last_lang is None: selected_langs = self._get_selected_langs() last_lang = selected_langs[-1] - + add_remove_box = self._add_remove_boxes[-1] buttons = add_remove_box.get_children() add_button, remove_button = buttons - + if last_lang.startswith('en_US'): add_button.props.visible = False else: @@ -271,10 +271,9 @@ class Language(SectionView): else: remove_button.props.visible = True - def __lang_timeout_cb(self, codes): self._lang_sid = 0 - self._model.set_languages(codes) + self._model.set_languages_list(codes) self.restart_alerts.append('lang') self.needs_restart = True self._lang_alert.props.msg = self.restart_msg diff --git a/extensions/cpsection/modemconfiguration/__init__.py b/extensions/cpsection/modemconfiguration/__init__.py index 8a219dc..61f5904 100644 --- a/extensions/cpsection/modemconfiguration/__init__.py +++ b/extensions/cpsection/modemconfiguration/__init__.py @@ -19,4 +19,3 @@ from gettext import gettext as _ CLASS = 'ModemConfiguration' ICON = 'module-modemconfiguration' TITLE = _('Modem Configuration') - diff --git a/extensions/cpsection/modemconfiguration/model.py b/extensions/cpsection/modemconfiguration/model.py index 2545ce1..1e83c44 100755 --- a/extensions/cpsection/modemconfiguration/model.py +++ b/extensions/cpsection/modemconfiguration/model.py @@ -20,51 +20,62 @@ from jarabe.model.network import GSM_USERNAME_PATH, GSM_PASSWORD_PATH, \ GSM_NUMBER_PATH, GSM_APN_PATH, GSM_PIN_PATH, \ GSM_PUK_PATH + def get_username(): client = gconf.client_get_default() return client.get_string(GSM_USERNAME_PATH) or '' + def get_password(): client = gconf.client_get_default() return client.get_string(GSM_PASSWORD_PATH) or '' + def get_number(): client = gconf.client_get_default() return client.get_string(GSM_NUMBER_PATH) or '' + def get_apn(): client = gconf.client_get_default() return client.get_string(GSM_APN_PATH) or '' + def get_pin(): client = gconf.client_get_default() return client.get_string(GSM_PIN_PATH) or '' + def get_puk(): client = gconf.client_get_default() return client.get_string(GSM_PUK_PATH) or '' + def set_username(username): client = gconf.client_get_default() client.set_string(GSM_USERNAME_PATH, username) + def set_password(password): client = gconf.client_get_default() client.set_string(GSM_PASSWORD_PATH, password) + def set_number(number): client = gconf.client_get_default() client.set_string(GSM_NUMBER_PATH, number) + def set_apn(apn): client = gconf.client_get_default() client.set_string(GSM_APN_PATH, apn) + def set_pin(pin): client = gconf.client_get_default() client.set_string(GSM_PIN_PATH, pin) + def set_puk(puk): client = gconf.client_get_default() client.set_string(GSM_PUK_PATH, puk) - diff --git a/extensions/cpsection/modemconfiguration/view.py b/extensions/cpsection/modemconfiguration/view.py index b236f3f..c31edba 100644 --- a/extensions/cpsection/modemconfiguration/view.py +++ b/extensions/cpsection/modemconfiguration/view.py @@ -25,10 +25,12 @@ from sugar.graphics import style from jarabe.controlpanel.sectionview import SectionView + APPLY_TIMEOUT = 1000 + class EntryWithLabel(gtk.HBox): - __gtype_name__ = "SugarEntryWithLabel" + __gtype_name__ = 'SugarEntryWithLabel' def __init__(self, label_text): gtk.HBox.__init__(self, spacing=style.DEFAULT_SPACING) @@ -53,7 +55,7 @@ class EntryWithLabel(gtk.HBox): def __entry_changed_cb(self, widget, data=None): if self._timeout_sid: gobject.source_remove(self._timeout_sid) - self._timeout_sid = gobject.timeout_add(APPLY_TIMEOUT, + self._timeout_sid = gobject.timeout_add(APPLY_TIMEOUT, self.__timeout_cb) def __timeout_cb(self): @@ -63,7 +65,7 @@ class EntryWithLabel(gtk.HBox): return False try: - self.set_value(self._entry.get_text()) + self.set_value(self._entry.get_text()) except ValueError: self._is_valid = False else: @@ -74,18 +76,19 @@ class EntryWithLabel(gtk.HBox): return False def set_text_from_model(self): - self._entry.set_text(self.get_value()) + self._entry.set_text(self.get_value()) def get_value(self): raise NotImplementedError def set_value(self): - raise NotImplementedError + raise NotImplementedError def _get_is_valid(self): return self._is_valid is_valid = gobject.property(type=bool, getter=_get_is_valid, default=True) + class UsernameEntry(EntryWithLabel): def __init__(self, model): EntryWithLabel.__init__(self, _('Username:')) @@ -97,6 +100,7 @@ class UsernameEntry(EntryWithLabel): def set_value(self, username): self._model.set_username(username) + class PasswordEntry(EntryWithLabel): def __init__(self, model): EntryWithLabel.__init__(self, _('Password:')) @@ -108,6 +112,7 @@ class PasswordEntry(EntryWithLabel): def set_value(self, password): self._model.set_password(password) + class NumberEntry(EntryWithLabel): def __init__(self, model): EntryWithLabel.__init__(self, _('Number:')) @@ -119,6 +124,7 @@ class NumberEntry(EntryWithLabel): def set_value(self, number): self._model.set_number(number) + class ApnEntry(EntryWithLabel): def __init__(self, model): EntryWithLabel.__init__(self, _('Access Point Name (APN):')) @@ -130,6 +136,7 @@ class ApnEntry(EntryWithLabel): def set_value(self, apn): self._model.set_apn(apn) + class PinEntry(EntryWithLabel): def __init__(self, model): EntryWithLabel.__init__(self, _('Personal Identity Number (PIN):')) @@ -141,6 +148,7 @@ class PinEntry(EntryWithLabel): def set_value(self, pin): self._model.set_pin(pin) + class PukEntry(EntryWithLabel): def __init__(self, model): EntryWithLabel.__init__(self, _('Personal Unblocking Key (PUK):')) @@ -164,10 +172,9 @@ class ModemConfiguration(SectionView): self.set_spacing(style.DEFAULT_SPACING) self._group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) - explanation = _("You will need to provide the following " \ - "information to set up a mobile " \ - "broadband connection to a cellular "\ - "(3G) network.") + explanation = _('You will need to provide the following information' + ' to set up a mobile broadband connection to a' + ' cellular (3G) network.') self._text = gtk.Label(explanation) self._text.set_width_chars(100) self._text.set_line_wrap(True) @@ -209,12 +216,12 @@ class ModemConfiguration(SectionView): self._group.add_widget(self._pin_entry.label) self.pack_start(self._pin_entry, expand=False) self._pin_entry.show() - + self._puk_entry = PukEntry(model) self._puk_entry.connect('notify::is-valid', self.__notify_is_valid_cb) self._group.add_widget(self._puk_entry.label) - self.pack_start(self._puk_entry, expand=False) + self.pack_start(self._puk_entry, expand=False) self._puk_entry.show() self.setup() @@ -247,4 +254,3 @@ class ModemConfiguration(SectionView): if entry.is_valid: self.needs_restart = True self._validate() - diff --git a/extensions/cpsection/network/__init__.py b/extensions/cpsection/network/__init__.py index 8fea274..86546f7 100644 --- a/extensions/cpsection/network/__init__.py +++ b/extensions/cpsection/network/__init__.py @@ -20,6 +20,3 @@ CLASS = 'Network' ICON = 'module-network' TITLE = _('Network') KEYWORDS = ['network', 'jabber', 'radio', 'server'] - - - diff --git a/extensions/cpsection/network/model.py b/extensions/cpsection/network/model.py index 2713f23..916ce8c 100644 --- a/extensions/cpsection/network/model.py +++ b/extensions/cpsection/network/model.py @@ -19,25 +19,33 @@ import dbus from gettext import gettext as _ import gconf +from jarabe.model import network + + _NM_SERVICE = 'org.freedesktop.NetworkManager' _NM_PATH = '/org/freedesktop/NetworkManager' _NM_IFACE = 'org.freedesktop.NetworkManager' 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(): client = gconf.client_get_default() return client.get_string('/desktop/sugar/collaboration/jabber_server') + def print_jabber(): print get_jabber() + def set_jabber(server): """Set the jabber server server : e.g. 'olpc.collabora.co.uk' @@ -47,11 +55,12 @@ def set_jabber(server): return 0 + def get_radio(): try: bus = dbus.SystemBus() obj = bus.get_object(_NM_SERVICE, _NM_PATH) - nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + nm_props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) except dbus.DBusException: raise ReadError('%s service not available' % _NM_SERVICE) @@ -61,18 +70,20 @@ def get_radio(): else: raise ReadError(_('State is unknown.')) + def print_radio(): print ('off', 'on')[get_radio()] - + + def set_radio(state): """Turn Radio 'on' or 'off' state : 'on/off' - """ + """ if state == 'on' or state == 1: try: bus = dbus.SystemBus() obj = bus.get_object(_NM_SERVICE, _NM_PATH) - nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + nm_props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) except dbus.DBusException: raise ReadError('%s service not available' % _NM_SERVICE) nm_props.Set(_NM_IFACE, 'WirelessEnabled', True) @@ -80,15 +91,16 @@ def set_radio(state): try: bus = dbus.SystemBus() obj = bus.get_object(_NM_SERVICE, _NM_PATH) - nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + nm_props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) except dbus.DBusException: raise ReadError('%s service not available' % _NM_SERVICE) nm_props.Set(_NM_IFACE, 'WirelessEnabled', False) else: - raise ValueError(_("Error in specified radio argument use on/off.")) + raise ValueError(_('Error in specified radio argument use on/off.')) return 0 + def clear_registration(): """Clear the registration with the schoolserver """ @@ -96,28 +108,36 @@ def clear_registration(): client.set_string('/desktop/sugar/backup_url', '') return 1 + def clear_networks(): """Clear saved passwords and network configurations. """ - pass + network.clear_wifi_connections() + + +def have_networks(): + return network.have_wifi_connections() + def get_publish_information(): client = gconf.client_get_default() publish = client.get_bool('/desktop/sugar/collaboration/publish_gadget') return publish - + + def print_publish_information(): print get_publish_information() + def set_publish_information(value): - """ If set to true, Sugar will make you searchable for + """ If set to true, Sugar will make you searchable for the other users of the Jabber server. value: 0/1 """ try: value = (False, True)[int(value)] except: - raise ValueError(_("Error in specified argument use 0/1.")) + raise ValueError(_('Error in specified argument use 0/1.')) client = gconf.client_get_default() client.set_bool('/desktop/sugar/collaboration/publish_gadget', value) diff --git a/extensions/cpsection/network/view.py b/extensions/cpsection/network/view.py index 588daeb..381dcb6 100644 --- a/extensions/cpsection/network/view.py +++ b/extensions/cpsection/network/view.py @@ -23,18 +23,20 @@ from sugar.graphics import style from jarabe.controlpanel.sectionview import SectionView from jarabe.controlpanel.inlinealert import InlineAlert + CLASS = 'Network' ICON = 'module-network' TITLE = _('Network') _APPLY_TIMEOUT = 3000 + class Network(SectionView): def __init__(self, model, alerts): SectionView.__init__(self) - self._model = model - self.restart_alerts = alerts + self._model = model + self.restart_alerts = alerts self._jabber_sid = 0 self._jabber_valid = True self._radio_valid = True @@ -64,8 +66,8 @@ class Network(SectionView): box_wireless.set_border_width(style.DEFAULT_SPACING * 2) box_wireless.set_spacing(style.DEFAULT_SPACING) - radio_info = gtk.Label(_("Turn off the wireless radio to save " - "battery life")) + radio_info = gtk.Label(_('Turn off the wireless radio to save battery' + ' life')) radio_info.set_alignment(0, 0) radio_info.set_line_wrap(True) radio_info.show() @@ -93,8 +95,8 @@ class Network(SectionView): self._radio_alert.props.msg = self.restart_msg self._radio_alert.show() - history_info = gtk.Label(_("Discard network history if you " - "have trouble connecting to the network")) + history_info = gtk.Label(_('Discard network history if you have' + ' trouble connecting to the network')) history_info.set_alignment(0, 0) history_info.set_line_wrap(True) history_info.show() @@ -104,6 +106,8 @@ class Network(SectionView): self._clear_history_button = gtk.Button() self._clear_history_button.set_label(_('Discard network history')) box_clear_history.pack_start(self._clear_history_button, expand=False) + if not self._model.have_networks(): + self._clear_history_button.set_sensitive(False) self._clear_history_button.show() box_wireless.pack_start(box_clear_history, expand=False) box_clear_history.show() @@ -135,24 +139,24 @@ class Network(SectionView): box_server = gtk.HBox(spacing=style.DEFAULT_SPACING) label_server = gtk.Label(_('Server:')) label_server.set_alignment(1, 0.5) - label_server.modify_fg(gtk.STATE_NORMAL, + label_server.modify_fg(gtk.STATE_NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) box_server.pack_start(label_server, expand=False) group.add_widget(label_server) - label_server.show() + label_server.show() self._entry = gtk.Entry() self._entry.set_alignment(0) - self._entry.modify_bg(gtk.STATE_INSENSITIVE, + self._entry.modify_bg(gtk.STATE_INSENSITIVE, style.COLOR_WHITE.get_gdk_color()) - self._entry.modify_base(gtk.STATE_INSENSITIVE, - style.COLOR_WHITE.get_gdk_color()) + self._entry.modify_base(gtk.STATE_INSENSITIVE, + style.COLOR_WHITE.get_gdk_color()) self._entry.set_size_request(int(gtk.gdk.screen_width() / 3), -1) box_server.pack_start(self._entry, expand=False) - self._entry.show() + self._entry.show() box_mesh.pack_start(box_server, expand=False) box_server.show() - - self._jabber_alert = InlineAlert() + + self._jabber_alert = InlineAlert() label_jabber_error = gtk.Label() group.add_widget(label_jabber_error) self._jabber_alert_box.pack_start(label_jabber_error, expand=False) @@ -176,13 +180,13 @@ class Network(SectionView): self.setup() def setup(self): - self._entry.set_text(self._model.get_jabber()) - try: - radio_state = self._model.get_radio() + self._entry.set_text(self._model.get_jabber()) + try: + radio_state = self._model.get_radio() except self._model.ReadError, detail: - self._radio_alert.props.msg = detail + self._radio_alert.props.msg = detail self._radio_alert.show() - else: + else: self._button.set_active(radio_state) self._jabber_valid = True @@ -195,13 +199,13 @@ class Network(SectionView): self._network_configuration_reset_handler = \ self._clear_history_button.connect( \ 'clicked', self.__network_configuration_reset_cb) - + def undo(self): self._button.disconnect(self._radio_change_handler) self._entry.disconnect(self._jabber_change_handler) self._model.undo() self._jabber_alert.hide() - self._radio_alert.hide() + self._radio_alert.hide() def _validate(self): if self._jabber_valid and self._radio_valid: @@ -209,7 +213,7 @@ class Network(SectionView): else: self.props.is_valid = False - def __radio_toggled_cb(self, widget, data=None): + def __radio_toggled_cb(self, widget, data=None): radio_state = widget.get_active() try: self._model.set_radio(radio_state) @@ -217,18 +221,21 @@ class Network(SectionView): self._radio_alert.props.msg = detail self._radio_valid = False else: - self._radio_valid = True + self._radio_valid = True + if self._model.have_networks(): + self._clear_history_button.set_sensitive(True) self._validate() return False - def __jabber_changed_cb(self, widget, data=None): + def __jabber_changed_cb(self, widget, data=None): if self._jabber_sid: gobject.source_remove(self._jabber_sid) - self._jabber_sid = gobject.timeout_add(_APPLY_TIMEOUT, - self.__jabber_timeout_cb, widget) - - def __jabber_timeout_cb(self, widget): + self._jabber_sid = gobject.timeout_add(_APPLY_TIMEOUT, + self.__jabber_timeout_cb, + widget) + + def __jabber_timeout_cb(self, widget): self._jabber_sid = 0 if widget.get_text() == self._model.get_jabber: return @@ -240,11 +247,15 @@ class Network(SectionView): self._jabber_alert.show() self.restart_alerts.append('jabber') else: - self._jabber_valid = True + self._jabber_valid = True self._jabber_alert.hide() self._validate() return False def __network_configuration_reset_cb(self, widget): + # FIXME: takes effect immediately, not after CP is closed with + # confirmation button self._model.clear_networks() + if not self._model.have_networks(): + self._clear_history_button.set_sensitive(False) diff --git a/extensions/cpsection/power/__init__.py b/extensions/cpsection/power/__init__.py index 8b2e85f..35f7efd 100644 --- a/extensions/cpsection/power/__init__.py +++ b/extensions/cpsection/power/__init__.py @@ -20,4 +20,3 @@ CLASS = 'Power' ICON = 'module-power' TITLE = _('Power') KEYWORDS = ['automatic', 'extreme', 'power', 'suspend', 'battery'] - diff --git a/extensions/cpsection/power/model.py b/extensions/cpsection/power/model.py index 48d05de..041e5cf 100644 --- a/extensions/cpsection/power/model.py +++ b/extensions/cpsection/power/model.py @@ -35,14 +35,17 @@ _logger = logging.getLogger('ControlPanel - Power') class ReadError(Exception): def __init__(self, value): self.value = value + def __str__(self): return repr(self.value) + def using_powerd(): # directory exists if powerd running, and it's recent # enough to be controllable. return os.access(POWERD_FLAG_DIR, os.W_OK) + def get_automatic_pm(): if using_powerd(): return not os.access(POWERD_INHIBIT_FLAG, os.R_OK) @@ -51,9 +54,11 @@ def get_automatic_pm(): client = gconf.client_get_default() return client.get_bool('/desktop/sugar/power/automatic') + def print_automatic_pm(): print ('off', 'on')[get_automatic_pm()] + def set_automatic_pm(enabled): """Automatic suspends on/off.""" @@ -74,42 +79,45 @@ def set_automatic_pm(enabled): bus = dbus.SystemBus() proxy = bus.get_object(OHM_SERVICE_NAME, OHM_SERVICE_PATH) keystore = dbus.Interface(proxy, OHM_SERVICE_IFACE) - + if enabled == 'on' or enabled == 1: - keystore.SetKey("suspend.automatic_pm", 1) + keystore.SetKey('suspend.automatic_pm', 1) enabled = True elif enabled == 'off' or enabled == 0: - keystore.SetKey("suspend.automatic_pm", 0) + keystore.SetKey('suspend.automatic_pm', 0) enabled = False else: - raise ValueError(_("Error in automatic pm argument, use on/off.")) + raise ValueError(_('Error in automatic pm argument, use on/off.')) client = gconf.client_get_default() client.set_bool('/desktop/sugar/power/automatic', enabled) return + def get_extreme_pm(): client = gconf.client_get_default() return client.get_bool('/desktop/sugar/power/extreme') + def print_extreme_pm(): print ('off', 'on')[get_extreme_pm()] + def set_extreme_pm(enabled): """Extreme power management on/off.""" - + bus = dbus.SystemBus() proxy = bus.get_object(OHM_SERVICE_NAME, OHM_SERVICE_PATH) keystore = dbus.Interface(proxy, OHM_SERVICE_IFACE) - + if enabled == 'on' or enabled == 1: - keystore.SetKey("suspend.extreme_pm", 1) + keystore.SetKey('suspend.extreme_pm', 1) enabled = True elif enabled == 'off' or enabled == 0: - keystore.SetKey("suspend.extreme_pm", 0) + keystore.SetKey('suspend.extreme_pm', 0) enabled = False else: - raise ValueError(_("Error in extreme pm argument, use on/off.")) + raise ValueError(_('Error in extreme pm argument, use on/off.')) client = gconf.client_get_default() client.set_bool('/desktop/sugar/power/extreme', enabled) diff --git a/extensions/cpsection/power/view.py b/extensions/cpsection/power/view.py index 8f1ed56..fd89efa 100644 --- a/extensions/cpsection/power/view.py +++ b/extensions/cpsection/power/view.py @@ -22,6 +22,7 @@ from sugar.graphics import style from jarabe.controlpanel.sectionview import SectionView from jarabe.controlpanel.inlinealert import InlineAlert + class Power(SectionView): def __init__(self, model, alerts): SectionView.__init__(self) diff --git a/extensions/cpsection/updater/backends/aslo.py b/extensions/cpsection/updater/backends/aslo.py index 5f257f9..6504e9e 100644 --- a/extensions/cpsection/updater/backends/aslo.py +++ b/extensions/cpsection/updater/backends/aslo.py @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -'''Activity information microformat parser. +"""Activity information microformat parser. Activity information is embedded in HTML/XHTML/XML pages using a Resource Description Framework (RDF) http://www.w3.org/RDF/ . @@ -46,7 +46,7 @@ An example:: </RDF:Description> </em:targetApplication> </RDF:Description></RDF:RDF> -''' +""" import logging from xml.etree.ElementTree import XML @@ -54,6 +54,9 @@ import traceback import gio +from sugar.bundle.bundleversion import NormalizedVersion +from sugar.bundle.bundleversion import InvalidVersionError + from jarabe import config _FIND_DESCRIPTION = \ @@ -127,17 +130,17 @@ class _UpdateFetcher(object): size = None else: try: - version = int(document.find(_FIND_VERSION).text) - except ValueError: - logging.error(traceback.format_exc()) - version = 0 + version = NormalizedVersion(document.find(_FIND_VERSION).text) + except InvalidVersionError: + logging.exception('Exception occured while parsing version') + version = '0' link = document.find(_FIND_LINK).text try: size = long(document.find(_FIND_SIZE).text) * 1024 except ValueError: - logging.error(traceback.format_exc()) + logging.exception('Exception occured while parsing size') size = 0 global _fetcher @@ -146,13 +149,13 @@ class _UpdateFetcher(object): def fetch_update_info(bundle, completion_cb): - '''Queries the server for a newer version of the ActivityBundle. + """Queries the server for a newer version of the ActivityBundle. completion_cb receives bundle, version, link, size and possibly an error message: - + def completion_cb(bundle, version, link, size, error_message): - ''' + """ global _fetcher if _fetcher is not None: diff --git a/extensions/cpsection/updater/model.py b/extensions/cpsection/updater/model.py index 9845371..7ea445f 100755 --- a/extensions/cpsection/updater/model.py +++ b/extensions/cpsection/updater/model.py @@ -14,12 +14,12 @@ # 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 -'''Sugar bundle updater: model. +"""Sugar bundle updater: model. This module implements the non-GUI portions of the bundle updater, including list of installed bundls, whether updates are needed, and the URL at which to find the bundle updated. -''' +""" import os import logging @@ -33,6 +33,7 @@ import gio from sugar import env from sugar.datastore import datastore from sugar.bundle.activitybundle import ActivityBundle +from sugar.bundle.bundleversion import NormalizedVersion from jarabe.model import bundleregistry @@ -64,14 +65,16 @@ class UpdateModel(gobject.GObject): def check_updates(self): self.updates = [] - self._bundles_to_check = \ - [bundle for bundle in bundleregistry.get_registry()] + self._bundles_to_check = list(bundleregistry.get_registry()) self._check_next_update() def _check_next_update(self): total = len(bundleregistry.get_registry()) current = total - len(self._bundles_to_check) + if not self._bundles_to_check: + return False + bundle = self._bundles_to_check.pop() self.emit('progress', UpdateModel.ACTION_CHECKING, bundle.get_name(), current, total) @@ -83,7 +86,8 @@ class UpdateModel(gobject.GObject): logging.error('Error getting update information from server:\n' '%s' % error_message) - if version is not None and version > bundle.get_activity_version(): + if version is not None and \ + version > NormalizedVersion(bundle.get_activity_version()): self.updates.append(BundleUpdate(bundle, version, link, size)) if self._cancelling: @@ -196,14 +200,17 @@ class UpdateModel(gobject.GObject): logging.debug('UpdateModel._cancel_checking') total = len(bundleregistry.get_registry()) current = total - len(self._bundles_to_check) - self.emit('progress', UpdateModel.ACTION_CHECKING, '', current, current) + self.emit('progress', UpdateModel.ACTION_CHECKING, '', current, + current) self._bundles_to_check = None self._cancelling = False def _cancel_updating(self): logging.debug('UpdateModel._cancel_updating') - current = self._total_bundles_to_update - len(self._bundles_to_update) - 1 - self.emit('progress', UpdateModel.ACTION_UPDATING, '', current, current) + current = (self._total_bundles_to_update - + len(self._bundles_to_update) - 1) + self.emit('progress', UpdateModel.ACTION_UPDATING, '', current, + current) if self._downloader is not None: self._downloader.cancel() @@ -216,6 +223,7 @@ class UpdateModel(gobject.GObject): self._bundles_to_update = None self._cancelling = False + class BundleUpdate(object): def __init__(self, bundle, version, link, size): @@ -226,7 +234,7 @@ class BundleUpdate(object): class _Downloader(gobject.GObject): - _CHUNK_SIZE = 10240 # 10K + _CHUNK_SIZE = 10240 # 10K __gsignals__ = { 'progress': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, @@ -262,7 +270,7 @@ class _Downloader(gobject.GObject): except: self.emit('error', traceback.format_exc()) return - + temp_file_path = self._get_temp_file_path(self.bundle_update.link) self._output_file = gio.File(temp_file_path) self._output_stream = self._output_file.create() diff --git a/extensions/cpsection/updater/view.py b/extensions/cpsection/updater/view.py index 2164c0b..814658f 100644 --- a/extensions/cpsection/updater/view.py +++ b/extensions/cpsection/updater/view.py @@ -145,7 +145,7 @@ class ActivityUpdater(SectionView): top_message = gobject.markup_escape_text(top_message) self._top_label.set_markup('<big>%s</big>' % top_message) - + if not available_updates: self._clear_center() else: @@ -161,7 +161,8 @@ class ActivityUpdater(SectionView): self._model.check_updates() def __install_button_clicked_cb(self, button): - self._top_label.set_markup('<big>%s</big>' % _('Installing updates...')) + text = '<big>%s</big>' % _('Installing updates...') + self._top_label.set_markup(text) self._model.update(self._update_box.get_bundles_to_update()) def __cancel_button_clicked_cb(self, button): @@ -176,12 +177,13 @@ class ActivityUpdater(SectionView): self._top_label.set_markup('<big>%s</big>' % top_message) self._clear_center() - def undo(self): + def undo(self): self._model.cancel() + class ProgressPane(gtk.VBox): - '''Container which replaces the `ActivityPane` during refresh or - install.''' + """Container which replaces the `ActivityPane` during refresh or + install.""" def __init__(self): gtk.VBox.__init__(self) @@ -359,7 +361,7 @@ class UpdateListModel(gtk.ListStore): row[self.SELECTED] = True row[self.ICON_FILE_NAME] = bundle_update.bundle.get_icon() - details = _('From version %(current)d to %(new)s (Size: %(size)s)') + details = _('From version %(current)s to %(new)s (Size: %(size)s)') details = details % \ {'current': bundle_update.bundle.get_activity_version(), 'new': bundle_update.version, @@ -374,9 +376,7 @@ class UpdateListModel(gtk.ListStore): def _format_size(size): - ''' - Convert a given size in bytes to a nicer better readable unit - ''' + """Convert a given size in bytes to a nicer better readable unit""" if size == 0: # TRANS: download size is 0 return _('None') @@ -385,7 +385,7 @@ def _format_size(size): return _('1 KB') elif size < 1024 * 1024: # TRANS: download size of small updates, e.g. '250 KB' - return locale.format(_('%.0f KB'), size / 1024.0) + return locale.format_string(_('%.0f KB'), size / 1024.0) else: # TRANS: download size of updates, e.g. '2.3 MB' - return locale.format(_('%.1f MB'), size / 1024.0 / 1024) + return locale.format_string(_('%.1f MB'), size / 1024.0 / 1024) diff --git a/extensions/deviceicon/Makefile.am b/extensions/deviceicon/Makefile.am index d46ddde..118d866 100644 --- a/extensions/deviceicon/Makefile.am +++ b/extensions/deviceicon/Makefile.am @@ -5,5 +5,5 @@ sugar_PYTHON = \ battery.py \ network.py \ speaker.py \ - touchpad.py \ + touchpad.py \ volume.py diff --git a/extensions/deviceicon/battery.py b/extensions/deviceicon/battery.py index edfcce4..4c1ef37 100644 --- a/extensions/deviceicon/battery.py +++ b/extensions/deviceicon/battery.py @@ -16,8 +16,9 @@ import logging from gettext import gettext as _ -import gconf +import sys +import gconf import gobject import gtk import dbus @@ -30,6 +31,7 @@ from sugar.graphics.xocolor import XoColor from jarabe.frame.frameinvoker import FrameWidgetInvoker + _ICON_NAME = 'battery' _STATUS_CHARGING = 0 @@ -37,35 +39,38 @@ _STATUS_DISCHARGING = 1 _STATUS_FULLY_CHARGED = 2 _STATUS_NOT_PRESENT = 3 -_LEVEL_PROP = 'battery.charge_level.percentage' -_CHARGING_PROP = 'battery.rechargeable.is_charging' -_DISCHARGING_PROP = 'battery.rechargeable.is_discharging' -_PRESENT_PROP = 'battery.present' +_UP_DEVICE_IFACE = 'org.freedesktop.UPower.Device' + +_UP_TYPE_BATTERY = 2 + +_UP_STATE_UNKNOWN = 0 +_UP_STATE_CHARGING = 1 +_UP_STATE_DISCHARGING = 2 +_UP_STATE_EMPTY = 3 +_UP_STATE_FULL = 4 +_UP_STATE_CHARGE_PENDING = 5 +_UP_STATE_DISCHARGE_PENDING = 6 + +_WARN_MIN_PERCENTAGE = 15 + class DeviceView(TrayIcon): FRAME_POSITION_RELATIVE = 102 - def __init__(self, udi): - client = gconf.client_get_default() + def __init__(self, battery): + client = gconf.client_get_default() self._color = XoColor(client.get_string('/desktop/sugar/user/color')) TrayIcon.__init__(self, icon_name=_ICON_NAME, xo_color=self._color) self.set_palette_invoker(FrameWidgetInvoker(self)) - self._model = DeviceModel(udi) + self._model = DeviceModel(battery) self.palette = BatteryPalette(_('My Battery')) self.palette.set_group_id('frame') - - self._model.connect('notify::level', - self._battery_status_changed_cb) - self._model.connect('notify::charging', - self._battery_status_changed_cb) - self._model.connect('notify::discharging', - self._battery_status_changed_cb) - self._model.connect('notify::present', - self._battery_status_changed_cb) + self._model.connect('updated', + self.__battery_status_changed_cb) self._update_info() def _update_info(self): @@ -86,27 +91,30 @@ class DeviceView(TrayIcon): style.COLOR_WHITE.get_svg())) elif self._model.props.discharging: status = _STATUS_DISCHARGING - if current_level <= 15: + if current_level <= _WARN_MIN_PERCENTAGE: badge_name = 'emblem-warning' else: status = _STATUS_FULLY_CHARGED - self.icon.props.icon_name = get_icon_state(name, current_level, step=-5) + self.icon.props.icon_name = get_icon_state(name, current_level, + step=-5) self.icon.props.xo_color = xo_color self.icon.props.badge_name = badge_name - self.palette.set_level(current_level) - self.palette.set_status(status) + self.palette.set_info(current_level, self._model.props.time_remaining, + status) - def _battery_status_changed_cb(self, pspec, param): + def __battery_status_changed_cb(self, model): self._update_info() + class BatteryPalette(Palette): def __init__(self, primary_text): Palette.__init__(self, primary_text) - self._level = 0 + self._time = 0 + self._status = _STATUS_NOT_PRESENT self._progress_bar = gtk.ProgressBar() self._progress_bar.set_size_request( style.zoom(style.GRID_CELL_SIZE * 4), -1) @@ -122,130 +130,128 @@ class BatteryPalette(Palette): self._progress_widget = vbox self.set_content(self._progress_widget) - def set_level(self, percent): - self._level = percent - fraction = percent / 100.0 - self._progress_bar.set_fraction(fraction) + def set_info(self, percentage, seconds, status): + self._level = percentage + self._time = seconds + self._status = status + self._progress_bar.set_fraction(percentage / 100.0) + self._update_secondary() - def set_status(self, status): - current_level = self._level + def _update_secondary(self): secondary_text = '' - status_text = '%s%%' % current_level + status_text = '%s%%' % (self._level, ) progress_widget = self._progress_widget - if status == _STATUS_NOT_PRESENT: + if self._status == _STATUS_NOT_PRESENT: secondary_text = _('Removed') progress_widget = None - elif status == _STATUS_CHARGING: + elif self._status == _STATUS_CHARGING: secondary_text = _('Charging') - elif status == _STATUS_DISCHARGING: - if current_level <= 15: + elif self._status == _STATUS_DISCHARGING: + if self._level <= _WARN_MIN_PERCENTAGE: secondary_text = _('Very little power remaining') else: - #TODO: make this less of an wild/educated guess - minutes_remaining = int(current_level / 0.59) - remaining_hourpart = minutes_remaining / 60 + minutes_remaining = self._time // 60 + remaining_hourpart = minutes_remaining // 60 remaining_minpart = minutes_remaining % 60 secondary_text = _('%(hour)d:%(min).2d remaining') % \ {'hour': remaining_hourpart, 'min': remaining_minpart} else: secondary_text = _('Charged') + self.set_content(progress_widget) self.props.secondary_text = secondary_text self._status_label.set_text(status_text) + class DeviceModel(gobject.GObject): __gproperties__ = { - 'level' : (int, None, None, 0, 100, 0, - gobject.PARAM_READABLE), - 'charging' : (bool, None, None, False, - gobject.PARAM_READABLE), - 'discharging' : (bool, None, None, False, - gobject.PARAM_READABLE), - 'present' : (bool, None, None, False, - gobject.PARAM_READABLE) + 'level': (int, None, None, 0, 100, 0, gobject.PARAM_READABLE), + 'time-remaining': (int, None, None, 0, sys.maxint, 0, + gobject.PARAM_READABLE), # unit: seconds + 'charging': (bool, None, None, False, gobject.PARAM_READABLE), + 'discharging': (bool, None, None, False, gobject.PARAM_READABLE), + 'present': (bool, None, None, False, gobject.PARAM_READABLE), } - def __init__(self, udi): - gobject.GObject.__init__(self) - - bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) - proxy = bus.get_object('org.freedesktop.Hal', udi, - follow_name_owner_changes=True) - self._battery = dbus.Interface(proxy, 'org.freedesktop.Hal.Device') - bus.add_signal_receiver(self._battery_changed, - 'PropertyModified', - 'org.freedesktop.Hal.Device', - 'org.freedesktop.Hal', - udi) - - self._level = self._get_level() - self._charging = self._get_charging() - self._discharging = self._get_discharging() - self._present = self._get_present() - - def _get_level(self): - try: - return self._battery.GetProperty(_LEVEL_PROP) - except dbus.DBusException: - logging.error('Cannot access %s', _LEVEL_PROP) - return 0 - - def _get_charging(self): - try: - return self._battery.GetProperty(_CHARGING_PROP) - except dbus.DBusException: - logging.error('Cannot access %s', _CHARGING_PROP) - return False + __gsignals__ = { + 'updated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), + } - def _get_discharging(self): + def __init__(self, battery): + gobject.GObject.__init__(self) + self._battery = battery + self._battery_props_iface = dbus.Interface(self._battery, + dbus.PROPERTIES_IFACE) + self._battery.connect_to_signal('Changed', + self.__battery_properties_changed_cb, + dbus_interface=_UP_DEVICE_IFACE) + self._fetch_properties_from_upower() + + def _fetch_properties_from_upower(self): + """Get current values from UPower.""" + # pylint: disable=W0201 try: - return self._battery.GetProperty(_DISCHARGING_PROP) + dbus_props = self._battery_props_iface.GetAll(_UP_DEVICE_IFACE) except dbus.DBusException: - logging.error('Cannot access %s', _DISCHARGING_PROP) - return False + logging.error('Cannot access battery properties') + dbus_props = {} - def _get_present(self): - try: - return self._battery.GetProperty(_PRESENT_PROP) - except dbus.DBusException: - logging.error('Cannot access %s', _PRESENT_PROP) - return False + self._level = dbus_props.get('Percentage', 0) + self._state = dbus_props.get('State', _UP_STATE_UNKNOWN) + self._present = dbus_props.get('IsPresent', False) + self._time_to_empty = dbus_props.get('TimeToEmpty', 0) + self._time_to_full = dbus_props.get('TimeToFull', 0) def do_get_property(self, pspec): + """Return current value of given GObject property.""" if pspec.name == 'level': - return self._level + return self._level if pspec.name == 'charging': - return self._charging + return self._state == _UP_STATE_CHARGING if pspec.name == 'discharging': - return self._discharging + return self._state == _UP_STATE_DISCHARGING if pspec.name == 'present': return self._present + if pspec.name == 'time-remaining': + if self._state == _UP_STATE_CHARGING: + return self._time_to_full + if self._state == _UP_STATE_DISCHARGING: + return self._time_to_empty + return 0 def get_type(self): return 'battery' - def _battery_changed(self, num_changes, changes_list): - for change in changes_list: - if change[0] == _LEVEL_PROP: - self._level = self._get_level() - self.notify('level') - elif change[0] == _CHARGING_PROP: - self._charging = self._get_charging() - self.notify('charging') - elif change[0] == _DISCHARGING_PROP: - self._discharging = self._get_discharging() - self.notify('discharging') - elif change[0] == _PRESENT_PROP: - self._present = self._get_present() - self.notify('present') + def __battery_properties_changed_cb(self): + old_level = self._level + old_state = self._state + old_present = self._present + old_time = self.props.time_remaining + self._fetch_properties_from_upower() + if self._level != old_level: + self.notify('level') + if self._state != old_state: + self.notify('charging') + self.notify('discharging') + if self._present != old_present: + self.notify('present') + if self.props.time_remaining != old_time: + self.notify('time-remaining') + + self.emit('updated') + def setup(tray): bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) - proxy = bus.get_object('org.freedesktop.Hal', - '/org/freedesktop/Hal/Manager') - hal_manager = dbus.Interface(proxy, 'org.freedesktop.Hal.Manager') - - for udi in hal_manager.FindDeviceByCapability('battery'): - tray.add_device(DeviceView(udi)) + up_proxy = bus.get_object('org.freedesktop.UPower', + '/org/freedesktop/UPower') + upower = dbus.Interface(up_proxy, 'org.freedesktop.UPower') + + for device_path in upower.EnumerateDevices(): + device = bus.get_object('org.freedesktop.UPower', device_path) + device_prop_iface = dbus.Interface(device, dbus.PROPERTIES_IFACE) + device_type = device_prop_iface.Get(_UP_DEVICE_IFACE, 'Type') + if device_type == _UP_TYPE_BATTERY: + tray.add_device(DeviceView(device)) diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py index 0789f9c..4c4f339 100644 --- a/extensions/deviceicon/network.py +++ b/extensions/deviceicon/network.py @@ -23,7 +23,6 @@ import logging import hashlib import socket import struct -import re import datetime import time import gtk @@ -40,16 +39,14 @@ from sugar.graphics.tray import TrayIcon from sugar.graphics.menuitem import MenuItem from sugar.graphics.icon import Icon from sugar.graphics import xocolor -from sugar.util import unique_id from sugar import profile from jarabe.model import network -from jarabe.model.network import Settings -from jarabe.model.network import IP4Config from jarabe.frame.frameinvoker import FrameWidgetInvoker from jarabe.view.pulsingicon import PulsingIcon -IP_ADDRESS_TEXT_TEMPLATE = _("IP address: %s") + +IP_ADDRESS_TEXT_TEMPLATE = _('IP address: %s') _NM_SERVICE = 'org.freedesktop.NetworkManager' _NM_IFACE = 'org.freedesktop.NetworkManager' @@ -73,8 +70,8 @@ class WirelessPalette(Palette): __gtype_name__ = 'SugarWirelessPalette' __gsignals__ = { - 'deactivate-connection' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])) + 'deactivate-connection': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([])), } def __init__(self, primary_text): @@ -107,7 +104,8 @@ class WirelessPalette(Palette): self._disconnect_item = MenuItem(_('Disconnect...')) icon = Icon(icon_size=gtk.ICON_SIZE_MENU, icon_name='media-eject') self._disconnect_item.set_image(icon) - self._disconnect_item.connect('activate', self.__disconnect_activate_cb) + self._disconnect_item.connect('activate', + self.__disconnect_activate_cb) self.menu.append(self._disconnect_item) def set_connecting(self): @@ -141,7 +139,7 @@ class WirelessPalette(Palette): self._set_channel(channel) def _set_channel(self, channel): - self._channel_label.set_text("%s: %d" % (_("Channel"), channel)) + self._channel_label.set_text('%s: %d' % (_('Channel'), channel)) def _set_ip_address(self, ip_address): if ip_address is not None: @@ -189,7 +187,7 @@ class WiredPalette(Palette): def _inet_ntoa(self, iaddress): address = ['%s' % ((iaddress >> i) % 256) for i in [0, 8, 16, 24]] - return ".".join(address) + return '.'.join(address) def _set_ip_address(self, ip_address): if ip_address is not None: @@ -199,14 +197,13 @@ class WiredPalette(Palette): ip_address_text = "" self._ip_address_label.set_text(ip_address_text) + class GsmPalette(Palette): __gtype_name__ = 'SugarGsmPalette' __gsignals__ = { - 'gsm-connect' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), - 'gsm-disconnect' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), + 'gsm-connect': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), + 'gsm-disconnect': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), } def __init__(self): @@ -302,7 +299,7 @@ class GsmPalette(Palette): icon = Icon(icon_name='media-eject', \ icon_size=gtk.ICON_SIZE_MENU) self._toggle_state_item.set_image(icon) - + elif self._current_state == _GSM_STATE_FAILED: message_error = self._get_error_by_nm_reason(reason) self.add_alert(message_error[0], message_error[1]) @@ -327,7 +324,8 @@ class GsmPalette(Palette): def add_alert(self, error, suggestion): self._failed_connection = True - self._toggle_state_item.get_child().set_label(_('Try connection again')) + action = _('Try connection again') + self._toggle_state_item.get_child().set_label(action) title = _('Error: %s') % error self.error_title_label.set_markup('<b>%s</b>' % title) @@ -347,8 +345,8 @@ class GsmPalette(Palette): def update_stats(self, in_bytes, out_bytes): in_KBytes = in_bytes / 1024 out_KBytes = out_bytes / 1024 - self._data_label_up.set_text(_("%d KB") % (out_KBytes)) - self._data_label_down.set_text(_("%d KB") % (in_KBytes)) + self._data_label_up.set_text(_('%d KB') % (out_KBytes)) + self._data_label_down.set_text(_('%d KB') % (in_KBytes)) def _get_error_by_nm_reason(self, reason): if reason in [network.NM_DEVICE_STATE_REASON_NO_SECRETS, @@ -390,8 +388,8 @@ class WirelessDeviceView(ToolButton): self._icon = PulsingIcon() self._icon.props.icon_name = get_icon_state('network-wireless', 0) - self._inactive_color = xocolor.XoColor( \ - "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(), + self._inactive_color = xocolor.XoColor( + '%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) self._icon.props.pulse_color = self._inactive_color self._icon.props.base_color = self._inactive_color @@ -406,9 +404,9 @@ class WirelessDeviceView(ToolButton): self.set_palette(self._palette) self._palette.set_group_id('frame') - self._device_props = dbus.Interface(self._device, - 'org.freedesktop.DBus.Properties') - self._device_props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, + self._device_props = dbus.Interface(self._device, + dbus.PROPERTIES_IFACE) + self._device_props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, reply_handler=self.__get_device_props_reply_cb, error_handler=self.__get_device_props_error_cb) @@ -448,7 +446,7 @@ class WirelessDeviceView(ToolButton): return self._active_ap_op = active_ap_op active_ap = self._bus.get_object(_NM_SERVICE, active_ap_op) - props = dbus.Interface(active_ap, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(active_ap, dbus.PROPERTIES_IFACE) props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True, reply_handler=self.__get_all_ap_props_reply_cb, @@ -497,7 +495,7 @@ class WirelessDeviceView(ToolButton): digest = hash(sha_hash.digest()) index = digest % len(xocolor.colors) - self._color = xocolor.XoColor('%s,%s' % + self._color = xocolor.XoColor('%s,%s' % (xocolor.colors[index][0], xocolor.colors[index][1])) self._update() @@ -510,7 +508,7 @@ class WirelessDeviceView(ToolButton): def _update(self): if self._flags == network.NM_802_11_AP_FLAGS_PRIVACY: - self._icon.props.badge_name = "emblem-locked" + self._icon.props.badge_name = 'emblem-locked' else: self._icon.props.badge_name = None @@ -552,7 +550,8 @@ class WirelessDeviceView(ToolButton): self._icon.props.pulsing = True elif state == network.DEVICE_STATE_ACTIVATED: address = self._device_props.Get(_NM_DEVICE_IFACE, 'Ip4Address') - self._palette.set_connected_with_frequency(self._frequency, address) + self._palette.set_connected_with_frequency(self._frequency, + address) self._icon.props.pulsing = False else: self._icon.props.badge_name = None @@ -565,21 +564,12 @@ class WirelessDeviceView(ToolButton): self._icon.props.base_color = self._color def __deactivate_connection_cb(self, palette, data=None): - if self._active_ap_op is not None: - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) - netmgr_props = dbus.Interface( - netmgr, 'org.freedesktop.DBus.Properties') - active_connections_o = netmgr_props.Get(_NM_IFACE, - 'ActiveConnections') - - for conn_o in active_connections_o: - obj = self._bus.get_object(_NM_IFACE, conn_o) - props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject') - if ap_op == self._active_ap_op: - netmgr.DeactivateConnection(conn_o) - break + if self._mode == network.NM_802_11_MODE_INFRA: + connection = network.find_connection_by_ssid(self._name) + if connection: + connection.disable_autoconnect() + + network.disconnect_access_points([self._active_ap_op]) def __activate_reply_cb(self, connection): logging.debug('Network created: %s', connection) @@ -602,8 +592,8 @@ class OlpcMeshDeviceView(ToolButton): self._channel = 0 self._icon = PulsingIcon(icon_name=self._ICON_NAME) - self._inactive_color = xocolor.XoColor( \ - "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(), + self._inactive_color = xocolor.XoColor( + '%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) self._icon.props.pulse_color = profile.get_color() self._icon.props.base_color = self._inactive_color @@ -612,7 +602,7 @@ class OlpcMeshDeviceView(ToolButton): self._icon.show() self.set_palette_invoker(FrameWidgetInvoker(self)) - self._palette = WirelessPalette(_("Mesh Network")) + self._palette = WirelessPalette(_('Mesh Network')) self._palette.connect('deactivate-connection', self.__deactivate_connection) self.set_palette(self._palette) @@ -621,7 +611,7 @@ class OlpcMeshDeviceView(ToolButton): self.update_state(state) self._device_props = dbus.Interface(self._device, - 'org.freedesktop.DBus.Properties') + dbus.PROPERTIES_IFACE) self._device_props.Get(_NM_OLPC_MESH_IFACE, 'ActiveChannel', reply_handler=self.__get_active_channel_reply_cb, error_handler=self.__get_active_channel_error_cb) @@ -655,7 +645,7 @@ class OlpcMeshDeviceView(ToolButton): def _update_text(self): channel = str(self._channel) - text = _("Mesh Network %s") % glib.markup_escape_text(channel) + text = _('Mesh Network %s') % glib.markup_escape_text(channel) self._palette.props.primary_text = text def _update(self): @@ -683,21 +673,21 @@ class OlpcMeshDeviceView(ToolButton): def __deactivate_connection(self, palette, data=None): obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) netmgr = dbus.Interface(obj, _NM_IFACE) - netmgr_props = dbus.Interface(netmgr, 'org.freedesktop.DBus.Properties') + netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE) active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections') for conn_o in active_connections_o: # The connection path for a mesh connection is the device itself. obj = self._bus.get_object(_NM_IFACE, conn_o) - props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject') try: obj = self._bus.get_object(_NM_IFACE, ap_op) - props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') - if type == network.DEVICE_TYPE_802_11_OLPC_MESH: + props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) + device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') + if device_type == network.DEVICE_TYPE_802_11_OLPC_MESH: netmgr.DeactivateConnection(conn_o) break except dbus.exceptions.DBusException: @@ -749,6 +739,7 @@ class GsmDeviceView(TrayIcon): signal_name='PppStats', path=self._device.object_path, dbus_interface=_NM_SERIAL_IFACE) + def create_palette(self): palette = GsmPalette() @@ -758,7 +749,7 @@ class GsmDeviceView(TrayIcon): self._palette = palette - props = dbus.Interface(self._device, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, reply_handler=self.__current_state_check_cb, error_handler=self.__current_state_check_error_cb) @@ -791,12 +782,12 @@ class GsmDeviceView(TrayIcon): def __gsm_disconnect_cb(self, palette, data=None): obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) netmgr = dbus.Interface(obj, _NM_IFACE) - netmgr_props = dbus.Interface(netmgr, 'org.freedesktop.DBus.Properties') + netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE) active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections') for conn_o in active_connections_o: obj = self._bus.get_object(_NM_IFACE, conn_o) - props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) devices = props.Get(_NM_ACTIVE_CONN_IFACE, 'Devices') if self._device.object_path in devices: netmgr.DeactivateConnection( @@ -961,7 +952,7 @@ class WiredDeviceObserver(object): self._device_view = None self._tray = tray - props = dbus.Interface(self._device, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, reply_handler=self.__get_device_props_reply_cb, error_handler=self.__get_device_props_error_cb) @@ -989,8 +980,7 @@ class WiredDeviceObserver(object): def _update_state(self, state): if state == network.DEVICE_STATE_ACTIVATED: - props = dbus.Interface(self._device, - 'org.freedesktop.DBus.Properties') + props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) address = props.Get(_NM_DEVICE_IFACE, 'Ip4Address') speed = props.Get(_NM_WIRED_IFACE, 'Speed') self._device_view = WiredDeviceView(speed, address) @@ -1001,6 +991,7 @@ class WiredDeviceObserver(object): del self._device_view self._device_view = None + class GsmDeviceObserver(object): def __init__(self, device, tray): self._device = device @@ -1015,6 +1006,7 @@ class GsmDeviceObserver(object): self._tray.remove_device(self._device_view) self._device_view = None + class NetworkManagerObserver(object): def __init__(self, tray): self._bus = dbus.SystemBus() @@ -1048,7 +1040,7 @@ class NetworkManagerObserver(object): def _check_device(self, device_op): nm_device = self._bus.get_object(_NM_SERVICE, device_op) - props = dbus.Interface(nm_device, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(nm_device, dbus.PROPERTIES_IFACE) device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') if device_type == network.DEVICE_TYPE_802_3_ETHERNET: @@ -1073,5 +1065,6 @@ class NetworkManagerObserver(object): device.disconnect() del self._devices[device_op] + def setup(tray): device_observer = NetworkManagerObserver(tray) diff --git a/extensions/deviceicon/speaker.py b/extensions/deviceicon/speaker.py index 3a54464..d396bfb 100644 --- a/extensions/deviceicon/speaker.py +++ b/extensions/deviceicon/speaker.py @@ -32,12 +32,13 @@ from jarabe.model import sound _ICON_NAME = 'speaker' + class DeviceView(TrayIcon): FRAME_POSITION_RELATIVE = 103 def __init__(self): - client = gconf.client_get_default() + client = gconf.client_get_default() self._color = XoColor(client.get_string('/desktop/sugar/user/color')) TrayIcon.__init__(self, icon_name=_ICON_NAME, xo_color=self._color) @@ -70,22 +71,24 @@ class DeviceView(TrayIcon): xo_color = XoColor('%s,%s' % (style.COLOR_WHITE.get_svg(), style.COLOR_WHITE.get_svg())) - self.icon.props.icon_name = get_icon_state(name, current_level, step=-1) + self.icon.props.icon_name = get_icon_state(name, current_level, + step=-1) self.icon.props.xo_color = xo_color def __button_release_event_cb(self, widget, event): - if event.button == 1: - self._model.props.muted = not self._model.props.muted - return True - else: + if event.button != 1: return False + self.palette_invoker.notify_right_click() + return True + def __expose_event_cb(self, *args): self._update_info() def __speaker_status_changed_cb(self, pspec_, param_): self._update_info() + class SpeakerPalette(Palette): def __init__(self, primary_text, model): @@ -167,10 +170,11 @@ class SpeakerPalette(Palette): self._update_level() self._update_muted() + class DeviceModel(gobject.GObject): __gproperties__ = { - 'level' : (int, None, None, 0, 100, 0, gobject.PARAM_READWRITE), - 'muted' : (bool, None, None, False, gobject.PARAM_READWRITE), + 'level': (int, None, None, 0, 100, 0, gobject.PARAM_READWRITE), + 'muted': (bool, None, None, False, gobject.PARAM_READWRITE), } def __init__(self): @@ -201,16 +205,17 @@ class DeviceModel(gobject.GObject): return 'speaker' def do_get_property(self, pspec): - if pspec.name == "level": + if pspec.name == 'level': return self._get_level() - elif pspec.name == "muted": + elif pspec.name == 'muted': return self._get_muted() def do_set_property(self, pspec, value): - if pspec.name == "level": + if pspec.name == 'level': self._set_level(value) - elif pspec.name == "muted": + elif pspec.name == 'muted': self._set_muted(value) + def setup(tray): tray.add_device(DeviceView()) diff --git a/extensions/deviceicon/touchpad.py b/extensions/deviceicon/touchpad.py index d9521c2..b3b34f5 100644 --- a/extensions/deviceicon/touchpad.py +++ b/extensions/deviceicon/touchpad.py @@ -33,10 +33,14 @@ from jarabe.frame.frameinvoker import FrameWidgetInvoker TOUCHPAD_MODE_CAPACITIVE = 'capacitive' TOUCHPAD_MODE_RESISTIVE = 'resistive' TOUCHPAD_MODES = [TOUCHPAD_MODE_CAPACITIVE, TOUCHPAD_MODE_RESISTIVE] -STATUS_TEXT = {TOUCHPAD_MODE_CAPACITIVE: _('finger'), - TOUCHPAD_MODE_RESISTIVE: _('stylus')} -STATUS_ICON = {TOUCHPAD_MODE_CAPACITIVE: 'touchpad-' + TOUCHPAD_MODE_CAPACITIVE, - TOUCHPAD_MODE_RESISTIVE: 'touchpad-' + TOUCHPAD_MODE_RESISTIVE} +STATUS_TEXT = { + TOUCHPAD_MODE_CAPACITIVE: _('finger'), + TOUCHPAD_MODE_RESISTIVE: _('stylus'), +} +STATUS_ICON = { + TOUCHPAD_MODE_CAPACITIVE: 'touchpad-' + TOUCHPAD_MODE_CAPACITIVE, + TOUCHPAD_MODE_RESISTIVE: 'touchpad-' + TOUCHPAD_MODE_RESISTIVE, +} # NODE_PATH is used to communicate with the touchpad device. NODE_PATH = '/sys/devices/platform/i8042/serio1/ptmode' diff --git a/extensions/deviceicon/volume.py b/extensions/deviceicon/volume.py index e7f62a2..ea2377d 100644 --- a/extensions/deviceicon/volume.py +++ b/extensions/deviceicon/volume.py @@ -28,8 +28,10 @@ from jarabe.journal import journalactivity from jarabe.view.palettes import VolumePalette from jarabe.frame.frameinvoker import FrameWidgetInvoker + _icons = {} + class DeviceView(TrayIcon): FRAME_POSITION_RELATIVE = 500 @@ -70,9 +72,11 @@ class DeviceView(TrayIcon): journal.reveal() return True + def setup(tray): gobject.idle_add(_setup_volumes, tray) + def _setup_volumes(tray): volume_monitor = gio.volume_monitor_get() @@ -86,9 +90,11 @@ def _setup_volumes(tray): volume_monitor.connect('mount-added', _mount_added_cb, tray) volume_monitor.connect('mount-removed', _mount_removed_cb, tray) + def _volume_added_cb(volume_monitor, volume, tray): _mount(volume, tray) + def _mount(volume, tray): # Follow Nautilus behaviour here # since it has the same issue with removable device @@ -102,20 +108,23 @@ def _mount(volume, tray): #TODO: pass None as mount_operation, or better, SugarMountOperation volume.mount(gtk.MountOperation(tray.get_toplevel()), _mount_cb) + def _mount_cb(volume, result): logging.debug('_mount_cb %r %r', volume, result) volume.mount_finish(result) + def _mount_added_cb(volume_monitor, mount, tray): _add_device(mount, tray) + def _mount_removed_cb(volume_monitor, mount, tray): icon = _icons[mount] tray.remove_device(icon) del _icons[mount] + def _add_device(mount, tray): icon = DeviceView(mount) _icons[mount] = icon tray.add_device(icon) - diff --git a/extensions/globalkey/screenshot.py b/extensions/globalkey/screenshot.py index 8b4d4c2..0afe964 100644 --- a/extensions/globalkey/screenshot.py +++ b/extensions/globalkey/screenshot.py @@ -17,7 +17,6 @@ import os import tempfile -import time from gettext import gettext as _ import gtk @@ -31,6 +30,7 @@ from jarabe.model import shell BOUND_KEYS = ['<alt>1', 'Print'] + def handle_key_press(key): tmp_dir = os.path.join(env.get_profile_path(), 'data') fd, file_path = tempfile.mkstemp(dir=tmp_dir) @@ -45,7 +45,7 @@ def handle_key_press(key): height=height) screenshot.get_from_drawable(window, window.get_colormap(), x_orig, y_orig, 0, 0, width, height) - screenshot.save(file_path, "png") + screenshot.save(file_path, 'png') client = gconf.client_get_default() color = client.get_string('/desktop/sugar/user/color') @@ -87,14 +87,15 @@ def handle_key_press(key): jobject.destroy() del jobject + def _get_preview_data(screenshot): preview = screenshot.scale_simple(style.zoom(300), style.zoom(225), gtk.gdk.INTERP_BILINEAR) preview_data = [] + def save_func(buf, data): data.append(buf) preview.save_to_callback(save_func, 'png', user_data=preview_data) return dbus.ByteArray(''.join(preview_data)) - diff --git a/extensions/globalkey/viewsource.py b/extensions/globalkey/viewsource.py index df3cd9e..96e7c6b 100644 --- a/extensions/globalkey/viewsource.py +++ b/extensions/globalkey/viewsource.py @@ -18,8 +18,10 @@ from jarabe.view.viewsource import setup_view_source from jarabe.model import shell + BOUND_KEYS = ['0xEC', '<alt><shift>v'] + def handle_key_press(key): shell_model = shell.get_model() activity = shell_model.get_active_activity() |