From 2d953d73194a1901e1a021d45bbadb2d26ff4408 Mon Sep 17 00:00:00 2001 From: Julien-Haudegond <44610840+Julien-Haudegond@users.noreply.github.com> Date: Fri, 24 Jul 2020 17:36:17 +0200 Subject: [PATCH] [core] add enabled property on attributes The new property "enabled" allows to define a lambda to dynamically enable/disable parameters. Disabled parameters are not used in the uid, not exported to the command line and not visible in the interface. --- meshroom/core/attribute.py | 18 +++++++++ meshroom/core/desc.py | 40 ++++++++++--------- meshroom/core/node.py | 21 ++++++---- .../ui/qml/GraphEditor/AttributeEditor.qml | 2 +- 4 files changed, 53 insertions(+), 28 deletions(-) mode change 100755 => 100644 meshroom/core/desc.py diff --git a/meshroom/core/attribute.py b/meshroom/core/attribute.py index dd28c9b6..b661fe43 100644 --- a/meshroom/core/attribute.py +++ b/meshroom/core/attribute.py @@ -58,6 +58,7 @@ class Attribute(BaseObject): self._isOutput = isOutput self._value = copy.copy(attributeDesc.value) self._label = attributeDesc.label + self._enabled = True # invalidation value for output attributes self._invalidationValue = "" @@ -95,6 +96,15 @@ class Attribute(BaseObject): def getLabel(self): return self._label + def getEnabled(self): + return self._enabled + + def setEnabled(self, v): + if self._enabled == v: + return + self._enabled = v + self.enabledChanged.emit() + def _get_value(self): return self.getLinkParam().value if self.isLink else self._value @@ -224,6 +234,12 @@ class Attribute(BaseObject): def getPrimitiveValue(self, exportDefault=True): return self._value + def updateInternals(self): + if isinstance(self.desc.enabled, types.FunctionType): + self.setEnabled(self.desc.enabled(self.node)) + else: + self.setEnabled(self.attributeDesc.enabled) + name = Property(str, getName, constant=True) fullName = Property(str, getFullName, constant=True) label = Property(str, getLabel, constant=True) @@ -237,6 +253,8 @@ class Attribute(BaseObject): isDefault = Property(bool, _isDefault, notify=valueChanged) linkParam = Property(BaseObject, getLinkParam, notify=isLinkChanged) node = Property(BaseObject, node.fget, constant=True) + enabledChanged = Signal() + enabled = Property(bool, getEnabled, setEnabled, notify=enabledChanged) def raiseIfLink(func): diff --git a/meshroom/core/desc.py b/meshroom/core/desc.py old mode 100755 new mode 100644 index 202b5f86..4cf348cc --- a/meshroom/core/desc.py +++ b/meshroom/core/desc.py @@ -10,7 +10,7 @@ class Attribute(BaseObject): """ """ - def __init__(self, name, label, description, value, advanced, uid, group): + def __init__(self, name, label, description, value, advanced, uid, group, enabled): super(Attribute, self).__init__() self._name = name self._label = label @@ -19,6 +19,7 @@ class Attribute(BaseObject): self._uid = uid self._group = group self._advanced = advanced + self._enabled = enabled name = Property(str, lambda self: self._name, constant=True) label = Property(str, lambda self: self._label, constant=True) @@ -27,6 +28,7 @@ class Attribute(BaseObject): uid = Property(Variant, lambda self: self._uid, constant=True) group = Property(str, lambda self: self._group, constant=True) advanced = Property(bool, lambda self: self._advanced, constant=True) + enabled = Property(Variant, lambda self: self._enabled, constant=True) type = Property(str, lambda self: self.__class__.__name__, constant=True) def validateValue(self, value): @@ -53,13 +55,13 @@ class Attribute(BaseObject): class ListAttribute(Attribute): """ A list of Attributes """ - def __init__(self, elementDesc, name, label, description, group='allParams', advanced=False, joinChar=' '): + def __init__(self, elementDesc, name, label, description, group='allParams', advanced=False, enabled=True, joinChar=' '): """ :param elementDesc: the Attribute description of elements to store in that list """ self._elementDesc = elementDesc self._joinChar = joinChar - super(ListAttribute, self).__init__(name=name, label=label, description=description, value=[], uid=(), group=group, advanced=advanced) + super(ListAttribute, self).__init__(name=name, label=label, description=description, value=[], uid=(), group=group, advanced=advanced, enabled=enabled) elementDesc = Property(Attribute, lambda self: self._elementDesc, constant=True) uid = Property(Variant, lambda self: self.elementDesc.uid, constant=True) @@ -82,13 +84,13 @@ class ListAttribute(Attribute): class GroupAttribute(Attribute): """ A macro Attribute composed of several Attributes """ - def __init__(self, groupDesc, name, label, description, group='allParams', advanced=False, joinChar=' '): + def __init__(self, groupDesc, name, label, description, group='allParams', advanced=False, enabled=True, joinChar=' '): """ :param groupDesc: the description of the Attributes composing this group """ self._groupDesc = groupDesc self._joinChar = joinChar - super(GroupAttribute, self).__init__(name=name, label=label, description=description, value={}, uid=(), group=group, advanced=advanced) + super(GroupAttribute, self).__init__(name=name, label=label, description=description, value={}, uid=(), group=group, advanced=advanced, enabled=enabled) groupDesc = Property(Variant, lambda self: self._groupDesc, constant=True) @@ -143,15 +145,15 @@ class GroupAttribute(Attribute): class Param(Attribute): """ """ - def __init__(self, name, label, description, value, uid, group, advanced): - super(Param, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced) + def __init__(self, name, label, description, value, uid, group, advanced, enabled): + super(Param, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, enabled=enabled) class File(Attribute): """ """ - def __init__(self, name, label, description, value, uid, group='allParams', advanced=False): - super(File, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced) + def __init__(self, name, label, description, value, uid, group='allParams', advanced=False, enabled=True): + super(File, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, enabled=enabled) def validateValue(self, value): if not isinstance(value, pyCompatibility.basestring): @@ -162,8 +164,8 @@ class File(Attribute): class BoolParam(Param): """ """ - def __init__(self, name, label, description, value, uid, group='allParams', advanced=False): - super(BoolParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced) + def __init__(self, name, label, description, value, uid, group='allParams', advanced=False, enabled=True): + super(BoolParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, enabled=enabled) def validateValue(self, value): try: @@ -175,9 +177,9 @@ class BoolParam(Param): class IntParam(Param): """ """ - def __init__(self, name, label, description, value, range, uid, group='allParams', advanced=False): + def __init__(self, name, label, description, value, range, uid, group='allParams', advanced=False, enabled=True): self._range = range - super(IntParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced) + super(IntParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, enabled=enabled) def validateValue(self, value): # handle unsigned int values that are translated to int by shiboken and may overflow @@ -194,9 +196,9 @@ class IntParam(Param): class FloatParam(Param): """ """ - def __init__(self, name, label, description, value, range, uid, group='allParams', advanced=False): + def __init__(self, name, label, description, value, range, uid, group='allParams', advanced=False, enabled=True): self._range = range - super(FloatParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced) + super(FloatParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, enabled=enabled) def validateValue(self, value): try: @@ -210,13 +212,13 @@ class FloatParam(Param): class ChoiceParam(Param): """ """ - def __init__(self, name, label, description, value, values, exclusive, uid, group='allParams', joinChar=' ', advanced=False): + def __init__(self, name, label, description, value, values, exclusive, uid, group='allParams', joinChar=' ', advanced=False, enabled=True): assert values self._values = values self._exclusive = exclusive self._joinChar = joinChar self._valueType = type(self._values[0]) # cast to value type - super(ChoiceParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced) + super(ChoiceParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, enabled=enabled) def conformValue(self, val): """ Conform 'val' to the correct type and check for its validity """ @@ -241,8 +243,8 @@ class ChoiceParam(Param): class StringParam(Param): """ """ - def __init__(self, name, label, description, value, uid, group='allParams', advanced=False): - super(StringParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced) + def __init__(self, name, label, description, value, uid, group='allParams', advanced=False, enabled=True): + super(StringParam, self).__init__(name=name, label=label, description=description, value=value, uid=uid, group=group, advanced=advanced, enabled=enabled) def validateValue(self, value): if not isinstance(value, pyCompatibility.basestring): diff --git a/meshroom/core/node.py b/meshroom/core/node.py index a59e4b1c..6e8cc5b1 100644 --- a/meshroom/core/node.py +++ b/meshroom/core/node.py @@ -541,21 +541,22 @@ class BaseNode(BaseObject): """ Compute node uids by combining associated attributes' uids. """ for uidIndex, associatedAttributes in self.attributesPerUid.items(): # uid is computed by hashing the sorted list of tuple (name, value) of all attributes impacting this uid - uidAttributes = [(a.getName(), a.uid(uidIndex)) for a in associatedAttributes] + uidAttributes = [(a.getName(), a.uid(uidIndex)) for a in associatedAttributes if a.enabled] uidAttributes.sort() self._uids[uidIndex] = hashValue(uidAttributes) def _buildCmdVars(self): def _buildAttributeCmdVars(cmdVars, name, attr): if attr.attributeDesc.group is not None: - # if there is a valid command line "group" - v = attr.getValueStr() - cmdVars[name] = '--{name} {value}'.format(name=name, value=v) - cmdVars[name + 'Value'] = str(v) + if attr.enabled: + # if there is a valid command line "group" + v = attr.getValueStr() + cmdVars[name] = '--{name} {value}'.format(name=name, value=v) + cmdVars[name + 'Value'] = str(v) - if v: - cmdVars[attr.attributeDesc.group] = cmdVars.get(attr.attributeDesc.group, '') + \ - ' ' + cmdVars[name] + if v: + cmdVars[attr.attributeDesc.group] = cmdVars.get(attr.attributeDesc.group, '') + \ + ' ' + cmdVars[name] elif isinstance(attr, GroupAttribute): assert isinstance(attr.value, DictModel) # if the GroupAttribute is not set in a single command line argument, @@ -678,6 +679,10 @@ class BaseNode(BaseObject): """ if self.nodeDesc: self.nodeDesc.update(self) + + for attr in self._attributes: + attr.updateInternals() + # Update chunks splitting self._updateChunks() # Retrieve current internal folder (if possible) diff --git a/meshroom/ui/qml/GraphEditor/AttributeEditor.qml b/meshroom/ui/qml/GraphEditor/AttributeEditor.qml index 62a6b2f2..c1d60119 100644 --- a/meshroom/ui/qml/GraphEditor/AttributeEditor.qml +++ b/meshroom/ui/qml/GraphEditor/AttributeEditor.qml @@ -26,7 +26,7 @@ ListView { model: attributes delegate: Loader { - active: !object.desc.advanced || GraphEditorSettings.showAdvancedAttributes + active: object.enabled && (!object.desc.advanced || GraphEditorSettings.showAdvancedAttributes) visible: active height: item ? item.implicitHeight : -spacing // compensate for spacing if item is hidden