[Sugar-devel] #1686 UNSP: Accessibility - virtual keyboard
Tomeu Vizoso
tomeu at tomeuvizoso.net
Wed May 26 05:01:46 EDT 2010
On Sun, May 23, 2010 at 21:46, Michael Stone <michael at laptop.org> wrote:
> On Sun, May 23, 2010 at 03:18:47PM -0400, Michael Stone wrote:
>>
>> On Wed, May 19, 2010 at 03:10:52PM +0200, Tomeu Vizoso wrote:
>>>
>>> On Sat, May 15, 2010 at 23:48, Sugar Labs Bugs
>>> <bugtracker-noreply at sugarlabs.org> wrote:
>>>>
>>>> #1686: Accessibility - virtual keyboard
>>>>
>>>> ------------------------------------------+---------------------------------
>>>> Reporter: earias | Owner: tomeu
>>>> Type: defect | Status: new
>>>> Priority: Unspecified by Maintainer | Milestone: Unspecified
>>>> by Release Team
>>>> Component: sugar | Version: Unspecified
>>>> Severity: Unspecified | Keywords: r?
>>>> Distribution: Unspecified | Status_field: Unconfirmed
>>>>
>>>> ------------------------------------------+---------------------------------
>>>> Changes (by bernie):
>>>>
>>>> * keywords: => r?
>>>>
>>>>
>>>> Comment:
>>>>
>>>> Can someone please review this patch?
>>>
>>> Any volunteers in the mailing list?
>>
>> I'll offer a couple of observations. First, though, I'll reproduce the
>> patch
>> inline so that I can reply inline and so that everyone can take a good
>> look at
>> it.
>>
>> Michael
>>
>> From 6781e1bec2c387a740aafe0943c0aa9250482e1a Mon Sep 17 00:00:00 2001
>> From: Esteban <earias at localhost.localdomain>
>> Date: Mon, 25 Jan 2010 14:52:17 -0200
>> Subject: [PATCH] virtualkeyboard
>>
>> ---
>> extensions/globalkey/Makefile.am | 4 +-
>> extensions/globalkey/virtualkeyboard.py | 12 +
>> src/jarabe/model/Makefile.am | 3 +-
>> src/jarabe/model/virtualkeyboard.py | 184 +++++++
>> src/jarabe/view/Makefile.am | 3 +-
>> src/jarabe/view/virtualkeyboard.py | 865
>> +++++++++++++++++++++++++++++++
>> 6 files changed, 1068 insertions(+), 3 deletions(-)
>> create mode 100644 extensions/globalkey/virtualkeyboard.py
>> create mode 100755 src/jarabe/model/virtualkeyboard.py
>> create mode 100755 src/jarabe/view/virtualkeyboard.py
>>
>> diff --git a/extensions/globalkey/Makefile.am
>> b/extensions/globalkey/Makefile.am
>> index 69afac2..dff13fb 100644
>> --- a/extensions/globalkey/Makefile.am
>> +++ b/extensions/globalkey/Makefile.am
>> @@ -3,4 +3,6 @@ sugardir = $(pkgdatadir)/extensions/globalkey
>> sugar_PYTHON = \
>> __init__.py \
>> screenshot.py \
>> - viewsource.py
>> + viewsource.py \
>> + virtualkeyboard.py
>> +
>> diff --git a/extensions/globalkey/virtualkeyboard.py
>> b/extensions/globalkey/virtualkeyboard.py
>> new file mode 100644
>> index 0000000..9291142
>> --- /dev/null
>> +++ b/extensions/globalkey/virtualkeyboard.py
>> @@ -0,0 +1,12 @@
>> +import os
>> +import gtk
>> +import logging
>> +
>> +from jarabe.model import shell
>> +import jarabe.view.virtualkeyboard
>> +
>> +BOUND_KEYS = ['<alt>k']
>> +
>> +def handle_key_press(key):
>> + logging.debug('load virtual keyboard')
>> + jarabe.view.virtualkeyboard.Teclado()
>> diff --git a/src/jarabe/model/Makefile.am b/src/jarabe/model/Makefile.am
>> index 18d44da..ae3dce9 100644
>> --- a/src/jarabe/model/Makefile.am
>> +++ b/src/jarabe/model/Makefile.am
>> @@ -14,4 +14,5 @@ sugar_PYTHON = \
>> shell.py \
>> screen.py \
>> session.py \
>> - sound.py
>> + sound.py \
>> + virtualkeyboard.py
>> diff --git a/src/jarabe/model/virtualkeyboard.py
>> b/src/jarabe/model/virtualkeyboard.py
>> new file mode 100755
>> index 0000000..6867f10
>> --- /dev/null
>> +++ b/src/jarabe/model/virtualkeyboard.py
>> @@ -0,0 +1,184 @@
>> +#!/usr/bin/env python
>> +# -*- coding: iso-8859-1 -*-
>> +# virtualkeyboard
>> +# Copyright (C) 2009 Plan Ceibal
>> +#
>> +# 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 3 of the License, or
>> +# (at your option) any later version.
>
> First observation: the patch is GPLv3+, yet Sugar is usually distributed
> under
> GPLv2+. Yes?
>
>> +#
>> +# 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, see <http://www.gnu.org/licenses/>.
>> +#
>> +# Contact information: comunidad at plan.ceibal.edu.uy
>> +# Plan Ceibal http://www.ceibal.edu.uy
>> +
>> +import pygtk
>> +pygtk.require('2.0')
>> +import gtk
>> +import sys, os
>> +import time
>> +import pango
>> +import Xlib.display
>> +import Xlib.X
>> +import Xlib.XK
>> +import Xlib.protocol.event
>
> Next observation: the patch introduces a dependency on python-xlib, which I
> don't think we've depended on before. This doesn't seem hard to support but
> it
> does need to be more clearly explained.
>
>> +
>> +class Teclado:
>> + special_X_keysyms = {
>> + ' ' : "space",
>> + '\t' : "Tab",
>> + '\n' : "Return", + '\r' : "BackSpace",
>> + '\e' : "Escape",
>> + '!' : "exclam",
>> + '#' : "numbersign",
>> + '%' : "percent",
>> + '$' : "dollar",
>> + '&' : "ampersand",
>> + '"' : "quotedbl",
>> + '\'' : "apostrophe",
>> + '(' : "parenleft",
>> + ')' : "parenright",
>> + '*' : "asterisk",
>> + '=' : "equal",
>> + '+' : "plus",
>> + ',' : "comma",
>> + '-' : "minus",
>> + '.' : "period",
>> + '/' : "slash",
>> + ':' : "colon",
>> + ';' : "semicolon",
>> + '<' : "less",
>> + '>' : "greater",
>> + '?' : "question",
>> + '@' : "at",
>> + '[' : "bracketleft",
>> + ']' : "bracketright",
>> + '\\' : "backslash",
>> + '^' : "asciicircum",
>> + '_' : "underscore",
>> + '`' : "grave",
>> + '{' : "braceleft",
>> + '|' : "bar",
>> + '}' : "braceright",
>> + '~' : "asciitilde",
>> + 'ñ' : "ntilde",
>> + 'Ñ' : "Ntilde"
>> + };
>> +
>> + def __init__(self):
>> + self.display = Xlib.display.Display()
>> + self.window = self.display.get_input_focus()._data["focus"];
>
> Spaces and tabs are mixed in the body of this __init__() method.
>
>> +
>> + def get_keysym(self, ch) :
>> + keysym = Xlib.XK.string_to_keysym(ch)
>> + if keysym == 0 :
>> +
>> + keysym =
>> Xlib.XK.string_to_keysym(self.special_X_keysyms[ch])
>> + return keysym
>> +
>> + def is_shifted(self, ch) :
>> + if ch.isupper() :
>> + return True
>> + if "/=~!@#$%^&()_*{}|:;\">?Ñ".find(ch) >= 0 :
>> + return True
>> + return False
>> +
>> + def char_to_keycode(self, ch) :
>> + keysym = self.get_keysym(ch)
>> + keycode = self.display.keysym_to_keycode(keysym)
>> + if keycode == 0 :
>> + print "Sorry, can't map", ch
>> +
>> + if (self.is_shifted(ch)) :
>> + shift_mask = Xlib.X.ShiftMask
>> + else :
>> + shift_mask = 0
>> +
>> + return keycode, shift_mask
>> +
>> +
>> + def send_string(self, ch):
>> + keycode, shift_mask = self.char_to_keycode(ch)
>> + self.escribir(keycode, shift_mask)
>> +
>> + def escribir(self, keycode, shift_mask):
>> + event = Xlib.protocol.event.KeyPress(
>> + time = int(time.time()),
>> + root = self.display.screen().root,
>> + window = self.window,
>> + same_screen = 0, child = Xlib.X.NONE,
>> + root_x = 0, root_y = 0, event_x = 0, event_y = 0,
>> + state = shift_mask,
>> + detail = keycode
>> + )
>> + self.window.send_event(event, propagate = True)
>> + event = Xlib.protocol.event.KeyRelease(
>> + time = int(time.time()),
>> + root = self.display.screen().root,
>> + window = self.window,
>> + same_screen = 0, child = Xlib.X.NONE,
>> + root_x = 0, root_y = 0, event_x = 0, event_y = 0,
>> + state = shift_mask,
>> + detail = keycode
>> + )
>> + self.window.send_event(event, propagate = True)
>> +
>> +
>> + def escribir_txt(self, txt):
>> + self.display = Xlib.display.Display()
>> + self.window = self.display.get_input_focus()._data["focus"];
>> +
>> + if (txt == "ü"): + self.escribir(34, 1)
>> + self.send_string("u")
>> + elif (txt == "Ü"): + self.escribir(34, 1)
>> + self.send_string("U")
>> + elif (txt == "|"): + self.escribir(10, Xlib.X.Mod5Mask)
>> + elif (txt == "@"): + self.escribir(11, Xlib.X.Mod5Mask)
>> + elif (txt == "#"): + self.escribir(12, Xlib.X.Mod5Mask)
>> + elif (txt == "º"): + self.escribir(49, 0)
>> + elif (txt == "ª"): + self.escribir(49, 1)
>> + elif (txt == "'"): + self.escribir(20, 0)
>> + elif (txt == "¿"): + self.escribir(21, 1)
>> + elif (txt == "¡"): + self.escribir(21, 0)
>> + elif (txt == "'"):
>> + self.escribir(34, 0)
>> + elif (self.tieneTilde(txt)):
>> + self.escribir(34, 0)
>> + self.escribirVocal(txt)
>> + else:
>> + self.send_string(txt)
>> +
>> + self.display.sync()
>> +
>> + def tieneTilde(self, txt):
>> + return "ÁÉÍÓÚáéíóú".find(txt) >= 0
>> +
>> + def escribirVocal(self, txt):
>> + if txt=="Á": self.send_string("A")
>> + if txt=="É": self.send_string("E")
>> + if txt=="Í": self.send_string("I")
>> + if txt=="Ó": self.send_string("O")
>> + if txt=="Ú": self.send_string("U")
>> + if txt=="á": self.send_string("a")
>> + if txt=="é": self.send_string("e")
>> + if txt=="í": self.send_string("i")
>> + if txt=="ó": self.send_string("o")
>> + if txt=="ú": self.send_string("u")
>
> These if-trees should be table lookups.
>
>> diff --git a/src/jarabe/view/Makefile.am b/src/jarabe/view/Makefile.am
>> index 1abea6d..4dbd815 100644
>> --- a/src/jarabe/view/Makefile.am
>> +++ b/src/jarabe/view/Makefile.am
>> @@ -9,4 +9,5 @@ sugar_PYTHON = \
>> pulsingicon.py \
>> service.py \
>> tabbinghandler.py \
>> - viewsource.py
>> + viewsource.py \
>> + virtualkeyboard.py
>> diff --git a/src/jarabe/view/virtualkeyboard.py
>> b/src/jarabe/view/virtualkeyboard.py
>> new file mode 100755
>> index 0000000..e7697cc
>> --- /dev/null
>> +++ b/src/jarabe/view/virtualkeyboard.py
>> @@ -0,0 +1,865 @@
>> +#!/usr/bin/env python
>> +# -*- coding: iso-8859-1 -*-
>> +# virtualkeyboard
>> +# Copyright (C) 2009 Plan Ceibal
>> +#
>> +# 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 3 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, see <http://www.gnu.org/licenses/>.
>> +#
>> +# Contact information: comunidad at plan.ceibal.edu.uy
>> +# Plan Ceibal http://www.ceibal.edu.uy
>> +
>> +import pygtk
>> +pygtk.require('2.0')
>> +import gtk
>> +import sys, os
>> +import time
>> +import pango
>> +import gconf
>> +import logging
>> +import threading
>> +import gobject
>> +
>> +import jarabe.model.virtualkeyboard
>> +from sugar.graphics.icon import Icon, get_icon_file_name
>> +
>> +gobject.threads_init()
>> +
>> +velocidades = {'lenta': 3, 'media': 2, 'rapida':1}
>> +
>> +class Teclado:
>> +
>> + def delete_event(self, widget, event=None):
>> + self.BOTONESxBARRIDOxFILA = False
>> + self.BOTONESxBARRIDO = False
>> +
>> + os.environ['virtualkeyboard'] = 'False'
>> + logging.debug('close virtual keyboard')
>> + return False
>> +
>> + def __init__(self):
>> + self.fila_1 = [];
>> + self.fila_2 = [];
>> + self.fila_3 = [];
>> + self.fila_4 = [];
>> + self.fila_5 = [];
>> + self.fila_6 = [];
>> + self.BOTONESxBARRIDO = False;
>> + self.BOTONESxBARRIDOxFILA = False;
>> + self.MAYUSCULA = True;
>> + self.fila_actual = None;
>> + self.btn_actual = None;
>> + self.fila_actual_nro = -1;
>> + self.seg = 2;
>
> More mixed indentation problems.
>
>> +
>> + if os.environ.has_key('virtualkeyboard'):
>> + self.visible = os.environ['virtualkeyboard']
>> + if self.visible == 'True':
>> + return
>> + else:
>> + if self.visible == 'False':
>> + self.desplegar()
>> + else:
>> + self.desplegar() +
>> + def desplegar(self):
>> + self._mTeclado=jarabe.model.virtualkeyboard.Teclado()
>> +
>> + self.dialog = gtk.Dialog()
>> + self.dialog.set_title("TECLADO VIRTUAL")
>> + try:
>> +
>> self.dialog.set_icon_from_file(get_icon_file_name('teclado'))
>> + except:
>> + logging.debug('dont show virtual keyboard icon')
>> +
>> + self.dialog.set_resizable(True)
>> + self.dialog.set_accept_focus(False)
>> + #gtk.Window.move(self.dialog, 0, 0)
>> +
>> + self.dialog.connect("delete_event", self.delete_event)
>> +
>> + self.vbox_teclado = self.mostrar_teclado()
>> +
>> + self.event_box = gtk.EventBox()
>> + self.event_box.add(self.vbox_teclado)
>> + self.event_box.set_events(gtk.gdk.BUTTON_PRESS)
>> + self.event_box.show()
>> +
>> +
>> + self.ebc = self.event_box.connect("button_press_event",
>> self.mouse_boton)
>> +
>> + self.dialog.vbox.pack_start(self.event_box, False, False, 5)
>> +
>> + self.vbox_teclado.show_all()
>> + self.dialog.show() +
>> + os.environ['virtualkeyboard'] = 'True'
>> +
>> +
>> + def mostrar_teclado(self):
>> + child = gtk.VBox(False, 2)
>> +
>> + self.btn_BACK_SPACE = self.new_button_borrar()
>> +
>> + self.btn_SPACE = self.new_button_espacio()
>> +
>> + self.btn_CAPS_LOCK = self.new_button_mayuscula()
>> + self.fila_3.append(self.btn_CAPS_LOCK)
>> +
>> + self.btn_ENTER = self.new_button_enter()
>> + self.fila_2.append(self.btn_ENTER)
>> +
>> + self.btn_TAB = self.new_button_tab()
>> + self.fila_2.append(self.btn_TAB)
>> +
>> + self.btn_do = self.new_button_escribir("º")
>> + self.fila_1.append(self.btn_do)
>> +
>> + self.btn_1 = self.new_button_escribir("1")
>> + self.fila_1.append(self.btn_1)
>> +
>> + self.btn_2 = self.new_button_escribir("2")
>> + self.fila_1.append(self.btn_2)
>> +
>> + self.btn_3 = self.new_button_escribir("3")
>> + self.fila_1.append(self.btn_3)
>> +
>> + self.btn_4 = self.new_button_escribir("4")
>> + self.fila_1.append(self.btn_4)
>> +
>> + self.btn_5 = self.new_button_escribir("5")
>> + self.fila_1.append(self.btn_5)
>> +
>> + self.btn_6 = self.new_button_escribir("6")
>> + self.fila_1.append(self.btn_6)
>> +
>> + self.btn_7 = self.new_button_escribir("7")
>> + self.fila_1.append(self.btn_7)
>> +
>> + self.btn_8 = self.new_button_escribir("8")
>> + self.fila_1.append(self.btn_8)
>> +
>> + self.btn_9 = self.new_button_escribir("9")
>> + self.fila_1.append(self.btn_9)
>> +
>> + self.btn_0 = self.new_button_escribir("0")
>> + self.fila_1.append(self.btn_0)
>> +
>> + self.btn_finPreg = self.new_button_escribir("'")
>> + self.fila_1.append(self.btn_finPreg)
>> +
>> + self.btn_inicioPreg = self.new_button_escribir("¡")
>> + self.fila_1.append(self.btn_inicioPreg)
>> +
>> + self.btn_Q = self.new_button_escribir("Q")
>> + self.fila_2.append(self.btn_Q)
>> +
>> + self.btn_W = self.new_button_escribir("W")
>> + self.fila_2.append(self.btn_W)
>> +
>> + self.btn_E = self.new_button_escribir("E")
>> + self.fila_2.append(self.btn_E)
>> +
>> + self.btn_R = self.new_button_escribir("R")
>> + self.fila_2.append(self.btn_R)
>> +
>> + self.btn_T = self.new_button_escribir("T")
>> + self.fila_2.append(self.btn_T)
>> +
>> + self.btn_Y = self.new_button_escribir("Y")
>> + self.fila_2.append(self.btn_Y)
>> +
>> + self.btn_U = self.new_button_escribir("U")
>> + self.fila_2.append(self.btn_U)
>> +
>> + self.btn_I = self.new_button_escribir("I")
>> + self.fila_2.append(self.btn_I)
>> +
>> + self.btn_O = self.new_button_escribir("O")
>> + self.fila_2.append(self.btn_O)
>> +
>> + self.btn_P = self.new_button_escribir("P")
>> + self.fila_2.append(self.btn_P)
>> +
>> + self.btn_asterisco = self.new_button_escribir("*")
>> + self.fila_2.append(self.btn_asterisco)
>> +
>> + self.btn_cierra_llave = self.new_button_escribir("]")
>> +
>> + self.btn_A = self.new_button_escribir("A")
>> + self.fila_3.append(self.btn_A)
>> +
>> + self.btn_S = self.new_button_escribir("S")
>> + self.fila_3.append(self.btn_S)
>> +
>> + self.btn_D = self.new_button_escribir("D")
>> + self.fila_3.append(self.btn_D)
>> +
>> + self.btn_F = self.new_button_escribir("F")
>> + self.fila_3.append(self.btn_F)
>> +
>> + self.btn_G = self.new_button_escribir("G")
>> + self.fila_3.append(self.btn_G)
>> +
>> + self.btn_H = self.new_button_escribir("H")
>> + self.fila_3.append(self.btn_H)
>> +
>> + self.btn_J = self.new_button_escribir("J")
>> + self.fila_3.append(self.btn_J)
>> +
>> + self.btn_K = self.new_button_escribir("K")
>> + self.fila_3.append(self.btn_K)
>> +
>> + self.btn_L = self.new_button_escribir("L")
>> + self.fila_3.append(self.btn_L)
>> +
>> + self.btn_enie = self.new_button_escribir("Ñ")
>> + self.fila_3.append(self.btn_enie)
>> +
>> + self.btn_mas = self.new_button_escribir("+")
>> + self.fila_3.append(self.btn_mas)
>> +
>> + self.fila_3.append(self.btn_cierra_llave)
>> +
>> + self.btn_abre_llave = self.new_button_escribir("[")
>> + self.fila_2.append(self.btn_abre_llave)
>> +
>> + self.btn_Z = self.new_button_escribir("Z")
>> + self.fila_4.append(self.btn_Z)
>> +
>> + self.btn_X = self.new_button_escribir("X")
>> + self.fila_4.append(self.btn_X)
>> +
>> + self.btn_C = self.new_button_escribir("C")
>> + self.fila_4.append(self.btn_C)
>> +
>> + self.btn_V = self.new_button_escribir("V")
>> + self.fila_4.append(self.btn_V)
>> +
>> + self.btn_B = self.new_button_escribir("B")
>> + self.fila_4.append(self.btn_B)
>> +
>> + self.btn_N = self.new_button_escribir("N")
>> + self.fila_4.append(self.btn_N)
>> +
>> + self.btn_M = self.new_button_escribir("M")
>> + self.fila_4.append(self.btn_M)
>> +
>> + self.btn_coma = self.new_button_escribir(",")
>> + self.fila_4.append(self.btn_coma)
>> +
>> + self.btn_punto = self.new_button_escribir(".")
>> + self.fila_4.append(self.btn_punto)
>> +
>> + self.btn_guion = self.new_button_escribir("-")
>> + self.fila_4.append(self.btn_guion)
>> +
>> + self.btn_A_tilde = self.new_button_escribir("Á")
>> + self.fila_5.append(self.btn_A_tilde)
>> +
>> + self.btn_E_tilde = self.new_button_escribir("É")
>> + self.fila_5.append(self.btn_E_tilde)
>> +
>> + self.btn_I_tilde = self.new_button_escribir("Í")
>> + self.fila_5.append(self.btn_I_tilde)
>> +
>> + self.btn_O_tilde = self.new_button_escribir("Ó")
>> + self.fila_5.append(self.btn_O_tilde)
>> +
>> + self.btn_U_tilde = self.new_button_escribir("Ú")
>> + self.fila_5.append(self.btn_U_tilde)
>> +
>> + self.btn_U_puntos = self.new_button_escribir("Ü")
>> + self.fila_5.append(self.btn_U_puntos)
>> +
>> + self.btn_pite = self.new_button_escribir("|")
>> + self.fila_5.append(self.btn_pite)
>> +
>> + self.btn_arroba = self.new_button_escribir("@")
>> + self.fila_5.append(self.btn_arroba)
>> +
>> + self.btn_menor = self.new_button_escribir("<")
>> + self.fila_5.append(self.btn_menor)
>
> This logic could be substantially simplified by first making a table of data
> representing the buttons that need to be created and then iterating over the
> table.
>
>> +
>> + self.chk_activarBarrido_botones = gtk.CheckButton("BOTONES")
>> + self.chk_activarBarrido_botones.connect("toggled",
>> self.set_botonesXbarridoXfila)
>> +
>> + self.cbo_time_btn = self.combo_tiempos_botones()
>> +
>> + #dibujo tabla
>> + table = gtk.Table(7, 15, False)
>> +
>> + table.set_row_spacing(0, 15)
>> + table.set_row_spacing(3, 15)
>> + table.set_col_spacing(12, 15)
>> + table.set_row_spacing(4, 10)
>> +
>> + table.attach(self.btn_do, 0, 1, 0, 1)
>> + table.attach(self.btn_1, 1, 2, 0, 1)
>> + table.attach(self.btn_2, 2, 3, 0, 1)
>> + table.attach(self.btn_3, 3, 4, 0, 1)
>> + table.attach(self.btn_4, 4, 5, 0, 1)
>> + table.attach(self.btn_5, 5, 6, 0, 1)
>> + table.attach(self.btn_6, 6, 7, 0, 1)
>> + table.attach(self.btn_7, 7, 8, 0, 1)
>> + table.attach(self.btn_8, 8, 9, 0, 1)
>> + table.attach(self.btn_9, 9, 10, 0, 1)
>> + table.attach(self.btn_0, 10, 11, 0, 1)
>> + table.attach(self.btn_finPreg, 11 ,12, 0, 1)
>> + table.attach(self.btn_inicioPreg, 12, 13, 0, 1)
>> + table.attach(self.btn_TAB, 0, 1, 1, 2)
>> + table.attach(self.btn_Q, 1, 2, 1, 2)
>> + table.attach(self.btn_W, 2, 3, 1, 2)
>> + table.attach(self.btn_E, 3, 4, 1, 2)
>> + table.attach(self.btn_R, 4, 5, 1, 2)
>> + table.attach(self.btn_T, 5, 6, 1, 2)
>> + table.attach(self.btn_Y, 6, 7, 1, 2)
>> + table.attach(self.btn_U, 7, 8, 1, 2)
>> + table.attach(self.btn_I, 8, 9, 1, 2)
>> + table.attach(self.btn_O, 9, 10, 1, 2)
>> + table.attach(self.btn_P, 10, 11, 1, 2)
>> + table.attach(self.btn_asterisco, 11, 12, 1, 2)
>> + table.attach(self.btn_abre_llave, 12, 13, 1, 2)
>> + table.attach(self.btn_A, 1, 2, 2, 3)
>> + table.attach(self.btn_S, 2, 3, 2, 3)
>> + table.attach(self.btn_D, 3, 4, 2, 3)
>> + table.attach(self.btn_F, 4, 5, 2, 3)
>> + table.attach(self.btn_G, 5, 6, 2, 3)
>> + table.attach(self.btn_H, 6, 7, 2, 3)
>> + table.attach(self.btn_J, 7, 8, 2, 3)
>> + table.attach(self.btn_K, 8, 9, 2, 3)
>> + table.attach(self.btn_L, 9, 10, 2, 3)
>> + table.attach(self.btn_enie, 10, 11, 2, 3)
>> + table.attach(self.btn_mas, 11, 12, 2, 3)
>> + table.attach(self.btn_cierra_llave, 12, 13, 2, 3)
>> + table.attach(self.btn_Z, 1, 2, 3, 4)
>> + table.attach(self.btn_X, 2, 3, 3, 4)
>> + table.attach(self.btn_C, 3, 4, 3, 4)
>> + table.attach(self.btn_V, 4, 5, 3, 4)
>> + table.attach(self.btn_B, 5, 6, 3, 4)
>> + table.attach(self.btn_N, 6, 7, 3, 4)
>> + table.attach(self.btn_M, 7, 8, 3, 4)
>> + table.attach(self.btn_coma, 8, 9, 3, 4)
>> + table.attach(self.btn_punto, 9, 10, 3, 4)
>> + table.attach(self.btn_guion, 10, 11, 3, 4)
>> +
>> + table.attach(self.btn_BACK_SPACE, 13, 15, 0, 1)
>> + table.attach(self.btn_ENTER, 13, 15, 1, 2)
>> + table.attach(self.btn_CAPS_LOCK, 13, 15, 2, 3)
>> + table.attach(self.cbo_time_btn, 13, 14, 4, 5)
>> + table.attach(self.chk_activarBarrido_botones, 13, 14, 3, 4)
>> + table.attach(self.btn_SPACE, 1, 13, 5, 6)
>> +
>> + table.attach(self.btn_A_tilde, 1, 2, 4, 5)
>> + table.attach(self.btn_E_tilde, 2, 3, 4, 5)
>> + table.attach(self.btn_I_tilde, 3, 4, 4, 5)
>> + table.attach(self.btn_O_tilde, 4, 5, 4, 5)
>> + table.attach(self.btn_U_tilde, 5, 6, 4, 5)
>> + table.attach(self.btn_U_puntos, 8, 9, 4, 5)
>> + table.attach(self.btn_pite, 9, 10, 4, 5)
>> + table.attach(self.btn_arroba, 10, 11, 4, 5)
>> + table.attach(self.btn_menor, 11, 12, 4, 5)
>> +
>> + child.pack_end(table, True, True, 0) +
>> + return child
>> +
>>
>> +####################################################################################
>> +
>> + def escribir(self, widget, *arg):
>> + hbox = widget.get_children()[0]
>> + label = hbox.get_children()[0]
>> + txt = label.get_text()
>> +
>> + self._mTeclado.escribir_txt(txt)
>> +
>> + def espacio(self, *arg):
>> + self._mTeclado.escribir_txt(" ")
>> +
>> + def tab(self, *arg):
>> + self._mTeclado.escribir_txt("\t")
>> +
>> + def enter(self, *arg):
>> + self._mTeclado.escribir_txt("\n")
>> +
>> + def borrar(self, *arg):
>> + self._mTeclado.escribir_txt("\r")
>> +
>> + def new_button_escribir(self, plabel):
>> + btn = Boton(plabel)
>> + btn.connect("pressed", self.escribir, plabel)
>> + btn.connect("activate", self.escribir, plabel)
>> + return btn
>> +
>> +
>> + def new_button_enter(self):
>> + btn = Boton("ENTER")
>> + btn.connect("pressed", self.enter)
>> + btn.connect("activate", self.enter)
>> + return btn
>> +
>> + def new_button_espacio(self):
>> + btn = Boton("ESPACIO")
>> + btn.connect("pressed", self.espacio)
>> + btn.connect("activate", self.espacio)
>> + return btn
>> +
>> + def new_button_borrar(self):
>> + btn = Boton("BORRAR")
>> + btn.connect("pressed", self.borrar)
>> + btn.connect("activate", self.borrar)
>> + return btn
>> +
>> + def new_button_tab(self):
>> + btn = Boton("TAB")
>> + btn.connect("pressed", self.tab)
>> + btn.connect("activate", self.tab)
>> + return btn
>> +
>> + def new_button_mayuscula(self):
>> + btn = Boton("MINÚSCULAS")
>> + btn.connect("pressed", self.set_mayuscula)
>> + btn.connect("activate", self.set_mayuscula)
>> + return btn
>> +
>> + def set_mayuscula(self, *arg):
>> + if (self.MAYUSCULA):
>> + self.btn_do.set_text("ª")
>> + self.btn_1.set_text("!")
>> + self.btn_2.set_text("\"")
>> + self.btn_3.set_text("#")
>> + self.btn_4.set_text("$")
>> + self.btn_5.set_text("%")
>> + self.btn_6.set_text("&")
>> + self.btn_7.set_text("/")
>> + self.btn_8.set_text("(")
>> + self.btn_9.set_text(")")
>> + self.btn_0.set_text("=")
>> + self.btn_finPreg.set_text("?")
>> + self.btn_inicioPreg.set_text("¿")
>> + self.btn_Q.set_text("q")
>> + self.btn_W.set_text("w")
>> + self.btn_E.set_text("e")
>> + self.btn_R.set_text("r")
>> + self.btn_T.set_text("t")
>> + self.btn_Y.set_text("y")
>> + self.btn_U.set_text("u")
>> + self.btn_I.set_text("i")
>> + self.btn_O.set_text("o")
>> + self.btn_P.set_text("p")
>> + self.btn_A.set_text("a")
>> + self.btn_S.set_text("s")
>> + self.btn_D.set_text("d")
>> + self.btn_F.set_text("f")
>> + self.btn_G.set_text("g")
>> + self.btn_H.set_text("h")
>> + self.btn_J.set_text("j")
>> + self.btn_K.set_text("k")
>> + self.btn_L.set_text("l")
>> + self.btn_enie.set_text("ñ")
>> + self.btn_menor.set_text(">")
>> + self.btn_Z.set_text("z")
>> + self.btn_X.set_text("x")
>> + self.btn_C.set_text("c")
>> + self.btn_V.set_text("v")
>> + self.btn_B.set_text("b")
>> + self.btn_N.set_text("n")
>> + self.btn_M.set_text("m")
>> + self.btn_coma.set_text(";")
>> + self.btn_punto.set_text(":")
>> + self.btn_guion.set_text("_")
>> + self.btn_A_tilde.set_text("á")
>> + self.btn_E_tilde.set_text("é")
>> + self.btn_I_tilde.set_text("í")
>> + self.btn_O_tilde.set_text("ó")
>> + self.btn_U_tilde.set_text("ú")
>> + self.btn_U_puntos.set_text("ü")
>> + self.btn_abre_llave.set_text("{")
>> + self.btn_cierra_llave.set_text("}")
>> +
>> + self.MAYUSCULA = False
>> + self.btn_CAPS_LOCK.set_text("MAYÚSCULAS")
>> + else:
>> + self.btn_do.set_text("º")
>> + self.btn_1.set_text("1")
>> + self.btn_2.set_text("2")
>> + self.btn_3.set_text("3")
>> + self.btn_4.set_text("4")
>> + self.btn_5.set_text("5")
>> + self.btn_6.set_text("6")
>> + self.btn_7.set_text("7")
>> + self.btn_8.set_text("8")
>> + self.btn_9.set_text("9")
>> + self.btn_0.set_text("0")
>> + self.btn_finPreg.set_text("'")
>> + self.btn_inicioPreg.set_text("¡")
>> + self.btn_Q.set_text("Q")
>> + self.btn_W.set_text("W")
>> + self.btn_E.set_text("E")
>> + self.btn_R.set_text("R")
>> + self.btn_T.set_text("T")
>> + self.btn_Y.set_text("Y")
>> + self.btn_U.set_text("U")
>> + self.btn_I.set_text("I")
>> + self.btn_O.set_text("O")
>> + self.btn_P.set_text("P")
>> + self.btn_A.set_text("A")
>> + self.btn_S.set_text("S")
>> + self.btn_D.set_text("D")
>> + self.btn_F.set_text("F")
>> + self.btn_G.set_text("G")
>> + self.btn_H.set_text("H")
>> + self.btn_J.set_text("J")
>> + self.btn_K.set_text("K")
>> + self.btn_L.set_text("L")
>> + self.btn_enie.set_text("Ñ")
>> + self.btn_menor.set_text("<")
>> + self.btn_Z.set_text("Z")
>> + self.btn_X.set_text("X")
>> + self.btn_C.set_text("C")
>> + self.btn_V.set_text("V")
>> + self.btn_B.set_text("B")
>> + self.btn_N.set_text("N")
>> + self.btn_M.set_text("M")
>> + self.btn_coma.set_text(",")
>> + self.btn_punto.set_text(".")
>> + self.btn_guion.set_text("-")
>> + self.btn_A_tilde.set_text("Á")
>> + self.btn_E_tilde.set_text("É")
>> + self.btn_I_tilde.set_text("Í")
>> + self.btn_O_tilde.set_text("Ó")
>> + self.btn_U_tilde.set_text("Ú")
>> + self.btn_U_puntos.set_text("Ü")
>> + self.btn_abre_llave.set_text("[")
>> + self.btn_cierra_llave.set_text("]")
>> +
>> + self.MAYUSCULA = True
>> + self.btn_CAPS_LOCK.set_text("MINÚSCULAS")
>> +
>> +
>> +########################################################################
>> +
>> + def set_botonesXbarridoXfila(self, widget):
>> + state = widget.get_active()
>> + if state:
>> + self.BOTONESxBARRIDOxFILA = True
>> + self.botonesXbarridoXfila()
>> + else:
>> + if (self.BOTONESxBARRIDOxFILA):
>> + self.iluminarFila(self.fila_actual_nro, "white")
>> + self.BOTONESxBARRIDOxFILA = False
>> + self.iluminarBoton(self.btn_actual, "white")
>> + self.BOTONESxBARRIDO = False
>> +
>> + def botonesXbarridoXfila(self):
>> + gobject.timeout_add(self.seg*1000, self.barrerFocusXfila1)
>> +
>> + def barrerFocusXfila1(self, *arg):
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.fila_actual_nro = 1
>> + self.fila_actual = self.fila_1
>> + self.iluminarBoton(self.btn_actual, "white")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.iluminarFila(1, "Yellow")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + if self.BOTONESxBARRIDOxFILA:
>> + gobject.timeout_add(self.seg*1000, self.barrer_el_boton,
>> self.btn_BACK_SPACE,1, 2)
>> +
>> + def barrer_el_boton(self, btn , fila_anterior, fila_a_seguir):
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.fila_actual_nro = -1
>> + self.fila_actual = None
>> + self.btn_actual = btn
>> + self.iluminarFila(fila_anterior, "white")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.iluminarBoton(self.btn_actual, "Yellow")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + if self.BOTONESxBARRIDOxFILA:
>> + if fila_a_seguir==1:
>> + gobject.timeout_add(self.seg*1000,
>> self.barrerFocusXfila1)
>> + if fila_a_seguir==2:
>> + gobject.timeout_add(self.seg*1000,
>> self.barrerFocusXfila2)
>> + if fila_a_seguir==3:
>> + gobject.timeout_add(self.seg*1000,
>> self.barrerFocusXfila3)
>> + if fila_a_seguir==4:
>> + gobject.timeout_add(self.seg*1000,
>> self.barrerFocusXfila4)
>> + if fila_a_seguir==5:
>> + gobject.timeout_add(self.seg*1000,
>> self.barrerFocusXfila5)
>> +
>> +
>> + def barrerFocusXfila2(self, *arg):
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> +
>> + self.fila_actual_nro = 2
>> + self.fila_actual = self.fila_2
>> + self.iluminarBoton(self.btn_actual, "white")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.iluminarFila(2, "Yellow")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> +
>> + if self.BOTONESxBARRIDOxFILA:
>> + gobject.timeout_add(self.seg*1000, self.barrer_el_boton,
>> self.btn_BACK_SPACE, 2, 3)
>> +
>> + def barrerFocusXfila3(self, *arg):
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.fila_actual_nro = 3
>> + self.fila_actual = self.fila_3
>> + self.iluminarBoton(self.btn_actual, "white")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.iluminarFila(3, "Yellow")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> +
>> + if self.BOTONESxBARRIDOxFILA:
>> + gobject.timeout_add(self.seg*1000, self.barrer_el_boton,
>> self.btn_BACK_SPACE, 3, 4)
>> +
>> + def barrerFocusXfila4(self, *arg):
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.fila_actual_nro = 4
>> + self.fila_actual = self.fila_4
>> + self.iluminarBoton(self.btn_actual, "white")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.iluminarFila(4, "Yellow")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + if self.BOTONESxBARRIDOxFILA:
>> + gobject.timeout_add(self.seg*1000, self.barrer_el_boton,
>> self.btn_BACK_SPACE, 4, 5)
>> +
>> + def barrerFocusXfila5(self, *arg):
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.fila_actual_nro = 5
>> + self.fila_actual = self.fila_5
>> + self.iluminarBoton(self.btn_actual, "white")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + self.iluminarFila(5, "Yellow")
>> + if not self.BOTONESxBARRIDOxFILA:
>> + return False
>> + if self.BOTONESxBARRIDOxFILA:
>> + gobject.timeout_add(self.seg*1000, self.barrer_el_boton,
>> self.btn_SPACE, 5, 1)
>> +
>> +
>> +########################################################################
>> +
>> + def iluminarFila(self, fila, color):
>> + if fila == 1:
>> + for f in range(0,len(self.fila_1)):
>> +
>> gobject.idle_add(self.pintarControl,self.fila_1[f], color)
>> + if fila == 2:
>> + for f in range(0,len(self.fila_2)):
>> +
>> gobject.idle_add(self.pintarControl,self.fila_2[f], color)
>> + if fila == 3:
>> + for f in range(0,len(self.fila_3)):
>> +
>> gobject.idle_add(self.pintarControl,self.fila_3[f], color)
>> + if fila == 4:
>> + for f in range(0,len(self.fila_4)):
>> +
>> gobject.idle_add(self.pintarControl,self.fila_4[f], color)
>> + if fila == 5:
>> + for f in range(0,len(self.fila_5)):
>> +
>> gobject.idle_add(self.pintarControl,self.fila_5[f], color)
>> + if fila == 6:
>> + for f in range(0,len(self.fila_6)):
>> +
>> gobject.idle_add(self.pintarControl,self.fila_6[f], color)
>> +
>> + def pintarControl(self, w, color):
>> + if not w == None:
>> + w.modify_bg( gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
>> +
>> + def mouse_boton(self, widget, event):
>> + #evita repeticion
>> + self.bloquearHandler()
>> +
>> + if self.BOTONESxBARRIDO:
>> + self.BOTONESxBARRIDO=False
>> + self.btn_actual.emit("pressed")
>> + #voler a empezar...
>> + self.iluminarBoton(self.btn_actual, "white")
>> + self.BOTONESxBARRIDOxFILA = True
>> + self.botonesXbarridoXfila()
>> + return
>> + if self.BOTONESxBARRIDOxFILA:
>> + if self.fila_actual_nro==-1: #es un boton
>>
>> + self.btn_actual.emit("pressed")
>> + else:
>> + self.BOTONESxBARRIDOxFILA = False;
>> + self.iluminarFila(self.fila_actual_nro, "white")
>> + self.BOTONESxBARRIDO = True;
>> + self.botonesXbarridoEnFila()
>> +
>> + def iluminarBoton(self, btn, color):
>> + gobject.idle_add(self.pintarControl,btn, color)
>> +
>> + def bloquearHandler(self):
>> + HILO_A = threading.Thread(target = self.bloquearHandler_aux_obj)
>> + HILO_A.start()
>> + HILO_A.quit = True
>> +
>> + def bloquearHandler_aux_obj(self):
>> + self.event_box.handler_block(self.ebc)
>> + try:
>> + seg=self.get_time_barrido_botones()
>> + except:
>> + seg = velocidades['media']
>> + if seg == velocidades['rapida']:
>> + time.sleep(seg-0.15)
>> + if seg == velocidades['media']:
>> + time.sleep(seg-0.30)
>> + if seg == velocidades['lenta']:
>> + time.sleep(seg-0.75)
>> + self.event_box.handler_unblock(self.ebc)
>> +
>> +
>> + def botonesXbarridoEnFila(self):
>> + gobject.idle_add(self.barrerEnFila)
>> +
>> + def barrerEnFila(self):
>> + if self.BOTONESxBARRIDO:
>> + i=0
>> + gobject.timeout_add(self.seg*1000, self.barrerEnFila_aux,
>> i)
>> +
>> +
>> + def barrerEnFila_aux(self, i):
>> + if not self.BOTONESxBARRIDO:
>> + return False
>> + try:
>> + self.btn_ant = self.fila_actual[i-1]
>> + except:
>> + return False
>> + try:
>> + self.btn_actual = self.fila_actual[i]
>> + except:
>> + self.BOTONESxBARRIDO = False
>> + self.BOTONESxBARRIDOxFILA = True
>> + self.botonesXbarridoXfila()
>> + return False
>> + if not self.BOTONESxBARRIDO:
>> + return False
>> + self.iluminarBoton(self.btn_ant, "white")
>> + if not self.BOTONESxBARRIDO:
>> + return False
>> + self.iluminarBoton(self.btn_actual, "Yellow")
>> + if not self.BOTONESxBARRIDO:
>> + return False
>> + else:
>> + gobject.timeout_add(self.seg*1000, self.barrerEnFila_aux,
>> i+1)
>> +
>> + def combo_tiempos_botones(self):
>> + cb = gtk.combo_box_new_text()
>> + cb.connect("changed", self.on_changed_cbo_time_btn)
>> + cb.append_text("RÁPIDO")
>> + cb.append_text("MEDIO")
>> + cb.append_text("LENTO")
>> + seg = velocidades['media']
>> + try:
>> + seg = self.get_time_barrido_botones()
>>
>> + except:
>> + seg=velocidades['media']
>> +
>> + if seg==velocidades['rapida']:
>> + cb.set_active(0)
>> + if seg==velocidades['media']:
>> + cb.set_active(1)
>> + if seg==velocidades['lenta']:
>> + cb.set_active(2)
>> +
>> + return cb
>> +
>> +
>> + def on_changed_cbo_time_btn(self, widget):
>> + s = widget.get_active()
>> +
>> + if s==0:
>> + seg = velocidades['rapida']
>> + if s==1:
>> + seg = velocidades['media']
>> + if s==2:
>> + seg = velocidades['lenta']
>> +
>> + self.set_time_barrido_botones(seg)
>> + self.seg=seg
>> +
>> +
>> + def get_time_barrido_botones(self):
>> + client = gconf.client_get_default()
>> + return client.get_int("/desktop/sugar/virtualkeyboard/time")
>> +
>> + def set_time_barrido_botones(self, seg):
>> + client = gconf.client_get_default()
>> + client.set_int("/desktop/sugar/virtualkeyboard/time", seg)
>> +
>> +class Boton(gtk.Button):
>> + font_desc = ''
>> + font_color = ''
>> + fondo_color = ''
>> + text = ''
>> +
>> + def __init__(self, nom=None):
>> + gtk.Button.__init__(self)
>> +
>> + self.hbox = gtk.HBox(False, 0)
>> + self.add(self.hbox)
>> + self.label = gtk.Label(nom)
>> +
>> + self.set_text(nom)
>> + self.set_font_desc('sans bold 13')
>> + self.set_font_color('black')
>> + self.set_fondo_color('white')
>> +
>> + self.label.set_use_underline(True)
>> + self.hbox.add(self.label)
>> +
>> + def set_font_desc(self, pfont_desc):
>> + self.font_desc = pfont_desc
>> + self.label.modify_font(pango.FontDescription(pfont_desc))
>> +
>> + def set_font_color(self, pfont_color):
>> + self.font_color = pfont_color
>> + self.label.modify_fg(gtk.STATE_NORMAL,
>> gtk.gdk.color_parse(pfont_color))
>> +
>> + def set_fondo_color(self, pfondo_color):
>> + self.fondo_color = pfondo_color
>> + self.modify_bg( gtk.STATE_NORMAL,
>> gtk.gdk.color_parse(pfondo_color))
>> +
>> + def set_text(self, ptext):
>> + if not ptext == None:
>> + self.text = ptext
>> + self.label.set_text(self.text)
>> +
>> + def get_font_desc(self):
>> + return self.font_desc
>> +
>> + def get_font_color(self):
>> + return self.font_color
>> +
>> + def get_fondo_color(self):
>> + return self.fondo_color
>> +
>> + def get_text(self):
>> + return self.text
>> +
>> + def is_visible(self):
>> + self.get_property('visible')
>> --
>> 1.6.2.5
>>
Thanks a lot for lending a hand here.
> Final remark: this patch names variables, methods, and classes in Spanish.
> Anyone troubled by this?
>
> (I ask because, while it's fine with me personally, I don't think I know a
> consensus opinion on the subject.)
I'm not so happy about it, I think it raises considerably the effort
needed to read the code, even for spanish speakers like me.
Regards,
Tomeu
> Regards,
>
> Michael
>
More information about the Sugar-devel
mailing list