Original por Brian Vogel. Las cintas en Windows, ya sea en el explorador de archivos o en programas específicos como MS-Word y otros, sólo son otra variante de un sistema de menús que tiene por objetivo situar los elementos más comunmente utilizados «al frente y centrados» para agilizar el acceso. Continuar leyendo «Cómo usar las cintas ribbon con NVDA»

Os dejamos a continuación el listado de episodios, con sus títulos, sobre NVDA del podcast Ciberaprendiendo, de eiberoamerica.com, producidos por Gerardo Corripio y otros colaboradores. El sistema de protección de las descargas implantado en este sitio web impide que incluyamos enlaces directos a los mismos.

  • Episodio 419: Algunos Atajos básicos Similares entre NVDA y Jaws para aprender más rápido su uso
  • Episodio 416: Reseñando Complemento para NVDA Synth Ring Selector
  • Episodio 406: VLC Player con módulo para NVDA VLC Enhance Accessibility
  • Episodio 399: NVDA y sus módulos CalendarioReloj y Día de la Semana
  • Episodio 378: Lo más descatable, e interesante, en NVDA 2018.2
  • Episodio 351: Cambiando el idioma y voces a la velocidad de la luz con SwitchSynth para Nvda
  • Episodio 349: Eficientizando NVDA
  • Tutorial Nuevo Sobre NVDA Y AddOnWeatherPlus: episodios 220 y 301
  • Episodio 225: Seguimos Aprendiendo Diferentes Maneras De Navegar En Youtube Con Lectores De Pantalla
  • Episodio 204: Novedades Sobre NVDA 2015
  • Episodio 203: NVdA Navegando Por Internet
  • Tutorial sobre NVDA: episodios del 198 al 201
  • Gerardo Corripio Nos Explica El Uso Del Lector De Pantalla NVDA: episodios 15 y 18

Feliz escucha.

¡Hola a todos!
Soy Carlos Esteban Martínez Macías, y en esta ocasión, les traigo un tutorial sobre un tema muy interesante, la lectura de subtítulos automáticamente con NVDA usando el reproductor multimedia Pot Player. Está basado en mi ponencia en el primer encuentro de usuarios y desarrolladores de NVDA en español, debido a que la ponencia no se ha podido conservar gravada por fallos técnicos (problemas serios de grabación).
Pues bien, ¡Vamos allá!

INTRODUCCIÓN

Pot Player es un reproductor multimedia para Windows, y gratuito, desarrollado por una organización Coreana llamada Kakao. Posee:

  • La capacidad de reproducir muchos formatos de audio y vídeo con Codex incluidos
  • Funciones interesantes, como televisión analógica o digital, por mencionar algunas
  • Funciona desde Windows XP con Serviss Pack 3, obviamente, hasta Windows 10

Y… ¿qué tiene que ver esto con los subtítulos?
Pues la situación actual es que en cualquier reproductor multimedia los subtítulos se pueden leer por las personas videntes. Sin embargo, para nosotros, hablando específicamente de Windows, hay lugares donde quizá se puedan leer con el OCR, o cuando aparecen en texto en Netflix por ejemplo se pueden leer normalmente pero no automáticamente, lo que supone dar flecha abajo cada vez que cambian, y esto se suma a que si somos ciegos totales no sabemos cuándo cambian automáticamente sin ayuda visual.
Pues bien, esto va avanzando. Y ahora, los desarrolladores de Pot Player han pensado en nosotros, y han puesto la capacidad de que podamos leer los subtítulos automáticamente con cualquier sintetizador de voz que sea sapi 5, o algo más interesante: Convertirlos en títulos de ventanas, ¡para que sean leídos por los lectores de pantalla! NVDA soporta muy bien cambios en el título de ventanas para decirlos automáticamente cuando están enfocados, ¡por lo que esto funciona!
Nota: En este tutorial, nos centraremos en cómo lograr leer automáticamente los subtítulos con NVDA. Si alguien desea utilizar Pot Player como reproductor predeterminado, por ejemplo, es algo muy fácil, e incluso en los menús se encuentran los atajos de los controles de reproducción y demás. De hecho, voy informando que Pot Player tiene por ejemplo efectos de audio para normalizar el volumen cuando está muy bajo en el audio original y esas cosas, además de efectos de vídeo, por lo tanto la calidad de sonido y vídeo en Pot Player es muy buena.

DESCARGA

Para descargar el programa:

  1. En cualquier navegador, nos dirigimos al siguiente sitio web:

https://daumpotplayer.com/

  1. En el menú de la página, buscamos el enlace DOWNLOAD y lo abrimos.
  2. Cuando se cargue la página, pulsa la H (con NVDA) para saltar al encabezado DOWNLOAD. Aquí tienes los enlaces para descargar la versión de 32 o 64 bits; descarga la correspondiente a la arquitectura de tu Windows, y si no la sabes, hay varias formas de saberla, entre ellas el complemento Resource Monitor (para NVDA) y el comando NVDA+Shift+6, desde sistema (panel de control de Windows), etc. Al pulsar alguno de estos enlaces simplemente ya inicia la descarga.

INSTALACIÓN

  • Abrir el instalador ya descargado. Desde Windows 8 se puede mostrar una advertencia de seguridad al abrir el archivo, así que pulsamos más información y luego ejecutar. Y si aparece el control de cuentas de usuario, pulsar Alt+S (atajo de Windows puesto en español)
  • Esperar a que el instalador termine de extraer los archivos
  • Aparece un cuadro combinado para seleccionar el idioma de la instalación, pero como el instalador no se encuentra en español lo dejamos en english y pulsamos enter o el botón aceptar
  • Nos dice (en inglés) bienvenido a la instalación de Pot Player, que se recomienda que cerremos todas las aplicaciones antes de continuar y pulsamos el botón next.
  • Aparece el acuerdo de licencia. Lo más importante es que el programa se puede usar por cualquier persona, institución, empresa, etc. Para la reproducción de archivos multimedia siempre y cuando no se use de forma comercial sin el permiso de sus autores. Debemos pulsar I agree (estoy de acuerdo) y pulsar el botón next.
  • A continuación nos aparecen varias casillas en una lista. La primera es para copiar los archivos del núcleo (para que se instale el programa) y las otras son para crear un icono en el escritorio, carpeta en el menú inicio, y luego las asociaciones de archivo de forma predeterminada (para que al abrirlos desde el explorador se abran con Pot Player), así que marcamos lo que deseamos y pulsamos el botón next.
  • Luego, el instalador nos dice que el programa por defecto se instalará en la carpeta archivos de programa. Si queremos instalarlo en otra ubicación pulsamos el botón browse, y si no, ¡el botón install para que se instale el programa!

Al terminar de instalarse, aparecen varias casillas: La primera es para ejecutar Pot Player, la segunda es para descargar e instalar open códec (componente que nos permite agregar Códex para más formatos de archivo que no sé cómo funciona) y otra para detectar decodificadores (tiene que ver con las funciones de televisión). Para terminar la instalación, ¡pulsamos el botón finish!
Nota sobre actualizaciones del programa usando los lectores de pantalla: Cuando aparezca una actualización disponible y el programa nos muestre el diálogo respectivo, tenemos que tener cuidado de no pasarnos de los botones con tab, porque si no Shift+tab no funciona y tab tampoco. Lo que hay que hacer con NVDA si esto ocurre, es usar el navegador de objetos.
Si no sabes usarlo tienes información en la guía del usuario de NVDA, en tutoriales, etc.

