[Sugar-devel] [PATCH 1/3] Touchpad extension for the frame

Marco Pesenti Gritti marco at marcopg.org
Thu Jul 8 19:19:39 EDT 2010


On 8 Jul 2010, at 17:23, Walter Bender <walter.bender at 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.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.sugarlabs.org/archive/sugar-devel/attachments/20100709/9edfbf71/attachment-0001.htm 


More information about the Sugar-devel mailing list