Añadir ayuda contextual en aplicaciones de KDE

manual de colaboración de KDE para no programadores (Parte I)

Autor: Aaron Seigo
Traductor: Marcos Fouces Lago
Correciones: Luis Llorente Campo

Esta es la primera entrega (N. del T. que yo sepa no hay otra :-)) del manual de colaboración de KDE para no programadores. Está espacialmente indicado para personas sin conocimientos de programación y que quiere echar una mano en el código. También es adecuada para quienes empiezan a programar y quieren empezar a "mancharse las manos" con el código de KDE. También es una tarea sencilla que no requiere demasiado tiempo.

Índice de contenidos

  1. ¿Qué es la ayuda contextual? (whatsthis)
  2. Preparativos previos
  3. Un ejemplo sencillo: KGpg
  4. Enviar las mejoras realizadas
  5. Algo más complejo: Ark.
  6. Más cosas
  7. Notas

¿Qué es la ayuda contextual? (whatsthis)

Example of WhatsThis Help
Diálogo mostrando una ayuda contextual en un widget de KDE

Esencialmente, la ayuda contextual consiste en pequeñas ayudas asociadas con un determinado widget (1). Para ver esa ayuda contextual tiene que ir a Ayuda>¿Qué es esto?, verá que el puntero del ratón cambia a un signo de interrogación, pinche sobre el widget que desee y verá (si existe) una viñeta de ayuda sobre el mismo.

Esta manera de obtener una breve explicación de un widget suele ser muy apreciada por aquellos usuarios novatos que traten de aprender a usar la aplicación o como referencia para los más avanzados. Desgraciadamente, si observa el código de KDE verá que muchos widgets carecen de este tipo de ayuda. Esto se debe a que los programadores suelen descuidar la necesidad de documentación bien por falta de tiempo, porque prefieren hacer otras cosas, o por cualquier otro motivo.
Un inconveniente de este tipo de ayuda es que puede variar a medida que se cambia la interfaz y se añaden/suprimen nuevos widgets. Por otra parte, también son muy fáciles de añadir, aunque no sepa nada sobre programación.

Preparativos previos

Antes de ponerse manos a la obra a añadir ayudas contextuales como posesos, será necesario algún trabajo previo. Necesitará la versión más reciente de la interfaz. En el caso de KDE, esto significa tener que bajar el código directamente del servidor SVN (2). No es necesario disponer de una cuenta. Bastará con acceso anónimo. Tampoco será necesario compilar el código, ni disponer de todo el código de la aplicación. Esto hace que no tenga que preocuparse de dependencias, opciones de compilación, configuraciones ni ninguna de esas cosas necesarias cuando se trabaja con código fuente.

Mirando las distintas utilidades que vienen con KDE podrás comprobar que ark, la herramienta de archivado y compresión de KDE, carece casi completamente de ayudas contextuales. La herramienta de KDE para GnuPG, de forma imaginativa llamada kgpg, también sufre el mismo problema. Éstas dos aplicaciones parecen pues, un buen punto de partida para comenzar nuestra exploración de la ayuda contextual. Por lo tanto empecemos descargando el módulo kdeutils del SVN, que es donde estas dos aplicaciones están disponibles:

user@locahost:~> svn co svn://anonsvn.kde.org/home/kde/trunk/KDE/kdeutils
A  kdeutils/kdessh
A  kdeutils/kdessh/kdessh.cpp
A  kdeutils/kdessh/sshdlg.cpp
A  kdeutils/kdessh/Makefile.am

Para saber qué otras aplicaciones están disponibles en el servidor SVN puede visitar la interfaz web KDE SVN o usar el comando svn ls en local. Para obtener información más detallada sobre como trabajar con SVN y KDE consulte la documentación del SVN anónimo de KDE.

Un ejemplo sencillo: KGpg

kgpg es una interfaz gráfica para gnupg que usaremos como primer ejemplo, nos centraremos en la pestaña "General" del diálogo de configuración.

KGpg Config UI
kdeutils/kgpg/conf_ui.ui tal como lo muestra Qt Designer

Una vez que ha descargado el módulo kdeutils del SVN, vea los archivos que contiene, sin duda encontrará una carpeta llamada 'kgpg'. En ella encontrará varios archivos con la extensión '.ui'; se trata de archivos XML que describen la interfaz externa de kgpg. Puede editarlos a mano con cualquier editor de texto, pero es preferible usar Qt designer.