PRIMEROS PASOS

Cuando ejecutemos el programa, NVDA simplemente dirá Pot Player. Hay que tener en cuenta que a los menús no se accede con ALT, sino con la tecla aplicaciones, o si el teclado no tiene tecla aplicaciones, shift+f10.
Al pulsar esta tecla, se nos muestran los menús típicos de un reproductor multimedia, con opciones tales como: Abrir archivo, un submenú para abrir varias cosas (archivos, carpetas, URL, etc), álbum/favoritos, cerrar reproducción (al pulsar espacio para reanudar continúa la reproducción del último archivo si este no se movió/eliminó incluso después de cerrar el programa y volverlo a abrir), y otros submenús para la apariencia visual, efectos y filtros de audio y vídeo y más.

CÓMO CONFIGURAR LA LECTURA DE SUBTÍTULOS

La opción que nos interesa del menú principal es preferencias, que se abre también con el atajo f5.
Tenemos varias categorías tales como general, configuraciones con respecto a los atajos de teclado, la reproducción, efectos de audio y vídeo, apariencia visual, etc. Puedes explorar todo esto.
La categoría a la que tenemos que acceder en el árbol es Accesibilidad.
Las primeras casillas que se encuentran pulsando tabulador activan la lectura de mensajes del programa, subtítulos e información al pasar el ratón encima, pero con voces sapi 5. Luego aparecen las opciones para configurar la voz, y, si solo quieres que NVDA lea los subtítulos, no necesitas activar las primeras casillas. Lo que nos interesa, es Mostrar mensajes en pantalla como títulos de ventanas, para que NVDA lea automáticamente mensajes que va poniendo el programa por ejemplo cuando se realizan ciertas acciones, por ejemplo, lo que nos cubre aquí (Mostrar los subtítulos de texto como títulos de ventana) para que NVDA lea automáticamente los subtítulos, y Aparece las herramientas al pasar el ratón por encima del tema como títulos de v… Bueno, dice ventana pero incompleto. Se deben marcar estas casillas y aceptar.

Lectura de subtítulos

Hay que tener en cuenta que para poder hacer esto, necesitamos tener los subtítulos aparte. Estos son los formatos de subtítulos soportados por Pot Player:
*.smi; *.srt; *.idx; *.sub; *.sup; *.psb; *.ssa; *.ass; *.txt; *.usf; *.xss; *.ssf; *.rt; *.lrc; *.sbv; *.vtt; *.ttml
Se pueden encontrar muchísimos subtítulos en estos formatos buscando en Internet. Hay páginas específicas que permiten descargarlos.
Una vez tengamos los que queramos, aremos lo siguiente:

  • Con Pot Player abierto o desde el explorador de archivos, buscamos la película/serie/ánime y lo abrimos. Hay que tener en cuenta que, como los subtítulos van aparte, no importa si es audio o vídeo.
  • Luego, pausamos la reproducción con barra espaciadora y nos vamos al menú abrir, cargar/añadir subtítulo, o bien ejecutamos la misma opción desde el menú subtítulos.
  • buscamos el subtítulo y lo abrimos. Ahora pulsaremos espacio para continuar la reproducción, ¡y notaremos que ahora nos lee los subtítulos NVDA!

Nota: Pensaba que se debe tener marcada la opción anunciar cambios en el contenido dinámico sí o sí, pero me he dado cuenta que esto no afecta a esta opción, por lo que con la opción desactivada los sigue leyendo al menos que desmarquemos la casilla para que Pot Player los muestre como títulos de ventana.

SINCRONIZACIÓN

Sin embargo, eso no es todo.
Dependiendo del subtítulo, a veces puede de sincronizarse con la reproducción (dependiendo en dónde comienza el subtítulo y en dónde paramos la reproducción) y hay que lograr sincronizarlo, para que no se lean muy adelantados o muy atrasados. Esto está en el menú subtítulo, en el submenú de la sincronización. Hay varias opciones de velocidad, así que hay que ir probando hasta llegar a la que más se acomode a la reproducción. Nota: Paciencia, sincronizar es algo complicado.
También hay que tener en cuenta que… ¡ también se pueden leer los subtítulos de los dvd’s de esta forma! Con el DVD ya insertado en la unidad, ejecutamos abrir DVD en el menú abrir de Pot Player. Luego, simplemente configuramos los subtítulos en sus respectivos menús, con ayuda visual, aunque también podríamos acceder a ellos con el OCR de NVDA (y si tenemos Windows10 es más fácil que con el complemento OCR).

NOTA SOBRE SUBTÍTULOS DEL TEXTO DENTRO DE UN vídeo

En Youtube, por ejemplo, dependiendo del vídeo, algunos subtítulos del texto se podrán leer. Para esto se descarga el vídeo y como formato de vídeo, o se abre pegando el enlace desde la opción abrir URL (dependiendo de nuestra conecsión a internet esto no siempre funciona por el tiempo de espera), y en el menú subtítulos tener activada la opción subtítulos de texto dentro del vídeo. Nota: Al abrir URL de vídeo con subtítulos de Youtube hay que tener marcada la casilla mostrar con subtítulos, para que estos aparezcan.

TRADUCCIÓN DE SUBTÍTULOS, IDIOMA, ETC

Desde el menú subtítulos también podremos traducir subtítulos que estén en otro idioma, aunque esto utiliza el traductor de Google y por lo tanto dramáticamente puede no traducir bien. También podremos seleccionar el idioma en el caso de un DVD.

CONCLUSIÓN

La lectura de subtítulos automática para nosotros era difícil, pero en los diferentes sistemas operativos esto se está logrando, por lo que ahora se puede resolver sin necesidad de que una persona vidente los esté leyendo o sin tener que estar pulsando flecha abajo de forma incómoda mientras se ve una película o serie, por ejemplo.
¡Esperamos que esto te haya sido útil!

Aquí te presentamos un videotutorial sobre el navegador de objetos, modos de revisión, OCR (el complemento) con el cursor de revisión y el complemento Obj Pad, que fazilita la navegación por objetos con modos para las teclas de flechas.
Haz clic en este enlace para ver el tutorial.
Notas:
Este tutorial fue realizado en marzo del 2017. Por lo tanto, NVDA todabía no funcionava con el OCR de Windows 10, así que aquí te mostramos de forma vrebe cómo utilizarlo. Si tienes una versión inferior a Windows 10, utiliza el complemento OCR que se usa en el tutorial.
Pasos:

  • Coloca el nabegador de objetos sobre la imagen que deseas reconocer.
  • Pulsa NVDA+R. Si el ocr de Windows 10 está disponible y si el objeto se puede reconocer, NVDA dirá reconociendo y mostrará el resultado en un documento con modo exploración, de tal forma que puedes leer el documento como si de cualquier documento en modo exploración se tratase y utilizar espacio o enter para activar (si es posible) un clic en alguna parte del texto (ejemplo, activar una opción en una aplicación).

En este tutorial, se trabaja con los comandos de la distrivución de teclado sobremesa o escritorio. Te recomendamos ver la Referencia rápida de órdenes para ver los jestos de la distrivución portátil, así como los jestos táctiles para equipos con pantalla táctil y Windows 8 o superior.
Este tutorial ha sido realizado por un colaborador de la comunidad de tiflojuegos.com conocido como Civerbadnnes, ya que esto llega a servir en algunos videojuegos para algo de accesibilidad.
¡Esperamos que sea útil!

En esta entrada te presentamos Tifloaudio, un podcast creado por Manolo Álvarez. En él, entre muchas otras curiosidades y tecnologías específicas para personas ciegas, se habla de NVDA. Escuchando en orden los episodios que te mostramos a continuación, harás un recorrido histórico por este lector de pantalla, desde que comenzó a ser un poco más conocido allá por el 2009 hasta la actualidad. Podrás ver su evolución, así como conocer en profundidad cómo funcionan algunas de sus características. Pulsando cada enlace, se abrirá la entrada correspondiente al episodio seleccionado en la web de Tifloaudio. Si estás preparado, ¡allá vamos!
Tiflo Audio 7: Demostración de NVDA
Tiflo Audio 55: Cambiar voces en el lector de pantalla NVDA
Tiflo Audio 70 – Utilizar Windows 10 con el lector de pantalla NVDA y una línea braille
Tiflo Audio 82 – Demostración novedades NVDA 2017.3: Nuevas voces Windows OneCore, Reconocimiento de textos OCR y entradas con líneas braille
Tiflo Audio 94 – Nuevos comandos para líneas braille con el lector de pantalla NVDA 2018
¡Esperamos que los disfrutes!

En este episodio, que ya tiene algún tiempo, se hace una introducción y se resuelven dudas comunes a la hora de dar el paso de Jaws a NVDA. No ha cambiado gran cosa desde que se publicó, salvo el nuevo diálogo de opciones. En él participan José María Ortiz, Daniel Montalvo, Juan Buño y José Manuel Delicado.
Visita la entrada con el episodio en la web de José María Ortiz
¡Que lo disfrutes!

A la hora de programar un complemento que tiene algún tipo de interfaz gráfica, o hacer modificaciones a la propia interfaz de NVDA, todos los desarrolladores ciegos nos hacemos la misma pregunta tarde o temprano: ¿cómo se ve en pantalla esto que estoy programando? Podemos probar distintas combinaciones de constantes, posiciones y tamaños para los controles, pero al no poder verlos, probablemente el resultado no sea el que esperamos. En la entrada de hoy vamos a hablar del módulo guiHelper, disponible desde la versión 2016.4 de NVDA. La misión de este módulo es abstraernos un poco de los detalles más visuales del diseño de nuestra interfaz, de tal forma que sólo debamos preocuparnos de añadir controles y funcionalidad. El módulo no hace magia, pero nuestras interfaces quedarán probablemente un poquito mejor que antes. Si quieres conocer este módulo un poco más, sigue leyendo. ¡Allá vamos!
Nota: en este artículo se asume que el lector tiene conocimientos sobre la programación de complementos con interfaz gráfica.

Importar el módulo

El módulo guiHelper se encuentra en el paquete gui. Si nuestro complemento tiene interfaz gráfica, en algún momento seguramente habremos importado los módulos gui y wx, por lo que sólo haría falta escribir esto:
from gui import guiHelper
Una vez hecho esto, ya podremos acceder a sus constantes, funciones y clases.

Constantes de guiHelper

Estas constantes vienen incluidas directamente en el módulo.

  • BORDER_FOR_DIALOGS: es el borde que se encuentra alrededor de cada control dentro de un diálogo.
  • SPACE_BETWEEN_VERTICAL_DIALOG_ITEMS: cuando los elementos de un diálogo se disponen de manera vertical, esta constante se puede emplear para indicar cuánto espacio hay entre cada elemento.
  • SPACE_BETWEEN_BUTTONS_HORIZONTAL: especifica el espacio que hay entre botones dispuestos de manera horizontal.
  • SPACE_BETWEEN_BUTTONS_VERTICAL: igual que en el caso anterior, pero se aplica cuando los botones están dispuestos verticalmente unos sobre otros.
  • SPACE_BETWEEN_ASSOCIATED_CONTROL_HORIZONTAL: es el espacio que separa a dos controles relacionados dispuestos en horizontal.
  • SPACE_BETWEEN_ASSOCIATED_CONTROL_VERTICAL: lo mismo que en el caso anterior, pero en disposiciones verticales.

Funciones de guiHelper

A día de hoy, guiHelper sólo dispone de una función a nivel de módulo: associateElements. Esta función introduce dos controles en un objeto Sizer de wx, situándolos en horizontal o vertical y separándolos adecuadamente según su tipo. Su cabecera es la siguiente:
def associateElements( firstElement, secondElement)
Los controles deben pasarse en el orden en que queremos que se asocien. Las posibles asociaciones son:

  • wx.StaticText y wx.Choice, wx.TextCtrl o wx.Button: asocia una etiqueta con un cuadro combinado, un cuadro de edición o un botón, en disposición horizontal.
  • wx.StaticText y wx.ListCtrl o wx.ListBox o wx.TreeCtrl: asocia una etiqueta con una presentación en lista, un cuadro de lista o una vista en árbol, en disposición vertical.
  • wx.Button y wx.CheckBox: asocia un botón y una casilla de verificación, disposición horizontal.
  • wx.TextCtrl y wx.Button: asocia un cuadro de texto y un botón en posición horizontal.

En todos los casos, los controles deben ser objetos ya instanciados. La función devuelve el objeto Sizer que los contiene, listo para añadirlo a un diálogo u otro Sizer.

Clases de guiHelper

El módulo guiHelper dispone de cuatro clases que nos ayudan a construir nuestra interfaz. Aunque vamos a verlas todas, la que más se usa es BoxSizerHelper. Todas ellas tienen el atributo sizer, empleado al construir el resto de la interfaz.

La clase ButtonHelper

Esta clase sirve para añadir el espacio adecuado entre botones, tanto en horizontal como en vertical. Al instanciar objetos a partir de ella, se debe especificar la orientación del Sizer que va a generar, ya sea wx.VERTICAL o wx.HORIZONTAL. Por ejemplo:
bh=guiHelper.ButtonHelper(wx.VERTICAL)
Una vez construido el objeto, podemos agregar botones llamando al método addButton:
bh.addButton(mydialog, label=_("Test button 1"))
El método addButton construye un nuevo botón con los parámetros que le pasemos, o también puede añadir un botón previamente creado. Es imprescindible indicar en el primer caso el diálogo o ventana padre que contendrá al botón, y una etiqueta por razones de accesibilidad con el parámetro label. Al acabar, se devuelve el botón creado para que podamos hacer cosas con él, como asociarle acciones.

La clase LabeledControlHelper

