Workspace 6.21.5
Public Slots | Signals | Public Member Functions | Static Public Member Functions | Protected Slots | Protected Member Functions | List of all members
QWidgetConnector Class Referenceabstract

Base class for objects handling the connection between data objects and QWidget instances. More...

#include <Workspace/Widgets/qwidgetconnector.h>

Inheritance diagram for QWidgetConnector:
[legend]

Public Slots

bool hasOutstandingDataUpdateRequests () const
 
void requestUpdateData ()
 
void requestUpdateWidget ()
 
void synchronizeWithData ()
 

Signals

void dataUpdated ()
 

Public Member Functions

void clearAllWidgetPropertyMonitors ()
 
WidgetPropertyMonitorcreateWidgetPropertyMonitor (const QString &propertyName)
 
NamePathgetNamePath ()
 
QUuid getUuid () const
 
QWidget & getWidget ()
 
bool setAdaptorFactory (const DataExecution::TypeAdaptorFactory *adaptorFactory)
 
virtual void setWidgetReadOnly (bool b)
 

Static Public Member Functions

static QStringList connectWidgetTree (QWidget &widget, DataExecution::Operation &forOperation)
 
static QStringList connectWidgetTree (QWidget &widget, DataExecution::Operation &forOperation, const std::function< bool(QString)> &isIgnoredGlobalName)
 
static QStringList connectWidgetTree (QWidget &widget, DataExecution::Workspace &relativeTo)
 
static QStringList connectWidgetTree (QWidget &widget, DataExecution::Workspace &relativeTo, const std::function< bool(QString)> &isIgnoredGlobalName)
 

Protected Slots

virtual void checkIfWidgetWantsUpdateTriggers ()
 
virtual void flushChanges (bool widgetWillRemainAlive=true)
 
void madeUncommittedChange ()
 

Protected Member Functions

 QWidgetConnector (QWidget &widget, const NamePath &namePath, bool directWidgetUpdates=false)
 
 ~QWidgetConnector () override
 
void clearUncommittedChanges ()
 
template<typename T >
void commitData (const T &value)
 
bool haveUncommittedChanges () const
 
void setWantUpdateTriggers (bool b)
 

Detailed Description

QWidgetConnector instances must be created in the GUI thread, just like any QWidget must be.

Constructor & Destructor Documentation

◆ QWidgetConnector()

QWidgetConnector ( QWidget &  widget,
const NamePath namePath,
bool  directWidgetUpdates = false 
)
protected
Parameters
widgetThe widget to connect to the workspace data.
namePathThe name path of the input or output whose data should be connected to the widget. If the input/output has hierarchical data associated with it (eg as an object group), the name path also specifies which data object within the hierarchy the connector is associated with. Note that namePath must be valid (ie returns true from its isValid() function). N.B. You should not assume the data type of the namePath to be the type used by this connector in the constructor. NamePaths for adapted types can be passed to this constructor that will be adapted to the correct DataObject type during calls to updateData() and updateWidget(). Eg. If your connector is for type int, don't assume WS_ASSERT_RUNTIME(namePath.getDataObject()->isType<int>()) is true during the constructor.
directWidgetUpdatesSome widget connectors have the ability to perform compute-intensive parts in the execution thread and lightweight parts in the widget's thread. By setting directWidgetUpdate to true, subclasses can indicate that they will manage the thread synchronization themselves and that they can have their updateWidget() functions called from the execution thread. Note that updateWidget() can be called from the execution thread or from the widget's thread in this arrangement, so the subclass should take care to handle both safely. The default for this parameter is false and the vast majority of subclasses will use this default value. One example where it might be true is an image rendering widget where the image is rendered off-screen to an image first in the execution thread, then the image is copied to the widget in the widget's thread.

The connector is made a child of widget, so if/when the widget is destroyed, the connector will be destroyed too. Qt's parent-child handling ensures that children are destroyed before their parents, so the connector will always be destroyed before the widget.

◆ ~QWidgetConnector()

~QWidgetConnector ( )
overrideprotecteddefault

Member Function Documentation

◆ checkIfWidgetWantsUpdateTriggers

void checkIfWidgetWantsUpdateTriggers ( )
protectedvirtualslot

◆ clearAllWidgetPropertyMonitors()

void clearAllWidgetPropertyMonitors ( )

◆ clearUncommittedChanges()

void clearUncommittedChanges ( )
protected

