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-nore...@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 <ear...@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. +# +# 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: comuni...@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 + +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"]; + + 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") 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: comuni...@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; + + 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) + + 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 _______________________________________________ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel