@@ -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,25 +442,52 @@ 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: root .pressed (mouse)
484+ onClicked: {
485+ expanded = ! expanded
486+ if (outputs .parentPins .has (modelData .name )) {
487+ outputs .parentPins .set (modelData .name , expanded)
488+ outputs .parentPinsUpdated ()
489+ }
490+ }
416491 onEdgeAboutToBeRemoved: root .edgeAboutToBeRemoved (input)
417492
418493 Component .onCompleted : attributePinCreated (attribute, outPin)
@@ -429,27 +504,55 @@ 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
448542
449- readOnly: root .readOnly || object .isReadOnly
543+ readOnly: Boolean ( root .readOnly || modelData .isReadOnly )
450544 Component .onCompleted : attributePinCreated (attribute, inPin)
451545 Component .onDestruction : attributePinDeleted (attribute, inPin)
546+
452547 onPressed: root .pressed (mouse)
548+ onClicked: {
549+ expanded = ! expanded
550+ if (inputs .parentPins .has (modelData .name )) {
551+ inputs .parentPins .set (modelData .name , expanded)
552+ inputs .parentPinsUpdated ()
553+ }
554+ }
555+
453556 onEdgeAboutToBeRemoved: root .edgeAboutToBeRemoved (input)
454557 onChildPinCreated: attributePinCreated (childAttribute, inPin)
455558 onChildPinDeleted: attributePinDeleted (childAttribute, inPin)
@@ -489,30 +592,62 @@ Item {
489592 id: inputParams
490593 width: parent .width
491594 spacing: 3
595+
596+ property var parentPins: new Map ()
597+ signal parentPinsUpdated ()
598+
492599 Repeater {
493- id : inputParamsRepeater
494- model : node ? node . attributes : undefined
600+ model : generateAttributesModel ( false , inputParams . parentPins ) // isOutput = false
601+
495602 delegate: Loader {
496603 id: paramLoader
497- active: ! object .isOutput && ! object .exposed && object .desc .visible
498- visible: Boolean (object .enabled || object .isLink || object .hasOutputConnections )
499- property bool isFullyActive: Boolean (m .displayParams || object .isLink || object .hasOutputConnections )
604+ active: ! modelData .isOutput && ! modelData .exposed && modelData .desc .visible
605+ visible: {
606+ if (Boolean (modelData .enabled || modelData .isLink || modelData .hasOutputConnections )) {
607+ if (modelData .root && modelData .root .type === " GroupAttribute" ) {
608+ return Boolean (inputParams .parentPins .get (modelData .root .name ))
609+ active: ! modelData .isOutput && modelData .desc .exposed && modelData .desc .visible }
610+ return true
611+ }
612+ return false
613+ }
614+ property bool isFullyActive: Boolean (m .displayParams || modelData .isLink || modelData .hasOutputConnections )
500615 width: parent .width
501616
617+ Connections {
618+ target: inputParams
619+
620+ function onParentPinsUpdated () {
621+ visible = updateChildPin (modelData, inputParams .parentPins , paramLoader .item )
622+ }
623+ }
624+
502625 sourceComponent: AttributePin {
503626 id: inParamsPin
504627 nodeItem: root
628+ attribute: modelData
629+
505630 property real globalX: root .x + nodeAttributes .x + inputParamsRect .x + paramLoader .x + inParamsPin .x
506631 property real globalY: root .y + nodeAttributes .y + inputParamsRect .y + paramLoader .y + inParamsPin .y
507632
508633 height: isFullyActive ? childrenRect .height : 0
509634 Behavior on height { PropertyAnimation {easing .type : Easing .Linear } }
510635 visible: (height == childrenRect .height )
511- attribute : object
512- readOnly: Boolean (root .readOnly || object .isReadOnly )
636+
637+ readOnly: Boolean (root .readOnly || modelData .isReadOnly )
513638 Component .onCompleted : attributePinCreated (attribute, inParamsPin)
514639 Component .onDestruction : attributePinDeleted (attribute, inParamsPin)
640+
515641 onPressed: root .pressed (mouse)
642+
643+ onClicked: {
644+ expanded = ! expanded
645+ if (inputParams .parentPins .has (modelData .name )) {
646+ inputParams .parentPins .set (modelData .name , expanded)
647+ inputParams .parentPinsUpdated ()
648+ }
649+ }
650+
516651 onEdgeAboutToBeRemoved: root .edgeAboutToBeRemoved (input)
517652 onChildPinCreated: attributePinCreated (childAttribute, inParamsPin)
518653 onChildPinDeleted: attributePinDeleted (childAttribute, inParamsPin)
0 commit comments