Dataclass delegate

dawiq.delegate.convertFromQt(dcls: Type[DataclassInstance], data: Dict[str, Any], ignoreMissing=True) Dict[str, Any][source]

Convert the dict from DataWidget to structured dict for dataclass.

If the field value does not exist in data or is None, it is considered to be absent. If ignoreMissing is True, the absent value is not included in the resulting dictionary. Else, the default value of the field is used if there is any.

Field may define fromQt_converter metadata to convert the widget data to field data. It is a unary callable which takes the widget data and returns the field data.

Examples

None is considered as missing value.

>>> from dataclasses import dataclass, field
>>> from dawiq.delegate import convertFromQt
>>> from typing import Optional
>>> @dataclass
... class Cls1:
...     a: int
...     b: int = 10
...     c: Optional[int] = None
...     d: list = field(default_factory=list)
>>> convertFromQt(Cls1, {})
{}
>>> convertFromQt(Cls1, dict(a=1, b=None, c=None))
{'a': 1}

ignoreMissing controls whether the default value should be used.

>>> convertFromQt(Cls1, {}, ignoreMissing=False)
{'b': 10, 'c': None, 'd': []}

Nested dataclasses are recusively converted.

>>> @dataclass
... class Cls2:
...     x: int = 20
...     y: Cls1 = field(default_factory=lambda: Cls1(a=5))
>>> convertFromQt(Cls2, {}, ignoreMissing=False)
{'x': 20, 'y': {'a': 5, 'b': 10, 'c': None, 'd': []}}

fromQt_converter metadata converts the data from the widet.

>>> def conv(arg):
...     return (arg,)
>>> @dataclass
... class Cls3:
...     x: tuple = field(default=(1,), metadata=dict(fromQt_converter=conv))
>>> convertFromQt(Cls3, dict(x=1))
{'x': (1,)}
dawiq.delegate.convertToQt(dcls: Type[DataclassInstance], data: Dict[str, Any], ignoreMissing=True) Dict[str, Any][source]

Convert structured dict from dataclass to dict for DataWidget.

If the field value does not exist in data or is None, it is considered to be absent. If ignoreMissing is True, None is used as the placeholder in the resulting dictionary. Else, the default value of the field is used if there is any.

Field may define toQt_converter metadata to convert the field data to widget data. It is a unary callable which takes the field data and returns the widget data.

Examples

None is considered as missing value.

>>> from dataclasses import dataclass, field
>>> from dawiq.delegate import convertToQt
>>> from typing import Optional
>>> @dataclass
... class Cls1:
...     a: int
...     b: int = 10
...     c: Optional[int] = None
...     d: list = field(default_factory=list)
>>> convertToQt(Cls1, dict(a=1, b=2, c=3))
{'a': 1, 'b': 2, 'c': 3, 'd': None}
>>> convertToQt(Cls1, {})
{'a': None, 'b': None, 'c': None, 'd': None}

ignoreMissing controls whether the default value should be used.

>>> convertToQt(Cls1, {}, ignoreMissing=False)
{'a': None, 'b': 10, 'c': None, 'd': []}

Nested dataclasses are recusively converted.

>>> @dataclass
... class Cls2:
...     x: int = 20
...     y: Cls1 = field(default_factory=lambda: Cls1(a=5))
>>> convertToQt(Cls2, {}, ignoreMissing=False)
{'x': 20, 'y': {'a': 5, 'b': 10, 'c': None, 'd': []}}

toQt_converter metadata converts the data to the widget.

>>> @dataclass
... class Cls3:
...     x: int = field(metadata=dict(toQt_converter=lambda tup: tup[0]))
>>> convertToQt(Cls3, dict(x=(1,)))
{'x': 1}
dawiq.delegate.highlightEmptyField(editor: DataWidget, dcls: Type[DataclassInstance] | None)[source]

Recursively highlight the empty field whose data is required.

class dawiq.delegate.DataclassDelegate(*args: Any, **kwargs: Any)[source]

Bases: QStyledItemDelegate

Delegate to update the model and the data widget.

This delegate stores dataclass type and dataclass data to the model, and updates the data widget with model data.

Supported data widgets are:

  • DataWidget

  • DataclassStackedWidget

  • DataclassTabWidget

Dataclass type is stored to the model with TypeRole as item data role and dataclass data is stored with DataRole.

By default, missing values are not replaced by default values of the fields. This is to preserve the intentional empty input by the user. Setting ignoreMissing() changes this behavior.

ignoreMissing() bool[source]

If True, default values are used for missing fields.

classmethod cacheModelData(model, index, value, role)[source]

Cache the value to model’s index with role so that submit() method of model can permanently store the data.

Caching API is not defined for general QAbstractItemModel. So by default, this method just stores the data to the model without caching.

Subclass may reimplement this method to actually cache the data to the model.

class dawiq.delegate.DataclassMapper(*args: Any, **kwargs: Any)[source]

Bases: QDataWidgetMapper

Mapper between the data widget and the model.

Supported data widgets are:

  • DataWidget

  • DataclassStackedWidget

  • DataclassTabWidget

Notes

When mapping DataWidget, propertyName argument of addMapping() must not be passed.