Qt Designer es una herramienta de diseño visual, una especie de Phostoshop para programadores. Probablemente su distribución lo haya empaquetado junto a otras herramientas de desarrollo de Qt. Al abrir un archivo .ui se le mostrará la interfaz gráfica en cuestión. Abra el archivo kdeutils/kgpg/conf_ui.ui, verá una de las ventanas de configuración de kgpg y podrá modificarla.

KGpg Config UI
Ventana de las propiedades de los Widget properties en Qt Designer
Comenzaremos con el archivo .ui que tiene abierto en Qt Designer: pinche sobre "Start KGpg automatically at login", verá como se marca ese fragmento.
Observe que tiene una pequeño recuadro abajo a la derecha llamado "Property Editor/Signal Handlers" donde se pueden seleccionar propiedades de una lista para asignárselas al widget que ha seleccionado, casi al final de esa lista aparecerá la propiedad "WhatsThis", pinche en la columna de la derecha y escriba el texto que desee para la ayuda contextual.

IMPORTANTE: como KDE se edita originalmente en inglés americano, deberá escribir todas las ayudas contextuales en ese idioma.

Así de sencillo!, puede hacer esto con cada uno de los widgets que considere oportunos. Puede mejorar el aspecto del texto usando etiquetas HTML poniendo negrita, subrayados... puede usar el editor HTML pinchando sobre el botón con tres puntos al lado de la caja de entrada de texto. Facilísimo ¿no?

Truquito Cuando utilice etiquetas HTML, ponga todo el contenido entre <qt> y </qt>. Así se asegurará que el texto siempre aparezca correctamente.

No olvide redactar clara y sucintamente el texto, el objetivo es ayudar al usuario, no confundirlo. No incluya referencias a otros widgets a no ser que sea absolutamente imprescindible. Compilar la aplicación y ver si ha conseguido el objetivo adecuado y compruebe bien la corrección ortográfica y gramatical.
Nadie es perfecto, pero tampoco se pierde nada por intentarlo...

Truquito Cuando escriba ayudas contextuales para widgets con algún título o etiqueta asociada, no olvide añadir exactamente la misma para éste. Piense que los usuarios puede pinchar sobre cualquiera de los dos y sería frustrante que aparecieran cosas distintas en ambos tratándose del mismo asunto.

Una vez que haya escrito ayudas para todos los widgets de la interfaz, seleccione Save en el menu File para guardar los cambios. Repita eso para cada archivo .ui y listo! Fácil ¿no?

Enviar las mejoras realizadas

Una vez que ha añadido ayudas contextuales en todas partes deberá crear un parche, pero antes deberá asegurarse de tener la última versión del SVN no vaya a ser que esté trabajando con archivos .ui que ya hayan sido actualizados. Ésto se hace así:

user@localhost:~/kdeutils/kgpg> svn up
? dcopiface.kidl
? dcopiface_skel.cpp
? groupedit.cpp
? groupedit.h
P ChangeLog
M conf_ui.ui
P kgpgview.cpp
Puede ignorar los archivos señalados con un interrogante: no pertenecen al SVN. Los archivos señalados con una 'P' (o una 'U') son los que han cambiado desde su última actualización, es decir que otra persona los ha modificado. Los archivos con una 'M' delante son aquellos que usted modificó en su disco duro. Lo que queremos es guardar estos cambios en un archivo 'diff' que usaremos como parche. Esto se hace de la siguiente manera:
user@localhost:~/kdeutils/kgpg> svn diff > kgpg.diff

Truquito El paquetes kdesdk (o Kit para Desarrolladores de KDE) contiene un programa llamado Cervisia, un interfaz gráfico para SVN que seguramente le sea más cómodo e intuitivo. Puede usar Cervisia tanto como aplicación independiente o directamente desde Konqueror. Consulte la documentación de Cervisia para más información sobre él.

Si todo ha ido bien, tendremos una archivo llamado kgpg.diff que podrá enviar por correo al encargado de la aplicación. Podrá encontrar su dirección de email en la opción "Acerca de" del menú "Ayuda", en el archivo AUTHORS en el código fuente, mirando en la licencia de uso... normalmente debería responder en 7-10 días. Si no lo hace envíe el parche a la lista de desarrollo de KDE (kde-devel at kde dot org).

