Posts Tagged ‘kde’

Versión 0.1 disponible

2008/04/04

Realmente, ya hace una semana que la publiqué. Pero fue una semana de locura con cosas de clase y no encontré un triste momento para escribirlo aquí en el blog 😦 Pero bueno, menos lamentar y más informar 😉

La versión 0.1, así como las instrucciones de compilación e instalación, puede encontrarse en la sección de descargas de la web del proyecto.

Aproveché también para incluir la documentación de la API, un tutorial de uso de la biblioteca (para desarrolladores de aplicaciones, no para usuarios finales) y un documento de diseño. El documento de diseño, no obstante, aún es más un simple borrador que un documento serio.

¿Y ahora? Ahora, lógicamente, a por la versión 0.2. Inicialmente era donde me proponía llegar antes de terminar el concurso,  con algo de tiempo para empezar a revelar la existencia del proyecto a los desarrolladores de KDE y con suerte recibir algo de feedback (la versión española de la palabra no acaba de gustarme 😉 ). Pero con todo el lío que tuve estas últimas semanas con cosas de la universidad, eso no va a ser posible. ¡Una pena!

La idea para esta versión 0.2 es poder crear tutoriales interpretados mediante scripts (gracias a Kross), en lugar de compilados en C++, y utilizar Get Hot New Stuff para poder descargar nuevos tutoriales con facilidad.

Así que nada, ahora, a intentar integrar Kross y GHNS en la medida de lo posible con el tiempo del que dispongo. Aún no investigué GHNS, pero Kross parece que no va a ser tan sencillo como pensaba. Mejor dicho, la integración en sí sí es sencilla. Conseguir lo que creía que podría conseguir directamente con ella, no 😉 Pero eso es otra historia, y como tal ya habrá tiempo de contarla.

¡Está vivo! ¡Viiivooo!

2008/02/07

Y por fin llegó el día de mostrar a la bestiecilla. Lo cierto es que me gustaría explayarme más, pero tengo examen mañana y no me sobra el tiempo, así que seré breve 😉

Enlazo tres vídeos de KTutorial en funcionamiento a través de una aplicación de prueba:

  • ktutorial-limpiar.ogg: muestra un tutorial muy sencillo y cómo puede moverse el Widget de los tutoriales por la pantalla.
  • ktutorial-mover.ogg: un tutorial ya más complejo (el código presenta filtrado de eventos para poder interceptar pulsaciones del ratón, por ejemplo) que muestra el uso de opciones en los pasos.
  • ktutorial-l10n.ogg: simplemente muestra cómo KTutorial está internacionalizado y puede localizarse como cualquier otra aplicación de KDE (en el vídeo se muestra la localización al español).

Los vídeos fueron realizados utilizando recordMyDesktop, por tanto utiliza sólo formatos libres. En concreto, el contenedor ogg y el formato de vídeo Theora. No hay audio en estos tres vídeos.

Los vídeos deberían estar alojados en la web del proyecto… pero hoy no soy capaz de conectarme mediante SCP a la forja de RedIRIS (me devuelve un hermoso “Lost connection”), así que temporalmente están alojados en otro servidor. ¡Gracias Luis!

Actualización:  los vídeos ya están alojados en la web del proyecto, pues se resolvió el problema de SCP (algo debía haber en el lado del servidor, ya que yo no hice nada más que probar lo mismo días más tarde).

En los próximos días intentaré subir el código fuente del framework y la aplicación de prueba a la forja, así como la documentación de la API en la página web (cuando consiga transferir ficheros a ella, claro).

Oh, huelga decir que los vídeos están bajo licencia Creative Commons Attribution-Share Alike 😉

Bibliotecas dinámicas en KDE 4

2008/02/06

