> +def read_touchpad_mode(): > + """ Read the touchpad mode from the node path. """ > + node_file_handle = open(NODE_PATH, "r") > + text = node_file_handle.read() > + node_file_handle.close()
.... > + > + > +def write_touchpad_mode(touchpad): > + """ Write the touchpad mode to the node path. """ > + touchpad_mode_index = TOUCHPAD_MODES.index(touchpad) > + > + node_file_handle = open(NODE_PATH, "w") > + node_file_handle.write(str(touchpad_mode_index)) > + node_file_handle.close() ... > + > + if touchpad_mode_index == 0: > + if os.path.exists(FLAG_PATH): > + os.remove(FLAG_PATH) > + else: > + flag_file_handle = open(FLAG_PATH, "w") > + flag_file_handle.close() Maybe s/"w"/'w'/ and s/"r"/'r'/ ;-) ? I missed reporting this earlier. On Fri, Jul 9, 2010 at 10:28 AM, Walter Bender <walter.ben...@gmail.com> wrote: > I think I addressed all of the issues raised by Marco and Anish: > > --- > extensions/deviceicon/touchpad.py | 129 > +++++++++++++++++++++++++++++++++++++ > 1 files changed, 129 insertions(+), 0 deletions(-) > create mode 100644 extensions/deviceicon/touchpad.py > > diff --git a/extensions/deviceicon/touchpad.py > b/extensions/deviceicon/touchpad.py > new file mode 100644 > index 0000000..a182d9c > --- /dev/null > +++ b/extensions/deviceicon/touchpad.py > @@ -0,0 +1,129 @@ > +# Copyright (C) 2010, Walter Bender, Sugar Labs > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 2 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write to the Free Software > +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > + > + > +from gettext import gettext as _ > + > +import gtk > +import gconf > +import os > + > +from sugar.graphics.tray import TrayIcon > +from sugar.graphics.xocolor import XoColor > +from sugar.graphics.palette import Palette > +from sugar.graphics import style > + > +from jarabe.frame.frameinvoker import FrameWidgetInvoker > + > +TOUCHPAD_MODES = ['capacitive', 'resistive'] > +STATUS_TEXT = {TOUCHPAD_MODES[0]: _('finger'), TOUCHPAD_MODES[1]: > _('stylus')} > +STATUS_ICON = {TOUCHPAD_MODES[0]: 'touchpad-' + TOUCHPAD_MODES[0], > + TOUCHPAD_MODES[1]: 'touchpad-' + TOUCHPAD_MODES[1]} > +# FLAG_PATH is used to preserve status between boots. > +FLAG_PATH = '/home/olpc/.olpc-pentablet-mode' > +# NODE_PATH is used to communicate with the touchpad device. > +NODE_PATH = '/sys/devices/platform/i8042/serio1/ptmode' > + > +class DeviceView(TrayIcon): > + """ Manage the touchpad mode from the device palette on the Frame. """ > + > + FRAME_POSITION_RELATIVE = 500 > + > + def __init__(self): > + """ Create the touchpad palette and display it on Frame. """ > + icon_name = STATUS_ICON[read_touchpad_mode()] > + > + client = gconf.client_get_default() > + color = XoColor(client.get_string('/desktop/sugar/user/color')) > + TrayIcon.__init__(self, icon_name=icon_name, xo_color=color) > + > + self.set_palette_invoker(FrameWidgetInvoker(self)) > + self.connect('button-release-event', self.__button_release_event_cb) > + > + def create_palette(self): > + """ On create, set the current mode """ > + self.palette = ResourcePalette(_('My touchpad'), self.icon) > + self.palette.set_group_id('frame') > + return self.palette > + > + def __button_release_event_cb(self, widget, event): > + """ On button release, switch modes """ > + self.palette.toggle_mode() > + return True > + > + > +class ResourcePalette(Palette): > + """ Query the current state of the touchpad and update the display. """ > + > + def __init__(self, primary_text, icon): > + """ Get the status. """ > + Palette.__init__(self, label=primary_text) > + > + self._icon = icon > + > + vbox = gtk.VBox() > + self.set_content(vbox) > + > + self._status_text = gtk.Label() > + vbox.pack_start(self._status_text, padding=style.DEFAULT_PADDING) > + self._status_text.show() > + > + vbox.show() > + > + self._mode = read_touchpad_mode() > + self._update() > + > + def _update(self): > + """ Update the label and icon based on the current mode. """ > + self._status_text.set_label(STATUS_TEXT[self._mode]) > + self._icon.props.icon_name = STATUS_ICON[self._mode] > + > + def toggle_mode(self): > + """ On mouse click, toggle the mode. """ > + self._mode = TOUCHPAD_MODES[1 - TOUCHPAD_MODES.index(self._mode)] > + write_touchpad_mode(self._mode) > + self._update() > + > + > +def setup(tray): > + """ Only appears when the device exisits """ > + if os.path.exists(NODE_PATH): > + tray.add_device(DeviceView()) > + > + > +def read_touchpad_mode(): > + """ Read the touchpad mode from the node path. """ > + node_file_handle = open(NODE_PATH, "r") > + text = node_file_handle.read() > + node_file_handle.close() > + > + return TOUCHPAD_MODES[int(text[0])] > + > + > +def write_touchpad_mode(touchpad): > + """ Write the touchpad mode to the node path. """ > + touchpad_mode_index = TOUCHPAD_MODES.index(touchpad) > + > + node_file_handle = open(NODE_PATH, "w") > + node_file_handle.write(str(touchpad_mode_index)) > + node_file_handle.close() > + > + if touchpad_mode_index == 0: > + if os.path.exists(FLAG_PATH): > + os.remove(FLAG_PATH) > + else: > + flag_file_handle = open(FLAG_PATH, "w") > + flag_file_handle.close() > > > -walter > > On Thu, Jul 8, 2010 at 7:19 PM, Marco Pesenti Gritti <ma...@marcopg.org> > wrote: >> On 8 Jul 2010, at 17:23, Walter Bender <walter.ben...@gmail.com> wrote: >> >> --- >> extensions/deviceicon/touchpad.py | 152 >> +++++++++++++++++++++++++++++++++++++ >> 1 files changed, 152 insertions(+), 0 deletions(-) >> create mode 100644 extensions/deviceicon/touchpad.py >> >> diff --git a/extensions/deviceicon/touchpad.py >> b/extensions/deviceicon/touchpad.py >> new file mode 100644 >> index 0000000..a182d9c >> --- /dev/null >> +++ b/extensions/deviceicon/touchpad.py >> @@ -0,0 +1,152 @@ >> +# Copyright (C) 2010, Walter Bender, Sugar Labs >> +# >> +# This program is free software; you can redistribute it and/or modify >> +# it under the terms of the GNU General Public License as published by >> +# the Free Software Foundation; either version 2 of the License, or >> +# (at your option) any later version. >> +# >> +# This program is distributed in the hope that it will be useful, >> +# but WITHOUT ANY WARRANTY; without even the implied warranty of >> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> +# GNU General Public License for more details. >> +# >> +# You should have received a copy of the GNU General Public License >> +# along with this program; if not, write to the Free Software >> +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 >> USA >> + >> + >> +from gettext import gettext as _ >> + >> +import gtk >> +import gconf >> +from os import system, path, remove >> >> The os import should be in the first block. I wouldn't import the methods, >> prepending os. to the actual calls makes it clearer what the methods are >> doing. >> >> +from sugar.graphics.tray import TrayIcon >> +from sugar.graphics.xocolor import XoColor >> +from sugar.graphics.palette import Palette >> +from jarabe.frame.frameinvoker import FrameWidgetInvoker >> + >> >> The jarabe import should be in a separate block. >> >> +_STATUS_TEXT = {'capacitive': _('finger'), 'resistive': _('stylus')} >> +_CAPACITIVE_ICON_NAME = 'touchpad-capacitive' >> +_RESISTIVE_ICON_NAME = 'touchpad-resistive' >> +_FLAG_PATH = '/home/olpc/.olpc-pentablet-mode' >> +_NODE_PATH = '/sys/devices/platform/i8042/serio1/ptmode' >> >> I think we don't need to mark these has private, the plugins code is not >> imported by other modules, so private/public doesn't matter. >> >> + >> + >> >> One less new line :) I'm sure everyone has been missing my nitpicks! >> >> +class DeviceView(TrayIcon): >> + """ Manage the touchpad mode from the device palette on the Frame """ >> + >> + FRAME_POSITION_RELATIVE = 500 >> + >> + def __init__(self): >> + """ Create the touchpad palette and display it on Frame """ >> + >> + # Only appears when the device exisits >> + if not path.exists(_NODE_PATH): >> + return >> + >> >> Aborting constructions looks wrong, better to move the check to the setup >> method. >> >> + if get_touchpad() == 'resistive': >> + icon_name = _RESISTIVE_ICON_NAME >> + else: >> + icon_name = _CAPACITIVE_ICON_NAME >> >> It would be nice to use a dictionary like you did with the label. >> >> + >> + client = gconf.client_get_default() >> + color = XoColor(client.get_string('/desktop/sugar/user/color')) >> + TrayIcon.__init__(self, icon_name=icon_name, xo_color= >> >> Splitting the blocks with a new line here would be more readable. >> >> + self.set_palette_invoker(FrameWidgetInvoker(self)) >> + self.connect('button-release-event', >> self.__button_release_event_cb) >> + self.connect('expose-event', self.__expose_event_cb) >> + >> + def create_palette(self): >> + """ On create, set the current mode """ >> + self.palette = ResourcePalette(_('My touchpad'), self.icon) >> + self.palette.set_group_id('frame') >> + return self.palette >> + >> + def __button_release_event_cb(self, widget, event): >> + """ On button release, switch modes """ >> + self.palette.toggle_mode() >> + return True >> + >> + def __expose_event_cb(self, *args): >> + pass >> >> >> Leftover? Seems unnecessary to connect the signal since you are just passing >> then. >> >> + >> +class ResourcePalette(Palette): >> + """ Query the current state of the touchpad and update the display """ >> + >> + def __init__(self, primary_text, icon): >> + """ Get the status """ >> + Palette.__init__(self, label=primary_text) >> + >> + self._icon = icon >> + >> + self.connect('popup', self.__popup_cb) >> + self.connect('popdown', self.__popdown_cb) >> + >> + self.updating = False >> + >> + vbox = gtk.VBox() >> + self.set_content(vbox) >> + >> + self._status_text = gtk.Label() >> + vbox.pack_start(self._status_text, padding=10) >> + self._status_text.show() >> + >> + vbox.show() >> + >> + self._mode = get_touchpad() >> + self.set_mode_graphics() >> + >> + def set_mode_graphics(self): >> >> Looks like this can be marked as private? update would be more appropriate >> then set since you are not passing a mode. >> >> + """ Set the label and icon based on the current mode """ >> + self._status_text.set_label(_STATUS_TEXT[self._mode]) >> + if self._mode == 'resistive': >> + self._icon.props.icon_name = _RESISTIVE_ICON_NAME >> + else: >> + self._icon.props.icon_name = _CAPACITIVE_ICON_NAME >> + >> + def toggle_mode(self): >> + """ On mouse click, toggle the mode """ >> + if self._mode == 'capacitive': >> + self._mode = 'resistive' >> + else: >> + self._mode = 'capacitive' >> + >> + set_touchpad(self._mode) >> >> I would write the new mode before assigning it to the object property so >> that if something goes wrong and we trace back, state doesn't go out of >> sync. >> >> + self.set_mode_graphics() >> + >> + def __popup_cb(self, gobject): >> + self.updating = True >> + >> + def __popdown_cb(self, gobject): >> + self.updating = False >> >> >> What does the updating property do? Is it a Palette thing? >> >> + >> +def setup(tray): >> + tray.add_device(DeviceView()) >> + >> + >> +def get_touchpad(): >> >> I think naming it read_touchpad_mode would be more clear >> >> + """ Get the touchpad mode. """ >> + _file_handle = open(_NODE_PATH, "r") >> + _text = _file_handle.read() >> + _file_handle.close() >> >> >> It seems unnecessary to mark these variables as private? >> >> >> + if _text[0] == '1': >> + return 'resistive' >> + else: >> + return 'capacitive' >> >> It would be nicer to use an enumeration for these instead of raw strings. >> >> + >> +def set_touchpad(touchpad): >> >> Suggest write_touchpad_mode >> >> + """ Set the touchpad mode. """ >> + if touchpad == 'capacitive': >> + if path.exists(_FLAG_PATH): >> + remove(_FLAG_PATH) >> >> Why do we need this flag? >> >> + system("echo 0 > %s" % (_NODE_PATH)) >> >> It would be better to use python to write instead of forking echo. >> >> + else: >> + _file_handle = open(_FLAG_PATH, "w") >> + _file_handle.close() >> >> Marking variable as private seems unnecessary. >> >> + system("echo 1 > %s" % (_NODE_PATH)) >> >> Same as above. >> >> + return >> >> I guess this is a leftover, we are exiting the function anyway. >> >> > > > > -- > Walter Bender > Sugar Labs > http://www.sugarlabs.org > _______________________________________________ > Sugar-devel mailing list > Sugar-devel@lists.sugarlabs.org > http://lists.sugarlabs.org/listinfo/sugar-devel > _______________________________________________ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel