4 El sistema de monitorización
4.4 Diseño del sistema de monitorización Como se mencionado anteriormente, la aplicación desarrollada sólo tiene un hilo de ejecución a
4.4.2 La representación gráfica de los MessageProcessor
Para la representación gráfica de los MessageProcessor en la ventana principal se usan varias clases derivadas de las clases que Qt provee para la visualización de elementos gráficos. Estas clases, incluidas en lo que la documentación de Qt denomina Graphics View Framework [10], cumplen tres funciones: • Gestión de la escena: la escena es el lienzo donde se dibujan y colocan los elementos gráficos y está implementada en la clase QgraphicsScene. Esta clase se encarga, entre otras cosas, de la propagación de los eventos de la interfaz gráfica a los ítems gráficos que estén contenidos en la escena. • Presentación de una vista de la escena: la clase QGraphicsView es la encargada de mostrar los contenidos de una escena. Permite que el contenido de una escena pueda ser alejado y acercado y añade a la escena las barras de desplazamiento.
• Creación de elementos gráficos: Qt ofrece la clase QGraphicsItem como base para la creación de elementos gráficos personalizados que pueden ser añadidos a una escena. Esta clase permite que cada ítem gráfico gestione los eventos que reciba de la interfaz gráfica, además de ofrecer otras funciones.
Basándose en QGraphicsItem Qt también tiene clases para formas típicas como rectángulos, círculos, textos, etc. Todas estas clases se pueden usar para la creación de formas personalizadas y pueden ser agrupadas entre sí creando nuevas formas constituidas por otras formas más simples.
El sistema de monitorización
A partir de las clases que Qt ofrece se han creado varias clases (QNodesEditor, QNEBlock,
QNEPort y QNEConnection) especializadas en la visualización de bloques y conexiones entre
bloques que representan a los MessageProcessor y sus relaciones.
4.4.2.1 La clase QNodesEditor
Con el objetivo de que el usuario pueda interactuar con la representación gráfica de los
MessageProcessor en la ventana principal se crea una instancia de la clase QGraphicsView que
presenta al usuario los elementos gráficos contenidos en una instancia de la clase QgraphicsScene. Esta clase, que es derivada de QObject, permite a otra clase, que debe ser también derivada de
QObject, capturar sus eventos. La clase QNodesEditor usa esta funcionalidad para capturar los
eventos dirigidos desde la interfaz gráfica a la escena y así permitir al usuario señalar, mover o eliminar los MessageProcessor y sus conexiones que se estén mostrando en la escena.
En el constructor de MainWindow se instancia la clase QNodesEditor y se llama al método que inicializa la captura de eventos dirigidos a la escena gráfica. También conecta las señales
updateListWidget y updateTableWidget de la instancia de QNodesEditor con las ranuras del mismo
nombre de MainWindow. Estas señales se usan respectivamente para actualizar los datos del
MessageProcessor que sea seleccionado por el usuario y para actualizar la tabla con la lista de MessageProcessor si se elimina uno de ellos mediante la representación gráfica. La clase QNodesEditor también implementa el guardado y recuperación de los MessageProcessor y conexiones que estén siendo mostrados en la representación gráfica. En estos métodos, la instancia de la clase QnodesEditor se limita a llamar a los métodos save y load de los respectivos ítems que se encuentran en la escena pasándoles como parámetro una instancia de la clase QDataStream. Esta instancia de la clase QDataStream se ha recibido de MainWindow, y es creada cuando se va a guardar o leer la configuración.
4.4.2.2 Las clases QNEBlock y QNEPort
Las clases QNEBlock y QNEPort implementan los elementos gráficos que representan a los
MessageProcessor en la interfaz gráfica. La primera clase implementa el MessageProcessor en sí
mismo y QNEPort implementa tanto los puntos desde los que se pueden crear conexiones entre
MessageProcessor como el texto que hay dentro de los MessageProcessor. Ambas clases siempre
trabajan en conjunto. Tal y como está hecha la aplicación no puede haber una instancia de
QNEBlock sin seis instancias de QNEPort, ni puede haber una instancia de QNEPort que no esté creada por una instancia de QNEBlock. Ambas clases son derivadas de QGraphicsItem que, como se ha mencionado anteriormente, es la clase base a partir de la cual se pueden desarrollar elementos gráficos que se pueden añadir a una escena. También ambas clases son derivadas de QObject, por lo que pueden usar el mecanismo señales y ranuras de Qt.
4.4.2.2.1 La clase QNEBlock
La clase QNEBlock puede ser instanciada por QNodesEditor, en el proceso de lectura de la configuración durante el arranque del sistema de monitorización, o por MainWindow, como resultado de una orden recibida por red.
En el primer caso, la instancia de QNodesEditor crea una instancia de QNEBlock y llama al método
load del nuevo objeto QNEBlock para que lea la configuración que se guardó en una ejecución
anterior de la aplicación. De esta forma todos los atributos del nuevo objeto quedan asignados con los valores correctos. En el segundo caso, llega por red una orden con el nombre del MessageProcessor, el modo de gestión de los datos de entrada y el modo de gestión de los datos de salida. MainWindow crea el MessageProcessor en la representación gráfica instanciando la clase QNEBlock con un constructor que establece a los valores por defecto los atributos del nuevo objeto que no han llegado en la orden proveniente del framework.
La clase QNEBlock implementa, además de otros, los métodos para asignar y leer los atributos propios de un MessageProcessor. Estos métodos implementan la asignación o lectura de: el nombre del MessageProcessor, del modo de gestión de los datos de entrada, del modo de gestión de los datos de salida, del estado del procesamiento del MessageProcessor y la asignación o lectura de su información adicional. Existe un método para leer el identificador del MessageProcessor, pero no para variarlo. Esta operación no es posible ya que el identificador de los MessageProcessor es unívoco y no puede variar. Los métodos de asignación de los atributos de la clase QNEBlock se encargan de que los cambios tengan su reflejo en la representación gráfica de los MessageProcessor. Por ejemplo, como se ha comentado en la descripción del protocolo de comunicaciones en el apartado 4.3.2, un
MessageProcessor puede tener parado o arrancado el estado del procesamiento. En base a esto, el
método de cambio de estado del procesamiento se encarga de que cuando un MessageProcessor está procesando, en el campo Run aparezca el tiempo que lleva transcurrido desde que se inició el procesamiento. Para implementar esto se usa la clase QTimer, un cronómetro de Qt, y se conecta la señal que esta emite periódicamente con una ranura que actualiza el tiempo mostrado en la representación gráfica. 4.4.2.2.2 La clase QNEPort La clase QNEPort solamente es instanciada en QNEBlock ya que, como se ha dicho anteriormente, un puerto sólo puede existir asociado a un MessageProcessor, no puede existir independientemente. Al igual que QNEBlock, la clase QNEPort ofrece, entre otros, métodos para variar la representación gráfica en base a los mensajes recibidos desde el framework. Estos son SetIsStarted y setIsSync. El método SetIsStarted asigna a un puerto el estado arrancado o parado. Cuando la aplicación recibe
El sistema de monitorización
un mensaje indicando que un MessageProcessor ha comenzado o parado de enviar o recibir datos se llama a este método del puerto apropiado. Este método se encarga de que el color del puerto cambie en la representación gráfica dependiendo del estado del puerto. Cuando un
MessageProcessor pasa a estar enviando su puerto de salida cambia de rojo a un parpadeo de verde y negro. Si para de enviar el puerto vuelve a rojo. De forma análoga el color del puerto de entrada cambia con el estado de la recepción del MessageProcessor. El parpadeo se implementa con una instancia de QTimer que se inicializa para que envíe una señal cada 250 milisegundos y se conecta esta señal periódica a una ranura de QNEPort que cambia el color del puerto. El método setIsSync es llamado por la instancia de QNEBlock a la que pertenece el puerto cuando la aplicación recibe una orden indicando que el modo de gestión de la entrada o la salida del MessageProcessor que representa el bloque ha cambiado. Este método se encarga de que la linea que representa la conexión entre dos MessageProcessor sea continua si los modos de gestión de los puertos de salida y entrada de la conexión son síncronos. En cualquier otro caso la linea mostrada es discontinua. Para realizar esto el método de QNEPort llama al método setIsAsync de
QNEConnection.
4.4.2.3 La clase QNEConnection
Esta clase implementa la representación gráfica de las conexiones entre MessageProcessor. La mayor parte del código implementa la gestión de las conexiones en sí y la representación gráfica de los enlaces entre bloques. Con respecto a las funcionalidades propias de la aplicación desarrollada sólo es destacable el método setIsAsync que es al que llaman las instancias de la clase QNEPort cuando se cambia el modo de gestión de los datos de entrada o salida de un MessageProcessor. Como se ha comentado en el apartado anterior, si ambos extremos de la conexión tienen una gestión de datos síncrona en la representación gráfica aparece una linea continua. En cualquier otro caso la linea es discontinua.