Truquitos Desde una determinada fecha en el ciclo de publicación de KDE, no se permiten cambios en las cadenas de texto ("strings" como suelen llamarle los programadores). Esto sirve para dejar tiempo para que los traductores hagan su trabajo. Consulte el calendario de publicación de KDE para saber hasta cuando se permitirá realizar estos cambios.

Algo más complejo: Ark.

En este ejemplo usaremos una herramienta veterana en KDE que también forma parte del módulo kdeutils. Sin embargo, cuando mire en el directorio kdeutils/ark/ no verá ningún archivo .ui, esto significa que tendremos que apañárnoslas directamente con el código fuente. Aunque es un poco más lioso que en el caso anterior, sigue siendo bastante sencillo y tampoco requiere especiales conocimientos.
Bien, pues vamos allá.

Diálogo de extracción de Ark
Diálogo de extracción de Ark

Lo primero que haremos será ejecutar el programa y ver de qué ayudas contextuales carece. Normalmente miraremos esto ventana a ventana. Para ello necesitaremos una versión relativamente reciente del programa por lo que lo mejor es que compile siempre la última versión disponible en el SVN3 como hemos visto antes.

Buscando en la interfaz de Ark, llegamos al diálogo de extracción y vemos que no hay ninguna ayuda contextual. La primera pista nos la darán las cadenas de texto que vemos en la interfaz:cosas como "Extract to:", "Files to be Extracted", etc...
Buscaremos estas cadenas en el código para saber en qué parte del código se define la interfaz de la siguiente forma 4:

user@localhost:~/kdeutils/ark> grep -in "Files to be Extracted" *cpp
arkwidget.cpp:1500   // list of files to be extracted
arkwidgetpart.cpp:370      // list of files to be extracted
extractdlg.cpp:110 bg->setTitle( i18n( "Files to Be Extracted" ) );
Las dos primeras líneas son comentarios por lo que no son de nuestro interés, pero la última sí nos interesa.

Truquito Para encontrar cadenas en las que se incluya algún atajo de teclado como "Extract here (donde la letra "x" es el atajo), ponga un & delante de la letra subrayada así: "E&xtract here". Si hay un & en la cadena, sustitúala por dos.

Abra el archivo kdeutils/ark/extractdlg.cpp en su editor de textos favorito y desplázese hasta la línea 110, debería ver algo así:

bg->setTitle( i18n( "Files to Be Extracted" ) );
y si bajamos unas pocas líneas veremos los botones de radio:
m_radioCurrent = new QRadioButton( bg, "m_radioCurrent" );
m_radioCurrent->setText( i18n( "Current" ) );
Layout2->addWidget( m_radioCurrent );

m_radioAll = new QRadioButton( bg, "m_radioAll" );
m_radioAll->setText( i18n( "All" ) );
Layout2->addWidget( m_radioAll );

m_radioSelected = new QRadioButton( bg, "m_radioSelected" );
m_radioSelected->setText( i18n( "Selected files" ) );
Layout2->addWidget( m_radioSelected );

Bien, una vez que hemos dado con el código, será bastante sencillo añadir una ayuda contextual para ese widget. Sin embargo, deberá tener en cuenta algunas cosas sobre C++. Al comienzo del archivo podrá ver algunas líneas que empiezan por #include, en nuestro caso concreto encontraremos varias como por ejemplo:

#include <qbuttongroup.h>
#include <qlabel.h>
#include <qapplication.h>
#include <qlayout.h>
Necesitamos encontrar este qwhatsthis.h, sino no podremos añadir ayudas contextuales sin obtener un error del compilador, así que si no está definida debería añadirla tal que así:
#include <qbuttongroup.h>
#include <qlabel.h>
#include <qapplication.h>
#include <qlayout.h>
#include <qwhatsthis.h>
Procure situar el nuevo #include cerca de otros similares, preferentemente cerca de otros encabezados de Qt. Podrá distinguir los encabezados de Qt porque empiezan con la letra 'q'.

Vamos ahora a la línea 111 (tenemos una línea más al haber añadido el encabezado nuevo), observe las líneas que contienen la cadena new QRadioButton. Cada una de estas líneas crea un botón y lo asigna a una "variable". En este caso, el nombre de la variable del botón que dice "Current" es "m_radioCurrent". Para añadirle una ayuda contextual haremos lo siguiente:

