camitk.Property

class camitk.Property

This class describes a property that can be used in components and actions or any class that needs to be passed to ObjectController. A property has a type, a description (to be displayed for example as a tooltip, can be rich-text, see https://doc.qt.io/qt-5/richtext-html- subset.html for supported html tags), a value, a unit of measurement (SI unit if possible), and some specific attributes (that depends on the type, e.g. minimal and maximal values, single steps, number of decimals, regular expression…). An enum type can also be used for properties.

Properties can be grouped in subgroups, see Property::setGroupName().

Basically this is a way to overcome the Qt Meta Object properties limitations. A camitk::Property enriches a Qt Meta Object property (a very simplified Decorator Design Pattern).

Using camitk::Property instead of directly using Qt Meta Object property helps to build a better interactive GUI (in the property explorer for components and in the ActionWidget for actions). Note that a camitk::Property is represented as a regular Qt Meta Object property as well (the value of the camitk::Property is in fact stored by the Qt Meta Object property)

Here are some examples to get started with:

Demonstrates how rich text can be used in description
addParameter(new Property("Bool Prop", false, "This a <i>normal</i> bool property.<br/>**Note:** Rich text description!<br/>See also: <a href=\"http://camitk.imag.fr\">CamiTK web page</a>", ""));

 beware: the action takes ownership of the Property pointer
 This means that the line above does not generate memory leak.

 Demonstrates how properties can be set as read-only
 Demonstrates how properties can be grouped.
 Here all read-only properties are assemble in the same eponymic group
Property *readOnlyBool = new Property("Read Only Bool", true, "This a read-only boolean", "");
readOnlyBool->setReadOnly(true);
readOnlyBool->setGroupName("Read Only Properties");
addParameter(readOnlyBool);

 beware: the action takes ownership of the Property pointer
 This means that you should NOT delete readOnlyBool in the action destructor

 Demonstrates how integer properties can be bounded
Property *boundedInt = new Property("Bounded Int", 12, "An integer bounded between 0 and 20", "");
boundedInt->setAttribute("minimum", 0);
boundedInt->setAttribute("maximum", 20);
boundedInt->setGroupName("Numeric Properties");
addParameter(boundedInt);

 Demonstrates how double properties can be half-bounded
Property *doubleWithMax = new Property("Double With Max", -10.0, "A double with a max value of -4.2", "");
doubleWithMax->setAttribute("maximum", -4.2);
doubleWithMax->setGroupName("Numeric Properties");
addParameter(doubleWithMax);

Property *intWithSingleStep = new Property("Int With Single Step", -10, "An integer with a single step of <i>5</i>", "");
intWithSingleStep->setAttribute("singleStep", 5);
intWithSingleStep->setGroupName("Numeric Properties");
addParameter(intWithSingleStep);

Property *doubleWithStepAndDecimal = new Property("Double With Single Step And Precision", 3.14159, "A double with 5 decimals and a single step of 1.10<sup>-5</sup>", "");
doubleWithStepAndDecimal->setAttribute("singleStep", 10e-6);
doubleWithStepAndDecimal->setAttribute("decimals", 5);
doubleWithStepAndDecimal->setGroupName("Numeric Properties");
addParameter(doubleWithStepAndDecimal);

Property *intWithDecimal = new Property("Int With Precision", 4, "An integer with a precision set to 5 decimals: this should not affect it.", "");
intWithDecimal->setAttribute("decimals", 5);
intWithDecimal->setGroupName("Numeric Properties");
addParameter(intWithDecimal);

Property *readOnlyQVector3D = new Property("Read Only QVector3D", QVector3D(-4.0, 2.0, 0.1), "A read-only QVector3D", "");
readOnlyQVector3D->setReadOnly(true);
readOnlyQVector3D->setGroupName("Read Only Properties");
addParameter(readOnlyQVector3D);

Property *stringWithRegExp = new Property("QString Constrained by RegExp", QString("loweronly"), "A QString constrained to lowercase characters only (no separators, numbers...)", "");
stringWithRegExp->setAttribute("regExp", QRegularExpression("[a-z]*"));
addParameter(stringWithRegExp);

Property *constrainedQRect = new Property("Constrained QRect", QRect(10,10,20,20), "A QRect constrained to (0,0,50,50)", "");
constrainedQRect->setAttribute("constraint", QRect(0,0,50,50));
addParameter(constrainedQRect);

Property *constrainedQVector3D = new Property("Constrained QVector3D", QVector3D(1.1, 2.2, 3.3), "A constrained QVector3D (not yet implemented)", "");
constrainedQVector3D->setAttribute("constraint", QVector3D(10.0, 10.0, 10.0));
addParameter(constrainedQVector3D);

To create a new Property, prefer using Property. To check if a Property has been added to your Component / Action, use either Component::getProperty() or Action::getProperty() methods. To modify an existing Property’s value, check if it exists: - if not, create a new instance of Property - if yes, directly modify its value by using QObject::setProperty() method.e

The GUI interaction is automatically build and managed by the class ObjectController.

An example for adding properties to an action can be seen in tutorials/actions/properties. More specifically see the EnumPropertyExample action to learn about how to use enum properties.

The class PropComponent and PropAction in the tutorials demonstrates how to use camitk::Property instead of Qt Meta Object Property.

The available property types are:

Property Type | Property Type Id ————- | —————– int | QVariant::Int double | QVariant::Double bool | QVariant::Bool QString | QVariant::String QVector3D | QVariant::QVector3D QColor | QVariant::Color QDate | QVariant::Date QTime | QVariant::Time QChar | QVariant::Char QDateTime | QVariant::DateTime QPoint | QVariant::Point QPointF | QVariant::PointF QKeySequence | QVariant::KeySequence QLocale | QVariant::Locale QSize | QVariant::Size QSizeF | QVariant::SizeF QRect | QVariant::Rect QRectF | QVariant::RectF QSizePolicy | QVariant::SizePolicy QFont | QVariant::Font QCursor | QVariant::Cursor enum | enumTypeId() flag | flagTypeId() group | groupTypeId()

Possible attributes depends on the property type, mostly (see also QtVariantPropertyManager API doc): Property Type | Attribute Name | Attribute Type ————- | :————: | :————: int | minimum | QVariant::Int int | maximum | QVariant::Int int | singleStep | QVariant::Int double | minimum | QVariant::Double double | maximum | QVariant::Double double | singleStep | QVariant::Double double | decimals | QVariant::Int QString | regExp | QVariant::RegExp QDate | minimum | QVariant::Date QDate | maximum | QVariant::Date QPointF | decimals | QVariant::Int QSize | minimum | QVariant::Size QSize | maximum | QVariant::Size QSizeF | minimum | QVariant::SizeF QSizeF | maximum | QVariant::SizeF QSizeF | decimals | QVariant::Int QRect | constraint | QVariant::Rect QRectF | constraint | QVariant::RectF QRectF | decimals | QVariant::Int enum | enumNames | QVariant::StringList (note that this can be build automatically) flag | flagNames (NOT IMPLEMENTED YET) | QVariant::StringList

Anywhere in your code use the property(..).toInt() method to get the classical enum value of the property, and use Property::getEnumValueAsString() to get the enum value as a string. If you declared your enum using Q_ENUM (Qt>=5.5), you can also use directly QMetaEnum::fromType to retrieve the enum value as strings (see below).

If your property is an action parameter, it is safer to use the dedicated methods getParameterValue(..), setParameterValue(..), getParameterValueAsString(..) as they will first check that the given parameter name is a declared parameter. For component properties, it is safer to use the dedicated methods getPropertyValue(..) and setPropertyValue(..) as they will also first check that the given property name is a declared property.

For enums, you need to do few things in the C++ class that has a enum typed property: - add Q_underscore_OBJECT macro in your class declaration - either setup a new enum (option 1) or just fill in strings in the enum names (option 2)

For option 1, you need - add the enum type in your class declaration - register your enum name using the Q_ENUM macro in your class declaration - register the enum type name to the property using the Property::setEnumTypeName (see example below)

For option 2 (recommended), just - create a QStringList with the GUI strings - use the Property::setAttribute(“enumNames”, yourQStringList)

Using option 2 is recommended as it will allow you to dynamically update the enum names at any time (for instance if you want to select a component, you can update the enum names using the currently opened components).

You can change the enum value names in the GUI using the “enumNames” attributes. There is also a way to automatically build nicer enumNames (see below).

Enum icons might be set using Property::setEnumIcons.

For instance in the header:

class MyAction : public camitk::Action {
 Really needed! (replace ‗ by _ in your code if you copy-paste this snippet)
Q‗OBJECT

-- option 1
 declare the C++ enum
enum MyEnum {
PossibleValue1,
PossibleValue2
};
 register the enum (Qt >= 5.5)
Q_ENUM(MyEnum)

-- option 2 (recommended)
 -> nothing to declare in the header
...
};

And then in the code:

MyAction::MyAction(ActionExtension * extension) : Action(extension) {
...
-- option 1
 build the dynamic prop based on the enumeration
Property *enumProp = new Property("My Enumeration", MyAction::PossibleValue2, "Enumeration support example","");
 register the enum type name for automatically manage the enum as a popup list
enumProp->setEnumTypeName("MyEnum",this);
 The Property class automatically build the enum names presented to the user in the GUI
 (it will changed the enum literals to get a cleaner look, e.g. PossibleValue1 becomes "Possible Value 1")

 OR

-- option 2 (recommended)
 build the dynamic prop based on a custom string list
Property *enumProp = new Property("My Enumeration", 0 /-* index of the initial value in the string list *-/, "Enumeration support example","");
 Set the enum names of your choice, using the enumNames property:
enumProp->setEnumTypeName("MyEnum");
 add strings to populate the GUI
QStringList enumValues;
enumValues << "Possible Value #1" << "Possible Value #2";
enumProp->setAttribute("enumNames", enumValues);

-- after either option 1 or 2: register the new prop as an action parameter
addParameter(enumProp);
}

...

-- option 1 usage
 option 1.1: get the value as classical C++ enum
MyEnum enumPropCurrentValue = (MyEnum) getParameterValue("My Enumeration").toInt();

 option 1.2: get the value as a QString (either "PossibleValue1" or "PossibleValue2", beware: this is different from the GUI names), you need the enumProp pointer
QString enumPropAsString = enumProp->getEnumValueAsString(this);

 option 1.3: using the Q_ENUM declaration in the header, get the value using Qt meta object
QMetaEnum metaEnum = QMetaEnum::fromType<EnumerationExample>();
QString enumPropAsStringDirect = metaEnum.valueToKey(enumPropCurrentValue);

-- option 2 usage (recommended)
QString QString enumPropAsString = enumValues.value(getParameterValue("My Enumeration").toInt()

This is not exactly a decorator design pattern, as the Property class is not abstract. The Qt Meta Object is still held by the QtObject inherited class (e.g. Component or Action). The camitk::Property class adds description, readOnly status and specific attributes to a QObject dynamic property.

__init__(self: camitk.Property, name: str, value: Any, description: str, unit: str) None

Constructor. The variant parameters also allows you to initialize the value of the property. By default a Property is enabled and editable (i.e. by default it is not read-only)

Parameter name: property name (unique identifier of your class property

Parameter variant: specify the property type (QVariant) and initial value

Parameter description: a sentence or two to describe the property (and its unit if any), can be Rich Text

Parameter unit: a unit of measurement (in SI unit), use symbols from https://en.wikipedia.org/wiki/SI_base_unit or https://en.wikipedia.org/wiki/SI_derived_unit when possible

Methods

__init__(self, name, value, description, unit)

Constructor.

getAttribute(self, arg0)

getDescription(self)

getName(self)

getReadOnly(self)

getUnit(self)

setAttribute(self, attribute, value)

setEnumTypeName(self, set the name of the enum)

setReadOnly(self, arg0)