Esta clase permite crear controles etiquetados y asociar etiqueta y control entre sí en un Sizer. Se apoya en la función associateElements que vimos más arriba. La cabecera de su constructor es:
def __init__(self, parent, labelText, wxCtrlClass, **kwargs)
Por lo tanto, para construir un objeto de tipo LabeledControlHelper necesitamos pasar como parámetros el diálogo o ventana padre, el texto de la etiqueta que acompañará al control, la clase del control (cuidado, aquí no valen controles previamente creados), y cualquier argumento que necesite el control para construirse. Veámoslo de forma más clara con un ejemplo:
lch=guiHelper.LabeledControlHelper(mydialog, "Selecciona una fruta", wx.Choice, choices=['pera', 'manzana', 'fresa'])
En el ejemplo anterior hemos pasado como clase wx.Choice para crear un cuadro combinado, y como parámetros adicionales las opciones que presentará.
La clase LabeledControlHelper dispone de dos atributos para que podamos trabajar cómodamente: sizer, igual que en el resto de clases, y control, que hace referencia al control de wx que hemos creado.

La clase PathSelectionHelper

Esta clase nos permite crear de una forma rápida, sencilla y abstrayéndonos de todos los detalles, un cuadro de edición y un botón «Examinar…» como los que aparecen en muchos programas, con el objetivo de que podamos fabricar un selector de rutas. En el constructor le pasamos el padre, como siempre, el texto del botón Examinar, y el título del diálogo que se desplegará para seleccionar una ruta cuando pulsemos dicho botón. Por ejemplo:
psh=guiHelper.PathSelectionHelper(mydialog, "Examinar...", "Selecciona la carpeta que contiene los documentos")
Como en los casos anteriores, tenemos la propiedad sizer, pero además aquí nos acompaña otra: pathControl, que contiene una referencia al cuadro de texto donde está escrita la ruta.
En caso de que sea necesario, se podría crear una clase que herede de esta y sobreescribir o extender los métodos getDefaultBrowseForDirectoryPath y onBrowseForDirectory. El primero devuelve la ruta por defecto que muestra el diálogo de seleccionar carpeta, y el segundo muestra este diálogo y almacena el resultado en el cuadro de edición.

La clase BoxSizerHelper

Llegamos a la clase más importante de este módulo, la más usada, y la que emplea la funcionalidad expuesta en casi todas las otras. BoxSizerHelper permite configurar la disposición interna de un objeto Sizer. La cabecera de su constructor es:
def __init__(self, parent, orientation=None, sizer=None)
Como siempre, el primer argumento que espera recibir es la ventana padre. Después, podemos pasar una orientación (wx.VERTICAL o wx.HORIZONTAL), en cuyo caso se creará internamente un objeto Sizer, o un Sizer ya creado, a ser posible vacío. Si pasamos ambos parámetros, se produce un error.
Al igual que sucede en los casos anteriores, tenemos un atributo sizer. Esta clase, además, presenta los siguientes métodos:

  • addItem(self, item, **keywordArgs): añade un control wx ya creado y lo sitúa adecuadamente. El último argumento es opcional y sólo se usa en raras ocasiones. El método devuelve el elemento que se pasa como parámetro, para que podamos asociarle acciones y hacer otras cosas con él.
  • addLabeledControl(self, labelText, wxCtrlClass, **kwargs): añade un control etiquetado. El primer parámetro que recibe es el texto con la etiqueta del control, seguido de la clase del control y los parámetros adicionales que se quieran pasar. Fíjate en el ejemplo anterior del cuadro combinado. Este método devuelve el control que se acaba de agregar.
  • addDialogDismissButtons(self, buttons): agrega y alinea los botones Aceptar, Cancelar y Aplicar de los diálogos estándar. Este método debería llamarse cuando ya se han añadido todos los demás controles. Buttons puede ser un objeto wx.Button, un objeto wx.Sizer o un objeto guiHelper.ButtonHelper. Devuelve el mismo objeto que se le pasa como parámetro.

Aplicaciones prácticas

Al igual que en una entrada anterior, vamos a poner como ejemplo el complemento Enhanced Aria (aunque esta vez no vendrá solo), para demostrar lo fácil que es adaptar nuestros complementos para que se apoyen en guiHelper. En la versión 1.3, para agregar la primera casilla de verificación del diálogo de ajustes de aria mejorada, se hacía esto:
self.bannerenabled=wx.CheckBox(self, wx.NewId(), label=(u"Report banners")) # Como self es una clase que hereda de wx.Dialog, se pasa como padre
self.bannerenabled.SetValue(config.conf['aria']['reportBanner']) # Se establece el valor de la casilla

sizer.Add(self.bannerenabled,border=10,flag=wx.BOTTOM) # se añade la casilla sizer
Como se puede comprobar, hay que crear la casilla con su etiqueta correspondiente, asignarle el valor adecuado y añadirla al objeto que va a contenerla, con indicadores de borde y alineación. Sin embargo, en la versión 2.0 basta con hacer esto:
def createSettings(obj, sizer):
helper=guiHelper.BoxSizerHelper(obj, sizer=sizer)
obj.bannerenabled=helper.addItem(wx.CheckBox(obj, wx.NewId(), label=
("Report banners")))
obj.bannerenabled.SetValue(config.conf['aria']['reportBanner'])

Como se puede ver, creamos un BoxSizerHelper pasando como parámetro el Sizer que nos dan en el método makeSettings, y que en el caso particular de esta implementación se pasa a createSettings. A continuación, agregamos una nueva casilla de verificación llamando a addItem, y luego establecemos su valor.
Veamos el diálogo de Windows 10 App Essentials, que también se apoya en este módulo. Lo podemos encontrar en el archivo w10config.py. Se trata de un diálogo completo, una clase que hereda de wx.Dialog. Por lo tanto, construirlo implica más esfuerzo, al no tener a nuestra disposición la clase SettingsDialog de NVDA o la clase SettingsPanel. En lugar del método makeSettings, que ya nos da un Sizer, las operaciones de construcción se hacen en el constructor del diálogo.
En primer lugar, se crea un objeto de tipo BoxSizer:
mainSizer = wx.BoxSizer(wx.VERTICAL)
Y a continuación, se crea un BoxSizerHelper con un Sizer nuevo, que será hijo del que se acaba de crear:
w10Helper = gui.guiHelper.BoxSizerHelper(self, orientation=wx.VERTICAL)
Teniendo el BoxSizerHelper, ya se pueden añadir controles. Vamos a ver dos de ellos, la casilla de verificación y el cuadro combinado.
self.autoUpdateCheckbox=w10Helper.addItem(wx.CheckBox(self,label=_("Automatically check for add-on &updates"))) # Se crea la casilla
self.autoUpdateCheckbox.SetValue(config.conf["wintenApps"]["autoUpdateCheck"]) # Se establece su valor
labelText = _("&Add-on update channel:") # Etiqueta del cuadro combinado
self.channels=w10Helper.addLabeledControl(labelText, wx.Choice, choices=["development", "stable"]) # Cuadro combinado

Ya para acabar, se añaden los botones Aceptar y cancelar, y se hace de una forma muy particular, ya predefinida en wx:
w10Helper.addDialogDismissButtons(self.CreateButtonSizer(wx.OK | wx.CANCEL))
En este caso no existe acceso directo a los botones, como sí pasa con el resto de los controles, así que las asociaciones se hacen de esta manera:
self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)
self.Bind(wx.EVT_BUTTON, self.onCancel, id=wx.ID_CANCEL)

