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 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 (septiembre de 2021) es la 5.8.1.

Instalación y configuración

Procedimiento automático

Teamtalk es un software tan potente como complejo. Por este motivo, se puede perder mucho tiempo configurándolo, así que hemos decidido facilitarte la tarea.
Si utilizas Windows, ponemos a tu disposición el cliente «Arranca y conecta». Descárgalo, ejecútalo, y aterrizarás directamente en nuestra sala de conferencias, listo para escuchar y participar en el encuentro. Este cliente no tienen ningún misterio: es una copia del cliente accesible de Teamtalk (versión 5.8.1), configurada de una forma determinada y empaquetada para facilitar su ejecución. Y todo ello, sin que tengas que instalar nada:

  • Cliente estándar: utilízalo si asistes como espectador a cualquiera de las ponencias. En este cliente se han desactivado todos los reductores de ruido, se ha configurado el nivel de activación por voz a 0, se ha cambiado el idioma a español y se han eliminado todos los demás idiomas, a excepción del inglés.
  • En el modo específico para ponentes, además de todo lo anterior, se han desactivado todos los eventos de texto a voz, se ha ocultado el panel de chat y se han suprimido los sonidos.

Cuando abras este cliente y llegues a la sala de conferencias, haz lo siguiente:

  • Pulsa f4, navega a la pestaña Sistema de sonido y comprueba que el micrófono y los altavoces sean los correctos. Si no lo son, cámbialos utilizando los cuadros combinados correspondientes y pulsa el botón Aceptar.

Como no todo puede ser perfecto, este cliente tampoco lo es: deberás realizar estos cambios cada vez que lo abras.
Si ya tienes TeamTalk instalado, o usas una plataforma distinta a Windows, disponemos también de un archivo de configuración que te llevará a nuestra sala de conferencias. Puedes abrirlo directamente desde cualquier plataforma para conectarte, o importarlo en tu lista de servidores si usas una de las aplicaciones de escritorio. Si utilizas el cliente para Android, deberás importar el archivo, ya que al abrirlo directamente el programa produce un error.
Pincha aquí para descargar el archivo de configuración.
Si TeamTalk no se abre al descargar el archivo, situación que se da en dispositivos como el iPhone, puedes utilizar este enlace directo para conectarte.

Procedimiento manual

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.
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.
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.
Si utilizas las aplicaciones de iPhone o Android, el procedimiento de conexión varía ligeramente. Deberás agregar un nuevo servidor a tu lista de servidores guardados. En nuestro caso, sólo es necesario que rellenes los dos primeros campos: un nombre que te permita reconocer el servidor, y la dirección del mismo, teamtalk.nvda.es. Después podrás conectarte utilizando el botón situado en la lista a tal efecto.

Breve recorrido por la ventana del cliente accesible para Windows

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.

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. Es posible que existan salas de conferencia de desdoble, que se señalizarán oportunamente y funcionarán de la misma manera.

Algunos atajos de teclado útiles en la aplicación de escritorio

  • 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

NVDA tiene una opción que, aunque desconocida para mucha gente, lo hace ser muy versátil a la hora de trabajar en entornos concretos con programas aún más concretos. La opción de la que hablamos son los perfiles, que podemos configurar según nuestras necesidades.

Contenido

¿Qué son?. 1

El menú de perfiles. 1

Creando un nuevo perfil. 1

Notas adicionales. 2

Referencias. 2

 

 

¿Qué son?

Son configuraciones concretas que podemos hacer a NVDA en escenarios concretos según las necesidades que tengamos al trabajar en determinada aplicación. Estos perfiles se lanzarán de dos maneras, o bien cuando los lancemos de forma manual o bien al configurarlos en determinados entornos, al estar usando una aplicación, por ejemplo. Realmente es mucho más sencillo de lo que parece.

Por ejemplo, puede que, al estar editando en Word, necesitemos que NVDA nos lea los atributos de la letra, los errores de ortografía, los ajustes de párrafo y las sangrías, pero esto nos incomode a la hora de navegar por internet con Firefox. En lugar de activarlo y desactivarlo manualmente, NVDA puede hacerlo por nosotros. La mayoría de las opciones de NVDA, menos las opciones generales, que se aplican a todo el programa, pueden aplicarse en un perfil de configuración cuando lo estamos editando. Incluso podríamos configurar que NVDA cambiara de sintetizador y/o velocidad de lectura al abrir un lector de e-books, por ejemplo.

 

El menú de perfiles

Accedemos a él desde el menú principal de NVDA, perfiles de configuración, o con NVDA+Control+P. Por defecto, solo tendremos el perfil de la configuración normal, que estamos editando. Si por ejemplo tenemos el complemento para Lambda instalado, veremos que tenemos un perfil para Lambda que este nos crea para aplicar sus configuraciones.

  • Al entrar en el menú, lo primero que tenemos es esta lista de perfiles mencionada más arriba.
  • Al movernos con tab, encontramos una opción para crear un nuevo perfil.
  • Al colocarnos en un perfil adicional de NVDA, podemos eliminarlo o editarlo desde este menú.
  • Si continuamos, podemos desplegar una lista de disparadores.
  • Si continuamos, podemos deshabilitar la actuación de los disparadores.

 