This function does not normally need to be called. It can be called if the subclass decides that it wants to discard any uncommitted changes it has notified the base class about. The more common case where it is called, however, is in an updateWidget() reimplementation immediately after the widget has been updated. The updating of the widget might trigger a signal which results in the madeUncommittedChange() being called, but since the widget was just updated, there is no uncommitted change, so calling clearUncommittedChanges() restores the correct state. Connectors that never call madeUncommittedChange() should not ever need to call clearUncommittedChanges().

See also
madeUncommittedChange(), haveUncommittedChanges(), flushChanges()

◆ commitData()

void commitData ( const T &  value)
inlineprotected

This function is specifically designed to be called in situations where the underlying data needs to be updated with a value, but the connector might not live long enough to apply the change. This situation often arises for connectors that do delayed data commits, such as those associated with text entry widgets. In such cases, the connector might need to apply any uncommitted changes before the widget is destroyed, but the execution threads might not allow a change to be committed immediately. If the data type is assignable, this function can be called with the value to be committed to the data and the connector can then be destroyed. The change will be applied to the data at the earliest opportunity and this can be after the connector is gone, since no references to it or its widget are used to implement the delayed commit (a copy is taken of the value parameter and stored internally if necessary).

◆ connectWidgetTree() [1/4]

QStringList connectWidgetTree ( QWidget &  widget,
DataExecution::Operation forOperation 
)
static

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
widgetThis widget and all its children will be visited and for any that have the appropriate property information, an attempt will be made to connect them to the specified operation's inputs and outputs.
forOperationAll connector information will be treated as relative to this specific operation. Because it is an operation and not a workspace, the connectors can will typically refer to input or output names rather than global names.

This function should only be called if op is not a Workspace. It is typically used to connect a widget hierarchy which was loaded from a .ui file meant for showing a particular type of operation.

Returns
A list of error strings, or an empty list if there were no errors.

◆ connectWidgetTree() [2/4]

QStringList connectWidgetTree ( QWidget &  widget,
DataExecution::Operation forOperation,
const std::function< bool(QString)> &  isIgnoredGlobalName 
)
static

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
widgetThis widget and all its children will be visited and for any that have the appropriate property information, an attempt will be made to connect them to the specified operation's inputs and outputs.
forOperationAll connector information will be treated as relative to this specific operation. Because it is an operation and not a workspace, the connectors can will typically refer to input or output names rather than global names.
isIgnoredGlobalNameFunction that checks if a global name is ignored by the caller. When a global name is ignored, the connection between the widget and the workspace will not be made.

This function should only be called if op is not a Workspace. It is typically used to connect a widget hierarchy which was loaded from a .ui file meant for showing a particular type of operation.

Returns
A list of error strings, or an empty list if there were no errors.

◆ connectWidgetTree() [3/4]

QStringList connectWidgetTree ( QWidget &  widget,
DataExecution::Workspace relativeTo 
)
static
Parameters
widgetThis widget and all its children will be visited and for any that have the appropriate property information, an attempt will be made to connect them to the specified workspace data.
relativeToAll connector information stored in the widgets specify paths to operations relative to some common workspace. The relativeTo workspace will serve as this common workspace.
Returns
A list of error strings, or an empty list if there were no errors.

◆ connectWidgetTree() [4/4]

QStringList connectWidgetTree ( QWidget &  widget,
DataExecution::Workspace relativeTo,
const std::function< bool(QString)> &  isIgnoredGlobalName 
)
static

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
widgetThis widget and all its children will be visited and for any that have the appropriate property information, an attempt will be made to connect them to the specified workspace data.
relativeToAll connector information stored in the widgets specify paths to operations relative to some common workspace. The relativeTo workspace will serve as this common workspace.
isIgnoredGlobalNameFunction that checks if a global name is ignored by the caller. When a global name is ignored, the connection between the widget and the workspace will not be made.
Returns
A list of error strings, or an empty list if there were no errors.

◆ createWidgetPropertyMonitor()

WidgetPropertyMonitor & createWidgetPropertyMonitor ( const QString &  propertyName)
Parameters
propertyNameName of the widget property to monitor.
Returns
A WidgetPropertyMonitor object. Connect widgets to its WidgetPropertyMonitor::handlePropertyChange slot to serialise widget properties to the connected IOBase.

◆ dataUpdated

void dataUpdated ( )
signal

◆ flushChanges

void flushChanges ( bool  widgetWillRemainAlive = true)
protectedvirtualslot
Parameters
widgetWillRemainAliveIf widgetWillRemainAlive is true, then the subclass implementation is allowed to access the widget with which this connector is associated. If it is false, then the widget might be undergoing destruction or even be completely deleted, so the connector should not attempt to access the widget. This latter case can occur when the window holding the widget is closed and the widget is destroyed, but the connector has not yet been told to delete itself. This occurs when a focus out event is sent as part of the widget destruction and this gets processed before the signal that leads to the connector being deleted.

This function is called under certain circumstances where the connector needs to ensure that any unsaved changes are committed to the data attached to this connector. Text entry widgets are one example where a form of delayed change commit is often used to prevent a data update from being triggered every time the user presses a key. In such cases, the connector will only update the data when some other event occurs, such as when the user presses Enter or certain focus-related events are raised. Note that the widget losing focus needs to be handled specially (see details below).

This function will only ever be called when there are uncommitted changes, ie when haveUncommittedChanges() returns true. If the subclass never calls madeUncommittedChange(), then flushChanges() will never be called and the subclass would not need to override flushChanges(). Conversely, if the subclass does call madeUncommittedChange(), then it must override flushChanges() to handle the situation where widgetWillRemainAlive is false.

The cases where this function will be called include things like just before an input is serialized (if the widget is connected to an input) or just before the workspace in which the underlying data resides starts execution. In these two cases, safeToAccessWidget will be true. The function can also be called when the widget loses focus or when the keyboard focus moves from one window to another. For these focus-related scenarios, safeToAccessWidget will be false because the widget could be in a state of partial destruction.

Even if safeToAccessWidget is true, it is not safe to assume that the underlying data can be safely accessed directly. If subclasses override this function, the normal steps taken when safeToAccessWidget is true are to update any internal data within the connector and/or the widget itself, then call requestUpdateData() to ensure the data is updated in a safe manner.

When safeToAccessWidget is false, subclasses that override this function will generally call commitData() instead of requestUpdateData(). This is because commitData() makes a copy of the data to be committed and it does not rely on the widget being in existence, whereas requestUpdateData() generally does rely on the widget still being available.

A typical reimplementation will look something like the following (this example is from the connector between QString data and a QTextEdit widget):

void StringTextEditConnector::flushChanges(bool widgetWillRemainAlive)
{
if (widgetWillRemainAlive)
{
}
else
{
const QTextEdit* textEdit = qobject_cast<QTextEdit*>(&getWidget());
WS_ASSERT_RUNTIME(textEdit);
commitData(textEdit->toPlainText());
}
}
void requestUpdateData()
Definition: qwidgetconnector.cpp:374
virtual void flushChanges(bool widgetWillRemainAlive=true)
Definition: qwidgetconnector.cpp:246
QWidget & getWidget()
Definition: qwidgetconnector.cpp:392
void commitData(const T &value)
Definition: qwidgetconnector.h:279
#define WS_ASSERT_RUNTIME(cond)
Definition: errorchecks.h:146

The default implementation calls requestUpdateData() if safeToAccessWidget is true and it does nothing if safeToAccessWidget is false.

See also
madeUncommittedChange(), haveUncommittedChanges(), clearUncommittedChanges()

◆ getNamePath()

NamePath & getNamePath ( )

◆ getUuid()

QUuid getUuid ( ) const

◆ getWidget()

QWidget & getWidget ( )

◆ hasOutstandingDataUpdateRequests

bool hasOutstandingDataUpdateRequests ( ) const
slot

◆ haveUncommittedChanges()

bool haveUncommittedChanges ( ) const
protected
Returns
True if there are uncommitted changes still to be applied.
See also
madeUncommittedChange(), clearUncommittedChanges(), flushChanges()

◆ madeUncommittedChange

void madeUncommittedChange ( )
protectedslot

Subclasses must call this function if they implement delayed commits. It should be called whenever a change is made in the widget which should ultimately be reflected in the underlying data, but for which the data does not need to be updated immediately. Text entry widgets are a classic example of this. They would call this function whenever any change is made to the text, but they might only request that the underlying data be updated when the user presses Enter or when the base class determines that data should be committed (eg the widget loses focus, serialization is about to occur on the data, etc.).

See also
haveUncommittedChanges(), clearUncommittedChanges(), flushChanges()

◆ requestUpdateData

void requestUpdateData ( )
slot

