nexxT.interface.PropertyCollections module

This module defines the PropertyCollection interface class of the nexxT framework.

class nexxT.interface.PropertyCollections.PropertyCollection[source]

Bases: QObject

Note

Import this class with from nexxT.interface import PropertyCollection.

This class represents a collection of properties. These collections are organized in a tree, such that there are parent/child relations. This is a generic base class, which is implemented in the core package. Access to properties throug the methods below is thread safe.

Properties are usually used in subclasses of nexxT.interface.Filters.Filter. They are presented in the GUI as editable entities and the settings are saved to the configuration file. They are defined during filter constructor and onInit(…), they can be used during the whole filter lifecycle. There is also the possibility to connect a callback function to the propertyChanged signal. Note that properties are automatically deleted from the config file if they disappear (e.g., due to code changes, changed dynamic ports, etc.).

Example:

class MyFilter(Filter):
    def __init__(self, env):
        super().__init__(False, False, env)
        pc = self.propertyCollection()
        pc.defineProperty("intProp", 1, "an unconstrained integer")
        pc.defineProperty("intPropMax", 1, "an max constrained integer", options=dict(max=10))
        pc.defineProperty("intPropBounded", 1, "a bounded integer", options=dict(min=-4, max=10))
        pc.defineProperty("floatProp", 1.0, "a floating point number", options=dict(min=-1e-4, max=10000))
        pc.defineProperty("boolProp", True, "a boolean")
        # it is also possible to connect a callback
        pc.propertyChanged.connect(self.onPropertyChanged)

    def onInit(self):
        pc = self.propertyCollection()
        pc.defineProperty("strProp", "Hello World", "a string")
        pc.defineProperty("enumProp", "Hello", "a string", options=dict(enum=["Hello", "World"]))

    def onStart(self):
        # queries the current value of the property
        pc = self.propertyCollection()
        intProp = pc.getProperty("intProp")
        # ...

    def onPropertyChanged(self, pc, name):
        logger.info("Property '%s' changed to %s", name, repr(pc.getProperty(name)))

In the above example, different editors will be created apropriate to the chosen values. For example, the enum property can be edited using a combo box while integer properties are edited with spin boxes. It is also possible to adapt this behaviour by passing custom propertyHandlers.

This class is an abstract base class.

Note

Usually, nexxT is using the wrapped C++ class instead of the python version. In python there are no differences between the wrapped C++ class and this python class. The C++ interface is defined in nexxT::PropertyCollection

defineProperty(name, defaultVal, helpstr, options=None, propertyHandler=None)[source]

Return the value of the given property, creating a new property if it doesn’t exist. If it does exist, the definition must be consistent, otherwise an error is raised.

Note that the parameters options and propertyHandler must not be present at the same time. That is because the options are already passed to the constructor of the propertyHandler.

Parameters:
  • name – the name of the property

  • defaultVal – the default value of the property. Note that this value will be used to determine the property’s type. Currently supported types are string, int and float

  • helpstr – a help string for the user (presented as a tool tip)

  • options – a dict mapping string to qvariant (common options: ‘min’, ‘max’, ‘enum’) all properties support the option ‘ignoreInconsistentOptions’ (default: False). If this option is True, then nexxT allows that the options change over time. Even if present, the option type and its default values are not allowed to change.

  • propertyHandler – a PropertyHandler instance, or None for automatic choice according to defaultVal

Returns:

the current value of this property

evalpath(path)[source]

Evaluates the string path. If it is an absolute path it is unchanged, otherwise it is converted to an absolute path relative to the config file path.

Parameters:

path – a string

Returns:

absolute path as string

getProperty(name)[source]

return the property identified by name

Parameters:

name – a string

Returns:

the current property value

propertyChanged

QT signal which is emitted after a property value of the collection has been changed by the user.

Parameters:
  • pc – the PropertyCollection instance (i.e., the same as self.sender())

  • propName – the name of the property which has been changed.

setProperty(name, value)[source]

Set the value of a named property.

Parameters:
  • name – property name

  • value – the value to be set

Returns:

None