El BoxSizerHelper ya está completo, hay que añadirlo al Sizer principal. Una vez más, se pide ayuda a guiHelper, y al propio motor wx para centrarlo y posicionarlo:
mainSizer.Add(w10Helper.sizer, border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
mainSizer.Fit(self)
self.Center(wx.BOTH | (wx.CENTER_ON_SCREEN if hasattr(wx, "CENTER_ON_SCREEN") else 2))

Conclusión

Es importante que nuestros complementos e interfaces gráficas en general sean visualmente usables. Aunque NVDA es un lector de pantalla empleado mayoritariamente por personas con discapacidad visual, estas personas suelen estar acompañadas por otras que ven perfectamente, especialmente cuando se introducen en el mundo de la informática. Por tanto, debemos tener en cuenta a todos los posibles usuarios.
En esta entrada hemos conocido el módulo guiHelper, que nos ayuda precisamente en esta tarea. GuiHelper no hace magia, no tiene ningún tipo de «inteligencia artificial» que coloque nuestros controles exactamente como deberían estar para que nuestra interfaz sea atractiva. Sin embargo, nos ayuda un poco a conseguirlo, simplifica nuestro código y por lo tanto facilita el mantenimiento.
Si tus complementos no se apoyan todavía en este módulo, no esperes más para adaptarlos. Tus usuarios lo agradecerán, ¡y tú también!

¡Hola!
Como dijimos el otro día en una entrada anterior, estamos organizando el primer encuentro de la comunidad de NVDA en español. Si quieres participar hablando de algún tema, ¡te esperamos!
La entrada de hoy vamos a dedicarla a Teamtalk, un conocido sistema de conferencias por chat, voz y vídeo, ya que lo utilizaremos para realizar el encuentro de forma remota. Daremos una breve descripción del programa, un resumen de sus características, y los primeros pasos que se deben llevar a cabo para conectarse al servidor que ya tenemos preparado para la ocasión. ¡Comencemos!

Descripción de Teamtalk

Teamtalk es un software multiplataforma que permite comunicarse a través de Internet mediante chat, voz y vídeo. Mucha gente lo compara con Skype, e incluso llega a utilizarlo como alternativa a este. Sin embargo, sus diferencias son tantas que aquí sólo podremos citar unas pocas:

  • En vez de llamadas de usuario a usuario o grupales, en Teamtalk existen canales. Los usuarios no llaman o contestan una llamada. Simplemente buscan un canal donde haya otro usuario y se unen a él.
  • Teamtalk es totalmente descentralizado. No hay un servidor único, tú puedes montar tu propio servidor.
  • La calidad de sonido es constante, con todo lo que ello implica. Si la conexión a Internet es mala, la calidad no se rebaja automáticamente, sino que el sonido se entrecorta.

Algunas de sus características más destacables son:

  • Canales: aunque la calidad sea constante, esto no significa que no se pueda regular. Cada servidor puede tener distintos canales, cada uno con unas características distintas (velocidad en bits del audio, códec utilizado, tasa de muestreo, etc.)
  • Capacidad para regular el sonido: se pueden configurar aspectos tales como la reducción de ruido, posicionamiento de los usuarios en el canal (escuchar algunos a la izquierda y otros a la derecha, por ejemplo), o el volumen de los altavoces y el micrófono sin tocar los ajustes del sistema. Además se puede elegir el motor de sonido, el nivel de activación del micrófono, y muchas más cosas
  • Capacidad para transmitir y recibir vídeo utilizando una WebCam
  • Capacidad para compartir el escritorio o controlar el escritorio compartido de otro usuario
  • Capacidad de emitir archivos multimedia
  • Opciones para compartir archivos subiéndolos al canal
  • Mensajes de chat tanto en el canal como privados con otros usuarios
  • Un cliente específico para usuarios de lectores de pantalla, que se mantiene al día con los últimos avances. Y por si fuera poco, hay un complemento para hacerlo un poco más accesible con NVDA!
  • Muchas otras funciones: grabación de conversaciones, posibilidad de gestionar las suscripciones a lo que envía un usuario concreto, etc.

Descarga e instalación de Teamtalk

Ahora que ya sabemos qué es, ¡toca pasar a la acción! La web oficial de Teamtalk es bearware.dk. Para ahorrar tiempo, vamos a poner los enlaces directos de la última versión, que en el momento de última actualización de esta entrada (julio de 2019) es la 5.4.

La instalación de Teamtalk en Android, iOs y Windows es relativamente sencilla. En este último caso, tras abrir el instalador, aparecerá el asistente de instalación en inglés y nos irá guiando por el proceso. Podemos pulsar el botón next en la mayoría de las pantallas, pero es importante que en una de ellas, que contiene un cuadro combinado, seleccionemos la opción TeamTalk Classic for Accessibility. De lo contrario se instalará la versión no accesible del programa, que resulta más difícil de manejar.

Configuración inicial en Windows

Si no desmarcamos la casilla correspondiente, el instalador abrirá Teamtalk al finalizar. En ese momento se nos preguntará si queremos agregar una excepción al firewall de Windows. Debemos responder que sí, y aceptar los avisos del control de cuentas de usuario, si aparecen. Al hacerlo, llegaremos por fin a la ventana principal de la aplicación.
La ventana de Teamtalk está formada por los siguientes elementos, presentados como aparecen al tabular por ellos:

  • Un árbol, en el que aparecerán tanto los canales como los usuarios cuando estemos conectados a un servidor.
  • Una barra deslizante para ajustar el volumen de los altavoces.
  • Una barra deslizante para ajustar la ganancia del micrófono. Se recomienda que su valor no supere el 50%, de lo contrario el ruido generado puede ser catastrófico para el resto de los usuarios.
  • Una barra deslizante para ajustar el nivel de activación del micrófono. Se recomienda ponerla a 0, de lo contrario hay que hacer mucho ruido para que Teamtalk decida transmitir.
  • Un control de pestañas, que permite seleccionar entre chat o archivos. Por el momento, no nos interesa la carga y descarga de archivos, por lo que ignoraremos la segunda pestaña.
  • Un cuadro de edición con el historial de mensajes.
  • Un cuadro de edición para escribir mensajes.
  • Una barra de menús en la que se encuentran muchísimas opciones que podrás utilizar más adelante.

Lo primero que haremos ahora que tenemos Teamtalk abierto es ir a sus preferencias y modificar algunos ajustes. Para ello, pulsaremos f4 desde la ventana de la aplicación.
En la pestaña general podemos escribir nuestro nombre, seleccionar nuestro sexo y las opciones de activación de voz. Se recomienda activar ambas, tanto la de activación por voz como la de pulsar para hablar (push to talk). En este último caso habrá que configurar un atajo de teclado, que deberemos mantener pulsado mientras hablemos.
La pestaña Display nos permite cambiar el idioma de Teamtalk y ponerlo en español, elegir si queremos minimizarlo a la bandeja y si queremos que se inicie minimizado, entre otras opciones. Se recomienda desmarcar una casilla llamada «Enable VU-meter updates» para evitar que se muestre una molesta barra de progreso.
La pestaña Sound System nos permite configurar los dispositivos de sonido. En la documentación de Teamtalk nos recomiendan que nos quedemos con Windows Audio Session como motor de sonido. Podemos elegir otros que nos dan más opciones, como Direct Sound, pero hay que tener en cuenta que si lo hacemos se deben elegir los dispositivos de sonido en los cuadros combinados que hay después, no se pueden dejar por defecto.
El resto de pestañas contienen valores que pueden dejarse como están, no es necesario modificarlos. Una vez hayamos configurado Teamtalk a nuestro gusto, podemos pulsar en Aceptar y conectarnos al servidor.

Conexión al servidor

Para abrir el diálogo de conexión puedes ir a la barra de menús, o directamente pulsar f2. Al hacerlo aparecerás en una lista. Pulsa tabulador hasta llegar a un cuadro de edición llamado Dirección del host. Escribe teamtalk.nvda.es y pulsa intro. ¡Tan sencillo como eso! Cuidado, no pulses las flechas en la lista, de lo contrario alterarás los valores por defecto y no podrás conectarte. Si ya te ha ocurrido esto, pulsa escape para cerrar el diálogo de conexión y vuelve a pulsar f2.
Al conectarte, verás mensajes en el cuadro de edición del historial del chat, y algunos elementos en el árbol. El primero de ellos es el canal raíz. Si pulsas flecha abajo, verás a los usuarios conectados, incluido tú. Si sigues bajando, verás el resto de canales. Pulsa ctrl+j o intro para unirte a ellos, o accede al menú de contexto para ver las opciones disponibles.

Los canales del servidor de Teamtalk de NVDA.es

Además del canal raíz, hay otros tres canales, y es importante que conozcas algunas particularidades de ellos. Eso sí, ten en cuenta que el chat está disponible en todos.

  • Canal raíz: tiene el códec de audio desactivado por defecto. Esto significa que en este canal sólo se puede usar el chat. Debes verlo como una «entrada» o zona de paso, ideal para permanecer mientras seleccionas otro canal.
  • Foro: es un canal libre para debatir sobre NVDA. Sin embargo, sólo se puede hablar utilizando el método pulsar para hablar (recuerda el atajo que configuraste antes), y no permite que ningún usuario grabe la conversación. Deberás desactivar «Usar activación por voz» desde el menú «yo» para poder hablar, de lo contrario los otros usuarios no te escucharán. Esto se hace para garantizar cierto orden, seguridad y privacidad.
  • Pruebas de sonido: este canal sólo permite tres usuarios conectados a la vez, y ha sido diseñado especialmente para los ponentes, aunque cualquiera puede entrar. Lo ideal es que entres a este canal, busques tu usuario en el árbol, pulses ctrl+4 para suscribirte a tu propia voz y te escuches. En cuanto hayas ajustado los parámetros de volumen, pulsa de nuevo ctrl+4 y únete a otro canal.
  • Sala de conferencias: en este canal hablarán los ponentes del encuentro de NVDA en español. Nadie más puede hablar, a no ser que obtenga permiso explícito del operador del canal, situación que se dará a la hora de hacer preguntas.

Algunos atajos de teclado útiles

  • f2: conecta y desconecta del servidor.
  • f4: abre las preferencias.
  • ctrl+shift+a: activa o desactiva la transmisión de voz. Imprescindible tenerla desactivada en el canal foro.
  • f5: permite cambiar rápidamente el nick.
  • f6: cambiar estado entre en línea o ausente, con mensaje opcional si fuera necesario.
  • ctrl+4: suscribirte o anular suscripción a tu propia voz.
  • ctrl+m: silenciar a todos los usuarios.
  • ctrl+j: unirse a un canal.
  • ctrl+l: abandonar el canal sin unirse a otro.

Conclusión

Después de hacer este breve recorrido por Teamtalk, toca despedir la entrada. Te recordamos que también buscamos a alguien que quiera transmitir el encuentro en su emisora de radio, ya que Teamtalk puede ser algo complejo para bastantes usuarios. Para cualquier pregunta o sugerencia, no dudes en escribirnos un comentario debajo, o contactar con nosotros en la lista de correo, las redes sociales o el formulario de contacto de esta web.
¡Hasta la próxima!

¡Hola a todos!
Faltan un par de semanas para que NVDA 2018.2 vea la luz, y sin embargo nadie ha parado de hablar de los cambios que trae desde hace ya un tiempo. Uno de los más importantes es el nuevo diálogo de preferencias organizado en categorías, al que hemos hecho referencia ya en varias entradas al hablar de complementos que se actualizan. En este tutorial veremos qué hay que hacer para que el diálogo de preferencias de nuestro complemento se integre en el nuevo diálogo de opciones de NVDA. Nos apoyaremos en el complemento Enhanced Aria, ya que su código es bastante simple, está en un único módulo y los cambios realizados son relativamente sencillos de entender. ¡Comencemos!
Nota: este es un artículo avanzado de desarrollo. Se asume que el lector sabe hacer complementos sencillos, y conoce el lenguaje Python con todo lo que ello conlleva.

Creación de ajustes sensibles a cambios de perfil

NVDA nos da mucha flexibilidad a la hora de crear diálogos para nuestros complementos. De hecho, nos da tanta que nos podemos perder, hacernos un lío, y programar todo con wx para luego darnos cuenta de que existen módulos que nos abstraen de un montón de detalles complejos. Con la configuración pasa exactamente lo mismo, podemos saber que existe configobj, pero ignorar que hay una capa por encima que nos facilita la vida. Definir una especificación de configuración es tan sencillo como crear una variable global en el módulo de nuestro complemento, indicando de qué tipo son los valores y el valor por defecto de cada uno. Esta es la configuración de Enhanced Aria:
confspec={
 "reportBanner":"boolean(default=true)",
 "reportMain":"boolean(default=true)",
 "reportContentinfo":"boolean(default=true)",
 "reportNavigation":"boolean(default=true)",
 "reportComplementary":"boolean(default=true)",
...}
En el caso de Enhanced Aria, todo lo que se configura es booleano, casillas que se marcan o desmarcan. Una vez definida la especificación, hay que decirle a NVDA que la añada al conjunto de especificaciones. Una variable global definida por sí sola en un módulo no va a hacer nada: config.conf.spec['aria']=confspec
Después de este inciso, breve pero necesario para entender todo lo demás, vamos a los diálogos en sí.

El diálogo tradicional de ajustes

Un diálogo tradicional de ajustes es una clase que hereda de gui.settingsDialogs.SettingsDialog. ¡Cuidado con las mayúsculas al programar, nos pueden hacer pasar un mal rato! Todos los diálogos de preferencias de NVDA heredan de esta clase, y los complementos también suelen hacerlo. La clase SettingsDialog nos ofrece varios métodos y propiedades que podemos redefinir:

  • title: propiedad que define el título del diálogo. Debe ser una cadena de caracteres.
  • makeSettings(self, sizer): este método se usa para rellenar el sizer que se recibe como parámetro con los controles que queramos. Enseguida vemos un ejemplo.
  • postInit(self): se ejecuta tras crear y mostrar el diálogo en pantalla. Sirve para llevar el foco por defecto a un control que nos interese, por ejemplo.
  • onOk(self, evt): NVDA llama a este método cuando se pulse el botón aceptar. Los botones Aceptar y Cancelar vienen ya en la clase padre, no tenemos que añadirlos en makeSettings. Aquí se hacen cosas tales como guardar la configuración. Importante llamar al método de la clase padre cuando terminemos.
  • onCancel(self, evt): método que se ejecuta al pulsar el botón cancelar. Importante llamar al método de la clase padre si lo redefinimos.

NVDA 2018.2 extiende este diálogo añadiendo un botón de aplicar, el evento asociado (onApply), y la posibilidad de que el diálogo pueda abrirse varias veces simultáneamente. Todas estas novedades son opcionales para conservar la compatibilidad con complementos que no se adapten a ellas.
Veamos algunos ejemplos. El título de Enhanced Aria es traducible a otros idiomas, y quedaría así: title=(u"Enhanced Aria settings")
El método makeSettings sería el siguiente. Para no hacer muy pesada la lectura, se pondrá sólo una parte:
 def makeSettings(self, sizer):
  #TRANSLATORS: report banners checkbox
  self.bannerenabled=wx.CheckBox(self, wx.NewId(), label=
(u"Report banners"))
  self.bannerenabled.SetValue(config.conf['aria']['reportBanner'])
  sizer.Add(self.bannerenabled,border=10,flag=wx.BOTTOM)
  #TRANSLATORS: report main content checkbox
  self.mainenabled=wx.CheckBox(self, wx.NewId(), label=(u"Report main content"))
  self.mainenabled.SetValue(config.conf['aria']['reportMain'])
  sizer.Add(self.mainenabled,border=10,flag=wx.BOTTOM)
#TRANSLATORS: report search forms checkbox
  self.searchenabled=wx.CheckBox(self, wx.NewId(), label=
(u"Report search forms"))
  self.searchenabled.SetValue(config.conf['aria']['reportSearch'])
  sizer.Add(self.searchenabled,border=10,flag=wx.BOTTOM)
...

Como se puede ver, no sólo creamos, etiquetamos y añadimos casillas de verificación, sino que establecemos su valor basándonos en la configuración actual. Una vez creadas, postInit hace lo siguiente:
 def postInit(self):
  self.bannerenabled.SetFocus()

Nuestro diálogo ya está listo. Como se puede intuir, no se ha redefinido el método onCancel, que simplemente descarta todo y no tiene que hacer nada más. Sin embargo, el método onOk sí tiene trabajo.
def onOk(self, evt):
  config.conf['aria']['reportBanner']=self.bannerenabled.GetValue()
  config.conf['aria']['reportMain']=self.mainenabled.GetValue()
  config.conf['aria']['reportSearch']=self.searchenabled.GetValue()
  config.conf['aria']['reportForm']=self.formenabled.GetValue()
  ...
  applyConfig()
  super(enhancedAriaSettings, self).onOk(evt) # Importante, llamada al padre!

Y ahora, ¿qué hacemos para poder llegar a este diálogo?
Como bien se ha dicho antes, la magia no existe. En el método init de la clase GlobalPlugin, hay que crear un elemento de menú y asociarlo al submenú preferencias de NVDA.
  self.prefsMenu = gui.mainFrame.sysTrayIcon.menu.GetMenuItems()[0]
  #TRANSLATORS: The configuration option in NVDA Preferences menu
  self.enhancedAriaSettingsItem = self.prefsMenu.Append(wx.ID_ANY, _(u"Enhanced aria settings..."), _(u"Change enhanced Aria settings"))
  gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onEnhancedAriaMenu, self.enhancedAriaSettingsItem) # Asociamos abrir el menú a activar el diálogo

