QmlNodeEditor
Node.qml
Go to the documentation of this file.
1 import QtQuick 2.15
2 import QtQuick.Controls 2.15
3 
4 Item {
5  id: nodeRoot
6 
7  property var nodeModel: model
8 
9  property bool active: nodeModel
10  property int nodeId: nodeModel.nodeId
11  property bool removable: nodeModel.removable || false
12  x: nodeModel.x
13  y: nodeModel.y
14 
15  property alias leftPortDockRepeater: nodeLeftPortDock.repeater
16  property alias rightPortDockRepeater: nodeRightPortDock.repeater
17 
18  function updateHeight() {
19  height = nodeHeaderLoader.height
20  + nodeView.style.nodeBorderWidth * 2
21  + nodeTopContentLoader.height
22  + Math.max(
23  nodeCenterLoader.height,
24  nodeLeftPortDock.height,
25  nodeRightPortDock.height);
26  }
27 
28  Loader {
29  id: nodeDeleteConfirmationDialogLoader
30  active: nodeRoot.active
31  property var nodeModel: nodeRoot.nodeModel
32  sourceComponent: nodeView.nodeDeleteConfirmationDialog
33  }
34  Connections {
35  target: nodeDeleteConfirmationDialogLoader.item
36  function onAccepted() {
37  nodeDeleteConfirmationDialogLoader.active = false;
38  nodeView.nodeRemoved(nodeRoot.nodeModel.nodeId);
39  }
40  }
41  function showNodeDeleteDialog() {
42  nodeDeleteConfirmationDialogLoader.item.open();
43  }
44 
45  Rectangle {
46  id: nodeRootRectangle
47  anchors.fill: parent
48  border.color: nodeView.style.nodeBorderColor
49  border.width: nodeView.style.nodeBorderWidth
50  color: nodeView.style.nodeBackgroundColor
51  gradient: nodeView.style.nodeBackgroundGradient
52  radius: nodeView.style.nodeBorderRadius
53  focus: true
54  activeFocusOnTab: true
55  clip: false
56 
57  states: [
58  State {
59  name: "focus"
60  when: nodeRootRectangle.activeFocus
61  PropertyChanges {
62  target: nodeRootRectangle
63  border.color: nodeView.style.nodeBorderFocusColor
64  }
65  },
66  State {
67  name: "hover"
68  when: nodeRootRectangleHover.hovered
69  PropertyChanges {
70  target: nodeRootRectangle
71  border.color: nodeView.style.nodeBorderHoverColor
72  }
73  }
74  ]
75 
76  Keys.onPressed: (event) => {
77  if (nodeRoot.removable && event.key === nodeView.deleteKey) {
78  showNodeDeleteDialog();
79  event.accepted = true;
80  }
81  }
82 
83  HoverHandler {
84  id: nodeRootRectangleHover
85  }
86 
87  TapHandler {
88  acceptedButtons: Qt.LeftButton
89  onTapped: nodeRootRectangle.forceActiveFocus();
90  }
91 
92  Column {
93  id: nodeRootColumn
94  anchors.top: parent.top
95  anchors.topMargin: nodeRootRectangle.border.width
96  anchors.horizontalCenter: parent.horizontalCenter
97  width: parent.width
98 
99  Loader {
100  id: nodeHeaderLoader
101  active: nodeRoot.active
102  property alias nodeModel: nodeRoot.nodeModel
103  property QtObject style: nodeView.style
104  anchors.left: parent.left
105  anchors.right: parent.right
106  anchors.leftMargin: nodeRootRectangle.border.width
107  anchors.rightMargin: nodeRootRectangle.border.width
108 
109  sourceComponent: nodeView.nodeHeaderComponent
110  onHeightChanged: nodeRoot.updateHeight()
111 
112  MouseArea {
113  id: nodeHeaderMouseArea
114  anchors.fill: parent
115  cursorShape: Qt.DragMoveCursor
116  acceptedButtons: Qt.LeftButton
117  drag.target: nodeRoot
118  drag.smoothed: false
119  drag.minimumX: 0
120  drag.maximumX: nodeView.width - nodeRoot.width;
121  drag.minimumY: 0
122  drag.maximumY: nodeView.height - nodeRoot.height;
123  onPressed: nodeRootRectangle.forceActiveFocus();
124 
125  onReleased: {
126  if (drag.active) {
127  nodeRoot.nodeModel.x = nodeRoot.x;
128  nodeRoot.nodeModel.y = nodeRoot.y;
129  nodeView.nodePositionChanged(nodeRoot.nodeModel.nodeId, nodeRoot.x, nodeRoot.y);
130  nodeRoot.x = Qt.binding(function() { return nodeRoot.nodeModel.x; });
131  nodeRoot.y = Qt.binding(function() { return nodeRoot.nodeModel.y; });
132  }
133  }
134 
135  onPositionChanged: (event) => {
136  var snapPosition = snapGrid.snapPosition(Qt.point(drag.target.x, drag.target.y));
137  drag.target.x = snapPosition.x;
138  drag.target.y = snapPosition.y;
139  }
140  }
141  }
142 
143  Loader {
144  id: nodeTopContentLoader
145  active: nodeRoot.active
146  anchors.left: parent.left
147  anchors.right: parent.right
148  anchors.leftMargin: nodeRootRectangle.border.width
149  anchors.rightMargin: nodeRootRectangle.border.width
150  property alias nodeModel: nodeRoot.nodeModel
151  property QtObject style: nodeView.style
152  sourceComponent: nodeView.nodeTopContentComponent
153  onHeightChanged: nodeRoot.updateHeight()
154  }
155 
156  Row {
157  id: nodeContentRow
158  anchors.left: parent.left
159  anchors.leftMargin: -nodeView.style.nodePortConnectorMargin
160 
161  width: nodeCenterLoader.width + nodeLeftPortDock.width + nodeRightPortDock.width
162 
163  property real relativeX: nodeRootRectangle.x + nodeRootColumn.x + nodeContentRow.x
164  property real relativeY: nodeRootRectangle.y + nodeRootColumn.y + nodeContentRow.y
165 
166  PortsDock {
167  id: nodeLeftPortDock
168  nodePortComponent: nodeView.nodeLeftPortComponent
169  relativeX: parent.relativeX + x
170  relativeY: parent.relativeY + y
171  model: nodeRoot.nodeModel.leftPorts
172  onHeightChanged: nodeRoot.updateHeight()
173  }
174 
175  Loader {
176  id: nodeCenterLoader
177  active: nodeRoot.active
178  property alias nodeModel: nodeRoot.nodeModel
179  property QtObject style: nodeView.style
180  sourceComponent: nodeView.nodeCenterContentComponent
181  onHeightChanged: nodeRoot.updateHeight()
182  onWidthChanged: nodeRoot.width = width
183  + nodeView.style.leftPortDockWidth
184  + nodeView.style.rightPortDockWidth
185  }
186 
187  PortsDock {
188  id: nodeRightPortDock
189  nodePortComponent: nodeView.nodeRightPortComponent
190  layoutDirection: Qt.RightToLeft
191  model: nodeRoot.nodeModel.rightPorts
192  onHeightChanged: nodeRoot.updateHeight()
193  }
194  }
195  }
196 
197  Repeater {
198  model: nodeRoot.nodeModel.connections
199  onItemAdded: (index, item) => {
200  var fromComponent = findConnectorRow(item.fromNodeId, item.fromPortId);
201  var toComponent = findConnectorRow(item.toNodeId, item.toPortId);
202  if (fromComponent && toComponent) {
203  addConnectionComponent(fromComponent, toComponent);
204  }
205  }
206  onItemRemoved: (index, item) => {
207  var fromComponent = findConnectorRow(item.fromNodeId, item.fromPortId);
208  var toComponent = findConnectorRow(item.toNodeId, item.toPortId);
209  if (fromComponent && toComponent) {
210  removeConnectionComponent(fromComponent, toComponent);
211  } else {
212  console.warn("Cannot found connection source or destination port " + item);
213  }
214  }
215 
216  delegate: Item {
217  property var connectionModel: model.fromNodeId ? model : modelData
218 
219  property int fromNodeId: connectionModel.fromNodeId
220  property int fromPortId: connectionModel.fromPortId
221  property int toNodeId: connectionModel.toNodeId
222  property int toPortId: connectionModel.toPortId
223  }
224  }
225  }
226 }
alias leftPortDockRepeater
Definition: Node.qml:18
real relativeX
Definition: PortsDock.qml:10