|
12 | 12 | from collections.abc import Iterable, Sequence |
13 | 13 | from string import Template |
14 | 14 | from meshroom.common import BaseObject, Property, Variant, Signal, ListModel, DictModel, Slot |
| 15 | +from meshroom.core.desc.validators import NotEmptyValidator |
15 | 16 | from meshroom.core import desc, hashValue |
16 | 17 | from meshroom.core.keyValues import KeyValues |
17 | 18 | from meshroom.core.exception import InvalidEdgeError |
@@ -84,6 +85,7 @@ def __init__(self, node, attributeDesc: desc.Attribute, isOutput: bool, root=Non |
84 | 85 | self._enabled: bool = True |
85 | 86 | self._depth: int = root.depth + 1 if root is not None else 0 |
86 | 87 | self._exposed: bool = root.exposed if root is not None else attributeDesc.exposed |
| 88 | + self._description: str = attributeDesc.description |
87 | 89 | self._invalidate = False if self._isOutput else attributeDesc.invalidate |
88 | 90 | self._invalidationValue = "" # invalidation value for output attributes |
89 | 91 | self._value = None |
@@ -235,6 +237,15 @@ def _setValue(self, value): |
235 | 237 | self.requestNodeUpdate() |
236 | 238 | self.valueChanged.emit() |
237 | 239 |
|
| 240 | + def _get_description(self): |
| 241 | + return self._description |
| 242 | + |
| 243 | + def _set_description(self, desc): |
| 244 | + if self._description == desc: |
| 245 | + return |
| 246 | + self._description = desc |
| 247 | + self.descriptionChanged.emit() |
| 248 | + |
238 | 249 | def _getKeyValues(self): |
239 | 250 | """ |
240 | 251 | Return the per-key values object of the attribute or of the linked attribute. |
@@ -487,6 +498,43 @@ def updateInternals(self): |
487 | 498 | # Emit if the enable status has changed |
488 | 499 | self._setEnabled(self._getEnabled()) |
489 | 500 |
|
| 501 | + def getErrorMessages(self) -> list[str]: |
| 502 | + """ Execute the validators and aggregate the eventual error messages""" |
| 503 | + |
| 504 | + result = [] |
| 505 | + |
| 506 | + for validator in self.desc.validators: |
| 507 | + isValid, errorMessages = validator(self.node, self) |
| 508 | + |
| 509 | + if isValid: |
| 510 | + continue |
| 511 | + |
| 512 | + for errorMessage in errorMessages: |
| 513 | + result.append(errorMessage) |
| 514 | + |
| 515 | + return result |
| 516 | + |
| 517 | + def _isValid(self) -> bool: |
| 518 | + """ Check the validation and return False if any validator return (False, erorrs) |
| 519 | + """ |
| 520 | + |
| 521 | + for validator in self.desc.validators: |
| 522 | + isValid, _ = validator(self.node, self) |
| 523 | + |
| 524 | + if not isValid: |
| 525 | + return False |
| 526 | + |
| 527 | + return True |
| 528 | + |
| 529 | + def _isMandatory(self) -> bool: |
| 530 | + """ An attribute is considered as mandatory it contain a NotEmptyValidator """ |
| 531 | + |
| 532 | + for validator in self.desc.validators: |
| 533 | + if isinstance(validator, NotEmptyValidator): |
| 534 | + return True |
| 535 | + |
| 536 | + return False |
| 537 | + |
490 | 538 | def _getEnabled(self) -> bool: |
491 | 539 | if callable(self._desc.enabled): |
492 | 540 | try: |
@@ -742,6 +790,11 @@ def validateIncomingConnection(self, connectingAttribute: Attribute) -> bool: |
742 | 790 |
|
743 | 791 | expressionApplied = Signal() |
744 | 792 |
|
| 793 | + errorMessageChanged = Signal() |
| 794 | + errorMessages = Property(Variant, lambda self: self.getErrorMessages(), notify=errorMessageChanged) |
| 795 | + isMandatory = Property(bool, _isMandatory, constant=True ) |
| 796 | + isValid = Property(bool, _isValid, constant=True) |
| 797 | + |
745 | 798 |
|
746 | 799 | def raiseIfLink(func): |
747 | 800 | """ |
|
0 commit comments