No debemos olvidarnos de eliminar el elemento de menú en el método terminate, de lo contrario aparecerá duplicado al recargar las extensiones: self.prefsMenu.RemoveItem(self.enhancedAriaSettingsItem)
Para activar el diálogo, hacemos algo como esto: gui.mainFrame._popupSettingsDialog(enhancedAriaSettings)
Esta es la clase que contiene nuestro diálogo, enhancedAriaSettings. Pero lo hará por poco tiempo, ¡es hora de dar el salto al diálogo de categorías!

El panel de configuración en el diálogo de categorías

Para añadir paneles de configuración al diálogo de opciones, simplemente debemos crear una clase que herede de gui.settingsDialogs.SettingsPanel, y añadir nuestro panel al diálogo de opciones de NVDA, que está definido como variable global en el módulo gui. Esta clase nos ofrece los siguientes métodos y propiedades:

  • title: el título del panel de configuración.
  • makeSettings(self, sizer): al igual que antes, se nos pasa un sizer que rellenaremos con controles.
  • onSave(self): código que se ejecuta al pulsar los botones aceptar o aplicar del diálogo. Ya no es necesario llamar al método padre, como sí pasaba en onOk.
  • onPanelActivated(self): código que se ejecuta cuando se selecciona este panel. Aquí sí se debería llamar al método padre. Sin embargo, no deberíamos mover el foco como se hacía en postInit.
  • onPanelDeactivated(self): código que se ejecuta al abandonar el panel. Se debe llamar al método padre si lo redefinimos.
  • onDiscard(self): método que se llama al salir del diálogo de opciones sin guardar los cambios.

