Design Mode Manual

About

This manual provides an overview of the CDP Studio Design mode and discuss important guidelines regarding GUI development.

The CDP Studio Design mode allows you to visually edit your user interface using drag and drop, and configure graphical elements by adjusting properties from a table. The output will get saved as a human readable xml file with .ui extension.

The graphical elements (widgets) that can be added to the form include properties for styling, control features and communication with CDP. The communication part is explained in more detail further down the page.

To get help about a certain property, press F1 on the keyboard. It will show relevant information about the property. Scrolling all the way to the top of the page will show a brief explanation about the widget in addition to a link that can be pressed for more information.

The Simple Meter Tutorial is a good starting point for understanding the different steps in creating a GUI application using CDP Studio.

Note: Before connecting the GUI to CDP, as described in the following sections, the user should have a good understanding of CDPComponents and communication objects like CDPSignal, CDPParameter, CDPProperty and Message. This is required to understand what features/properties that must be configured for the different communication. For instance, making a CDPComponent change state is usually done using a message handler in the component and a button in GUI for sending the message. However, if you rather wanted to switch states using a combo box in GUI it would have to be done differently. The current combo box doesn't send messages, but can toggle a CDPSignal, CDPProperty or CDPParameter to the index of its selected item. The component will in this case have to check the value periodically and change state if the value changes.

Note that the CDPComponents do not know anything about GUI. Instead, GUI connects to the CDPComponents and reads/updates their signal/property values or sends/receives CDPMessages.

The GUI Application

To add a GUI application to your system, see Adding Applications manual.

This adds a CDP application with empty user interface and extra CDP2Qt component. The CDP2Qt component provides communication functionality between CDP communication objects and widgets. The communication object can be a CDPSignal, CDPParameter or any CDPProperty in a CDP component. The communication is bi-directional, meaning that values are directed to and from UI elements (needle position, number indicator, slider position etc.).

In addition to communication, CDP2Qt loads ui files dynamically and enables global features for widgets that inherit ICDPWidgetBase. This is required to be able to switch themes, fonts and styles in runtime.

Visual Introduction

The following sections provides a brief introduction to the CDP Studio Design mode. The mode is activated only if GUI application is selected in the system tree.

The Designer Panels

  • The form editor provides a canvas where you will create and edit your user interface. Widgets are dragged in from the widget box and their properties are edited in the property editor. The form is stored in a xml formatted file with .ui extension.
  • The widget box shows widgets that can be used in your user interface. Note the filter and grouping that can be used to easily find the widgets you are looking for.
  • The object inspector shows the object hierarchy, and lets you edit the names of the objects, as well as supporting right-click to get the context-menu for the object.
  • The property editor lets you edit properties of a widget, such as font, color etc. Select a property and hit the F1 key to know more about a property.

Layouts

Layouts are used for positioning widgets in relation to each other. A “vertical layout” arranges widgets vertically, while a “horizontal layout” arranges widgets horizontally. A “form layout” lays out its children in a two column form, while a “grid layout” lays out its items in any number of rows and columns.

Sometimes it can be awkward to put a widget on the right position in a layout. A useful trick is to use the property editor to add some margin where the new widget is to be put. The margin can be removed afterwards.

Read the Using Layouts in Qt Designer for more information.

Widget Configuration

The widget configuration is usually done using the property editor/panel. However, some dynamic functionality, like the items of a combo box, is often edited using a separate dialog. Such dialogs are often launched from the widget context menu. For instance, to edit the items of a combo box, right-click on the widget in the form and select Edit Items... from the context menu.

It should be noted that some styling properties, like fill color of a meter, can be changed both using SVG files and by properties. The properties will override the SVG styling if the property is listed after the property that sets the SVG file. Also, such styling properties are likely to get overridden by a theme change unless the widget has a property for not updating all styling features by SVG.

Connecting Widgets to CDP

Selecting suitable widgets and configuring the correct communication properties require that the user has a good understanding of CDPComponents and communication objects like CDPSignal, CDPParameter, CDPProperty and Message. The widgets are connected to the various CDP objects by adding routing to communication properties in the widgets. All properties related to communication are prefixed with cdp.

The above image shows how to connect a bar widget to the CDPSignal named CPULoad in an application named TestGUI. First, select the widget that you want to connect as shown in . This makes the property panel show all the properties of the bar. Use the filter at the top of the panel to only show properties related to CDP communication. This is shown in . Finally, we have to add routing to the correct routing property as shown in . The different widgets usually have several properties for setting routing to different features. In the bar widget it is possible to control features like visibility, maximum values, widget style and current value. The current/main display value of the widgets are usually named cdpRouting without any other explanation, while optional properties like widget style include the feature as part of the name.

The routing properties use a special editor that auto completes routings as it is typed . Start typing the name of the application and possible choices will get listed below the editor. It is also possible to filter the list by clicking on the filter button in fron of the line edit. Select the object type you want to locate and the list will get filtered.

Messaging is one of the most common ways to communicate with CDPComponents. Such communication is usually done by buttons and requires that the CDPComponent has a message handler for the message we want to send. For instance, to suspend a component, we could use a CDPBaseButtonMsg. Configure its cdpRouting property with the component routing and add CM_SUSPEND in the cdpTextCommand property.

Most widgets are connected to CDP using routings, but there are also special widgets like the CDPEventList. It is used to receive and display CDPAlarms (received by the CDPEventSubscriber component that is default in in all application).

Note: More communication examples are usually located in the detailed description of the different widgets.

Connection Mode

The Design mode has a special connection mode that makes it possible to connect widgets within the form. For instance, we can connect a slider to a bar to make it control the bar fill. This is useful while prototyping and wanting to see how widgets behave without connecting them to CDP, but we do not recommend adding to much logic to the form. It complicates the design and can make it hard to read and maintain. Also, making copies of connected widgets will not copy the connections and is thus error prone.

Connections are made by first entering connection mode by pressing F4 on the keyboard. We can now click and drag connections between widgets. A click, drag and release will open a dialog for selecting which Qt signal should be connected to which Qt slot. A Qt signal is not the same as a CDPSignal, but an internal value transfer from the widget sender to a function in the widget receiver. In the above image we have connected sliderMoved to setValue. To test that the connection works and that the slider actually controls the bar we can enter preview mode as explained in the following section.

Note: The CDPComWidget is a special widget that can be used to connect widgets to more CDP communication objects than the standard routing properties can provide.

Preview Mode

The preview mode is useful when doing prototyping and designing. Press Alt+Shift+R, and the form will show in a separate window similar to a running application. Communication with CDP will not be enabled, but global features like theme changing, fonts and signal/slot connections will work similar to running the actual application.

NumPad and KeyPad

There are several widgets that support both num pad and key pads, like buttons, CDPBaseLineEdit and CDPBaseSpinBox. Filtering the properties with the string, "pad", should bring up the required properties. On buttons and line edits, use the padType property to select wanted pad type.

Dialogs

The CDPBaseButtonPopDlg widget makes it possible to open separate ui files when the button is pushed. Enter the name of the ui file in the property named, uiFileName. This will make the ui file load dynamically when the button is clicked. The ui file must be placed within the Application directory (the directory that also contains mainwidget.ui) or added to the application as a resource. The latter is required to ensure that studio can locate the ui independent of working directory.

Create UI Files

Create ui files using File > New File or Project... and select Qt > Qt Designer Form. In the next dialog, Choose a Form Template, select CDPBaseDialog under Custom Widgets. Click Next and add name and location in the following dialog. The defaults should be fine in the remaining steps.

The following can be added as a dialog style sheet if you do not want to show the content background while editing the dialog form:

QWidget > QWidget { background: transparent; }

Note: The mainwidget.ui file will get selected every time you enter Design mode even though work was being done on a different form. Switch between open forms by clicking on the form name in the top left corner of the page.

Create a Resource File and Add a Dialog

Go into Code mode and right-click the GUI application where we want to add the resource file. Select Add New...

Create a resource file using File > New File or Project... and select Qt > Qt Resource File. Give it a proper name and and select the defaults in the following dialogs. This creates and adds a resource file to the application.

Add an existing ui file to the resource file. First, locate the resource file within the application tree, right-click and select Open in Editor. In the editor, click Add > Add Prefix and edit the prefix to /. Click add one more time, but this time we'll select Add Files. Select the ui file. Afterwards it could be useful to select it and add an Alias to avoid long names in the uiFileName property.

QML

QML (Qt Modeling Language) is a declarative language for designing user interfaces. The QML elements can include JavaScript code and can be extended in C++ using the Qt framework.

In Design mode, the widget named QQuickWidget can be used to load custom QML files. Drag it into the form and edit the property named source with the name of the file to load. If the widgets is not there or if there is a problem with the plugin, have a look at section How to Add Custom Widgets to Design Mode for instructions about how to create a placeholder/promoted widget.

The developer can extend the QML with custom elements by writing code in C++ (or by making a collection of importable QML files). A common way to handle this is to create custom QML plugins. Currently, the process of building and deploying such plugins is manual work that must be carried out by the developer. Alternatively, the developer can register the custom QML elements directly in the main function of the GUI application. This approach is described in the following section that discuss how to add communication with CDP.

How to Make QML Elements Communicate With CDP

To make CDP communication available in QML we need to provide QML elements that can connect and send/receive data to and from CDP objects. The CDPSignalObject class located within the CDP2Qt library is one example of such object. The CDP2Qt library is already linked into the application. Hence, one way to make CDPSignalObject available in QML is to register it in the main function, located in CDPMain.cpp, as shown in the following code.

...
#include <qqml.h>
#include <CDP2Qt/CDPSignalObject.h>

int main (int argc, char* argv[])
{
  int ret = 0;
  QApplication app(argc, argv);
  qmlRegisterType<CDPSignalObject>("CDP2Qt", 1, 0, "CDPSignalObject");
  ...

The CDPSignalObject can now be imported and used in QML as shown in the following example.

import QtQuick 2.0
import CDP2Qt 1.0

Rectangle {
    id: page

    CDPSignalObject {
        id: mySig
        routing: "AppName.SignalName.Value"
    }
    Text {
        id: cdpText
        text: mySig.value
        anchors.horizontalCenter: page.horizontalCenter
        font.pointSize: 24; font.bold: true
    }
}

How to Manually Add a Custom QML Plugin to an Application

Custom QML plugins can be added to an application by placing them within the Application directory of the project. All files that are placed within these directories will get deployed to the target. For the plugins to load successfully, the plugins must have been built with a toolkit that are compatible with the target.

The plugin requires a directory with identical name to what was registered within the plugin class. This is the name that will also be used within the QML file when importing the plugin elements. In addition to the plugin, the directory must contain a file for mapping the plugin to the class name. If the plugin is named, chartsplugin and have elements registered to a module named Charts, the qmldir would look something like the following.

module Charts
plugin chartsplugin

The elements of the Charts module are now available in the QML file by importing it as shown in the following example.

import QtQuick 2.0
import Charts 1.0

Item {
    width: 300; height: 200
    PieChart {
    ...
    }
}

Themes

Global features like themes are configured and controlled by CDPBaseMainWindow. Select it in the Object Inspector or by clicking it in the form and write theme in the property editor filer. This will show properties displaying the names of the night and day themes, a check box for toggling which theme should be active and properties for remote control and theme location.

The light and dark themes are also selectable in a dialog that lists available themes along with preview images. It can be launched by right-clicking CDPBaseMainWindow and pressing "Select Theme..." in the context menu.

The various themes can be quite different and the user might want to place contents differently depending on the selected theme. Hence, it is important that a theme is selected at the beginning of a project and not the other way around. Also, if wanting to be able to switch between light and dark colors (day and night mode) in run time, select two themes that have similar widget shapes. This will provide the best result.

The themes named, cdp_light and cdp_dark, are a bit different than the rest, as they are designed to have main titles at the bottom of the containers. Combining one of these with a theme that is designed to have titles at the top will probably not look that good.

Themes and other global features can be toggled by buttons in GUI using Qt signal and Qt slot connections. For instance, drag in a CDPBaseToggleButton, press F4 and drag a connection from the button to the main window. Select toggled(bool) in the left list and setDayTheme(bool) or setNightTheme(bool) in the right, based on what is active at startup.

Example showing the light version of the flat CDP theme:

Example showing the dark version of the flat CDP theme:

Example showing the light version of the first CDP theme:

Example showing the dark version of the first CDP theme:

Global Features

Global features like theme, font, style, time and sound are configured and controlled by the CDPBaseMainWindow. This is the root object in the main ui file, located at the top of the object list in the Object Inspector. Select it by pressing it with the mouse and have a look in the Property Editor for available feature properties.

Some features, like theme, sound and time offset have properties for configuring routing, while others, like font and sound, require Qt signal and Qt slot connections as described in the section regarding themes.

Note: Global features that do not have properties for remote control can still be controlled externally as long as there are Qt slots supporting it. This can be done using the Com Widget. Drag it into the form and connect it to the main window using Qt signal and slot connections.

GUI Development Methods

Normal (Recommended)

The default method for developing GUI applications is to graphically edit .ui files in Design mode. Thus, after compiling the initial application, the user might actually do updates to the GUI even without recompiling the app.

Custom Plugins (Qt Development)

The application, as described in the above section, can be extended with additional widgets using plugins. The plugins are added to both the application and studio. Note that the plugins added to studio must match the qt version and compiler used when building studio. Plugins added to the application must be built using the same kit as used when building the application.

Note: Users are on their own doing such custom development and studio will not help in the deployment process.

Custom Application (Qt Development)

Some projects might require the developers to build entire applications in C++. The reason could be embedded hardware, little disk space or similar. Again, this requires qt and c++ experience and is out of scope for this manual.

How to Add Custom Widgets to Design Mode

Adding custom widgets to Design mode requires that the widgets and plugins are built with the same toolkit as CDP Studio. This toolkit is not available for download on any platform. Hence, the user will have to create a toolkit with correct versions, which is a hard task, or create a placeholder/promoted widget to imitate the custom widget.

Creating a promoted widget is simple. Select a widget from the panel that is also a base for the widget you want to imitate. Drag it to the form, right-click and select, Promote to .... In the dialog that pops up, fill in base class name, the name of the class you want to imitate, the header file and whether or not the header is global. Click Add to add it to the list of promoted widgets for the current base class. If we again right-click on the base widget in the form, there is now a choice to promote the widget in the Promote to sub context menu.

To configure properties in the promoted widget we need to add dynamic properties. This is done using the button with a plus sign, located to the right of the filter at the top of the property panel. Click it and select Other... from the context menu to open a dialog for setting property name and type. The name and type must be identical to that of the custom widget to trigger the correct functions.

The following illustrates how to add a promoted widget for QQuickWidget (if it is not present in Design mode). Right-click on QWidget in the form and select Promote to .... Select QWidget as base class and write QQuickWidget as promoted class name. The header file should be set to QtQuickWidgets/QQuickWidget and global include checkbox must be ticked. Click Add and close the dialog. Now, any QWidget in the form can be promoted to QQuickWidget.

Adding a promoted QQuickWidget to the form won't do anything unless it's also configured to load a QML file. Add the source property by clicking on the button with the plus sign in the property panel and make a new dynamic property of type Url and name source.

How to Add Custom Graphics to Your GUI Application

When wanting a different look than the default styling can provide, follow these instructions for adding custom graphics. Note that to support multiple themes as supported by the CDP Widgets, the user has to create a version of the image for each theme that is to be used in the application.

Note: Information about themes and styling for a certain widget is found by selecting the widget in the Design mode form and pressing F1.

Step 1: Add a Resource File for Custom Graphics

  • Enter CDP Studio Code mode, right click on the application directory and select "Add New...".
  • In the dialog that pops up, select Qt and "Qt Resource File" before pressing "Choose...".
  • Give the file a name and click "Next".
  • Make sure that the file gets added to your project pro and click "Finish".

Step 2: Add a Custom Image to Your Application

  • Enter CDP Studio Code mode and locate the "Resources" directory of your GUI application in the Project tree.
  • Right click the directory and select "Show in explorer".
  • Copy your images to this location. Remember to add the graphics in "themes/flat_light" and "themes/flat_dark" if you wish to have images that changes look based on theme. Replace flat_light and flat_dark with the name of the themes you are working on.
  • Go back to Code mode and right click on your resource file. Select "Add Existing Files" to add your images.

Step 3: Using a Custom Image on a GUI Widget

  • Enter Design mode as usual and click on an element in the form.
  • Ensure that styling is set to svg and edit the svgFile property.
  • When the image has been added to the resource file as described in the previous sections, the image path has to start with ":/", followed by the path to your image.
  • Note: properties like svgBorderPixmap, scaledContents and lockAspectRatio will have great impact on how your image will look and scale. Setting a minimum height on your widget is also a good tip for controlling element size.

  • Note: that you might have to adjust form size for the new image to start showing in the form.

Note: Using resource files within CDP Studio Design mode might result in some image files not showing correctly when loading an existing form. This is because resources are not always available when a form is loaded. To avoid problems, use the themeRootDir property located within CDPBaseMainWindow and make sure that it is configured with the root path of the project resources. Press F1 on the property for further details.

The CDP Studio Help mode contains more details regarding CDP widgets and how to create custom themes in CDP Widgets and sub page Themes (SVG).

Widgets

Qt Widgets

A graphical object in Qt is called a widget. Widgets have signals, slots and properties.

A Qt signal is a special function that the widget calls when something happens. The only task of the signal is to call the connected slot(s). A signal is said to be emitted when it is called.

A Qt slot is a function that can be called to make something happen. A slot is just a function marked as a slot.

The Qt signals and slots can be connected so that when a certain signal is emitted, the connected slot slot is invoked. To allow connecting a signal to a slot, the signal and the slot must have identical parameters (the number and type of the parameters must be equal).

Example

The QLabel is a text field that visualizes a value. Think of it as a 'collector' object. It has few signals, but many slots. Some of the 'Slots' of the Widget 'QLabel' are:

Qlabel Slots:Description / Explanation
setEnabled(bool)Enables the QLabel if the boolean value is true, disables it otherwise
setDisabled(bool)Disables the QLabel if the boolean value is true, enables it otherwise
setVisible(bool)Shows the QLabel if the boolean value is true, hides it otherwise
setHidden(bool)Hides the QLabel if the boolean value is true, shows it otherwise
setText(QString)Sets the QLabel text to the contents of the string
setNum(int)Sets the text of the QLabel to a decimal number
setNum(double)Sets the text of the QLabel to a floating point number

Select a property for a widget and hitting the F1 key, will provide help for that widget. You can use that help to view information about the signals and slots available in that widget, and in widgets that it inherits.

CDP Widgets

The widgets included in CDP Studio Design mode are highly optimized and scalable. They are all based on SVG and can change appearance by loading different SVG files (formatted as described in the chapter about themes). The widgets are configured both by properties and by named elements in the SVG. Note that some properties can only be changed in the SVG and vice versa.

The various widgets are connected to CDP by editing the properties prefixed with cdp (e.g. cdpRouting and cdpProperty). Check out the CDP Widgets documentation by pressing F1 on any widget in the Design mode.

Comparison of CDP and Qt

Similar Definitions

Both CDP and Qt define a component based framework that makes programming fast and efficient. They also share some of the same definitions, like signals and connections. The following sections will briefly describe a few important differences. Read the CDP and Qt documentation for more details.

CDP Signals vs Qt Signals

The Qt signal is a special kind of function that can be emitted by an event such as the push of a button. By connecting the Qt signal to a function defined as a slot, that function will be run when the signal is emitted. See the Qt documentation at trolltech.org for a more detailed description.

In CDP, a signal is more like a variable and also a means of communication, but here the signal might as well be connected to a component in a different application, running on a different physical machine. The CDP signals are handled and updated by the CDP core components, and though they are objects, they can be used within the application as if they were ordinary variables. There are no slots, as signals are defined as output and inputs, and are routed to each other by name (e.g. “SomeApp.WaveGenerator.Sinus”).

The routing is configured in XML.

CDP Connector and Qt Connections

CDP Connectors are used to send messages to other CDP Components. Unlike the connection between Qt Signals and Qt Slots, these components do not have to reside on the same physical machine. The address of the target (remote) CDP Component is specified in XML.

Notes Regarding GUI Applications

Where to Add Functionality

In a real time system, the user should separate GUI and logic as much as possible. Hence, we recommend avoiding qt signals/slots and rather use cdp communication (properties prefixed with cdp) to control widgets.

Creating Custom Widgets

The cdp base widgets can be changed both by editing properties and by creating new svg files for a totally different look. Hence, it is usually not necessary to create custom widgets.

The steps in creating a custom widgets are described in the qt documentation and will not be covered in this manual. However, the following sections provides a brief introduction regarding.

The most common way to integrate custom or third party widgets into a GUI application is to add them to a designer plugin. To communicate with cdp, the user can either inherit and implement one of the interface classes of CDPInterface in their widget or create the widget as usual and use qt signals/slots to connect to cdp in the form. Note that if wanting the widget to support themes and other global features similar to that of the CDP Widgets, the widget must inherit and implement one or more of the interfaces located in the CDP2QtFactory library.

For the custom plugin to show in studio it has to be built against the same qt version and with the same compiler as the studio version you are using. Further, the release version of your plugin has to be placed in the correct studio plugin directory. When the plugin widgets show in the widget box of the Design mode, they can be dragged and dropped to the form and configured similar to other cdp widgets.

Note that when it is time to deploy and test the application the user must ensure that the plugin is also deployed along with the application. The plugin must be placed in a directory named plugins next to the application binary. It is critical that the plugin is built with the same kit as the application (it probably includes a different qt and compiler than studio). Also, it must be built with the same relase/debug configuration as the application binary.

Note: Users who get confused by the above should not attempt to create custom widgets.

Manually Running Applications

Running the application in studio automagically sets paths that are necessary for the application to locate library dependencies. Deployed applications should include all dependencies that are required in addition to system libraries. Hence, they can be started from the terminal like any application.