Schedules an update request for the widget. The next time the execution thread responsible for the connector's associated input/output is paused, the connector will call updateWidget() in the main GUI thread. Clients may call this function as and when necessary. Multiple calls will be compressed into a single call so that only one update is triggered for a given execution thread pause.

See also
requestUpdateData()

◆ requestUpdateWidget

void requestUpdateWidget ( )
slot

Schedules an update request for the widget. The next time the execution thread responsible for the connector's associated input/output is paused, the connector will call updateWidget() in the main GUI thread. Clients may call this function as and when necessary. Multiple calls will be compressed into a single call so that only one update is triggered for a given execution thread pause.

See also
requestUpdateData()

◆ setAdaptorFactory()

bool setAdaptorFactory ( const DataExecution::TypeAdaptorFactory adaptorFactory)
Parameters
adaptorFactoryAn AdaptorFactory that could adapt the underlying data object to be used in the widget. Or nullptr to not doing any adaption.
Returns
True if the widget have to be read only because no backward adaptor available.

◆ setWantUpdateTriggers()

void setWantUpdateTriggers ( bool  b)
protected

◆ setWidgetReadOnly()

void setWidgetReadOnly ( bool  b)
virtual
Parameters
bToggles widget to read only model.

The Workspace editor calls this function to toggle read only behavior where modification of underlying data has no meaningful effect. Consider the scenario where a widget is attached to an Input which is connected to some other Output in a workflow. Any changes through this widget are lost when the Input is brought up to date because the data type is overwritten by data from the connected output.

The default implementation for this virtual method simply disables the entire widget. This method should be overridden for widgets that require some level of interaction in read only mode.

Reimplemented in ConversionSpinBoxConnector, ChartWidgetConnector, ImageWidgetConnector, PlotWidgetConnector, DataCollectionWidgetConnector, DataSeriesWidgetConnector, ImageTileViewConnector, ScientificDoubleSpinBoxConnector, SqlDatabaseWidgetConnector, SqlDataTableWidgetConnector, SqlResultSetTableWidgetConnector, Matrix3x3WidgetConnector, MeshModelInterfaceComboBoxConnector, MeshModelInterfaceInspectorWidgetConnector, MeshModelInterfaceSummaryWidgetConnector, MeshModelInterfaceWidgetConnector, MeshModelWidgetConnector, MeshReadersComboBoxConnector, QVectorVector3dWidgetConnector, TransformByComponentsConnector, TransformMatrixConnector, Vector3dGroupDegreesWidgetConnector, Vector3dGroupWidgetConnector, SchedulerServerSelectionWidgetConnector, WSGLGridWidgetConnector, WSGLWidgetConnector, SceneInteractionWidgetConnector, ScreenNumberWidgetConnector, ScreenSerialNumberWidgetConnector, MergeProgressWidgetConnector, WorkflowDifferencesWidgetConnector, WorkflowValidatorWidgetConnector, DataTableWidgetConnector, DateTimeWidgetConnector, DoubleLineEditConnector, DoubleSpinBoxConnector, FileNameWidgetConnector, FloatSpinBoxConnector, IntegerLineEditConnector, IntegerSpinBoxConnector, JsonJSEditConnector, MultipleFileNamesWidgetConnector, ObjectArrayWidgetConnector, ObjectDictionaryTableViewWidgetConnector, ObjectDictionaryWidgetConnector, ObjectGroupWidgetConnector, PasswordWidgetConnector, QByteArrayLabelConnector, QPointFLineEditConnector, QVariantWidgetConnector, RangedSpinBoxConnector, ShowWidgetButtonConnector, StringComboBoxConnector, StringJSEditConnector, StringLineEditConnector, StringListLineEditConnector, StringListWidgetConnector, StringSelectionWidgetConnector, StringTextEditConnector, TimeStampFormatWidgetConnector, VariantLabelConnector, and VariantLineEditConnector.

◆ synchronizeWithData

void synchronizeWithData ( )
slot

This function is somewhat similar to requestUpdateWidget() in that it updates the widget to reflect the value of the underlying data it is attached to. The difference here is that synchronizeWithData() will try to bring the underlying input up to date if there is one to update and if it is safe to do so as part of the call. If there is no running updater but the input cannot be brought up to date, this function does nothing and simply lets the usual update mechanisms take their course to eventually update the widget when it can be done.

Note
Client code would not normally call this function directly. It is primarily used when the connector is first created to make its associated widget get in sync with the underlying data as soon as possible.