@@ -115,6 +115,54 @@ Item {
115115 return str
116116 }
117117
118+ function updateChildPin (attribute , parentPins , pin ) {
119+ /*
120+ * Update the pin of a child attribute: if the attribute is enabled and its parent is a GroupAttribute,
121+ * the visibility is determined based on the parent pin's "expanded" state, using the "parentPins" map to
122+ * access the status.
123+ * If the current pin is also a GroupAttribute and is expanded while its newly "visible" state is false,
124+ * it is reset.
125+ */
126+ if (Boolean (attribute .enabled )) {
127+ // If the parent's a GroupAttribute, use status of the parent's pin to determine visibility
128+ if (attribute .root && attribute .root .type === " GroupAttribute" ) {
129+ var visible = Boolean (parentPins .get (attribute .root .name ))
130+ if (! visible && parentPins .has (attribute .name ) && parentPins .get (attribute .name ) === true ) {
131+ parentPins .set (attribute .name , false )
132+ pin .expanded = false
133+ }
134+ return visible
135+ }
136+ return true
137+ }
138+ return false
139+ }
140+
141+ function generateAttributesModel (isOutput , parentPins ) {
142+ if (! node)
143+ return undefined
144+
145+ const attributes = []
146+ for (let i = 0 ; i < node .attributes .count ; ++ i) {
147+ let attr = node .attributes .at (i)
148+ if (attr .isOutput == isOutput) {
149+ attributes .push (attr)
150+ if (attr .type === " GroupAttribute" ) {
151+ parentPins .set (attr .name , false )
152+ }
153+
154+ for (let j = 0 ; j < attr .flattenedChildren .count ; ++ j) {
155+ attributes .push (attr .flattenedChildren .at (j))
156+ if (attr .flattenedChildren .at (j).type === " GroupAttribute" ) {
157+ parentPins .set (attr .flattenedChildren .at (j).name , false )
158+ }
159+ }
160+ }
161+ }
162+
163+ return attributes
164+ }
165+
118166 // Main Layout
119167 MouseArea {
120168 id: mouseArea
@@ -394,26 +442,53 @@ Item {
394442 width: parent .width
395443 spacing: 3
396444
445+ property var parentPins: new Map ()
446+ signal parentPinsUpdated ()
447+
397448 Repeater {
398- model: node ? node . attributes : undefined
449+ model: generateAttributesModel ( true , outputs . parentPins ) // isOutput = true
399450
400451 delegate: Loader {
401452 id: outputLoader
402- active: Boolean (object .isOutput && object .desc .visible )
403- visible: Boolean (object .enabled || object .hasOutputConnections )
453+ active: Boolean (modelData .isOutput && modelData .desc .visible )
454+
455+ visible: {
456+ if (Boolean (modelData .enabled || modelData .hasOutputConnections )) {
457+ if (modelData .root && modelData .root .type === " GroupAttribute" ) {
458+ return Boolean (outputs .parentPins .get (modelData .root .name ))
459+ }
460+ return true
461+ }
462+ return false
463+ }
404464 anchors .right : parent .right
405465 width: outputs .width
406466
467+ Connections {
468+ target: outputs
469+
470+ function onParentPinsUpdated () {
471+ visible = updateChildPin (modelData, outputs .parentPins , outputLoader .item )
472+ }
473+ }
474+
407475 sourceComponent: AttributePin {
408476 id: outPin
409477 nodeItem: root
410- attribute: object
478+ attribute: modelData
411479
412480 property real globalX: root .x + nodeAttributes .x + outputs .x + outputLoader .x + outPin .x
413481 property real globalY: root .y + nodeAttributes .y + outputs .y + outputLoader .y + outPin .y
414482
415483 onPressed : function (mouse ) { root .pressed (mouse) }
416484 onEdgeAboutToBeRemoved : function (input ) { root .edgeAboutToBeRemoved (input) }
485+ onClicked: {
486+ expanded = ! expanded
487+ if (outputs .parentPins .has (modelData .name )) {
488+ outputs .parentPins .set (modelData .name , expanded)
489+ outputs .parentPinsUpdated ()
490+ }
491+ }
417492
418493 Component .onCompleted : attributePinCreated (attribute, outPin)
419494 onChildPinCreated: attributePinCreated (childAttribute, outPin)
@@ -429,19 +504,38 @@ Item {
429504 width: parent .width
430505 spacing: 3
431506
507+ property var parentPins: new Map ()
508+ signal parentPinsUpdated ()
509+
432510 Repeater {
433- model: node ? node . attributes : undefined
511+ model: generateAttributesModel ( false , inputs . parentPins ) // isOutput = false
434512
435513 delegate: Loader {
436514 id: inputLoader
437- active: ! object .isOutput && object .exposed && object .desc .visible
438- visible: Boolean (object .enabled )
515+ active: ! modelData .isOutput && modelData .exposed && modelData .desc .visible
516+ visible: {
517+ if (Boolean (modelData .enabled )) {
518+ if (modelData .root && modelData .root .type === " GroupAttribute" ) {
519+ return Boolean (inputs .parentPins .get (modelData .root .name ))
520+ }
521+ return true
522+ }
523+ return false
524+ }
439525 width: inputs .width
440526
527+ Connections {
528+ target: inputs
529+
530+ function onParentPinsUpdated () {
531+ visible = updateChildPin (modelData, inputs .parentPins , inputLoader .item )
532+ }
533+ }
534+
441535 sourceComponent: AttributePin {
442536 id: inPin
443537 nodeItem: root
444- attribute: object
538+ attribute: modelData
445539
446540 property real globalX: root .x + nodeAttributes .x + inputs .x + inputLoader .x + inPin .x
447541 property real globalY: root .y + nodeAttributes .y + inputs .y + inputLoader .y + inPin .y
@@ -450,6 +544,13 @@ Item {
450544 Component .onCompleted : attributePinCreated (attribute, inPin)
451545 Component .onDestruction : attributePinDeleted (attribute, inPin)
452546 onPressed : function (mouse ) { root .pressed (mouse) }
547+ onClicked: {
548+ expanded = ! expanded
549+ if (inputs .parentPins .has (modelData .name )) {
550+ inputs .parentPins .set (modelData .name , expanded)
551+ inputs .parentPinsUpdated ()
552+ }
553+ }
453554 onEdgeAboutToBeRemoved : function (input ) { root .edgeAboutToBeRemoved (input) }
454555 onChildPinCreated : function (childAttribute , inPin ) { attributePinCreated (childAttribute, inPin) }
455556 onChildPinDeleted : function (childAttribute , inPin ) { attributePinDeleted (childAttribute, inPin) }
@@ -489,30 +590,59 @@ Item {
489590 id: inputParams
490591 width: parent .width
491592 spacing: 3
593+
594+ property var parentPins: new Map ()
595+ signal parentPinsUpdated ()
596+
492597 Repeater {
493- id : inputParamsRepeater
494- model : node ? node . attributes : undefined
598+ model : generateAttributesModel ( false , inputParams . parentPins ) // isOutput = false
599+
495600 delegate: Loader {
496601 id: paramLoader
497- active: ! object .isOutput && ! object .exposed && object .desc .visible
498- visible: Boolean (object .enabled || object .isLinkNested || object .hasOutputConnections )
499- property bool isFullyActive: Boolean (m .displayParams || object .isLinkNested || object .hasOutputConnections )
602+ active: ! modelData .isOutput && ! modelData .exposed && modelData .desc .visible
603+ visible: {
604+ if (Boolean (modelData .enabled || modelData .isLinkNested || modelData .hasOutputConnections )) {
605+ if (modelData .root && modelData .root .type === " GroupAttribute" ) {
606+ return Boolean (inputParams .parentPins .get (modelData .root .name ))
607+ }
608+ return true
609+ }
610+ return false
611+ }
612+ property bool isFullyActive: Boolean (m .displayParams || modelData .isLinkNested || modelData .hasOutputConnections )
500613 width: parent .width
501614
615+ Connections {
616+ target: inputParams
617+
618+ function onParentPinsUpdated () {
619+ visible = updateChildPin (modelData, inputParams .parentPins , paramLoader .item )
620+ }
621+ }
622+
502623 sourceComponent: AttributePin {
503624 id: inParamsPin
504625 nodeItem: root
626+ attribute: modelData
627+
505628 property real globalX: root .x + nodeAttributes .x + inputParamsRect .x + paramLoader .x + inParamsPin .x
506629 property real globalY: root .y + nodeAttributes .y + inputParamsRect .y + paramLoader .y + inParamsPin .y
507630
508631 height: isFullyActive ? childrenRect .height : 0
509632 Behavior on height { PropertyAnimation {easing .type : Easing .Linear } }
510633 visible: (height == childrenRect .height )
511- attribute : object
512- readOnly: Boolean (root .readOnly || object .isReadOnly )
634+
635+ readOnly: Boolean (root .readOnly || modelData .isReadOnly )
513636 Component .onCompleted : attributePinCreated (attribute, inParamsPin)
514637 Component .onDestruction : attributePinDeleted (attribute, inParamsPin)
515638 onPressed : function (mouse ) { root .pressed (mouse) }
639+ onClicked: {
640+ expanded = ! expanded
641+ if (inputParams .parentPins .has (modelData .name )) {
642+ inputParams .parentPins .set (modelData .name , expanded)
643+ inputParams .parentPinsUpdated ()
644+ }
645+ }
516646 onEdgeAboutToBeRemoved : function (input ) { root .edgeAboutToBeRemoved (input) }
517647 onChildPinCreated : function (childAttribute , inParamsPin ) { attributePinCreated (childAttribute, inParamsPin) }
518648 onChildPinDeleted : function (childAttribute , inParamsPin ) { attributePinDeleted (childAttribute, inParamsPin) }
0 commit comments