Una vez definido nuestro panel, debemos agregarlo al diálogo de opciones de NVDA. Por ejemplo, en el método init de la clase GlobalPlugin: NVDASettingsDialog.categoryClasses.append(enhancedAriaPanel)
Y por supuesto, eliminarlo en el método terminate, de lo contrario nos arriesgamos a que se duplique: NVDASettingsDialog.categoryClasses.remove(enhancedAriaPanel)
El código queda más simple, ¿verdad? Es muy sencillo hacer un complemento con preferencias que se adapte a NVDA 2018.2. Y como a mí no me gusta lo fácil, vamos a complicarlo un poco: vamos a añadir compatibilidad entre versiones. Puede haber gente que no quiera actualizar NVDA, y no debemos olvidarnos de ellos.

Soporte para todas las versiones de NVDA posibles

Llegados a este punto, podríamos tener dos clases: una con el diálogo y otra con el panel. Podríamos añadir el panel al diálogo de opciones y crear un elemento de menú en el submenú preferencias, y no pasaría nada. Como ya se ha dicho, NVDA nos da flexibilidad. ¿Permitiría esto que nuestro complemento adaptado funcionase con versiones antiguas? La respuesta ya te la puedes imaginar, si fuera afirmativa no existiría este apartado en el tutorial.
Por un lado, tal y como está, nuestro complemento muere estrepitosamente en NVDA 2018.1.1, diciendo que hay módulos que no encuentra. Por otro, queremos que el elemento de menú aparezca en versiones antiguas, y el panel del diálogo de opciones en las nuevas. Para lo último, en los métodos init y terminate de GlobalPlugin, podemos hacer algo como esto.
Método init:
  if hasattr(settingsDialogs, 'SettingsPanel'): # Es el nuevo NVDA
   NVDASettingsDialog.categoryClasses.append(enhancedAriaPanel)
  else:
   self.prefsMenu = gui.mainFrame.sysTrayIcon.menu.GetMenuItems()[0].GetSubMenu()
   #TRANSLATORS: The configuration option in NVDA Preferences menu
   self.enhancedAriaSettingsItem = self.prefsMenu.Append(wx.ID_ANY, _(u"Enhanced aria settings..."), _(u"Change enhanced Aria settings"))
   gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onEnhancedAriaMenu, self.enhancedAriaSettingsItem)