Versión corta: si desarrollas una biblioteca dinámica para KDE, debes marcar tus clases con la macro KNOMBREBIBLIOTECA_EXPORT (de forma que su definición quede como “class KNOMBREBIBLIOTECA_EXPORT nombreClase: public claseBase {…“), y definir esa macro en un archivo de cabecera knombrebiblioteca_export.h (los nombres no tienen por qué ser necesariamente así, pero por seguir la práctica común) con un contenido adaptado a la biblioteca en cuestión. Véase como ejemplo cualquiera de los archivos include/kloquesea_export.h de KDE 4, así como los archivos de cabecera de las clases que los usan.

Para quien quiera aburrirse con la versión larga y detallada de mis aventuras y desventuras hasta llegar a tan sencilla conclusión, a continuación viene la versión larga.

“El miedo es el camino hacia el Lado Oscuro. El miedo lleva a la ira, la ira lleva al odio, el odio lleva al sufrimiento. Veo mucho miedo en ti.” Con estas palabras el maestro Yoda expresaba su preocupación ante el entrenamiento en los caminos de la Fuerza del joven Anakin Skywalker. Pues bien, si hoy el maestro Yoda me hubiese examinado a mí, miedo no habría encontrado. Ahora que de ira, odio y sufrimiento iba servido.

Este cúmulo de sensaciones tan poco agradables eran debidas al cansancio y desesperación acumuladas durante las ¿5? horas que había pasado intentando averiguar por qué cuando convertí la biblioteca KTutorial de estática a dinámica el enlazado desde una aplicación de prueba fallaba (una larga retahíla de “undefined reference to `vtable for NombreClase::metodo()‘” en los lugares de la aplicación de prueba que se usaba la biblioteca).

Pero, ¿por qué? Inicialmente pensé que tal vez habría que hacer algo más que añadir la opción SHARED en el objetivo para crear la biblioteca (“kde4_add_library(ktutorial SHARED ${ktutorial_LIB_SRCS})“) y por ese motivo fallaba. Sin embargo, el amigo Google no me devolvía nada concluyente a este respecto. Según parecía, con añadir esa opción ya era suficiente para crear la biblioteca.

Así que busqué en las kdelibs algún archivo de CMake que generase una biblioteca dinámica, para ver si había algo que se me escapase. La mayoría eran archivos “grandes”, aunque buscando, llegué al archivo de CMake para kdelibs/kde3support/kunittest. Generaba una biblioteca y un ejecutable que enlazaba con ésta, era pequeño y fácil de entender. ¡Excelente!

O no tanto. Porque resulta que el archivo de CMake tenía lo mismo que los que utilizaba yo. Tras varias pruebas, entre ellas aislar esa biblioteca y generarla de 0 (por si acaso CMake utilizaba objetivos heredados de los directorios padre) y ver que funcionaba, supuse que el problema no estaría en los objetivos de CMake. Pero, ¿dónde entonces?

Pensé que el problema podía residir en que la biblioteca dinámica enlazaba con una biblioteca estática temporal. Esta biblioteca estática simplemente contiene las clases de la vista, que están separadas del modelo en un subdirectorio. Me parecía extraño que fuese el problema, ya que anteriormente había trabajado con un esquema similar, aunque en una biblioteca que no era de KDE, y no presentaba problemas. Pero como no sabía dónde buscar, intenté por ese lado. Y como era de esperar… seguía sin funcionar.

Puestos a dar palos de ciego, decidí enlazar la biblioteca no con una aplicación de verdad, sino con la mínima expresión de un programa de C++, a ver qué pasaba. Así que hice simplemente un método main que crease un objeto de una clase de la biblioteca. Enlacé y… ¡funcionó! Por probar, cree un objeto de otra clase, y enlacé de nuevo. Y esta vez, fallaba al enlazar con el nuevo objeto. Ni que decir tiene que miraba incrédulo a la pantalla, esperando que mi querido ordenador sacase un diálogo llamándome inocente y diciéndome que ya paraba con la broma.

Pero en vista de que eso no ocurría, decidí mirar dónde estaba la diferencia entre ambas clases, para que una enlazase y la otra no. Y la diferencia era que la que enlazaba era una clase normal, mientras que la que no, era derivada de QObject. Me encanta Qt, adoro todas sus características, me emociono sólo de pensar en señales y ranuras. Pero en ese instante quise que David el gnomo acabase con todos los trolls (por si alguien no sabe a qué me refiero, Qt es obra de Trolltech, a cuyos empleados se les conoce como “los trolls”. Sí, es el peor intento de chiste que leíste en mucho tiempo, lo sé. Pero qué quieres, estoy cansado 😛 ).

Con todo esto, decidí volver sobre el código de kunittest. El sistema de construcción era igual al que yo usaba, por lo que la diferencia tenía que estar en el código de las clases. Lo primero que advertí era que dichas clases incluían en los cpp los archivos moc generados por la herramienta de Qt para hacer su magia.

No me constaba que en KDE 4 fuese necesario (aunque, hasta donde sé, con KDE 3 sí), pero dado que a esas alturas si alguien me decía que mi problema se solucionaría dando tres vueltas sobre mi mismo y diciendo “Oh todopoderoso enlazador yo te invoco” en arameo antes de construir la biblioteca yo lo intentaría, pues probé incluyendo los archivos moc.

Jamás adivinaríais qué pasó. Exacto, siguió sin funcionar. A punto de subirme a la silla gritando “Je suis Napoléon!”, vi algo que me llamó la antención en un archivo .h de kunittest: “class KUNITTEST_EXPORT Runner : public QObject“. Tenía que ser eso. Miré qué valor tenía la macro, y cuando se construía la biblioteca éste era “KDE_EXPORT“. “Eso suena a exportar símbolos de la biblioteca”, pensé.

Así que hice una prueba rápida y añadí dicha macro en la clase que utilizaba en mi main simplificado y que no enlazaba. Y un coro celestial bajó a arroparme entre cánticos de júbilo y felicidad. ¡¡¡AL FIN!!!

Tras esto, hice los cambios necesarios en la biblioteca para que todas las clases derivadas directa o indirectamente de QObject utilizasen dicha macro, y todo funcionó como era de esperar 🙂

Realmente no estoy seguro de la explicación técnica de por qué ocurre esto. Mis conocimientos sobre enlazado de C++ en Linux no llegan a tanto, y tampoco tengo tiempo de ponerme a investigarlo. Pero sí se la regla de oro: si haces una biblioteca dinámica en KDE, tienes que marcar tus clases públicas para que se pueda enlazar con ellas. Para ver cómo deben marcarse, a la versión corta del artículo me remito 😉

Una vez arreglado esto, a seguir con los objetivos de instalación de CMake para poder usar la internacionalización.

Y tras este artículo es cuando el anterior pasa a ser claramente anacrónico, ya que no pude dedicarme la tarde entera a investigar lo narrado en él, cuando en éste se ve cómo estuve haciendo otra cosa distinta 😉

Añadiendo la entrada “Tutoriales” al menú ayuda de KDE

2008/02/06

El siguiente artículo es un anacronismo. Debería haberlo publicado ya hace varios días, que fue cuando lo escribí, pero no sé por qué no lo hice aún. Así que aquí está, para regocijo y disfrute de pequeños y mayores 😛

Tras una tarde de investigación, lectura de código (ventajas del software libre 🙂 ) y depuración no encontré la manera de que una biblioteca añada automáticamente una entrada en un punto concreto del menú de ayuda de KDE de una aplicación que utiliza XMLGUI (que deberían ser todas).

¿Y qué quiere decir todo eso? Bueno, expliquémoslo un poco más. En KDE 4 se utiliza (por el momento al menos) una tecnología denominada XMLGUI para crear las interfaces gráficas de usuario de las aplicaciones. En un fichero XML se indican cómo estarán organizados el menú y las barras de tareas y qué acciones corresponderán a cada elemento, y luego esas acciones se definen en el propio código de la aplicación.

Los archivos XML que describen la interfaz son jerárquicos, pudiendo mezclarse con otros. De esta forma, puede tenerse un archivo que describe la interfaz común de las aplicaciones de KDE, y luego cada una de éstas puede tener su propio archivo en el que se añaden nuevos elementos. La unión (virtual, no física) de ambos archivos da como resultado la interfaz final.

La mezcla, en el caso de los menús que es lo que nos ocupa, se realiza mediante los elementos Merge, MergeLocal y DefineGroup. Reconozco no tener muy claro cómo funciona el elemento Merge, principalmente porque por más que busqué, no encontré documentación al respecto de los elementos, por lo que lo que sé de ellos es fruto del mero análisis del código fuente y la experimentación.

En cuanto a MergeLocal, se establece en el documento padre de forma que los elementos que en el hijo pertenezcan al mismo menú en el que está se incluyan en lugar del elemento MergeLocal. En lo que respecta a DefineGroup, define la posición en la que se añadirán todos los elementos pertenecientes a un determinado grupo. En el documento hijo simplemente se añade en los elementos deseados el atributo group con el nombre del grupo en cuestión.

Si no existe ninguno de estos elementos de mezcla, los nuevos elementos del documento hijo se añaden al final del menú al que pertenezcan.

El problema se presenta cuando aparece un tercer documento XML. O, mejor dicho, cuando aparece un tercer documento que deba mezclarse… en el MergeLocal del primer documento. Por ejemplo, el que indica dónde debe incluirse en el menú de ayuda una acción correspondiente a una biblioteca utilizada por una aplicación (que, obviamente, era lo que intentaba 😉 ).

El menú de ayuda viene definido, como era de esperar, en el documento de XMLGUI general de KDE: kdelibs/kdeui/xmlgui/ui_standards.rc. A este documento se le añade el documento específico de cada aplicación. Y a estos dos debe añadirse el documento de KTutorial, de forma que se añada una entrada en la interfaz final en el menú de ayuda, y que ésta lógicamente esté ubicada en el espacio habilitado para la mezcla, no al final del menú.

El problema está en que MergeLocal sólo sirve para mezclar el documento padre con el documento hijo inmediatamente inferior. Es decir, el documento general de KDE con el documento de la aplicación. En KXMLGUIClientPrivate::mergeXML(…), en el archivo kxmlguiclient.cpp puede verse cómo, una vez mezclado un documento padre con el hijo, el elemento se elimina.

Podría pensarse en mezclar el documento de la aplicación con el de la biblioteca, y luego todo ello con el general de KDE. Pero tampoco serviría. Dejando a un lado que los métodos que permitirían hacer eso son protegidos (lo que quizás podría salvarse con un sucio apaño en el preprocesador definiendo la cadena “protected” como “public” e incluyendo los archivos de cabecera), el principal problema reside en el código del método KXmlGuiWindow::setupGUI(), el encargado de crear la interfaz gráfica a partir de los documentos de XMLGUI.

En éste se carga primero el documento general de KDE, y luego éste se mezcla con el específico de la aplicación. Y una vez hecho eso, ya se analizan los demás documentos a utilizar. Te pongas como te pongas, eso es algo contra lo que no puedes luchar 🙂

Y entonces, todo esto, ¿en qué acaba? La conclusión es que no se puede habilitar KTutorial en una aplicación únicamente llamando a KTutorial::setup(), como sería deseable, sino que es necesario además modificar el documento XMLGUI que utiliza, definiendo en el menú de ayuda el grupo ktutorial. De este modo, cuando se cargue el documento de KTutorial, los elementos definidos en éste se añadirán al grupo, que a su vez ocupará la posición indicada en el documento general de KDE para la mezcla en el menú de ayuda.

Sí, ciertamente es una investigación muy larga para un problema tan pequeño, pero bueno, sería mejor que funcionase sin tener que añadir nada en el documento de XMLGUI, ¿no? 🙂


Design a site like this with WordPress.com
Get started