KDevelop"> ]> El manual de programación de &tdevelop; 2002-12-05 2.0 Ralf Nolden
Ralf.Nolden@post.rwth-aachen.de
Caleb Tennis
caleb@aei-tech.com
1999 Ralf Nolden 2002 Caleb Tennis &FDLNotice; La guía de usuario de diseño de aplicaciones C++ para el entorno de escritorio K (KDE) con el IDE &tdevelop; KDE KDevelop IDE desarrollo programación
Introducción A medida que los sistemas Unix se van haciendo más populares (incluso para los principiantes que trabajan con ordenadores) debido a sus ventajas relacionadas con la estabilidad y con la funcionalidad, muchas personas se quejan de que las aplicaciones diseñadas para ellos no poseen un aspecto consistente, y que algunas se comportan de un modo diferente al de otras. Con KDE, los desarrolladores disponen de una forma casi perfecta de crear aplicaciones de primera clase para que los sistemas de escritorio Unix consigan una amplia comunidad de usuarios por la mera razón de la calidad que sus aplicaciones pueden ofrecer. De este modo, KDE se va haciendo cada vez más popular como base de diseño de programación, y los desarrolladores pueden aprovechar las posibilidades que este sistema ofrece. Qué debería saber previamente Para aprovechar al máximo este manual de programación, se asume que usted posee conocimientos del lenguaje de programación C++. En caso contrario, debería familiarizarse con él en primer lugar. Puede obtener información sobre C++ a través de varias fuentes, tanto impresas, en sus librerías locales, como en forma de manuales, que puede encontrar en Internet. No se requiere tener conocimientos sobre el diseño de interfaces gráficas, ya que este manual trata de cubrir el diseño de aplicaciones para KDE, que también incluye una introducción a las bibliotecas Qt y KDE, y el diseño de interfaces gráficas. También debería de sentirse cómodo con &tdevelop;, para lo que puede leer el «Manual de usuario de &tdevelop;», que contiene una revisión descriptiva de las funcionalidades proporcionadas por el IDE. Sobre este manual Este manual ha sido escrito para proporcionar a los desarrolladores una introducción al desarrollo de aplicaciones de KDE usando el entorno de desarrollo integrado KDevelop. Por lo tanto, los siguientes capítulos le proporcionan una introducción sobre cómo crear proyectos, explican el código fuente generado y muestran cómo extender dicho código para diversos temas, como barras de herramientas, menús y áreas de vistas. Luego se discute en detalle el editor de diálogos, explicando cómo se crean los widgets y cubriendo la modificación de sus propiedades. Finalmente, aprenderá algunas cosas que completarán su conocimiento sobre el diseño de proyectos y que le ayudarán a trabajar en cuestiones adicionales a la programación, como añadir documentación de API y ampliar los manuales en línea. En el siguiente capítulo Echaremos un vistazo a las bibliotecas Qt y KDE, mostrando sus conceptos básicos y por qué las cosas son como son. También discutiremos cómo crear las aplicaciones que proporciona el tutorial de la biblioteca Qt usando &tdevelop;, de modo que los principiantes puedan comprobar el resultado de sus primeros pasos, y también aprenderemos cómo hacer uso de algunas de las mejores características de &tdevelop;. En los capítulos siguientes Aprenderá cómo: Crear una aplicación con el KAppWizard Qué proporciona el esqueleto de un proyecto Qué significa el código generado Cómo crear sus propias vistas Cómo extender la funcionalidad de su aplicación mediante diálogos, barras de menú y barras de herramientas Cómo hacer que su aplicación sea amigable proporcionando funciones de ayuda Cómo escribir documentación en línea Información adicional Puede obtener información adicional sobre la programación Qt/KDE a través de diferentes fuentes: «Programación con Qt», por Matthias Kalle Dalheimer El manual de usuario de KDevelop, proporcionado con el IDE KDevelop La referencia en línea de la biblioteca Qt El sitio web de «KDE Developer» Adicionalmente, puede buscar ayuda suscribiéndose a múltiples listas de correo, cuyas direcciones están disponibles en las páginas web mencionadas, y en los grupos de noticias de Usenet dedicados a los usuarios de KDE y de los sistemas Unix, y también al lenguaje de programación C++. Para obtener ayuda sobre el entorno integrado de KDevelop, debe enviar sus peticiones a nuestra lista de correo en la dirección tdevelop@tdevelop.org. Recuerde que el equipo de KDevelop se dedica a proporcionarle los medios para que pueda programar aplicaciones, por lo que no debería entender que se dedica a dar soporte técnico en el caso de que las aplicaciones que esté desarrollando no funcionen debido a errores de implementación o a una mala configuración de su sistema operativo. Con esto queremos animar a que los usuarios aprovechen las listas de correo en el caso de que tengan problemas con el uso del propio IDE, y también para informar de errores y hacer sugerencias para mejorar la funcionalidad de este entorno de desarrollo. Las bibliotecas KDE y Qt La compañía noruega TrollTech (http://www.trolltech.com) proporciona lo que se conoce como un conjunto de herramientas GUI, llamado Qt. GUI significa «interfaz gráfica de usuario», por lo que las aplicaciones basadas en Qt utilizan botones, ventanas, etc., que permiten la interacción con el usuario visualizando las funciones que proporciona una aplicación. Estos conjuntos de herramientas son necesarios para desarrollar aplicaciones gráficas que se ejecuten sobre la interfaz X-Window de los sistemas Unix, ya que X no contiene por sí mismo ninguna interfaz de usuario predefinida. Aunque también dispone de otros conjuntos de herramientas para crear interfaces de usuario, Qt ofrece diversas ventajas técnicas que hacen que el diseño de aplicaciones sea muy fácil. Adicionalmente, las herramientas de Qt también están disponibles para los sistemas de Microsoft Windows, lo que permite a los desarrolladores ofrecer sus aplicaciones para ambas plataformas. El equipo de KDE (http://www.kde.org) se ha unido al esfuerzo de hacer que el uso de los sistemas Unix sea más amistoso, y ha decidido usar el conjunto de herramientas de Qt para el desarrollo de un gestor de ventanas sobre X-Window, además de la gran variedad de herramientas que se incluyen en los paquetes de distribución de KDE. El «entorno de escritorio K» contiene, pues, el gestor de ventanas «kwm», el gestor de archivos «kfm» y el panel de ejecución «kpanel» como componentes principales, además de gran cantidad de utilidades y aplicaciones de primera clase. Cuando apareció KDE, muchos desarrolladores se sintieron atraídos por el nuevo entorno y por lo que les ofrecía. Las bibliotecas de KDE proporcionan métodos esenciales y clases que hacen que todas las aplicaciones diseñadas con ellas se comporten de un modo similar y consistente, de modo que el usuario tenga la gran ventaja de tener que familiarizarse solo con el uso de una aplicación, no con el manejo de diálogos o de botones. Además, los programas de KDE se integran en el escritorio y son capaces de interactuar con el gestor de archivos mediante el mecanismo de «arrastrar y soltar», proporcionar gestión de sesiones y mucho más, si se usan todas las características ofrecidas por las bibliotecas de KDE. Tanto las herramientas de Qt como las bibliotecas de KDE están implementadas usando el lenguaje de programación C++, por lo que las aplicaciones que las usan también están escritas en C++. En el capítulo siguiente daremos un rápido repaso a estas bibliotecas para comprobar lo que proporcionan y tener una idea general sobre cómo crear aplicaciones Qt y KDE. Tanto la biblioteca del juego de herramientas Qt como la de KDE están construidas en el lenguaje de programación C++, por lo que las aplicaciones que las usan también están escritas principalmente en C++. En el siguiente capítulo haremos un corto viaje a través de estas bibliotecas para ver qué proporcionan y cómo se crean las aplicaciones de Qt y KDE, en general. El juego de herramientas gráficas Qt Como se ha dicho, la biblioteca Qt es un juego de herramientas que ofrece elementos gráficos que se usan para crear aplicaciones gráficas que son necesarias en la programación X-Window. Adicionalmente, este juego de herramientas ofrece: Un completo juego de clases y métodos listos para usar incluso para cuestiones de programación no gráfica Una buena solución en materia de interacción con el usuario mediante el uso de métodos virtuales y el mecanismo señal/contenedor Un juego de elementos gráficos predefinidos, llamados «widgets», que pueden ser fácilmente usados para crear los elementos visibles Diálogos adicionales completamente predefinidos que son usados a menudo en las aplicaciones, como los diálogos de progreso y de archivos Por ello, el conocimiento de las clases Qt es esencial, incluso si solo va a programar aplicaciones KDE. Para comprender el concepto básico de cómo se construyen y compilan las aplicaciones gráficas, echaremos un vistazo a un programa de ejemplo que solo usa Qt, y que más adelante convertiremos en un programa de KDE. La primera aplicación Qt Como era de esperar, los programas en C++ tienen que contener una función main(), que constituye el punto de inicio para la ejecución de la aplicación. Como queremos que se muestren en forma de ventanas gráficas y ofrezcan interacción, tendremos que saber primero cómo se muestran al usuario. Como ejemplo, consultaremos el primer manual que se incluye en la documentación de referencia en línea de Qt, y explicaremos los pasos básicos de la ejecución, además de por qué y cómo aparece la ventana de la aplicación. #include <qapplication.h> #include <qpushbutton.h> int main( int argc, char **argv ) { QApplication a( argc, argv ); QPushButton hello( "¡Hola mundo!", 0 ); hello.resize( 100, 30 ); a.setMainWidget( &hello ); hello.show(); return a.exec(); } Lo único que hace esta aplicación es dibujar una ventana que contiene un botón con el texto «Hola mundo». Como para todas las aplicaciones basadas en Qt, en primer lugar tiene que crear una instancia de la clase QApplication, representada por la variable «a». A continuación, el programa crea una instancia de la clase QPushButton llamada «hello», que será el botón. El constructor de «hello» tiene como parámetro una cadena de texto, que es el texto del widget que será visible como etiqueta del botón. Luego, el botón «hello» llama al método resize(), que cambia el tamaño predeterminado que tiene el widget (que es, en este caso, QPushButton) cuando es creado a 100 píxels de ancho y 30 de alto. Finalmente, «a» llama al método setMainWidget(), y «hello» llama al método show(). La QApplication se ejecuta finalmente mediante a.exec(), entra en el bucle de eventos principal y espera hasta que deba devolver un valor entero al sistema operativo anfitrión para indicarle que la aplicación ha terminado. La documentación de referencia de Qt Ahora, echemos un rápido vistazo a la documentación de referencia de la biblioteca Qt. Para ello, inicie &tdevelop; y seleccione «Qt» en el árbol de la pestaña de documentación. Se abrirá el navegador de la documentación y le mostrará la página inicial de la referencia de Qt. Este será el lugar principal donde obtener información sobre Qt, sus clases y las funciones que proporciona. Además, el programa anterior es el primero que se incluye en la sección de manuales. Para acceder a las clases que queremos consultar, QApplication y QPushButton, seleccione «Listado alfabético de clases» y busque los correspondientes nombres. Siga cualquiera de ellos para ver la documentación de su clase. De modo alternativo, puede usar la documentación en línea existente en la Documentación de Qt de Trolltech. Para la clase QApplication, verá el constructor y el resto de métodos que proporciona. Si sigue un enlace podrá obtener más información sobre el uso y significado del método, lo que resulta muy útil cuando a veces no es posible intuir su correcto uso o cuando se quiere ver un ejemplo. Esto también vale para la documentación de la biblioteca de KDE, que utiliza una estructura similar. Y esto es casi todo cuanto necesita saber sobre el uso de las referencias de las clases en el navegador de documentación. Interpretación del ejemplo Comenzando por QApplication, encontrará todos los métodos utilizados en nuestro primer ejemplo: el constructor QApplication() el método setMainWidget() el método exec() La interpretación sobre por qué utilizamos estos métodos es muy simple: Crear una instancia de la clase QApplication con el constructor, de modo que podamos usar los elementos de la interfaz gráfica que proporciona Qt Crear un widget que será el contenido de la ventana de nuestro programa Establecer el widget principal de «a» Ejecutar la instancia de «a» de QApplication El segundo objeto de nuestro programa es el botón pulsable, una instancia de la clase QPushButton. Hemos usado el segundo de los dos constructores que se nos ofrecen para crear una instancia de este objeto. Este constructor acepta como parámetro un texto, que será la etiqueta que mostrará el botón (aquí es la cadena «¡Hola mundo!»). Luego hemos llamado al método resize() para cambiar el tamaño del botón en relación a su contenido (el botón debe ser más ancho para que la cadena aparezca completamente). Pero, ¿qué hay del método show()? Ahora veremos que, al igual que la mayor parte de de widgetds, QPushButton se basa en la herencia simple. La documentación dice que esta clase hereda de QButton. Siga el enlace de la clase QButton y verá más widgets que han sido heredados por QPushButton (y que usaremos más adelante para explicar el mecanismo señal/slot). No obstante, el método show() no aparece listado, por lo que también tiene que haber sido proporcionado mediante herencia. La clase de la que hereda QButton es QWidget. Vuelva a seguir el enlace y verá el gran número de métodos que proporciona QWidget, incluido el método show(). Ahora entendemos lo que se ha hecho con el botón en el ejemplo: Crear una instancia de QPushButton, usar el segundo constructor para establecer el texto del botón Modificar el tamaño del widget según su contenido Establecer el widget como widget principal de la instancia «a» de QApplication Indicarle al widget que se muestre a sí mismo en la pantalla llamando a show(), un método heredado de QWidget Tras llamar al método exec() la aplicación se hace visible al usuario, mostrando una ventana con el botón, que muestra el texto «¡Hola mundo!». Tenga en cuenta que los programas gráficos se comportan de un modo algo distinto al de las aplicaciones basadas en procedimientos. El punto principal es que aquí la aplicación entra en lo que se denomina un «bucle principal de eventos». Esto significa que el programa debe esperar las acciones del usuario y luego reaccionar a ellas. Además, para una aplicación Qt, el programa tiene que estar en el bucle principal de eventos para comenzar a manejar los eventos. La siguiente sección le enseñará brevemente lo que significa esto para el programador y qué ofrece Qt para procesar los eventos del usuario. Para los usuarios avanzados: El botón no tiene un padre declarado en el constructor, por lo que es un widget aislado de nivel superior que se ejecuta en un bucle de eventos locales que no necesita esperar al bucle de eventos principal. Consulte la documentación de la clase QWidget y la «Guía de referencia de la biblioteca KDE». Interacción con el usuario Tras leer las últimas secciones, ya debería saber: Qué proporciona la biblioteca Qt en términos de aplicaciones gráficas Cómo se crea un programa que utilice Qt, y Dónde y cómo encontrar información sobre las clases que desea utilizar con el navegador de documentación Ahora le daremos «vida» a la aplicación procesando los eventos del usuario. Generalmente, el usuario tiene dos formas de interactuar con un programa: el ratón y el teclado. Para ambas, una interfaz gráfica de usuario debe proporcionar métodos que detecten acciones y métodos que hagan algo como respuesta a estas acciones. Para ello, el sistema de ventanas envía todos los eventos de interacción a la aplicación correspondiente. El objeto QApplication los envía luego a la ventana activa como objetos QEvent, y los widgets deben decidir por sí mismos qué hacer con ellos. Cuando un widget recibe el evento, procesa el método QWidget::event(QEvent*), que se encarga de decidir qué evento ha sido ejecutado y cómo reaccionar a él. Por lo tanto, event() es el manejador principal de eventos. A continuación, el método event() pasa el evento a los llamados «filtros de eventos» para determinar qué ha ocurrido y qué se debe hacer con el evento. Si no existe ningún filtro que se haga responsable para dicho evento, se llama a los manejadores de eventos especializados. Mediante ellos podemos decidir entre: Eventos del teclado -- Teclas «Tabulador» y «Mayúsculas-Tabulador»: virtual void focusInEvent(QFocusEvent *) virtual void focusOutEvent(QFocusEvent *) El resto de entradas del teclado: virtual void keyPressEvent(QKeyEvent *) virtual void keyReleaseEvent(QKeyEvent *) Los movimientos del ratón: virtual void mouseMoveEvent(QMouseEvent *) virtual void enterEvent(QEvent *) virtual void leaveEvent(QEvent *) Acciones de los botones del ratón virtual void mousePressEvent(QMouseEvent *) virtual void mouseReleaseEvent(QMouseEvent *) virtual void mouseDoubleClickEvent(QMouseEvent *) Eventos de la ventana que contiene el widget virtual void moveEvent(QMoveEvent *) virtual void resizeEvent(QResizeEvent *) virtual void closeEvent(QCloseEvent *) Note que todas las funciones de eventos son virtuales y protegidas, por lo que puede reimplementar los métodos encargados de manejar eventos que necesite en sus propios widgets y especificar cómo deben reaccionar. QWidget también contiene varios métodos virtuales más que pueden resultar de utilidad en sus programas. De ahí que sea recomendable conocer bien la clase QWidget. Interacción entre objetos mediantes señales y slots Estamos llegando a una de las ventajas más obvias del juego de herramientas Qt: el mecanismo señal/objeto, que ofrece una solución útil y provechosa para la interacción de objetos (que normalmente se resuelve mediante funciones «callback» de las herramientas del sistema X-Window). Como esta comunicación requiere una programación estricta y a menudo dificulta la creación de interfaces de usuario (como se dice en la documentación de Qt y se explica en «Programando con Qt», de K. Dalheimer), Trolltech creó un nuevo sistema en el que los objetos pueden emitir señales que se pueden conectar a métodos declarados como «slots». Desde el punto de vista del programador de C++, solo es necesario saber ciertas cosas sobre este mecanismo: la declaración de una clase que use señales y slots debe contener la macro Q_OBJECT al principio (sin punto y coma); también debe derivar de la clase QObject se puede emitir una señal mediante la palabra clave «emit»; por ejemplo, «emit señal(parámetros);», desde dentro de cualquier función miembro de una clase que permita señales y slots todas las señales usadas por las clases que no sean heredadas deben ser añadidas a la declaración de la clase mediante una sección «signals» todos los métodos que puedan ser conectados con una señal se declaran en secciones con la palabra clave «slot»; por ejemplo, «public slots:» dentro de la declaración de la clase el compilador de metaobjetos «moc» debe ejecutarse con el archivo de cabecera para expandir las macros y generar la implementación (que no es necesario conocer). Los archivos de salida de «moc» también son compilados por el compilador de C++. Otra forma de usar señales sin derivar de QObject consiste en usar la clase QSignal (consulte la documentación de referencia para obtener más información y un ejemplo de uso). En lo sucesivo asumiremos que está derivando de QObject. De este modo, su clase será capaz de enviar señales a cualquier otro sitio y de proporcionar «slots» a los que se puedan conectar señales. Gracias al uso de estas señales no tendrá que preocuparse de quién va a recibirlas: solo tiene que emitir la señal, y cualquier «slot» al que quiera conectarla reaccionará a la emisión. Los «slots» también pueden ser usados como métodos normales en la implementación. Ahora, para conectar una señal a un «slot», tendrá que usar los métodos connect() proporcionados por la clase QObject o, cuando estén disponibles, otros métodos especiales proporcionados por diversos objetos para establecer la conexión con ciertas señales. Ejemplo de uso Para explicar el modo en que establecemos la interacción entre objetos, tomaremos nuestro primer ejemplo y lo extenderemos con una conexión sencilla: #include <qapplication.h> #include <qpushbutton.h> int main( int argc, char **argv ) { QApplication a( argc, argv ); QPushButton hello( "¡Hola mundo!" , 0); hello.resize( 100, 30 ); a.setMainWidget( &hello ); QObject::connect(&hello, SIGNAL( clicked() ), &a, SLOT( quit() )); hello.show(); return a.exec(); } Como puede comprobar, la única adición para dar más interacción al botón consiste en usar un método connect(): connect(&hello, SIGNAL( clicked() ), &a, SLOT( quit() )); es todo cuanto tiene que añadir. ¿Cuál es su significado? La declaración de la clase QObject dice lo siguiente sobre el método connect(): bool connect ( const QObject * emisor, const char * señal, const QObject * receptor, const char * miembro ) Esto significa que debe especificar como primer parámetro un puntero de una instancia de la clase QObject, que es el emisor de la señal (lo que significa que puede emitir esta señal); a continuación debe especificar la señal que desea conectar. Los dos últimos parámetros son, en primer lugar, el objeto receptor que proporciona un «slot», y, finalmente, la función miembro de dicho objeto que va a actuar como «slot» (y que será ejecutada tras la emisión de la señal). Mediante el uso de señales y «slots», los objetos de su programa pueden interactuar con otros fácilmente sin depender explícitamente del tipo de objeto receptor. Aprenderá más sobre el uso de este mecanismo para usos productivos en sucesivas secciones de este manual. También puede encontrar más información sobre el mecanismo de señales y «slots» en la Guía de referencia de la biblioteca KDE y la referencia en línea de Qt. Qué proporciona KDE Las bibliotecas KDE 3.x Las principales bibliotecas de KDE que usará para crear sus propias aplicaciones para KDE son: la biblioteca «tdecore», que contiene todas las clases que no son elementos visibles y que proporcionan funcionalidad a las aplicaciones la biblioteca «tdeui», que contiene los elementos de la interfaz del usuario, como barras de menú, barras de herramientas, etc. la biblioteca «kfile», que contiene diálogos de selección de archivos Adicionalmente, KDE ofrece las siguientes bibliotecas para soluciones específicas: la biblioteca «tdefx», que contiene mapas de píxels, efectos de imagen y la extensión KStyle de QStyle la biblioteca «khtml», que contiene el componente «html» de KDE la biblioteca «kjs», que contiene el soporte Javascript para KDE la biblioteca «kio», que contiene el acceso a bajo nivel a los archivos de la red la biblioteca «kparts», que contiene soporte para aplicaciones reutilizables, incrustables y extensibles A continuación veremos qué se necesita para convertir su primera aplicación Qt en una aplicación KDE. Ejemplo de aplicación KDE A continuación comprobará que escribir una aplicación para KDE no es más difícil que escribir una aplicación Qt. Para usar algunas características de KDE tendrá que utilizar otras clases, y eso es casi todo. Como ejemplo, veamos la versión modificada del ejemplo Qt anterior: #include <kapplication.h> #include <qpushbutton.h> int main( int argc, char **argv ) { TDEApplication a( argc, argv ); QPushButton hello( "¡Hola mundo!", 0 ); hello.resize( 100, 30 ); a.setTopWidget( &hello ); QObject::connect(&hello, SIGNAL( clicked() ), &a, SLOT( quit() )); hello.show(); return a.exec(); } Vea que en primer lugar hemos cambiado de QApplication a TDEApplication . Además, hemos tenido que cambiar elmétodo setMainWidget() anteriormente usado por setTopWidget, que utiliza TDEApplication para establecer el «widget» principal. ¡Y ya está! Su primera aplicación de KDE ya está terminada. Ahora solo le falta indicarle al compilador la ruta de inclusión de KDE, y al enlazador que utilice la biblioteca tdecore mediante el parámetro -ltdecore. Como ahora ya sabe qué suele proporcionar como mínimo la función main(), cómo se hace visible una aplicación y cómo permite la interacción entre usuario y objetos, seguiremos con el siguiente capítulo, donde nuestra primera aplicación se construirá con &tdevelop;. Ahí tambień podrá probar todo lo que se ha dicho hasta ahora y comprobar sus efectos. Adicionalmente, hasta ahora ha consultado la documentación de referencia de Qt, especialmente las clases QApplication, QWidget y QObject, y la documentación de la biblioteca «tdecore» sobre la clase TDEApplication. El Manual d referencia de la biblioteca KDE también contiene una completa descripción sobre cómo llamar a los constructores de QApplication y de TDEApplication, incluido el procesamiento de los argumentos pasados como parámetros en la línea de comando. Creación de aplicaciones nuevas El asistente para aplicaciones El asistente para aplicaciones de &tdevelop; ha sido concebido para permitirle comenzar a trabajar en nuevos proyectos con &tdevelop;. Para ello, todos los proyectos nuevos serán creados primero por el asistente, y luego podrá comenzar a construirlos y a extender lo que se le ha proporcionado en un esqueleto de código fuente. Puede elegir entre varios tipos de proyecto según sus necesidades: Infraestructura de aplicación KDE: incluye código fuente para la infraestructura de una aplicación estándar de KDE. Proyecto QMake: crea una infraestructura de aplicación basada en el sistema de configuración QMake de Trolltech. Sencillo programa «Hola mundo»: crea un programa en C++ basado en la terminal sin soporte de interfaz gráfica. Una multitud de esqueletos para otros programas En este capítulo veremos cómo se llama al asistente para aplicaciones y qué se debe hacer para generar un proyecto de aplicación para KDE. Este es también el primer paso de nuestro objetivo, en el que crearemos la versión inicial de un proyecto de ejemplo. Para el resto de tipos de proyectos, los pasos suelen ser idénticos, aunque es posible que no disponga de tantas opciones. Llamar al asistente para aplicaciones y generación del proyecto Iniciar el asistente para aplicaciones y su primera página Para comenzar con su aplicación para KDE, abra &tdevelop;. En el menú «Proyecto» seleccione «Nuevo proyecto». Se iniciará el asistente para aplicaciones, en cuya primera página verá un árbol de selección que contiene los tipos de proyectos que se pueden crear. Seleccione el elemento «C++», y luego «KDE», y finalice con «Infraestructura de aplicación». Para nuestro proyecto de ejemplo vamos a crear la aplicación KScribble. Introduzca esto como nombre de la aplicación y cambie cualquier otra información de la parte inferior de esta pantalla que considere necesario. Luego, pulse sobre «Adelante». Asistente para aplicaciones Información sobre control de versiones En esta pantalla tendrá la opción de decidir si su proyecto usará un sistema de control de versiones como CVS. Para nuestro proyecto de ejemplo no usaremos ningún control del código fuente, así que nos aseguraremos de que esté marcada la opción «Ninguno» y pulsaremos sobre «Adelante». Plantillas de cabecera y código fuente Las dos siguientes páginas muestran cabeceras de ejemplo que se incluirán en la parte superior de todos los archivos de cabecera y de código fuente que cree usando &tdevelop;. Por ahora, deje esto tal y como está y seleccione «Adelante», y luego «Finalizar». Si el botón «Finalizar» no está activado se debe a que no habrá rellenado correctamente alguna opción. En este caso, utilice el botón «Atrás» para volver a las páginas anteriores y corregir cualquier posible error. Terminando Tras finalizar, el asistente para aplicaciones debe cerrarse y aparecerá la ventana de mensajes mostrando información sobre las tareas que está realizando &tdevelop;. Al final debería ver el mensaje «*** conseguido ***», que indica que todo ha terminado correctamente. La primera construcción Tras generar nuestro proyecto, realizaremos una excursión a través de su código fuente para hacernos una idea de cómo es una infraestructura de aplicación. Esto no solo nos ayudará a comenzar, sino que nos enseñará dónde tendremos que cambiar ciertas cosas en los pasos siguientes. En este capítulo se asume que ya conoce la navegación básica con &tdevelop;. Consulte el «Manual del usuario de KDevelop» si necesita más información. El gestor de «automake» muestra los archivos del proyecto del modo siguiente: Los archivos de nuestro proyecto Antes de sumergirnos en el código fuente, dejaremos que &tdevelop; construya y ejecute nuestra nueva aplicación. Para ello, seleccione «Construir proyecto» en el menú «Construir», o pulse F8. La ventana de salida se abrirá y mostrará mensajes de salida durante la fase de compilación. 1 cd /home/caleb/kscribble && WANT_AUTOCONF_2_5=1 WANT_AUTOMAKE_1_6=1 gmake k 2 gmake all-recursive 3 gmake[1]: Entering directory `/home/caleb/kscribble' 4 Making all in doc 5 gmake[2]: Entering directory `/home/caleb/kscribble/doc' 6 Making all in . 7 gmake[3]: Entering directory `/home/caleb/kscribble/doc' 8 gmake[3]: Nothing to be done for `all-am'. 9 gmake[3]: Leaving directory `/home/caleb/kscribble/doc' 10 Making all in en 11 gmake[3]: Entering directory `/home/caleb/kscribble/doc/en' 12 /usr/local/kde3/bin/meinproc --check --cache index.cache.bz2 /home/caleb/kscribble/doc/en/index.docbook 13 gmake[3]: Leaving directory `/home/caleb/kscribble/doc/en' 14 gmake[2]: Leaving directory `/home/caleb/kscribble/doc' 15 Making all in po 16 gmake[2]: Entering directory `/home/caleb/kscribble/po' 17 gmake[2]: Nothing to be done for `all'. 18 gmake[2]: Leaving directory `/home/caleb/kscribble/po' 19 Making all in src 20 gmake[2]: Entering directory `/home/caleb/kscribble/src' 21 source='main.cpp' object='main.o' libtool=no \ 22 depfile='.deps/main.Po' tmpdepfile='.deps/main.TPo' \ 23 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \ 24 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -c -o main.o `test -f 'main.cpp' || echo '/home/caleb/kscribble/src/'`main.cpp 25 /usr/lib/qt/bin/moc /home/caleb/kscribble/src/kscribble.h -o kscribble.moc 26 source='kscribble.cpp' object='kscribble.o' libtool=no \ 27 depfile='.deps/kscribble.Po' tmpdepfile='.deps/kscribble.TPo' \ 28 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \ 29 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -c -o kscribble.o `test -f 'kscribble.cpp' || echo '/home/caleb/kscribble/src/'`kscribble.cpp 30 kscribble.cpp: In member function `void KScribble::setupActions()' 31 kscribble.cpp:107: warning: unused variable `KAction*custom' 32 /usr/lib/qt/bin/moc /home/caleb/kscribble/src/kscribbleview.h -o kscribbleview.moc 33 source='kscribbleview.cpp' object='kscribbleview.o' libtool=no \ 34 depfile='.deps/kscribbleview.Po' tmpdepfile='.deps/kscribbleview.TPo' \ 35 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \ 36 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -c -o kscribbleview.o `test -f 'kscribbleview.cpp' || echo '/home/caleb/kscribble/src/'`kscribbleview.cpp 37 kscribbleview.cpp: In member function `void KScribbleView::print(QPainter*, 38 int, int)': 39 kscribbleview.cpp:79: warning: unused parameter `QPainter*p' 40 kscribbleview.cpp:79: warning: unused parameter `int height' 41 kscribbleview.cpp:79: warning: unused parameter `int width' 42 /usr/lib/qt/bin/moc /home/caleb/kscribble/src/pref.h -o pref.moc 43 source='pref.cpp' object='pref.o' libtool=no \ 44 depfile='.deps/pref.Po' tmpdepfile='.deps/pref.TPo' \ 45 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \ 46 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -c -o pref.o `test -f 'pref.cpp' || echo '/home/caleb/kscribble/src/'`pref.cpp 47 /usr/local/kde3/bin/dcopidl /home/caleb/kscribble/src/kscribbleiface.h > kscribbleiface.kidl || ( rm -f kscribbleiface.kidl ; /bin/false ) 48 /usr/local/kde3/bin/dcopidl2cpp --c++-suffix cpp --no-signals --no-stub kscribbleiface.kidl 49 source='kscribbleiface_skel.cpp' object='kscribbleiface_skel.o' libtool=no \ 50 depfile='.deps/kscribbleiface_skel.Po' tmpdepfile='.deps/kscribbleiface_skel.TPo' \ 51 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \ 52 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -c -o kscribbleiface_skel.o `test -f 'kscribbleiface_skel.cpp' || echo '/home/caleb/kscribble/src/'`kscribbleiface_skel.cpp 53 /bin/sh ../libtool --silent --mode=link --tag=CXX g++ -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -o kscribble -R /usr/local/kde3/lib -R /usr/lib/qt/lib -R /usr/X11R6/lib -L/usr/X11R6/lib -L/usr/lib/qt/lib -L/usr/local/kde3/lib main.o kscribble.o kscribbleview.o pref.o kscribbleiface_skel.o -lkio 54 source='kscribble_client.cpp' object='kscribble_client.o' libtool=no \ 55 depfile='.deps/kscribble_client.Po' tmpdepfile='.deps/kscribble_client.TPo' \ 56 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \ 57 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -c -o kscribble_client.o `test -f 'kscribble_client.cpp' || echo '/home/caleb/kscribble/src/'`kscribble_client.cpp 58 /bin/sh ../libtool --silent --mode=link --tag=CXX g++ -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -o kscribble_client -R /usr/local/kde3/lib -R /usr/lib/qt/lib -R /usr/X11R6/lib -L/usr/X11R6/lib -L/usr/lib/qt/lib -L/usr/local/kde3/lib kscribble_client.o -ltdecore 59 gmake[2]: Leaving directory `/home/caleb/kscribble/src' 60 gmake[2]: Entering directory `/home/caleb/kscribble' 61 gmake[2]: Nothing to be done for `all-am'. 62 gmake[2]: Leaving directory `/home/caleb/kscribble' 63 gmake[1]: Leaving directory `/home/caleb/kscribble' 64 *** conseguido *** Como puede ver, hemos colocado números al comienzo de cada línea que no aparecerán cuando realice este proceso; aquí nos ayudarán a describir qué está ocurriendo durante el proceso de construcción. En primer lugar, «gmake» trabaja recursivamente. Esto significa que comienza en la carpeta donde fue llamado y entra primero en las subcarpetas, de una en una, y luego vuelve a la carpeta en la que se inició, la procesa, y luego finaliza su ejecución. La primera línea de interés es la 24. Vea que «g++» (que se refiere a nuestro compilador de C++) ha sido llamado por «make» para compilar el primer archivo de código fuente de nuestro proyecto (en este caso, «main.cpp»). En la línea de comando del compilador «g++» se usan muchas opciones extra, algunas de ellas de forma predeterminada y otras configuradas mediante &tdevelop;. Antes de compilar el siguiente archivo («kscribble.cpp», en la línea 29), el compilador de metaobjetos «moc» se llama por primera vez sobre «kscribble.h» (línea 25). Esto se debe a que las clases de KScribble usan señales y slots, de modo que la macro Q_OBJECT debe ser expandida antes de ser usada, y esto es lo que «moc» hace por nosotros. El archivo resultante («kscribble.moc»), se usa en «kscribble.cpp» mediante una sentencia #include dentro de él. El esqueleto del código fuente Para tener un concepto de cómo funciona una aplicación de KDE, echaremos en primer lugar un vistazo al esqueleto de código fuente proporcionado por el asistente para aplicaciones. Como ya hemos visto, tenemos un conjunto de archivos de cabecera y de código fuente para generar el código inicial de nuestra aplicación y dejarla preparada para ser ejecutada. De ahí que el modo más fácil de explicar lo que hace el código fuente consista en seguir la implementación línea a línea a medida que se procesan durante la ejecución del programa hasta que se entra en el bucle principal de eventos y se está preparado para recibir entradas del usuario. A continuación veremos la funcionalidad que permite la interacción del usuario y cómo funcionan ciertas cosas. Probablemente esta es la mejor forma de entender la infraestructura, que es similar a la del resto de aplicaciones para KDE, y también le permitirá comprender el código fuente de otros proyectos. Adicionalmente, sabrá dónde cambiar ciertas partes del código para hacer que su aplicación se comporte del modo en que ha sido diseñada. La función main() Como la aplicación comienza su ejecución entrando en la función main(), este será nuestro punto de partida para examinar nuestro código fuente. La función main() de KScribble está implementada en el archivo «main.cpp». También se puede localizar usando el navegador de clases, seleccionando la carpeta «Funciones globales». 1 int main(int argc, char **argv) 2 { 3 TDEAboutData about("kscribble", I18N_NOOP("KScribble"), version, description, 4 TDEAboutData::License_GPL, "(C) 2002 Su nombre", 0, 0, "you@you.com"); 5 about.addAuthor( "Your Name", 0, "you@you.com" ); 6 TDECmdLineArgs::init(argc, argv, &about); 7 TDECmdLineArgs::addCmdLineOptions(options); 8 TDEApplication app; 9 10 // registrarnos como cliente dcop 11 app.dcopClient()->registerAs(app.name(), false); 12 13 // comprobar si estamos iniciando la gestión de la sesión 14 if (app.isRestored()) 15 RESTORE(KScribble) 16 else 17 { 18 // sin sesión... comenzar de modo normal 19 TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); 20 if (args->count() == 0) 21 { 22 KScribble *widget = new KScribble; 23 widget->show(); 24 } 25 else 26 { 27 int i = 0; 28 for (; i < args->count(); i++) 29 { 30 KScribble *widget = new KScribble; 31 widget->show(); 32 widget->load(args->url(i)); 33 } 34 } 35 args->clear(); 36 } 37 38 return app.exec(); 39 } Ahora, lo que ocurre en primer lugar es la creación de un objeto TDEApplication, pero hemos añadido algunos métodos de KDE para configurar la información sobre el programa y sobre el autor de esta aplicación. Inicio de la aplicación del usuario ... (pendiente de escribir) El constructor Veamos el constructor y cómo se llama a esta instancia 1 KScribble::KScribble() 2 : KMainWindow( 0, "KScribble" ), 3 m_view(new KScribbleView(this)), 4 m_printer(0) 5 { 6 // aceptar dnd 7 setAcceptDrops(true); 8 9 // comunicar a KMainWindow que este es el widget principal 10 setCentralWidget(m_view); 11 12 // a continuación, preparar nuestras acciones 13 setupActions(); 14 15 // y una barra de estado 16 statusBar()->show(); 17 18 // permitir que la vista pueda cambiar la barra de estado y el título 19 connect(m_view, SIGNAL(signalChangeStatusbar(const QString&)), 20 this, SLOT(changeStatusbar(const QString&))); 21 connect(m_view, SIGNAL(signalChangeCaption(const QString&)), 22 this, SLOT(changeCaption(const QString&))); 23 24 } Note que KScribble hereda la clase KMainWindow (una clases base muy utilizada en las aplicaciones de KDE). Inicializamos una clase llamada KScribbleView como nuestro widget central, creamos una KStatusBar mediante el método statusBar() (línea 16), y conectamos algunas señales y slots. Diseño de vistas de la aplicación Introducción Cuando se desarrola una aplicación con una interfaz gráfica de usuario, el trabajo principal consiste en proporcionar lo que se denomina una «vista» para la aplicación. Una vista generalmente es un widget que muestra los datos de un documento y proporciona métodos para manipular su contenido. El usuario realiza todo esto mediante los eventos que emite al usar el teclado o el ratón. Otras operaciones más complejas se procesan a menudo por las barras de herramientas y los menús, que interactúan con la vista y el documento. La barra de estado proporciona información sobre el documento, la vista o el estado de la aplicación. Como ejemplo, podemos ver cómo se construye un editor y dónde se encuentra cada cosa. Se supone que un editor debe proporcionar una interfaz para que un usuario pueda ver y/o modificar el contenido de un documento de texto. Si inicia «Kate», verá la interfaz visual siguiente: La barra del menú: proporciona operaciones complejas, como abrir, guardar y cerrar archivos, y salir de la aplicación. La barra de herramientas: ofrece iconos que permiten un rápido acceso a las funciones más utilizadas. La barra de estado: muestra el estado de la posición del cursor (su fila y columna actuales). La vista en la parte central de la ventana, que muestra el documento y ofrece un cursor conectado al teclado y al ratón que permite operar con los datos. Ahora es fácil entender que la vista es casi la única parte integrante de la aplicación, y que el diseño de la vista incide sobre la usabilidad y aceptabilidad de una aplicación. Esto significa que uno de los primeros pasos del desarrollo consiste en determinar el propósito de nuestra aplicación y qué tipo de vista se ajustará mejor para permitir que el usuario trabaje con la aplicación con un mínimo de esfuerzo para aprender a manejer la interfaz de usuario. Para algunos propósitos como la edición de texto y la visualización de archivos HTML, las vistas son proporcionadas por las bibliotecas de Qt y de KDE (discutiremos algunas observaciones sobre estos widgets de alto nivel en la siguiente sección). Pero la mayor parte de las aplicaciones se deben diseñar e implementar nuevos widgets. Esto es lo que hace que un programador también sea un diseñador y donde se demuestran sus capacidades de creatividad: debe buscar la intuición en primer lugar. Recuerde que un gran número de usuarios no aceptará una aplicación que no sea: gráficamente atractiva rica en características fácil de manejar: fácil de aprender a usar Tampoco es necesario decir que la estabilidad es uno de los principales objetivos del diseño. Nadie puede evitar los errores, pero se puede conseguir bastante mediante objetivos diseñados inteligentemente y el amplio uso de diseños orientados a objetos. C++ hace que la programación sea un juego si sabe cómo explotar sus capacidades: herencia, ocultación de información y reusabilidad del código existente. Cuando cree un proyecto KDE o Qt, siempre tendrá una vista que herede de QWidget, ya sea por herencia directa o porque el widget de la biblioteca que desea usar hereda de QWidget. De ahí que el asistente para aplicaciones haya construido una vista que es una instancia de una clase «aplicaciónView», que hereda de QWidget. Este capítulo describe cómo usar widgets de bibliotecas para crear vistas para aplicaciones de KDE o Qt que han sido generadas con &tdevelop;. Luego veremos las bibliotecas y qué tipo de vistas nos ofrecen. Uso de bibliotecas de vistas Cuando haya ajustado el diseño de su aplicación, debería buscar en primer lugar código ya existente que haga su vida más fácil. Una parte de esta búsqueda consiste en encontrar un widget que pueda ser usado como vista, o al menos como una parte de ella, ya sea directamente o mediante herencia. Las bibliotecas de KDE y de Qt contienen un conjunto de widgets que se pueden usar para este propósito. Dispone de dos opciones para usarlos: Eliminar la clase de la nueva vista y crear una instancia de un widget de biblioteca, y luego establecerlo como vista. Cambiar la herencia de la clase de vista proporcionada a la clase del widget de la biblioteca que va a usar. De cualquier modo, es importante saber que si la infraestructura de la aplicación no está enlazada actualmente con la biblioteca que contiene el widget, el enlazador fallará. Una vez que haya decidido usar cierto widget, busque la biblioteca que debe enlazar; luego abra «Proyecto» -> «Opciones» en el menú de &tdevelop; y vaya a la página «Opciones del enlazador» y busque las marcas que indican las bibliotecas que se están usando en la actualidad. Si la biblioteca que contiene su widget ya está marcada, puede dejar sin tocar las opciones del proyecto. En caso contrario, y si las opciones del enlazador le permiten marcar la biblioteca para añadirla, márquela y pulse «Aceptar» para salir de las opciones del proyecto. En cualquier otro caso, añada la biblioteca en el campo de edición que más abajo con la opción «-l». Para las bibliotecas que su aplicación debe buscar, antes de preparar los Makefiles con el guión «configure» en el sistema del usuario final, añada la correspondiente macro de búsqueda en el archivo «configure.in» situado en la carpeta principal de su proyecto, y añada la macro a la línea de edición. Recuerde que debe ejecutar «Construir» -> «Autoconf y automake», y luego «Construir» -> «Configure» antes de que los Makefiles contengan la expansión correcta para la macro de la biblioteca. Además, si los archivos de cabecera de la biblioteca a añadir no están en la ruta de inclusión actual (que se puede ver con las opciones «-l» en la ventana de salida de «make»), debe añadir su ruta en el diálogo de opciones del proyecto, en la página «Opciones del compilador», con la opción «-l» o la macro de automake correspondiente en la línea de edición de las «Opciones adicionales». Vistas de Qt Si observa la primera página de la documentación en línea de Qt encontrará un enlace a «capturas de pantalla de los widgets», donde podrá ver cómo son los widgets que contiene Qt. Estos widgets están listos para usar y pueden ser combinados entre sí para formar widgets más complicados que le permitirán crear vistas y diálogos para su aplicación. A continuación describiremos algunos de estos widgets que le resultarán de utilidad para crear vistas de aplicaciones, pero recuerde que las bibliotecas de KDE suelen contener otros widgets para el mismo propósito. Veremos esto en la próxima sección. A continuación le damos una lista de pistas sobre para qué propósito puede usar cada componente de Qt: Si el área de su vista no es lo suficientemente amplia para mostrar todos sus datos, el usuario debería poder desplazarse por el documento con barras situadas a la derecha y en la parte inferior de la vista. Para ello, Qt proporciona la clase QScrollView, que ofrece un área hija que se puede desplazar. Como se ha explicado, puede derivar su propio widget de la clase QScrollView o usar una instancia de ella para gestionar el widget que contendrá la vista de su documento. Para crear una vista propia que se pueda deslazar, derive su widget de vista de la clase QWidget y añada un QScrollBar horizontal y otro vertical (esto es lo que hace, por ejemplo, el widget KHTMLView de KDE). Para procesar texto, utilice QTextEdit. Esta clase proporciona un widget con un completo editor de texto que es capaz de cortar, copiar y pegar texto, y está gestionado por una vista que se puede desplazar. Use QTable para mostrar datos organizados en forma de tabla. Como QTable también está dotada de barras de desplazamiento, ofrece una buena solución para aplicaciones de cálculo de tablas. Para mostrar dos widgets diferentes o dos instancias del mismo widget a la vez, utilice QSplitter. Esta clase le permite distribuir las vistas mediante divisores horizontales o verticales. KMail es un buen ejemplo de la apariencia de esta clase (la vista principal está dividida verticalmente por un «splitter» o divisor, y la ventana de la derecha también está dividida horizontalmente). QListView muestra información en forma de lista o de árbol. Resulta útil para crear árboles de archivos, por ejemplo, o para mostrar cualquier tipo de información jerárquica con la que desee interactuar. Como ve, Qt solo ya ofrece un completo conjunto de widgets listos para usar, de modo que no será necesario que invente nuevas soluciones si alguno de ellos se ajusta a sus necesidades. Un efecto adicional de usar widgets estándares consiste en que los usuarios ya saben cómo manejarlos y solo necesitan concentrarse en los datos mostrados. Vistas de KDE Las bibliotecas de KDE fueron creadas para hacer más fácil el diseño de aplicaciones para KDE, y además disponen de más funcionalidad de la que ofrece Qt. La biblioteca «tdeui» ofrece: KListView: una versión más potente de QListView KIconView: un visor gráfico de archivos de icono La biblioteca «khtml», por otra parte, ofrece un completo widget de interpretación HTML listo para usar. Ya contiene barras de desplazamiento, así que no tendrá que preocuparse por ello. Un posible uso puede ser el de integrarlo como parte de un widget editor de HTML para previsualizar el resultado. Este widget se usa en aplicaciones como Konqueror para mostrar archivos HTML. Creación de sus propias vistas ... (pendiente de escribir) Configuración de menús y de barras de herramientas Introducción Las barras de menú y de herramientas son unas de las partes más importantes de una aplicación para proporcionar métodos para trabajar con la estructura de un documento. Como regla general, todas las funciones deben residir en la barra de menú, y todos los métodos que no deban estar disponibles en el estado actual de la aplicación deberían aparecer desactivados. Aún más, una aplicación solo puede contener una barra de menú, aunque puede tener varias barras de herramientas. Por otra parte, las barras de herramientas deben contener solo los comandos usados más frecuentemente, representados por iconos, o proporcionar métodos de acceso rápido, como listas desplegables para seleccionar valores. ¿Cómo funciona? Nuestra aplicación hereda la clase KMainWindow, que maneja de forma automática la creación de una barra de menú y de barras de herramientas. En el método KScribble::setupActions() se realiza una llamada a KMainWindow::createGUI(). Este método carga un archivo de recursos (en nuestro caso, «kscribbleui.rc») para inicializar los menús durante el inicio. Observe que «kscribbleui.rc» se lista como uno de los archivos del proyecto en el «Gestor de automake». Si abre este archivo verá lo siguiente: 1 <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> 2 <kpartgui name="kscribble" version="1"> 3 <MenuBar> 4 <Menu name="custom" ><text >P&ersonalizar</text> 5 <Action name="custom_action" /> 6 </Menu> 7 </MenuBar> 8 </kpartgui > Explicación... Otro modo de modificar el contenido del menú y de las barras de herramientas consiste en manipularlos directamente mediante los métodos que proporcionan sus respectivas clases. Por ejemplo, el método menuBar() devuelve el widget KMenuBar de contiene la barra de menú de nuestro programa. Si consulta la documentación de KMenuBar y de su clase heredada, QMenuBar, encontrará un gran número de métodos insertItem(); que le permiten añadir elementos a la barra de menú. Los métodos statusBar() y toolBar() de KMainWindow también le proporcionan widgets aplicables. Configuración de los accesos rápidos de teclado Los accesos rápidos de teclado son algo muy profesional que siempre debería añadir a sus aplicaciones. Son usados principalmente por usuarios avanzados que desean trabajar más rápido con sus aplicaciones. Para implementarlos, las bibliotecas de KDE ofrecen la clase KAction, que proporciona las teclas de acceso rápido y también brinda acceso a los aceleradores de teclado estándares configurados globalmente. De forma predeterminada, las aplicaciones generadas con &tdevelop; solo utilizan accesos rápidos de teclado estándares, como «F1» para acceder a la ayuda en línea, «Ctrl+N» para «Nuevo archivo», etc. Si su aplicación contiene gran número de aceleradores, debería hacer que se pudieran configurar desde el menú de «Opciones», ya sea combinados con la configuración de otras aplicaciones en un QWidget o bien de modo aislado. La biblioteca de KDE proporciona una clase KKeyChooser para usar en diálogos que contienen pestañas, para los que KKeyDialog proporciona un diálogo de configuración de teclas listo para usar. Funciones de ayuda Introducción Una parte muy importante del proceso de desarrollo consiste en proporcionar funcionalidades de ayuda al usuario siempre que sea posible. Muchos desarrolladores tienden a dejar esto para otro momento, pero debería recordar que un usuario normal no es necesariamente un experto en Unix. Es posible que provenga del «lado oscuro» del uso del software informático proporcionando todas las golosinas que un usuario pueda necesitar para trabajar usando una aplicación incluso sin haber tocado nunca un manual. Por ello, las bibliotecas Qt y KDE ofrecen todos los métodos que usualmente se consideran profesionales en una aplicación a los ojos de un usuario, como funciones de ayuda listas para usar. En una aplicación, son: Ayudas emergentes Ayuda de la barra de estado Botones «¿Qué es esto?» Además, la aplicación debe proporcionar algún modo de acceder directamente al manual en línea basado en HTML usando la tecla estándar de ayuda, «F1». Este sistema de ayuda basado en contextos se proporciona automáticamente por la clase KMainWindow, aunque el autor debe proporcionar el contenido de la ayuda. Del mismo modo que &tdevelop; ofrece todos los tipos de ayuda, nuestra infraestructura de aplicación para KDE generada por el asistente para aplicaciones también contiene soporte para ellos. Este capítulo le ayudará a determinar dónde y cuándo añadir funcionalidades de ayuda. Durante el desarrollo de su aplicación debería tratar de ser consistente con lo que está haciendo. Para ello debería de dar los pasos necesarios mientras amplía el código. Esto le evitará tener que sumergirse en el código fuente de nuevo y tratar de imaginarse lo que hace su aplicación o qué quiso hacer en ciertas partes del código. Ayudas emergentes Un modo bastante fácil de proporcionar ayuda son las «ayudas emergentes», que son pequeños mensajes con texto explicativo que aparecen cuando el usuario sitúa el puntero del ratón sobre un widget, y que desaparecen cuando el ratón se mueve a otro lugar. El uso más popular de las ayudas emergentes se realiza en las barras de herramientas, donde el texto de ayuda se debe mantener lo más corto que sea posible debido a que la barra de herramientas se puede configurar para mostrar su contenido de varias formas (mostrando botones, botones con texto a la derecha, botones con texto debajo, o solo texto). El usuario debería poder configurar estas posibilidades, aunque no es estrictamente necesario. El texto se muestra como ayuda emergente y la barra de herramientas suele constar de botones y de otros widgets, como líneas de edición y listas desplegables. Para una referencia más completa, consulte la clase KToolBar que proporciona la biblioteca «tdeui». Como ejemplo, veamos el botón «Archivo nuevo» de una aplicación genérica: Aquí, la parte «i18n("Archivo nuevo")» proporciona un mensaje de ayuda emergente. Está encerrado en el interior de una macro «i18n()» (ofrecida por «kapp.h») que permite traducir el texto del mensaje al idioma actualmente seleccionado en el sistema del usuario. Las ayudas emergentes también se pueden añadir a cualquier widget personalizado usando la clase QToolTip proporcionada por Qt. Un ejemplo de esto sería: Extendiendo la barra de estado Como las aplicaciones que heredan de KMainWindow también contienen una barra de estado, se ofrece un conjunto de mensajes de estado para todos los elementos del menú y de las barras de herramientas. Un mensaje de estado consiste en un texto corto que extiende el significado de una ayuda emergente; y también se puede considerar como un sustituto de las ayudas emergentes para los elementos del menú. Como su nombre indica, se muestra en la barra de estado cuando el usuario despliega un menú y sitúa el ratón sobre una de sus entradas. El botón <guibutton >¿Qué es esto?</guibutton > El botón ¿Qué es esto? proporciona ventanas de ayuda con la idea de que el usuario necesita ayuda sobre cierto widget de la vista activa o de un elemento de una barra de herramientas. Se suele colocar en la misma barra de herramientas y se activa cuando el usuario pulsa su botón. El cursor cambia a una flecha con un signo de interrogación (con el mismo aspecto que muestra el botón). A partir de ese momento, el usuario puede pulsar sobre cualquier widget visible y obtener una ventana de ayuda. Como ejercicio, pruebe el comportamiento del botón ¿Qué es esto? de &tdevelop;. Para añadir ayudas «¿Qué es esto?» a cualquiera de sus widgets, utilice el método estático QWhatsThis::add(QWidget *widget, const QString &texto) Documentación Introducción Debido al hecho de que los proyectos suelen carecer a menudo de documentación para el usuario, todos los proyectos que crea &tdevelop; contienen un manual previamente construido que puede ser fácilmente adaptado a sus necesidades. De este modo se satisface otro de los objetivos de KDE: proporcionar la suficiente ayuda en línea para los usuarios que no están familiarizados con el uso de una aplicación. Este capítulo le enseñará cómo extender la plantilla de documentación proporcionada y qué hacer para que el usuario disponga de ella. Documentación del usuario La documentación de su proyecto reside en la carpeta «proyecto/doc/en», o tal vez en otra carpeta si el inglés no es su idioma nativo. Ahí existe un archivo («index.docbook») en el que se almacena la documentación. La forma de editar este archivo se explica en la web de documentación de KDE. Documentación del programador Otra parte importante de la documentación consiste en incluir ayuda descriptiva para las interfaces de las clases que implementa su programa. Esto le ayudará a usted y a otros programadores a usar sus clases leyendo la documentacióń HTML de las clases que se puede crear con KDoc. &tdevelop; soporta el uso de KDoc completamente creando la documentación de la biblioteca KDE. Del mismo modo, su infraestructura de aplicación ya está documentada. Antes de trabajar en el código proporcionado, sería interesante que leyera la documentación incluida en línea. A continuación se describe qué hacer para obtener la documentación del API, dónde le ayuda &tdevelop; a añadirla y qué tipos de etiquetas especiales proporciona KDoc. Internacionalización Introducción i18n es un sistema de internacionalización que se usa para ofrecer versiones multilingües de una aplicación o proyecto. La dificultad de escribir aplicaciones reside en que solo soportan el idioma para el que han sido programadas. Esto se observa visualmente en las etiquetas, entradas de menú, y demás. El objetivo de la internacionalización es dotar de funciones a las aplicaciones y a las bibliotecas en el idioma del usuario, permitiendo a los que no dominan el idioma en el que fueron hechas que puedan utilizar su funcionalidad y sentirse más cómodos. Créditos (... pendiente de escribir ...) Bibliografía <ulink url="info://make/Top" >Manual de GNU Make</ulink > Richard M.Stallman RolandMcGrath <ulink url="info://automake/Top" >GNU Automake</ulink > DavidMacKenzie TomTromey <ulink url="info://autoconf/Top" >GNU Autoconf</ulink > DavidMacKenzie BenElliston <ulink url="info://gcc/Top" >Uso de la colección del compilador GNU</ulink > Richard M.Stallman <ulink url="info://libtool/Top" >GNU Libtool</ulink > GordonMatzigkeit AlexandreOliva ThomasTanner Gary V.Vaughan GNU Autoconf, Automake y Libtool 1st edition October 2000 Gary V.Vaughan BenElliston TomTromey Ian LanceTaylor New Riders Publishing ISBN 1578701902 Programación avanzada en el entorno UNIX(R) 1st edition June 1992 W. RichardStevens Addison-Wesley Pub Co ISBN 0201563177 Pensando en C++, volumen 1: Introducción al C++ estándar 2nd Edition April 15, 2000 BruceEckel Prentice Hall ISBN 0139798099 Desarrollo de código abierto con CVS 2nd Edition October 12, 2001 KarlFogel MosheBar The Coriolis Group ISBN 158880173X Programación en PHP 1st edition March 2002 RasmusLerdorf KevinTatroe O'Reilly & Associates ISBN 1565926102 Programación en Python 2nd Edition March 2001 MarkLutz O'Reilly & Associates ISBN 0596000855 Programación GUI con Python: Uso del toolkit Qt Bk&Cd-r edition January 2002 BoudewijnRempt Opendocs Llc ISBN 0970033044 Programación en Perl El libro del camello 3rd Edition July 2000 LarryWall TomChristiansen JonOrwant O'Reilly & Associates ISBN 0596000278 Aprenda Perl El libro del lama 3rd Edition July 15, 2001 Randal L.Schwartz TomPhoenix O'Reilly & Associates ISBN 0596001320 &underFDL;