Método terminate:
   if hasattr(settingsDialogs, 'SettingsPanel'):
    NVDASettingsDialog.categoryClasses.remove(enhancedAriaPanel)
 else: # Es el antiguo
    self.prefsMenu.RemoveItem(self.enhancedAriaSettingsItem)

Como se puede comprobar, miramos si existen atributos que sólo podrían existir en NVDA 2018.2.
De cara a la importación de módulos, podríamos hacer algo como esto:
import gui
from gui import settingsDialogs
try:
 from gui import NVDASettingsDialog
 from gui.settingsDialogs import SettingsPanel
except:
 pass # No hacer nada si falla

El planteamiento está muy bien. Si falla al importar las clases es porque no existen, ya que estamos en un NVDA antiguo. Por lo tanto, nos olvidamos del panel y usamos el elemento de menú y el diálogo clásico. ¿Todos estamos deacuerdo? Sí, excepto el intérprete Python.
Cuando Python lea nuestro archivo de complemento, verá que intentamos definir la clase del panel, y que indicamos un padre que no existe porque no lo hemos importado. Por suerte, Python es tan flexible como NVDA: cualquier variable se puede asignar a cualquier cosa, sin importar el tipo e incluso sin que importe que sea una clase o función. Lo único que nos pide es algo de lo que pueda heredar el panel, así que vamos a darle el objeto base del lenguaje: object. En la cláusula except, en vez de poner pass para que no haga nada, hacemos: SettingsPanel=object

Optimización de código

Es tentador copiar y pegar código de unos métodos a otros. En el caso de EnhancedAria, siempre define las mismas casillas, y siempre guarda la misma configuración. Sin embargo, no es una buena práctica, ya que si tenemos un fallo este también se duplica, y hay que corregirlo tantas veces como se haya hecho el copia-pega. Por lo tanto, se ha sacado el código repetido y se ha metido en funciones globales del módulo:

  • addonSettingsTitle: título del diálogo y del panel. Es el mismo en ambos casos. Si lo dejamos duplicado, un traductor tendría que modificarlo dos veces.
  • createSettings(obj, sizer): obj es una referencia al objeto que llama a la función. Es como el self que vimos antes. Esta función crea las casillas.
  • storeSettings(obj): almacena los ajustes al pulsar el botón aceptar.

Haciendo estos cambios, el tamaño de las clases se reduce. Así quedaría el método onSave:
 def onSave(self):
  storeSettings(self)

Conclusión

Existen muchas formas de adaptar nuestros complementos para que aprovechen las nuevas características introducidas en NVDA 2018.2. Podemos modificarlos, o podemos dejarlos como están. Sin embargo, para proporcionar una experiencia de usuario consistente, se recomienda lo primero más que lo segundo. En este tutorial se ha visto sólo una de las muchísimas alternativas existentes. Tanto Python como NVDA son flexibles, permitiendo que cada desarrollador haga las cosas a su manera y optimice el código como le parezca oportuno. Por ejemplo, la simplificación de código vista anteriormente podría haberse hecho definiendo una clase y aplicando herencia múltiple, si bien es cierto que este enfoque podría complicar un poco las cosas. Espero que hayáis disfrutado leyendo este tutorial tanto como yo al escribirlo, y que os sirva para poner vuestros complementos al día. Para cualquier pregunta o sugerencia, no dudéis en dejarnos un comentario debajo.
¡Hasta la próxima!

Aunque hace unos días os hablábamos de que no es conveniente utilizar portables modificados de NVDA, sí es cierto que tener copias portables creadas bajo nuestra propia responsabilidad y en principio para nuestro uso o de personas cercanas en las que confiemos, puede resultar muy útil en determinados momentos, como tener acceso a un PC en el que ayudar a alguien, en lugares públicos como bibliotecas o centros de trabajo, etc. Lo malo es que NVDA ejecutándose de manera portable no tendrá todos los privilegios necesarios para acceder al sistema entero, pero lo bueno es que al menos sí podremos hacerlo.

¿Qué es un portable?

Una copia portable de NVDA es aquella que podemos llevar en un Pen drive o cualquier otro soporte de almacenamiento que se nos ocurra, con nuestras configuraciones (o no), que nos permite ejecutar NVDA en cualquier equipo donde podamos conectar un USB y que cumpla los requisitos mínimos para ejecutar NVDA. Esto resulta especialmente útil a la hora de trabajar en un equipo que no es nuestro o en momentos similares.

¿Es recomendable? Depende de para qué. Aunque desde nvda.es no lo recomendamos para el uso habitual del equipo, nadie te impide no instalar NVDA y ejecutarlo desde donde más te gusta, al igual que nadie te asegura su óptimo funcionamiento, y esto es porque probablemente no lo tendrás. Al ser una copia portable, a la que no permitimos privilegios para acceder a determinadas partes del sistema, como las ventanas del control de usuarios, por ejemplo, habrá partes del sistema con las que nos será imposible trabajar con NVDA portable.

¿Cómo se crea?

Tenemos dos formas de crearlo, las dos igual de sencillas.

  • Desde el instalador de NVDA.
    1. Abrimos el instalador de NVDA.
    2. Nos movemos con Tab hasta el botón crear una copia portable.
    3. Seleccionamos donde queremos que se guarde.
  • Desde nuestro NVDA ya instalado.
    1. Abrimos el menú de NVDA.
    2. Bajamos hasta herramientas y pulsamos crear copia portable.
    3. Pulsamos el botón de examinar, y seleccionamos en la ventana de Explorador de Archivos que se nos abre el directorio donde queremos que se guarde nuestra copia portable.
    4. Si queremos que lo haga, marcamos la casilla correspondiente para que se copien la configuración y los complementos de nuestra copia instalada al portable que estamos creando. Esto copiará todos los complementos instalados, los sintetizadores y sus licencias y todo cuanto tengamos personalizado (salvo la aplicación de los ajustes de NVDA a ventanas seguras).
    5. Pulsamos continuar y después aceptar cuando se nos haya creado.

Es recomendable crear el portable en una carpeta vacía, ya que genera más de 50 archivos.

¿Cómo se ejecuta?

Para ejecutar NVDA portable, será tan sencillo como navegar al directorio donde se haya guardado y ejecutar el archivo nvda.exe. Si queremos instalarlo en nuestro equipo, será tan sencillo como navegar de nuevo al menú herramientas, donde la opción de crear copia portable se habrá sustituido por la de instalar. Al instalarlo, podemos aplicar (o no) los complementos y configuraciones que teníamos en el portable.

Conclusiones

La creación de este artículo viene motivada por la grabación de un vídeo de Félix Couce, donde explica de forma más detallada el uso y creación de las copias portables de NVDA que se puede encontrar en nuestro canal de YouTube y que insertamos aquí.

En definitiva. ¿Conviene crear copias portables de NVDA? Depende del uso que vayamos a darle, pero desde luego es algo que se le ha reprochado en multitud de ocasiones a JAWS y que incluso se ha tratado de emular para este lector de pantalla en muchas ocasiones. No obstante, todas estas iniciativas han resultado fallidas. No creemos que sea conveniente para el uso continuo del lector, ya que se le puede sacar todo el potencial instalado, pero es la mejor opción para utilizar equipos ajenos.

Referencias