QmlNodeEditor
NodeView.qml
Go to the documentation of this file.
1 import QtQuick 2.15
2 import QtQuick.Controls 2.15
3 import QtQuick.Shapes 1.15
4 import QtQml.Models
5 
6 import QmlNodeEditor 1.0
7 import "private" as Private
8 
33 Item {
34  id: nodeView
35 
136  required property var model
137 
141  property int deleteKey: Qt.Key_Delete
142 
146  property QtObject style: NodeViewStyle {}
147 
163  property Component connectionShape: Private.ConnectionShape {}
164 
170  property Component connectionComponent: Private.ConnectionComponent {}
171 
179  property Component nodeDeleteConfirmationDialog: Private.NodeDeleteConfirmationDialog {}
180 
188  property Component connectionDeleteConfirmationDialog: Private.ConnectionDeleteConfirmationDialog {}
189 
198  property Component nodeHeaderComponent: Private.NodeHeader {}
199 
208  property Component nodeTopContentComponent: Private.NodeTopContent {}
209 
218  property Component nodeCenterContentComponent: Private.NodeCenterContent {}
219 
231  property Component nodeLeftPortComponent: Private.NodeLeftPort {}
232 
244  property Component nodeRightPortComponent: Private.NodeRightPort {}
245 
257  property Component nodePortConnectorComponent: Private.NodePortConnector {}
258 
264  property Component nodePortConnectorMouseArea: Private.NodePortConnectorMouseArea {}
265 
273  property Component snapGridComponent: Private.SnapGrid {}
274 
278  property ObjectModel connectionsModel: ObjectModel {}
279 
288  signal connectionAdded(int fromNodeId, int fromPortId, int toNodeId, int toPortId)
289 
290 
298  signal connectionRemoved(int fromNodeId, int fromPortId, int toNodeId, int toPortId)
299 
300 
306  signal nodeRemoved(int nodeId)
307 
308 
316  signal nodePositionChanged(int nodeId, real x, real y)
317 
318  Loader {
319  id: snapGrid
320  anchors.fill: parent
321  sourceComponent: nodeView.snapGridComponent
322 
323  function snapPosition(point) {
324  return item ? item.snapPosition(point) : point;
325  }
326  }
327 
328  Item {
329  id: nodesContainer
330  anchors.fill: parent
331 
332  Repeater {
333  id: nodesRepeater
334  model: nodeView.model
335 
336  delegate: Private.Node {
337  id: nodeRoot
338  }
339 
340  onItemAdded: (index, node) => updateAllConnectionComponentsByNodeId(node.nodeId);
341  onItemRemoved: (index, node) => removeAllConnectionComponentsByNodeId(node.nodeId);
342  }
343  }
344 
345  Item {
346  id: nodePortConnectorDragTarget
347  Drag.active: false
348  }
349 
350  Private.ShapeContainer {
351  id: shapeContainer
352  }
353 
361  function findConnectorRow(nodeId, portId) {
362  for(var nodeIndex = 0; nodeIndex < nodesRepeater.count; nodeIndex++) {
363  var nodeElement = nodesRepeater.itemAt(nodeIndex);
364  if (nodeElement && nodeElement.nodeId === nodeId) {
365  var leftPortDockRepeater = nodeElement.leftPortDockRepeater;
366  if (leftPortDockRepeater) {
367  for(var leftPortIndex = 0; leftPortIndex < leftPortDockRepeater.count; leftPortIndex++) {
368  var leftPortElement = leftPortDockRepeater.itemAt(leftPortIndex);
369  if (leftPortElement && leftPortElement.portId === portId) {
370  return leftPortElement;
371  }
372  }
373  }
374  var rightPortDockRepeater = nodeElement.rightPortDockRepeater
375  if (leftPortDockRepeater) {
376  for(var rightPortIndex = 0; rightPortIndex < rightPortDockRepeater.count; rightPortIndex++) {
377  var rightPortElement = rightPortDockRepeater.itemAt(rightPortIndex);
378  if (rightPortElement && rightPortElement.portId === portId) {
379  return rightPortElement;
380  }
381  }
382  }
383  }
384  }
385 
386  return undefined;
387  }
388 
392  function updateAllConnectionComponents() {
393  var model = nodeView.model;
394  removeAllConnectionComponents();
395  for(var nodeIndex = 0; nodeIndex < model.count; nodeIndex++) {
396  var nodeModel = model.get(nodeIndex);
397  if (nodeModel) {
398  var nodeConnections = nodeModel.connections;
399  if (nodeConnections) {
400  for (var i = 0; i < nodeConnections.count; i++) {
401  var connection = nodeConnections.get(i);
402  if (connection) {
403  var fromComponent = findConnectorRow(connection.fromNodeId, connection.fromPortId);
404  var toComponent = findConnectorRow(connection.toNodeId, connection.toPortId);
405  if (fromComponent && toComponent) {
406  addConnectionComponent(fromComponent, toComponent, connection.removable);
407  }
408  }
409  }
410  }
411  }
412  }
413  }
414 
419  function updateAllConnectionComponentsByNodeId(nodeId) {
420  var model = nodeView.model;
421  removeAllConnectionComponentsByNodeId(nodeId);
422  for(var nodeIndex = 0; nodeIndex < model.count; nodeIndex++) {
423  var nodeModel = model.get(nodeIndex);
424  if (nodeModel && nodeModel.nodeId === nodeId) {
425  var nodeConnections = nodeModel.connections;
426  if (nodeConnections) {
427  for (var i = 0; i < nodeConnections.count; i++) {
428  var connection = nodeConnections.get(i);
429  if (connection) {
430  var fromComponent = findConnectorRow(connection.fromNodeId, connection.fromPortId);
431  var toComponent = findConnectorRow(connection.toNodeId, connection.toPortId);
432  if (fromComponent && toComponent) {
433  addConnectionComponent(fromComponent, toComponent, connection.removable);
434  }
435  }
436  }
437  }
438  }
439  }
440  }
441 
448  function addConnectionComponent(from, to, removable) {
449  var connection = {to: to, from: from, connectionShape: connectionShape, style: nodeView.style, removable: removable || false};
450  connectionsModel.append(connectionComponent.createObject(from, connection));
451  }
452 
456  function removeAllConnectionComponents() {
457  for (var connectionIndex = 0; connectionIndex < connectionsModel.count;) {
458  var connectionComponent = connectionsModel.get(connectionIndex);
459  if (connectionComponent) {
460  connectionsModel.remove(connectionIndex);
461  connectionComponent.destroy();
462  }
463  }
464  }
465 
470  function removeAllConnectionComponentsByNodeId(nodeId) {
471  for (var connectionIndex = 0; connectionIndex < connectionsModel.count;) {
472  var connectionComponent = connectionsModel.get(connectionIndex);
473  if (connectionComponent && (connectionComponent.from.nodeId === nodeId || connectionComponent.to.nodeId === nodeId)) {
474  connectionsModel.remove(connectionIndex);
475  connectionComponent.destroy();
476  } else {
477  connectionIndex++;
478  }
479  }
480  }
481 
488  function removeConnectionComponent(from, to) {
489  for (var connectionIndex = 0; connectionIndex < connectionsModel.count; connectionIndex++) {
490  var connectionComponent = connectionsModel.get(connectionIndex);
491  if (connectionComponent && connectionComponent.from === from && connectionComponent.to === to) {
492  connectionsModel.remove(connectionIndex);
493  connectionComponent.destroy();
494  console.debug("Connection destroyed");
495  return true;
496  }
497  }
498  console.warn("Connection not found!");
499  return false;
500  }
501 
507  function setPortsState(state, filter) {
508  for(var nodeIndex = 0; nodeIndex < nodesRepeater.count; nodeIndex++) {
509  var nodeElement = nodesRepeater.itemAt(nodeIndex);
510  if (nodeElement) {
511  var leftPortDockRepeater = nodeElement.leftPortDockRepeater;
512  if (leftPortDockRepeater) {
513  for(var leftPortIndex = 0; leftPortIndex < leftPortDockRepeater.count; leftPortIndex++) {
514  var leftPortElement = leftPortDockRepeater.itemAt(leftPortIndex);
515  if (leftPortElement && checkFilterOnTags(leftPortElement.tags, filter)) {
516  leftPortElement.state = state;
517  }
518  }
519  }
520  var rightPortDockRepeater = nodeElement.rightPortDockRepeater
521  if (leftPortDockRepeater) {
522  for(var rightPortIndex = 0; rightPortIndex < rightPortDockRepeater.count; rightPortIndex++) {
523  var rightPortElement = rightPortDockRepeater.itemAt(rightPortIndex);
524  if (rightPortElement && checkFilterOnTags(rightPortElement.tags, filter)) {
525  rightPortElement.state = state;
526  }
527  }
528  }
529  }
530  }
531  }
532 
539  function checkFilterOnTags(tags, filter) {
540  if (!filter) {
541  return true;
542  } else if (!tags) {
543  return false;
544  }
545 
546  var tagsList = tags.split(",");
547  for (var tagIndex = 0; tagIndex < tagsList.length; tagIndex++) {
548  var filterList = filter.split(",");
549  var tagValue = tagsList[tagIndex].trim();
550  for (var filterIndex = 0; filterIndex < filterList.length; filterIndex++) {
551  var filterValue = filterList[filterIndex].trim();
552  if (tagValue === filterValue) {
553  return true;
554  }
555  }
556  }
557  return false;
558  }
559 }