m_radioCurrent = new QRadioButton( bg, "m_radioCurrent" );
m_radioCurrent->setText( i18n( "Current" ) );
Layout2->addWidget( m_radioCurrent );
QWhatsThis::add( m_radioCurrent,
                 i18n( "Selecting this option will cause only the last "
                       "selected file to be extracted." ) );

m_radioCurrent = new QRadioButton( bg, "m_radioCurrent" );
m_radioCurrent->setText( i18n( "Current" ) );
m_radioAll = new QRadioButton( bg, "m_radioAll" );
m_radioAll->setText( i18n( "All" ) );
Layout2->addWidget( m_radioAll );
QWhatsThis::add( m_radioAll,
                 i18n( "Selecting this option will cause all files in the "
                       " archive to be extracted." ) );

m_radioCurrent = new QRadioButton( bg, "m_radioCurrent" );
m_radioCurrent->setText( i18n( "Current" ) );
m_radioSelected = new QRadioButton( bg, "m_radioSelected" );
m_radioSelected->setText( i18n( "Selected files" ) );
Layout2->addWidget( m_radioSelected );
QWhatsThis::add( m_radioSelected,
                 i18n( "Selecting this option will cause all the files "
                       "you selected in the archive to be extracted." ) );

Como puede ver, lo único que hemos hecho fue añadir algunas líneas sencillas de código. Para añadir una ayuda contextual usaremos el método QWhatsThis::add con la siguiente sintaxis:

QWhatsThis::add( widget, i18n( "WhatsThis text") );
El widget es la variable del widget, por ejemplo: m_radioCurrent. WhatsThis text es el texto de la ayuda contextual que se mostrará al usuario. No olvide la parte de i18n para señalar que la cadena de texto deberá traducirse a otros idiomas.
Como ve no es tan dificil, sin embargo hay algunas cosas que deberá tener presentes.

En el diálogo de extracción aparece una etiqueta "Extract to:" frente a un widget que abre un diálogo de búsqueda de archivo. Cuando buscamos la cadena "Extract to:" en el archivo kdeutils/ark/extractdlg.cpp nos encontramos con el siguiente código:

extractToLabel->setText( i18n( "Extract to:" ) );
Layout3->addWidget( extractToLabel );

m_extractDirCB = new KHistoryCombo( true, mainFrame, "m_extractDirCB" );
Aunque no esté familiarizado con C++, podría deducir que extractToLabel es el texto que se mostrará al usuario mientras m_extractDirCB es el cuadro que se abre para indicar la ruta donde quiere extraer los archivos. El código para nuestra ayuda contextual se parecerá a esto:
extractToLabel->setText( i18n( "Extract to:" ) );
Layout3->addWidget( extractToLabel );
QString whatsThis = i18n( "<qt>Enter the location you wish to extract the "
                          "files to in the provided text area. You can click on "
                          "the file button to bring up a file dialog.<p>"
                          "<Tip:> In addition to local file paths, you may "
                          "use any URL that allows saving of files, such as "
                          "ftp and fish (ssh file transfer) URLs.</qt>" );
QWhatsThis::add( extractToLabel, whatsThis );

m_extractDirCB = new KHistoryCombo( true, mainFrame, "m_extractDirCB" );
QWhatsThis::add( m_extractDirCB, whatsThis );
Observe que hemos añadido la misma ayuda contextual tanto al texto que se muestra al usuario como al widget que se abre. También hemos usado un truquito para no tener que reescribirlo dos veces: hemos creado un QString, que es la forma estándar para almacenar cadenas de texto. Lo que hemos hecho ha sido crear un QString whatsThis y le hemos asignado (mediante el signo igual) el texto deseado. Podremos reutilizar más veces esta cadena whatsThis dentro de ese mismo bloque de código si así lo deseamos. Para ello no tendremos que reescribir otra vez QString whatsThis = sino whatsThis =. Un bloque de código es aquel que se encierra dentro de las unas llaves ({ y }).
No olvide que todas las variables deben tener un nombre único así que no podremos usar el nombre "whatsThis" si ya lo hemos hecho. Esto no es demasiado problema, si cometemos este error, el compilador nos lo dirá enseguida.

Aparte de la utilidad de insertar ayudas contextuales por todas partes, es importante pensar en los programadores. Muchos de ellos odian encontrar líneas demasiado largas, suelen preferir que tengan menos de 80 caracteres. Así que asegúrese de que esto sea así, cortando las líneas de la ayuda si fuese necesario. Recuerde también que en C y C++ no es posible que una misma cadena ocupe varias líneas, como en este caso:

QWhatsThis::add(m_radioCurrent,
               i18n( "Selecting this option will cause only the last
                      selected file to be extracted." ) );
Lo correcto sería hacerlo de este modo:
QWhatsThis::add(m_radioCurrent,
               i18n( "Selecting this option will cause only the last "
                     "selected file to be extracted." ) );
Fíjese que hemos puesto comillas para abrir y cerrar cada línea. También es obligatorio usar comillas dobles y no sencillas (') y terminar cada sentencia con punto y coma (;). Si desea incluir comillas dentro de la propia ayuda contextual deberá "escaparlas" con una barra invertida de este modo:
i18n( "Here we will use a \"quotation mark or two\"" )

Preste atención también al formateo del código fuente, muchos programadores son bastante quisquillosos con esto aunque no existe un acuerdo general sobre cómo debe hacerse. Algunos usan tabuladores, otros espacios; unos indentan las líneas con 2 espacios, otros con 4, otros con... Bueno, las combinaciones sobre todo esto son infinitas, sólo trate de que su código se parezca lo más posible al del autor.

El último paso es tratar de compilar el programa para asegurarse de no haber introducido errores y que el código compila. una vez compilado, pruebe las ayudas contextuales que acaba de añadir y vea si funcionan como esperaba.
Si todo va bien, puede crear un archivo .diff igual que hemos hecho para el caso de kgpg y enviárselo al encargado del programa.

Truquito Cuando compile puede que vea errores acerca de que i18n no está definido. Si le ocurre esto, añada está línea junto al otro #include al principio del archivo:
#include <klocale.h>

Más cosas

Enhorabuena! ha llegado al final. Si tiene alguna pregunta, puede encontrarnos en el IRC en freenode.net (#kde-devel en irc.kde.org:6667 o irc.freenode.net:6667), en las listas de desarrollo o (sólo si lo anterior no ha dado resultado) enviar un email al autor.
N. del T. si prefiere hacerlo en castellano puede encontrarnos en http://www.kdehispano.org.
Si quiere comentar algo acerca de este tutorial, cosas como errores, aclaraciones... diríjase al autor sin tardanza. Si el problema es con la traducción, pues al traductor

Espero que se divierta añadiendo ayudas contextuales por todas partes, nos veremos otra vez en el próximo tutorial sobre gestión de bugs.

Notas

(1) Widget: un "widget" es una ventanita o objeto de cualquier tipo que se muestra al usuario, por ejemplo: barras de scroll, casillas de verificación, menús.
Volver al artículo...
(2) SVN: SVN significa Subversion. Es similar a CVS. Proporciona un sistema para que varias personas trabajen a la vez en un conjunto de documentos. El proyecto KDE usa SVN de forma extensiva para coordinar su desarrollo y está disponible para los principales sistemas operativos. En sistemas tipo UNIX el paquete SVN se encuentra normalmente agrupado junto con otras herramientas de desarrollo. Si no dispones del comando svn en tu sistema consulta los manuales de tu sistema operativo para saber cómo instalar nuevo software.
Volver al artículo...
(3) Compilar código del SVN: puede encontrar información para descargar y compilar código del SVN de KDE en http://developer.kde.org/build/compile_cvs.html
Volver al artículo...
(4) grep: es el comando usado para buscar a través del código fuente de Ark. grep es un útil comando de UNIX para buscar palabras en archivos de texto. Usamos la opción -i para que la búsqueda no distinga mayúsculas de minúsculas, así evitaremos pasar por alto cadenas mal escritas, la opción -n mostrará el número de línea que cumpla el patrón. Sólo buscamos archivos *cpp, código fuente C++, aunque debe tener presente que algunas veces se usa la terminación .cc. En general no es necesario realizar búsquedas en librerías ni encabezados, sólo con eso debería ser suficiente.
Volver al artículo...

Aaron J. Seigo

Acerca del autor...

Aaron J. Seigo es programador de KDE, vive en Calgary, Alberta, Canada. Aparte de programar para KDE, también trabaja como programador y lleva una vida relativamente activa (por lo menos para un hacker) con su familia y amigos. Le gusta que la gente programe para KDE, la cerveza, el chocolate y otras muestras de afecto. Pero no la cerveza chocolateada, eso está rematadamente mal, tampoco las postales, es alérgico a ellas.