Creando un nuevo perfil.

                Para crear un nuevo perfil, pulsamos el botón nuevo. Podemos ponerle un nombre, que nos ayudará a identificarlo, y al pulsar tab seleccionaremos qué actuará como disparador, es decir, en qué situación se activará este perfil. Lo ideal es que, si queremos que se ejecute en una aplicación, Word, por ejemplo, lo creemos con una ventana de Word abierta. Será entonces cuando podremos seleccionar aplicación actual (Winword) y solo se lanzará al abrir Word. Esto, por supuesto, podríamos aplicarlo a la mayoría de las aplicaciones para las que consideremos que necesitamos una configuración diferente.

                Es importante reseñar que, si no rellenamos el nombre, al seleccionar que se ejecute en una aplicación, se asignará un nombre automáticamente que nos permitirá identificar el perfil.

 

 

Notas adicionales

  • Se puede activar un perfil manual mediante su opción correspondiente, pero esto no evitará que los lanzadores activen otros. Las opciones del primer perfil, el manual, primarán sobre las que active el lanzador. Por ejemplo, si en el perfil activado manualmente no tenemos activado el aviso de errores de ortografía, pero sí lo tenemos en el automático activado por un lanzador, al no estar activado en el primero no se leerán. No obstante, sin en el del disparador se ha cambiado la voz y esto no se ha hecho en el manual, se utilizará la voz del perfil disparado y las configuraciones modificadas se guardarán en el manual.
  • Desde la opción de disparadores podemos ver que disparador está asociado a cada perfil y editarlo.
  • Si se ha activado manualmente un perfil, las opciones que se modifiquen se guardarán en él. Si no se ha hecho, las opciones modificadas se guardarán en el perfil que más recientemente se haya lanzado. Si no hay perfil, asociado o manual, las opciones modificadas se guardarán en el perfil normal.
  • Para editar el perfil asociado a verbalizar todo, este se debe activar de forma manual.
  • Se pueden desactivar todos los disparadores marcando la casilla de verificación correspondiente. Esto puede ser útil para hacer determinadas configuraciones sin que interfieran los perfiles.

 

Referencias

 

Nota: Esta guía fue publicada en el año 2015 en la antigua web de NVDA en español. La versión que se ofrece a continuación ha sido actualizada solucionando errores producidos por la conversión entre lenguajes de marcado, eliminando algunos fallos ortográficos y gramaticales del autor y cambiando la referencia al apartado de la guía de usuario que habla de los diccionarios. Si detectas algún error, déjanos un comentario más abajo.

Como se explica en la sección 11.1.14 de Diccionarios del Habla en la Guía de Usuario, gracias a la creación o modificación de los diccionarios NVDA permite personalizar la forma en que el sintetizador lee ciertas palabras, símbolos o dígitos.

En esta pequeña guía vamos a ver como utilizar Expresiones regulares en los diccionarios del habla del lector de pantalla NVDA, ya que en la guía de usuario no se explican con detalle.

A continuación se muestra una breve introducción a las expresiones regulares, seguida de una lista de caracteres y secuencias especiales. No trates de memorizar estas listas, por ahora solo debes tener en cuenta que cada carácter y secuencia especial tiene su propio significado y función.

Con los ejemplos aprenderás a entender el funcionamiento y a crear tu propio diccionario con expresiones regulares.

¿Estás listo? ¡Vamos!

Expresiones regulares: conceptos básicos

En esta sección se presentan conceptos de expresiones regulares, y se explica cómo se crean y se utilizan en los diccionarios de voz de NVDA.

Una expresión regular, llamada también regex, es una secuencia de caracteres que forma un patrón de búsqueda, principalmente utilizada para la búsqueda de cadenas de caracteres y operaciones de sustitución.

Específicamente, NVDA va a aplicar Expresiones regulares para reemplazar patrones cada vez que se encuentre una coincidencia en la lectura.

Podemos decir que es una operación de sustitución cuando el texto escrito se reemplaza antes de ser procesado por el sintetizador de voz.

Las expresiones regulares pueden contener caracteres ordinarios y caracteres especiales.

Los caracteres ordinarios son las letras de la a a la z, los números, el signo subrayado y otros signos de puntuación que no están incluidos en los caracteres especiales.

La mayoría de los caracteres ordinarios, como «a A b 9 0», son las expresiones regulares más simples, simplemente coinciden consigo mismos.

Por ejemplo, se pueden concatenar caracteres ordinarios así:

la expresión «Odissea2001» coincide con «Odissea2001».

Caracteres Especiales

