qumbia-tango-controls 1.x
Library on top of cumbia-qtcontrols and cumbia-tango
|
In this tutorial we will learn how to adapt a Qt widget to display data from an engine like Tango or Epics. In other words, we will write a cumbia-qtcontrols widget. The tutorial is inspired by QuLabel from the cumbia-qtcontrols library. See qulabel.h and qulabel.cpp for the complete widget.
Let the widget inherit from the Qt widget suitable to display the data in the form you require. It must implement the CuDataListener interface in order to receive updates and CuContextI so that the clients can get a reference to the CuContext used by the object.
In order to offer maximum flexibility, two constructors should be provided:
Implementing CuDataListener implies writing the onUpdate method:
The method will update the contents of the label.
A method returning a pointer to the CuContext in use must be written:
To make a class binary compatible across several versions in the future, we choose to store the private attributes of the class into a QuLabelPrivate object.
Two methods are provided to tell QuLabel the name of the connection end point. Methods names and usage will be familiar to QTango users:
The QuLabel can be designed to provide an option to show a dialog window with statistics on the readings, a plot of the trend of the variable (if scalar) and other piecese of information about the health of the link. To enable this feature, a special Qt signal must be defined and a contextMenuEvent implementation must be given, from where the signal is emitted. Add this to the header file:
Add the class destructor and the header file is now complete:
The QuLabel interface has been designed; focus now on its implementation.
The following include files are needed to write the code that will follow.
As discussed above, we decide to place the class attributes into a private class, applying the bridge design pattern to save future issues with binary compatibility across updates.
QLabel's constructor is invoked with the parent widget. The other two parameters are forwarded to the CuContext to delegate the connection setup depending on the chosen engine.
The setSource function will rely on the CuContext method to replace the existing source. Don't forget to call setSource on the CuControlsReader returned by the CuContext replace_reader call:
The source method gets a pointer to the reader from the CuContext and returns its source
If no readers have been set up with setSource, then NULL is returned by CuContext::getReader and an empty string is in turn returned by source.
Reimplement QWidget's virtual method contextMenuEvent and use the CuContextMenu menu as a means to request statistics, connecting its linkStatsTriggered signal to QuLabel's linkStatsRequest signal:
The last necessary piece of code receives the read data in input, extracts necessary information about errors, a message describing the result of the operation, the value and some other relevant fields. This is a simplified version of the QuLabel::onUpdate version, for educational purposes. A label displays data as text, so we declare a QString named txt for the purpose.
The read_ok class attribute is updated early in the function, and the widget is disabled if an error occurred, to strike that the value is not available.
Link statistics are then updated and, in case of error, the addError method is invoked to record the error within the CuContext link stats. In case of error, the string *"####"* is set on the label.
The message is set as QWidget tooltip and the value is extracted by the CuVariant paired with the *"value"* key in the CuData bundle.
The written code is enough to make a Qt QLabel read from an engine like Tango and Epics.
Let's now see how a client uses the new label. If you create a new cumbia project with the qumbiaprojectwizard application (see Setting up a graphical application with cumbia and tango), you will have the necessary variables automatically declared for you and ready to use.
If you choose tango as engine in the qumbiaprojectwizard, your main class declaration will contain something like this in the private section:
The cu_t and cu_tango_r_fac class attributes are what you need to instantiate the new label. Supposing to instantiate the label in the MycumbiatangoWidget constructor: