CDPBaseUiLoaderWidget Class
The UI Loader Widget class loads form (.ui) files dynamically and includes functionality to replace routings in real-time. More...
Header: | #include <CDPBaseWidgets/CDPBaseUiLoaderWidget.h> |
Inherits: | DialogLoader, RoutingContainerBase, and |
Public Types
typedef | ComRoutingsMap |
typedef | ICDPRoutingsMap |
Properties
|
|
Public Functions
CDPBaseUiLoaderWidget(QWidget *parent = 0) | |
QString | cdpUiLoadRouting() |
QString | replacementIndexRouting() |
void | setCdpUiLoadRouting(const QString &routing) |
void | setReplacementIndexRouting(const QString &routing) |
- 11 public functions inherited from DialogLoader
- 3 public functions inherited from RoutingContainerBase
Public Slots
virtual void | setCdpTargetRouting(const QString &routing) override |
void | setRoutingReplacement(const QString &replaceable) |
void | setRoutingReplacement(int dynamicRouting) |
void | setRoutingReplacement(double dynamicRouting) |
void | setUiFileName(const QString &filename) |
Protected Functions
void | mapRoutedObjectsThatContainString(const QString &replaceable, QObject *mainObject) |
void | replaceRoutingsInMappedObjects() |
Additional Inherited Members
- 3 static public members inherited from RoutingContainerBase
Detailed Description
The UI Loader Widget class loads form (.ui) files dynamically and includes functionality to replace routings in real-time.
Relative Routing
The widget supports being used as a routing target, similar to the Routing Container, to enable relative routings in the loaded form. This makes it easy to load multiple instances of a UI file for different targets without having to create separate UI files with different routings.
For instance, in a UI page showing information about multiple identical elements, like valves, we could create a UI file representing a valve and then load that for each valve using the UI Loader Widget. Using relative routing in the UI file requires that all valve routings are below one parent component in the control system. Let's imagine that the state of a valve has the routing "App.Valve1.State". The relative routing to use for showing the valve state would be ".State", and the target routing on the UI loader would be set to "App.Valve1". The second valve could then use the same UI file but with the target routing set to "App.Valve2".
The target routing can be configured via the cdpTargetRouting property or dynamically adjusted at runtime by connecting a Qt signal to the setCdpTargetRouting slot. Alternatively, developers can create a dynamic property, cdpTargetRoutingRouting, to allow the control system to set the target routing.
Relative routings are configured in the form as described in the Design Mode Manual. To make the routing completer show selectable nodes, the top-level widget in the UI file needs to support target routing. This is ensured by selecting a Routing Container or Container widget as the Form Template when creating the UI file. Adding an absolute routing in the cdpTargetRouting property of that widget will enable relative routings in the completer for all widgets in the form. The target routing will only affect Design mode and get ignored when loaded by a UI Loader Widget. See the Examples section for a short example.
Delayed Loading to Reduce Startup Time
The cdpUiLoadRouting feature allows the control system to manage the loading of UI files, optimizing startup time by loading elements only when needed. This is particularly useful for UIs with a large number of elements, where only a subset is required initially. By deferring the loading of non-essential elements until they are needed, the system can significantly reduce initial load times and improve overall performance.
However, on hardware with limited resources, dynamically loading elements can lead to unpredictable memory usage. This could potentially cause performance issues if memory demands exceed the system's capacity. Testing is advised to ensure the UI remains stable under expected conditions.
Routing Replacement
The routing replacement functionality allows one form file to show data from different objects with the click of a button. Routings can be changed either by providing replacement strings to the slot named setRoutingReplacement(QString) or by configuring replacement strings as dynamic properties in the following format:
stringReplacement1="$(REPLACE1)=Replacement1;$(REPLACE2)=OtherReplacement1" stringReplacement2="$(REPLACE1)=Replacement2;$(REPLACE2)=OtherReplacement2"
You can provide any number of replacements separated by ";". The replacements are added by first specifying the string that is to be replaced in the routings, followed by an equal sign, and then the string that we want to replace it with (e.g. $(COMPONENT)=Pump1).
The dynamic properties must be named stringReplacement followed by a number. In CDP Studio Design mode, this is done similarly to adding dynamic routings as described in the Design Mode Manual. After configuring the properties, providing the numbers to the slot named setRoutingReplacement(int) or setRoutingReplacement(double) will select the routing replacements. It is also possible to control this using a cdp object by adding routing to the property named cdpSelectReplacementRouting. To select an initial replacement without using routing, we can add a dynamic property of int
type named initReplacement. It is important that the property is added after the last stringReplacement property to ensure that the replacement is available when executing the replacement:
stringReplacement0="$(REPLACE)=ReplacementString1" stringReplacement1="$(REPLACE)=ReplacementString2" initReplacement=0
The replacement strings are executed on the routings from left to right. The order of the first replacements will be used in all consecutive replacements. Meaning, that if stringReplacement2 in the first example had $(REPLACE2) as its first replacement, it would still be executed after $(REPLACE1) as this is the order used in stringReplacement1. The same goes if the replacements are added using setRoutingReplacement(QString).
To avoid broken routings in the application, the template variables need to be wrapped in $(). The alternative is to ensure that the initial routings are valid (e.g. use MyComp1 instead of $(REPLACE1) in the above example and then use MyComp1=MyComp2 in stringReplacement2 etc.).
Note: Make sure that all objects that are connected using signals and slots have unique names across .ui files. Failing to do so might cause source objects to connect wrong targets. In addition, be aware that connections are error prone when maintaining projects as they are not visible in normal mode and not possible to copy.
Examples
The following examples discuss how to use the CDPBaseUiLoaderWidget.
How to Load a Form within a Form
A simple example of using the CDPBaseUiLoaderWidget is to create two form files, main.ui, and load.ui. The main form is typically based on CDPBaseMainWindow and the second one is usually based on a standard QWidget. Add a CDPBaseUiLoaderWidget to the main form and make it load the load.ui form by editing the property named, uiFileName.
How to Replace Routings in a Loaded Form
Start by adding a CDPBaseMeter to the load.ui form and add the following routing to the cdpRouting property; AppName.$(SIGNAL).Value
. In this string, the word $(SIGNAL)
is what we want to replace. Replace AppName
with the name of your application if it is named differently.
Next, we need to set up the replacement strings on the CDPBaseUiLoaderWidget in the main.ui form. Create a dynamic property by clicking on the plus icon next to the filter in the property panel and selecting String... Name the property stringReplacement1
and repeat the steps to create a second property named stringReplacement2
. Add the following value in the first property $(SIGNAL)=CPULoad
and add $(SIGNAL)=MemUsedRelative
to the second one.
Now, when the CDPBaseUiLoaderWidget receives the value 1 or 2, either by setRoutingReplacement slot or by adding routing in the property named cdpSelectReplacementRouting, the CDPBaseMeter will show CPULoad or MemUsedRelative respectively.
How to Use Relative Routings in a Loaded Form
Create a form, mysine.ui, to be loaded by the CDPBaseUiLoaderWidget, and make sure that the template form is based on a widget that supports target routing. Add a temporary routing in the top-level widget of the form. For instance, by configuring cdpTargetRouting with App.Sine. Any widget in the form can now use relative routing to connect objects within the Sine component (e.g. .Output.Value).
Configure a CDPBaseUiLoaderWidget to load the new ui file by setting uiFileName to mysine.ui. To replace the target routing in the form, configure the cdpTargetRouting property to the Sine you want to target, for instance, MyApp.Sine.
Member Type Documentation
typedef CDPBaseUiLoaderWidget::ComRoutingsMap
typedef CDPBaseUiLoaderWidget::ICDPRoutingsMap
Property Documentation
cdpFullTargetRouting : const QString
This property holds the context routing when the cdpTargetRouting contains relative routing.
cdpSelectReplacementRouting : QString
This property holds the routing to the cdp object that are to control the index of the replacement strings to use on the loaded ui.
See the class details for more information about template variables and replacement strings.
Access functions:
QString | replacementIndexRouting() |
void | setReplacementIndexRouting(const QString &routing) |
cdpTargetRouting : QString
This property holds the target routing that will be used as base for relative routing in child widget properties.
Access functions:
virtual void | setCdpTargetRouting(const QString &routing) override |
cdpUiLoadRouting : QString
This property holds the optional routing to control when the system loads UI elements, allowing them to be loaded only when needed and reducing initial load times for UIs with many elements. If not set, the UI will be fully loaded right away.
Access functions:
QString | cdpUiLoadRouting() |
void | setCdpUiLoadRouting(const QString &routing) |
uiFileName : QString
This property holds the path to the dialog we want to load when clicking the button.
Note: Make sure that all objects that are connected using signals and slots have unique names across .ui files. Failing to do so might cause source objects to connect wrong targets. In addition, be aware that connections are error prone when maintaining projects as they are not visible in normal mode and not possible to copy.
Access functions:
void | setUiFileName(const QString &filename) |
Member Function Documentation
CDPBaseUiLoaderWidget::CDPBaseUiLoaderWidget(QWidget *parent = 0)
Default constructs an instance of CDPBaseUiLoaderWidget.
[protected]
void CDPBaseUiLoaderWidget::mapRoutedObjectsThatContainString(const QString &replaceable, QObject *mainObject)
[protected]
void CDPBaseUiLoaderWidget::replaceRoutingsInMappedObjects()
[override virtual slot]
void CDPBaseUiLoaderWidget::setCdpTargetRouting(const QString &routing)
Reimplemented from RoutingContainerBase::setCdpTargetRouting().
Sets the target routing that will be used as base for relative routing in child widget properties.
This method, exposed as a Qt slot, allows the user to configure the target routing for the container widget and propagate it to all of its child widgets. By connecting a signal to this slot, the routing can be dynamically adjusted at runtime, ensuring that all child widgets follow the specified routing pattern.
Note: Setter function for property cdpTargetRouting.
[slot]
void CDPBaseUiLoaderWidget::setRoutingReplacement(const QString &replaceable)
[slot]
void CDPBaseUiLoaderWidget::setRoutingReplacement(int dynamicRouting)
[slot]
void CDPBaseUiLoaderWidget::setRoutingReplacement(double dynamicRouting)
Get started with CDP Studio today
Let us help you take your great ideas and turn them into the products your customer will love.