staticMetaObject = PySide6.QtCore.QMetaObject("PropertyCollection" inherits "QObject": Methods:   #4 type=Signal, signature=propertyChanged(PyObject,QString), parameters=PyObject, QString   #5 type=Slot, signature=setProperty(QString,PyObject), parameters=QString, PyObject )
class nexxT.interface.PropertyCollections.PropertyHandler[source]

Bases: object

Note

Import this class with from nexxT.interface import PropertyHandler.

This class represents a property definition for a specific type. The type handles loading/saving from and to .json configs as well as providing editor widgets for modifying the property in a model/view framework.

It is an abstrct base class.

For illustration, the implementation of the IntHandler is given here as an example:

class IntHandler(PropertyHandler):
    """
    The property handler for integer properties; Supported options: min and max.
    """

    def __init__(self, options):
        """
        Constructor

        :param options: the options given to the defineProperty(...) function.
        """
        for k in options:
            if k in ["min", "max"]:
                if not isinstance(options[k], int):
                    raise PropertyParsingError(f"Unexpected type of option {k}; expected int.")
            else:
                raise PropertyParsingError(f"Unexpected option {k}; expected 'min' or 'max'.")
        self._options = options

    def options(self):
        """
        return this handler's options

        :return: a python dict with the actual options.
        """
        return self._options

    def fromConfig(self, value):
        """
        import value from config file and return the adapted version.

        :param value: an integer is expected
        :return: the validated integer
        """
        assert isinstance(value, (float, int, bool))
        return self.validate(value)

    def toConfig(self, value):
        """
        export value to config file and return the adapted version

        :param value: an integer is expected
        :return: the exported value
        """
        assert isinstance(value, int)
        return value

    def toViewValue(self, value):
        """
        create a view of this option value.

        :param value: the current option value
        :return: a string
        """
        assert isinstance(value, int)
        return str(value)

    def validate(self, value):
        """
        Validate an option value and return an adapted, valid value

        :param value: the value to be tested (an integer)
        :return: the adapted, valid value
        """
        if isinstance(value, str):
            try:
                value = int(value)
            except ValueError:
                logger.warning("Cannot interpret value '%s' as int. Using 0.", value)
                value = 0
        if "min" in self._options:
            if value < self._options["min"]:
                logger.warning("Adapted option value %d to minimum value %d.", value, self._options["min"])
                return self._options["min"]
        if "max" in self._options:
            if value > self._options["max"]:
                logger.warning("Adapted option value %d to maximum value %d.", value, self._options["max"])
                return self._options["max"]
        return int(value)

    def createEditor(self, parent):
        """
        Creates a QSpinBox instance for GUI editing of integer values

        :param parent: the parent of the widget
        :return: a QSpinBox instance
        """
        res = QSpinBox(parent)
        res.setFrame(False)
        if "min" in self._options:
            res.setMinimum(self._options["min"])
        else:
            res.setMinimum(-2147483648)
        if "max" in self._options:
            res.setMaximum(self._options["max"])
        else:
            res.setMaximum(2147483647)
        return res

    def setEditorData(self, editor, value):
        """
        set the value of the QSpinBox

        :param editor: the instance returned by createEditor
        :param value: the option value (an integer)
        :return: None
        """
        editor.setValue(value)

    def getEditorData(self, editor):
        """
        return the currently edited value

        :param editor: the instance returned by createEditor
        :return: the integer value
        """
        return self.validate(editor.value())

Note

Usually, nexxT is using the wrapped C++ class instead of the python version. In python there are no differences between the wrapped C++ class and this python class. The C++ interface is defined in nexxT::PropertyHandler

createEditor(parent)[source]

This is called in QStyledItemDelegate::createEditor; creates an editor widget instance.

Parameters:

parent – a QWidget instance

Returns:

a QWidget instance

fromConfig(value)[source]

Converts the value read from the json file into the native python format

Parameters:

value – a QVariant instance

Returns:

the native value (also a QVariant)

getEditorData(editor)[source]

This is called in QStyledItemDelegate::setModelData; converts the value from the editor back to native python value.

Parameters:

editor – the editor widget

Returns:

a QVariant, the new native property value

options()[source]

Returns the options set for this handler as a QVariantMap

Returns:

a QVariantMap instance

setEditorData(editor, value)[source]

This is called in QStyledItemDelegate::setEditorData; populates the editor widget with the actual data.

Parameters:
  • editor – the editor widget as rezurned by createEditor

  • value – the current property value, given as native python value

Returns:

None

toConfig(value)[source]

Converts the native python format into a value suitable for json files.

Parameters:

value – a QVariant instance (the native value)

Returns:

the json value (also a QVariant)

toViewValue(value)[source]

Converts the native python format into a value suitable for display in the Qt model/view framework.

Parameters:

value – a QVariant instance (the native value)

Returns:

a QVariant value (suitable value for display)

validate(value)[source]

Returns a validated version of value.

Parameters:

value – the value to be set

Returns:

a validated version of value