Lista completa de caracteres especiales y su comportamiento en el contexto de las expresiones regulares:

  • «\». Marca el siguiente caracter como un caracter especial, un literal, una referencia inversa. Por ejemplo, «r» coincide con el caracter «r», mientras que «\r» coincide con un caracter de retorno de carro. Cuando precede a caracteres que normalmente se tratan de forma especial, indica que el siguiente caracter no es especial y debe ser interpretado literalmente. Por ejemplo, la secuencia \» coincide con » y ( coincide con (.
  • «.». Coincide con cualquier caracter excepto con «\n».
  • «^». Coincide con la posición al principio de la cadena de entrada. La propiedad Multiline está establecida para coincidir también con la siguiente posición después de «\n» o «\r». Es decir, este caracter corresponde también a la posición inmediatamente después de una nueva línea o un retorno de carro.
  • «$». Coincide con la posición al final de la cadena de entrada. La propiedad Multiline está establecida para que $ coincida también con la posición anterior a «\n» o «\r».
  • «?». Cuando este caracter va inmediatamente después de cualquier otro cuantificador (se mencionan a continuación), el modelo coincidente es no expansivo. Un modelo no expansivo coincide lo menos posible con la cadena buscada, mientras que el modelo expansivo predeterminado coincide tanto como sea posible con la cadena buscada.
  • «?». Un cuantificador,coincide una vez o ninguna con el caracter o subexpresión anterior. Equivale a {0,1}
  • «*». Un cuantificador, coincide cero o más veces con el caracter o subexpresión anterior. Equivale a {0,N}.
  • «+». Un cuantificador, coincide una o más veces con el caracter o subexpresión anterior. Equivale a {1,N}.
  • «{n}». Un cuantificador: coincide exactamente n veces, donde n es un entero no negativo. Por ejemplo, «o{2}» no coincide con la ‘o’ de «soy», pero coincide con las dos oes de «Cooperar».
  • «{n,}». Un cuantificador: coincide como mínimo n veces, donde n es un entero no negativo. Por ejemplo, «o{2,}» coincide con todas las oes de «nooooo», pero no coincide con la «o» de «sol».
  • «{n,m}». Un cuantificador. M y n son enteros no negativos donde n es menor o igual de m. Coincide n veces como mínimo y m veces como máximo. Tener en cuenta que no se puede incluir un espacio entre la coma y los números.
  • «[xy]». Un juego de caracteres, coincide con cualquiera de los caracteres incluidos entre corchetes. Por ejemplo, «[aeu]» coincide con «a» en «Madrid».
  • «[^xy]». Un juego de caracteres negativo. Coincide con cualquier caracter no incluido entre corchetes. Por ejemplo, «[^aeu]» coincide con la «M», la»d», la «r», la «d» de «Madrid», pero no coincide con la «a».
  • «[a-z]». Un intervalo de caracteres, coincide con cualquier caracter del intervalo especificado. Por ejemplo, «[a-z]» coincide con cualquier caracter alfabético en minúsculas dentro del intervalo de la ‘a’ a la ‘z’.
  • «[^a-z]». Caracteres de un intervalo negativo. Es decir, coincide con cualquier caracter que no esté incluido en el intervalo especificado. Por ejemplo, «[^a-z]» coincide con cualquier caracter que no esté incluido en el intervalo de la ‘a’ a la ‘z’.
  • «|» Es un carácter disyuntivo: x|y, coincide con x o con y. Por ejemplo, la expresión «Juli(a|o)» coincide con «Julia» o con «Julio».
  • «(…)». Una subexpresión que coincide con el modelo entre paréntesis y captura la coincidencia. La coincidencia capturada se puede recuperar en el remplazo mediante las secuencias especiales «\1» «\2» etc. Para que coincidan los paréntesis ( ), utilice «(» o «)».
  • «(?:…)». Una subexpresión que coincide con el modelo entre los paréntesis, pero que no captura la coincidencia, es decir, la coincidencia no se almacena para un posible uso posterior. La expresión «(?:\d+)(Salir)» coincide con la palabra «Salir» después de un conjunto de números en una cadena como por ejemplo «123456Salir Gráfico Enlace». Nota, los números no se almacenan y además no serán procesados por el sintetizador. El sintetizador simplemente ignora el contenido de esta Afirmación. Esta subexpresión se considera como grupo de cadena irregular, No se utiliza mucho en los diccionarios.
  • «(?=…)». Una subexpresión que realiza una búsqueda anticipada positiva, la cual coincide con la cadena en cualquier punto donde empiece una cadena que coincida con el modelo entre los paréntesis. Por ejemplo, «Juli(?=a|o)» coincide con «Juli» en «Julia» pero no con «Juli» en «Juliu». Ésta es una coincidencia sin captura, es decir, la coincidencia no se captura para un posible uso posterior. Las búsquedas anticipadas no consumen caracteres, es decir, después de que se produce una coincidencia, la búsqueda de la siguiente comienza inmediatamente después de la última coincidencia, no después de los caracteres que componen la cadena de búsqueda anticipada.
  • «(?!…)». Una subexpresión que realiza una búsqueda anticipada negativa, la cual coincide con la cadena de búsqueda en cualquier punto donde empiece una cadena que no coincida con el modelo. Por ejemplo, «Juli(?!e|u)» coincide con «Juli» en «Julia» pero no coincide con «Juli» en «Julie». Ésta es una coincidencia sin captura, es decir, la coincidencia no se captura para un posible uso posterior. Las búsquedas anticipadas no consumen caracteres, es decir, después de que se produce una coincidencia, la búsqueda de la siguiente comienza inmediatamente después de la última coincidencia, no después de los caracteres que componen la cadena de búsqueda anticipada.
  • «(?<=…)». Afirmación look-behind positiva, es decir, es válida la siguiente expresión sólo si la condición del modelo entre paréntesis se verifica. Por ejemplo, «(?<=0)\d» coincide con cualquier número precedido por cero. Las afirmaciones son sin captura, es decir, no se captura para un posible uso posterior.
  • «(?<!…)». Afirmación look-behind no positiva, es decir, es válida la siguiente expresión sólo si la condición del modelo entre paréntesis no se verifica. Por ejemplo, «(?<![1-9])\d» coincide con cualquier número que no está precedido por un número comprendido entre 1 y 9.

Secuencias Especiales

Las secuencias especiales consisten en «\» y un caracter ordinario como en la lista de abajo. Si el caracter ordinario no está en la lista, entonces la expresión resultante coincidirá con el segundo caracter.

  • «\A». Coincide sólo en el inicio de la cadena.
  • «\Z». Coincide sólo con el final de la cadena.
  • «\b». Coincide con el límite de una palabra. Es decir, la posición entre una palabra y un espacio. Por ejemplo, «ir\b» coincide con ‘ir’ en «mentir», pero no coincide con ‘ir’ en «mentira».
  • «\B». Coincide con una posición que no es un límite de palabra. La expresión «ir\B» coincide con «ir» en «mentiras», pero no coincide con «ir» en «mentir».
  • «\d». Coincide con un dígito. Equivale a «[0-9]».
  • «\D». Coincide con un caracter que no sea un dígito. Equivale a «[^0-9]».
  • «\s». Coincide con cualquier caracter de espacio en blanco incluidos espacio, tabulación, salto de página, etc. Equivale a «[\f\n\r\t\v]».
  • «\S». Coincide con cualquier caracter que no sea un espacio en blanco. Equivale a «[^\f\n\r\t\v]».
  • «\w». Coincide con cualquier caracter alfanumérico incluido el subrayado. Equivale a «[A-Za-z0-9_]».
  • «\W». Coincide con cualquier caracter que no pertenezca a los caracteres alfanuméricos. Equivale a «[^A-Za-z0-9_]».

Ejemplos

Finalmente llegamos a la parte práctica con los ejemplos.

Por conveniencia usaremos un diccionario temporál en los ejemplos. Para ello, necesitamos ajustar la opción para las expresiones regulares desde el diálogo correspondiente.

Ejemplo 1

El sintetizador eSpeak en español pronuncia con C suave palabras extranjeras que comienzan con «ch», como Christ, christmass, Christofer o Christopher, Christian, etc. Si deseamos escuchar una pronunciación mejor, podemos usar la siguiente expresión regular, muy sencilla.

Patrón: «\bChri\B»

Reemplazar: «Cri»

Explicación: la secuencia especial «\b» marca el inicio de la palabra, mientras que la secuencia «\B» (la B mayúscula) dice que en esta posición no hay limite de palabra.

Cada vez que se encuentra el prefijo «Chri» en el texto, el sintetizador lee el texto indicado en el Reemplazo «Cri».

Tener en cuenta que las secuencias especiales \b y \B son marcadores de posición, no necesitan una recuperación en el reemplazo.

La mayoría de las secuencias especiales, como por ejemplo \s, \w, \d, necesitan ser recuperadas en el reemplazo, si no vamos a recuperarlas no se envierán al sintetizador.

Ejemplo 2

A veces puede ser útil leer el nombre de unidades de medida cuando en el texto aparecen como abreviaturas.

Por ejemplo, 1ml 12 ml. ¿no sería fantástico que el sintetizador las leyera así?

Un mililitro y doce mililitros.

Necesitamos dos expresiones regulares para distinguir el plural y el singular.

Primera expresión regular.

Patrón: «(^|\s)1[ ]?ml\b»

Reemplazar: «\1un mililitro»

Segunda expresión:

Patrón: «(?<=\d)[ ]?ml\b».

Reemplazar: » Mililitros».

Explicación: la primera subexpresión «(^|\s)» tiene en cuenta si la posición está al principio o si hay un espacio antes del número 1.

Esta subexpresión se puede recuperar en el remplazo mediante la secuencia especial \1.

Recuerda que las subexpresiones regulares entre paréntesis, llamadas también grupos de cadena, se pueden recuperar en el remplazo con la secuencia especial correspondiente. Es decir, el primer grupo de cadena de izquierda a derecha se recupera con \1, el segundo con \2, etcétera. Después del grupo está el número 1, ya que estamos buscando en el texto 1ml o 1 ml, puede ser que haya o no un espacio entre el número y la abreviatura.

Entre corchetes se ha puesto un espacio, se pueden añadir distintos caracteres de espacio. Luego hay un cuantificador, cerrar interrogación, que indica que este espacio puede aparecer una vez o ninguna.

Finalmente, nuestra abreviatura ml y una secuencia especial «\b» para cerrar la expresión regular.

La secuencia al fin indica un límite de palabra, es decir que «ml\b» no puede coincidir por ejemplo con «mls» o «mla».

La segunda expresión regular se abre con una aserción «(?<=\d), significa que nuestra expresión Es válida solo si hay un dígito antes.

La aserción usa una secuencia especial «\d» que coincide con cualquier número.

Entonces, ¿por qué no funciona si antes está solo el número 1?

Te toca adivinar la respuesta…

Ahora, gracias a las dos expresiones regulares, cuando «ml» es precedido por 1 o ningún caracter alfanumérico, el sintetizador lee «mililitro». En los demás casos el sintetizador lee «mililitros».

El orden es importante, las expresiones regulares más arriba Tienen prioridad y pueden cancelar las expresiones posteriores. Por eso la segunda expresiónSe inserta a continuación de la primera.

¿A qué estás esperando? Ahora trata de crear reglas para leer otras unidades como Kg, MB, m² o cm³.

Ejemplo 3

Todavía es común separar los millares, millones, etc., mediante un espacio Para facilitar la lectura de números cuando constan de más de cuatro cifras:

12 354 o 1 303 404.

Algunos sintetizadores no leen correctamente esta forma de escribir los números enteros, más adelante se explica cómo configurar una expresión regular para leerlos correctamente.

Abrimos un diálogo para crear nuestro diccionario del habla desde el menú Preferencias.

Necesitamos ajustar el patrón para comparar como expresión regular desde el botón de opción correspondiente, y rellenar el campo Patrón y el campo de reemplazar.

Patrón: «(?<=\d)([  ]?)(\d{3})»

reemplazar: «\2»

Vamos a explicar.

La primera afirmación indica que la búsqueda es cierta si hay un dígito antes de la cadena. Sigue una subexpresión entre paréntesis con un conjunto de espacios dentro, son tres signos distintos de espacio que se pueden encontrar.

Recuerda que solo uno de los caracteres entre corchetes coincide con la búsqueda, luego hay un cuantificador «?» para indicar que se puede encontrar cero o una sola vez. Sigue a la derecha otra subexpresión entre paréntesis que indica un número de tres dígitos. El cuantificador «{3}» significa que el dígito «\d» debe repetirse tres veces, ni más ni menos.

Vamos a ver lo que tenemos que insertar en el campo reemplazar.

La primera subexpresión «(?<=\d)» en el patrón es una afirmación, no se almacena para un posible uso en el remplazo. Esto no significa que no se tengan en cuenta los caracteres de esa afirmación, el sintetizador va a leer estos dígitos junto a los otros sin recuperar la subexpresión en el campo reemplazar.

El segundo grupo o subexpresión «([ ]?)» es una subexpresión regular y se puede recuperar en el remplazo mediante la secuencia especial \1. Pero nosotros queremos excluirlo, así que no lo recuperamos.

Por el contrario, vamos a recuperar la tercera subexpresión «(\d{3})» mediante la secuencia especial \2.

De esta manera enviamos al sintetizador un número sin espacios entre los dígitos.

Ejemplo 4

Cuando consultamos una lista de números de teléfono o algo similar, puede ser útil leer los números dígito a dígito.

Por ejemplo, si encontramos 3332211444 podríamos leerlo como si estuviera escrito «3 3 3 2 2 1 1 4 4 4».

Necesitamos una secuencia especial en el patrón de búsqueda que encuentre o coincida con cualquier número, y luego añadir un espacio después de cada dígito sólo cuando es seguido por otro dígito.

Patrón: «(\d)(?=\d)»

Reemplazar: «\1 «.

En el reemplazo recuperamos el primer grupo «(\d)» con «\1», e inmediatamente después hay un espacio. El patrón de búsqueda encuentra cualquier dígito solo si va seguido de otro dígito.

Este es un ejemplo de una expresión regular que se puede utilizar en determinados casos, pero la mayoría de las veces dá como resultado una lectura tediosa. Está bien para leer números de teléfono, pero no sería agradable leer por ejemplo «Son las 13:26».

Como hemos visto, las expresiones regulares permiten encontrar un texto específico y reemplazarlo a nuestro gusto antes de enviarlo al sintetizador.

La mayoría de las veces es suficiente utilizar expresiones regulares simples, aunque debemos tener en cuenta que cuanto más simple sea la expresión regular, menos específica será la búsqueda.

Una sugerencia antes de concluir: no se deberían crear diccionarios del habla muy largos. Si el diccionario es demasiado grande puede ralentizar mucho el lector de pantalla. (1500 expresiones o más).

Además, no hay necesidad de corregir los errores de ortografía, o tratar de simular la pronunciación extranjera cuando el sintetizador no tiene los fonemas necesarios.

¡Hola a todos!
En este videotutorial, que ya tiene algún tiempo, Felipe Ibarra nos explica cómo instalar complementos en NVDA de una forma clara y sencilla. El vídeo dura aproximadamente 24 minutos, y ha sido grabado teniendo en cuenta también a personas sin discapacidad visual, de tal forma que todo el mundo pueda aprender de un modo guiado cómo se instalan complementos en este lector de pantalla. ¡Que lo disfrutes! Y como siempre, si tienes cualquier inquietud, no dudes en compartirla con nosotros más abajo, en los comentarios.

Nota: a partir de NVDA 2019.3, Java Access Bridge va incluido en el propio lector de pantalla, por lo que los procedimientos descritos en esta entrada ya no son necesarios. Tampoco es obligatorio instalar Java para 32 bits ni limitarse a la versión 8.
En esta entrada vamos a hablar de la integración entre NVDA y las aplicaciones Java, y cómo administrar Java Access Bridge, la librería de accesibilidad ofrecida para este propósito.

¿Qué es Java Access Bridge?

Java Access Bridge es una librería de accesibilidad que permite que las tecnologías de asistencia, incluyendo lectores de pantalla, puedan comunicarse con las aplicaciones Java que disponen de interfaz gráfica hecha con el motor de interfaces Swing. Esta librería no es necesaria para aplicaciones que utilizan la línea de órdenes (consola), y aplicaciones que usan otros motores gráficos con controles nativos del sistema (motor SWT, Eclipse).

Java Access Bridge debe habilitarse en el sistema para que los lectores de pantalla puedan acceder a las aplicaciones Java mencionadas anteriormente. Si no está habilitado, estas aplicaciones se mostrarán inaccesibles. Algunos programas que lo necesitan para ser compatibles con tecnologías de asistencia son:

  • Open Office y Libre Office, aunque en sus últimas versiones ya están eliminando este requisito
  • Android Studio
  • IBM SPSS
  • Entorno de desarrollo para Arduino
  • JDownloader, el popular gestor de descargas
  • Aplicaciones Java integradas en el navegador
  • El propio panel de control de Java
  • Autofirma
  • Y muchos otros programas que no se mencionan aquí

Nota: el hecho de que Java Access Bridge esté activado no implica necesariamente que todas las aplicaciones Java sean accesibles. Es responsabilidad del desarrollador programar los controles de forma adecuada. En la mayoría de controles estándar, basta con etiquetarlos de forma correcta.

Instalación

Hasta hace un tiempo, instalar Java Access Bridge siempre ha sido una operación complicada, en la que se veían involucradas una descarga con archivos extra, la línea de órdenes y la copia de archivos a los lugares adecuados. Con la llegada de Java 7 y Windows 7, el procedimiento se ha simplificado muchísimo, y es el que documentamos a continuación.

Descarga del entorno de ejecución de Java (JRE)

El entorno de ejecución de Java es lo primero que debemos obtener. Sin él, ningún programa basado en Java funcionará. Se puede descargar de dos sitios oficiales distintos: la web de java.com, y la página de descargas de Oracle. Otras instalaciones silentes, como la realizada por el portal ninite.com, no son válidas. Visita una u otra dependiendo de lo que necesites descargar. Si tienes un sistema de 64 bits, es muy importante que descargues el entorno de 32 bits para que funcione con NVDA. Lo ideal es instalar ambos entornos: el de 32 bits para activar las funciones de accesibilidad e integrar complementos en los navegadores web de 32 bits, y el de 64 bits para garantizar un rendimiento máximo y el funcionamiento con otros lectores de pantalla, como Jaws for Windows. Una vez descargados, instálalos en el orden que prefieras.

Activación de Java Access Bridge

Para activar Java Access Bridge, debes ir al centro de accesibilidad en el panel de control. En la vista por categorías, se encuentra bajo Accesibilidad. Si tienes Windows 8 o posterior, no uses la aplicación de configuración. Java Access Bridge sólo está disponible en el panel de control.

Una vez en el centro de accesibilidad, pulsa un enlace llamado «Facilitar uso del equipo».

Busca la casilla «Activar Java Access Bridge» y márcala. A continuación, pulsa aceptar y cierra el centro de accesibilidad.

Para acabar, comprueba que todo funciona. En el panel de control, busca la opción Java. Cambia la vista a Iconos grandes o iconos pequeños, en la vista por categoría te puede costar más encontrarlo.

Si al abrir el panel de control de Java NVDA detecta la pestaña General, ¡enhorabuena, ya has terminado! De no ser así, reinicia NVDA y prueba de nuevo.

Consideraciones al actualizar el entorno de ejecución de Java

De vez en cuando, Java nos avisará de que hay una nueva versión. En estos casos siempre se recomienda actualizar, ya que seguramente habrá algún fallo de seguridad solucionado o mejoras en el rendimiento y la estabilidad. Sin embargo, si usas NVDA, ¡cuidado! Hay algo que debes hacer antes.

Cuando NVDA se inicia, busca la librería Java Access Bridge en el sistema y la carga. El problema es que la mantiene siempre cargada, aunque ninguna aplicación Java esté abierta. El instalador de Java no tiene esto en cuenta. Al actualizar, ve que no puede sobreescribir el archivo dll de la librería, programa su actualización para el siguiente reinicio… y siempre sale algo mal porque NVDA interfiere, haciendo que la dll desaparezca y nos quedemos sin soporte para aplicaciones Java irremediablemente.

Al actualizar el entorno Java para 64 bits no hay ningún problema (salvo que debes hacerlo a mano). Sin embargo, cuando actualices el entorno de 32 bits, toma las siguientes precauciones:

Haz copia de seguridad de la librería

Navega al directorio C:\windows\system32 en sistemas de 32 bits, o a C:\windows\SysWOW64 en sistemas de 64 bits. Busca el archivo windowsAccessBridge-32.dll, y cópialo a cualquier parte de tu disco duro. Si algo sale mal, puedes restaurarlo después y continuar con tus tareas como siempre.

Haz que NVDA libere la librería antes de actualizar Java

Mucha gente podría tomar la sabia decisión de cerrar NVDA para actualizar Java. Por desgracia, si es el único lector de pantalla que tenemos, esa no es una opción válida. Hay que desactivar aquellas partes de NVDA que van a causar problemas, y activarlas más adelante. El hecho de que NVDA sea tan modular, permite hacerlo con facilidad.

Para desactivar el soporte para Java Access Bridge, haz lo siguiente:

  • Pulsa NVDA+ctrl+z para abrir la consola Python de NVDA. También puedes abrirla desde el submenú herramientas del menú de NVDA.
  • Escribe las siguientes líneas:

    import JABHandler
    JABHandler.terminate()

  • Actualiza el entorno de Java para 32 bits con normalidad.
  • Reactiva el soporte para Java Access Bridge. Puedes hacerlo reiniciando NVDA directamente, o escribiendo las siguientes líneas en la consola:

    reload(JABHandler)
    JABHandler.initialize()

¿Qué pasa con Java 9?

Actualmente, mientras escribimos esta entrada, la versión recomendada de Java es la 8. Sin embargo, ya se ha liberado el entorno de ejecución de Java 9, con muchísimas ventajas y mejoras. Por desgracia, sólo es compatible con sistemas de 64 bits. No hay ningún entorno de Java 9 para 32 bits, por lo que NVDA no funciona con Java Access Bridge. Habrá que esperar a que NVAccess y Oracle pongan soluciones a este contratiempo. Mientras tanto, no queda más remedio que continuar en Java 8.

¿Tienes dudas o quieres aportar algo nuevo no documentado en esta guía? No lo pienses dos veces, escribe un comentario más abajo. ¡Estaremos encantados de actualizar esta entrada con nueva información!

El mes pasado se publicó la versión definitiva de Windows 10 Fall Creators, también conocida como versión 1709 o actualización de características 1709. No vamos a entrar en detalles sobre sus múltiples ventajas y novedades, ya que son bastantes y por la red circulan infinidad de noticias que hablan de ellas. En esta entrada vamos a hablar de una nueva característica de seguridad que, si bien es cierto que no interfiere con NVDA al usarlo de forma cotidiana, sí nos puede ocasionar un gran dolor de cabeza al instalar o actualizar. Se trata del control de acceso a carpetas.

¿Qué es el control de acceso a carpetas?

El control de acceso a carpetas es una nueva característica de Windows Defender que monitoriza y puede bloquear el acceso no autorizado a las carpetas y archivos de nuestro disco duro por parte de programas de terceros, como es el caso de NVDA. Esta característica viene muy bien para protegernos contra virus y programas dañinos, pero también provocará fallos en la instalación y actualización de NVDA. Por ejemplo, el icono de acceso directo del escritorio nunca llegará a crearse, y podremos obtener errores que harán que el proceso no se complete, dejando nuestra copia de NVDA en un estado inconsistente. Por suerte, esta característica parece venir desactivada por defecto, según han informado la mayoría de los usuarios. Si este no es tu caso, sigue leyendo. Te explicaremos cómo desactivarla.

¿Cómo se desactiva?

Sigue estos pasos para desactivar el control de acceso a carpetas:

  • Pulsa las teclas windows+i para abrir la aplicación de configuración.
  • En la lista, pulsa intro sobre actualización y seguridad, y después sobre Windows Defender. Es posible que cada vez que pulses intro en la lista el foco se sitúe en el cuadro de búsqueda. No hay problema, pulsa una vez el tabulador para volver.
  • Tabula y pulsa el botón «Abre el centro de seguridad de Windows Defender»
  • Cuando se abra el centro de seguridad, pulsa el botón «Protección antivirus y contra amenazas»
  • Tabula y pulsa el botón «Configuración de antivirus y protección contra amenazas»
  • Pulsa tabulador hasta llegar al botón «Controla el acceso a la carpeta». Si NVDA te indica que está pulsado, significa que la protección está activada. Si el estado del botón es no pulsado, no tienes que hacer nada más.
  • Pulsa espacio para desactivar la protección. Es posible que se muestre una ventana del control de cuentas de usuario pidiendo confirmación. Si es así, pulsa alt+s para confirmar.

Ahora que tienes el control de acceso a carpetas desactivado, NVDA se instalará y actualizará con normalidad. El hecho de tenerlo activado, como hemos dicho, no afecta al uso regular del lector de pantalla. Por lo tanto, si quieres estar más seguro, ¡no te lo pienses dos veces y actívalo!

Cuando está activado, el control de acceso a carpetas permite agregar aplicaciones excluidas; es decir, aplicaciones que podrán entrar a las carpetas saltándose la protección. Si consigues instalar o actualizar NVDA por este medio, sin desactivar la protección, déjanos un comentario explicando cómo lo has hecho. ¡De esa forma podremos actualizar esta entrada con más posibilidades y opciones!

Como ya sabrán los usuarios de NVDA, NVDA reproduce sonidos para cuando se inicia, se cierra, se conmuta entre modos foco o exploración, cuando hay un error en NVDA (aunque veo que ese sonido solo se reproduce en las versiones en desarrollo), un error de ortografía cuando se escribe (en programas que revisen la ortografía mientras se escribe) y cuando se abren y cierran auto sugerencias en varios cuadros de edición, por ejemplo los de búsqueda en el menú inicio de Windows.
Sin embargo, puede haber ocasiones en los que estos sonidos que reproduce NVDA los quisieras cambiar, talvez porque ya estás aburrido de escuchar los mismos sonidos, o por alguna otra razón. Esto se puede hacer, de la siguiente forma:

  • Si tienes NVDA instalado, dirígete a la carpeta archivos de programa en 32 bits, o archivos de programa (x86) en 64 bits. A veces, en lugar de archivos de programa la carpeta puede llamarse Progran Files, pero en este caso es lo mismo dicho en inglés.
  • Luego, navega hasta la carpeta NVDA.
  • A continuación, abre la carpeta Waves. Si tu NVDA es un portable, puedes ir a la carpeta donde tienes el portable, y luego a la carpeta Waves.
  • Aquí es donde se encuentran los sonidos, y, si activaste la visualización de extensiones para tipos de archivos conocidos en el explorador de archivos de Windows, en opciones de carpeta, te darás cuenta que están en .Wav.

A continuación, veremos qué evento corresponde a cada sonido:

  • BrowseMode.wav, Modo exploración.
  • Error.wav, Error.
  • Exit.wav, Salida.
  • FocusMode.wav, Modo foco.
  • screenCurtainOff.wav: Cortina de pantalla desactivada.
  • screenCurtainOn.wav: Cortina de pantalla activada
  • Start.wav, Inicio.
  • SuggestionsClosed.wav, Sugerencia cerrada.
  • SuggestionsOpened.wav, Sugerencia abierta.
  • TextError.wav, Error de ortografía.

Ahora, ¿Cómo se cambian? Supongo que ya lo imaginas, ¿No? Pero supongo que muchos usuarios no sabrán cómo hacerlo…
Bien.
Primero, debemos tener varios sonidos en formato.wav. Si no tienes el sonido que le quieres poner en ese mismo formato, puedes utilizar algún editor de audio, o algún otro programa, para convertir el archivo (por ejemplo en .mp3) a.wav.
Luego, debemos cambiarle el nombre a estos sonidos, a los mismos nombres de los sonidos de la carpeta Waves, que podemos leer arriba.
Después, copiar esos archivos de sonido en formato.wav y con los mismos nombres de los sonidos de NVDA, y pegarlos en la carpeta Waves, que ya dije cómo se encuentra. Le damos que sí a la pregunta sobre reemplazar los archivos, y, si nos aparece un cuadro de diálogo indicándonos que necesitamos tener derechos de administrador para hacer esto (generalmente sucede cuando hacemos operaciones en las carpetas de archivos de programa y no tenemos privilegios de administrador), y queremos cambiar los sonidos, le damos en continuar con derechos de administrador automáticos.
Luego, para que veas el efecto, reinicia NVDA, ¡Y verás que los sonidos han cambiado!
En el archivo.zip Dejo este documento, junto con 3 Pacx con otros sonidos para NVDA, uno de la web grossgan.com, otro, con sonidos de Windows XP que lo hice yo mismo, y otro con nuevos sonidos que iba a incorporar NVDA en la versión 2017.3, que al final no se pusieron, pero sin embargo estuvieron en las versiones en desarrollo. Puedes probarlos copiándolos y pegándolos en la carpeta Waves.
También, dejo los sonidos originales de NVDA, por si quisieras volver a esos.
Haz clic en este enlace para descargar un archivo.zip con tres packs de sonidos y un documento con estas mismas instrucciones