nexxT.interface.PropertyCollections module
This module defines the PropertyCollection interface class of the nexxT framework.
- class nexxT.interface.PropertyCollections.PropertyCollection[source]
Bases:
QObjectNote
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 thepropertyChangedsignal. 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:
objectNote
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)