diff --git a/examples/calculator/MathOperationDataModel.cpp b/examples/calculator/MathOperationDataModel.cpp index f6a3a26d..5cf03e26 100644 --- a/examples/calculator/MathOperationDataModel.cpp +++ b/examples/calculator/MathOperationDataModel.cpp @@ -1,5 +1,4 @@ #include "MathOperationDataModel.hpp" - #include "DecimalData.hpp" unsigned int MathOperationDataModel::nPorts(PortType portType) const @@ -21,7 +20,9 @@ NodeDataType MathOperationDataModel::dataType(PortType, PortIndex) const std::shared_ptr MathOperationDataModel::outData(PortIndex) { - return std::static_pointer_cast(_result); + auto output = std::static_pointer_cast(_result); + + return output; } void MathOperationDataModel::setInData(std::shared_ptr data, PortIndex portIndex) diff --git a/examples/calculator/MathOperationDataModel.hpp b/examples/calculator/MathOperationDataModel.hpp index 6d279642..8d56f263 100644 --- a/examples/calculator/MathOperationDataModel.hpp +++ b/examples/calculator/MathOperationDataModel.hpp @@ -1,7 +1,6 @@ #pragma once #include - #include #include #include diff --git a/include/QtNodes/internal/BasicGraphicsScene.hpp b/include/QtNodes/internal/BasicGraphicsScene.hpp index 568835ff..6bb30d67 100644 --- a/include/QtNodes/internal/BasicGraphicsScene.hpp +++ b/include/QtNodes/internal/BasicGraphicsScene.hpp @@ -5,7 +5,6 @@ #include "ConnectionIdHash.hpp" #include "Definitions.hpp" #include "Export.hpp" - #include "QUuidStdHash.hpp" #include @@ -17,7 +16,6 @@ #include #include - class QUndoStack; namespace QtNodes { @@ -29,7 +27,7 @@ class ConnectionGraphicsObject; class NodeGraphicsObject; class NodeStyle; -/// An instance of QGraphicsScene, holds connections and nodes. +/// An instance of QGraphicsScene , holds connections and nodes. class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene { Q_OBJECT @@ -112,6 +110,8 @@ class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene */ virtual QMenu *createSceneMenu(QPointF const scenePos); + void freezeModelAndConnections(bool isFreeze); + Q_SIGNALS: void modified(BasicGraphicsScene *); void nodeMoved(NodeId const nodeId, QPointF const &newLocation); diff --git a/include/QtNodes/internal/ConnectionState.hpp b/include/QtNodes/internal/ConnectionState.hpp index ddd31cdb..d1373826 100644 --- a/include/QtNodes/internal/ConnectionState.hpp +++ b/include/QtNodes/internal/ConnectionState.hpp @@ -25,6 +25,7 @@ class NODE_EDITOR_PUBLIC ConnectionState ConnectionState(ConnectionGraphicsObject &cgo) : _cgo(cgo) , _hovered(false) + , _frozen(false) {} ConnectionState(ConnectionState const &) = delete; @@ -42,6 +43,9 @@ class NODE_EDITOR_PUBLIC ConnectionState bool hovered() const; void setHovered(bool hovered); + bool frozen() const { return _frozen; } + void setFrozen(bool frozen) { _frozen = frozen; } + public: /// Caches NodeId for further interaction. void setLastHoveredNode(NodeId const nodeId); @@ -56,5 +60,7 @@ class NODE_EDITOR_PUBLIC ConnectionState bool _hovered; NodeId _lastHoveredNode{InvalidNodeId}; + + bool _frozen; }; } // namespace QtNodes diff --git a/include/QtNodes/internal/DataFlowGraphicsScene.hpp b/include/QtNodes/internal/DataFlowGraphicsScene.hpp index e9f89cac..30bcc949 100644 --- a/include/QtNodes/internal/DataFlowGraphicsScene.hpp +++ b/include/QtNodes/internal/DataFlowGraphicsScene.hpp @@ -1,8 +1,10 @@ #pragma once #include "BasicGraphicsScene.hpp" +#include "ConnectionGraphicsObject.hpp" #include "DataFlowGraphModel.hpp" #include "Export.hpp" +#include "NodeConnectionInteraction.hpp" namespace QtNodes { @@ -22,6 +24,7 @@ class NODE_EDITOR_PUBLIC DataFlowGraphicsScene : public BasicGraphicsScene public: std::vector selectedNodes() const; QMenu *createSceneMenu(QPointF const scenePos) override; + void updateConnectionGraphics(const std::unordered_set &connections, bool state); public Q_SLOTS: bool save() const; diff --git a/include/QtNodes/internal/NodeDelegateModel.hpp b/include/QtNodes/internal/NodeDelegateModel.hpp index 04cc78a1..6aa10bad 100644 --- a/include/QtNodes/internal/NodeDelegateModel.hpp +++ b/include/QtNodes/internal/NodeDelegateModel.hpp @@ -12,6 +12,7 @@ #include "NodeData.hpp" #include "NodeStyle.hpp" #include "Serializable.hpp" +#include namespace QtNodes { @@ -132,6 +133,10 @@ class NODE_EDITOR_PUBLIC NodeDelegateModel virtual bool resizable() const { return false; } + bool frozen() const { return _frozen; } + + void setFrozenState(bool state) { _frozen = state; } + public Q_SLOTS: virtual void inputConnectionCreated(ConnectionId const &) {} virtual void inputConnectionDeleted(ConnectionId const &) {} @@ -185,6 +190,8 @@ public Q_SLOTS: private: NodeStyle _nodeStyle; + bool _frozen{false}; + NodeValidationState _nodeValidationState; NodeProcessingStatus _processingStatus{NodeProcessingStatus::NoStatus}; diff --git a/src/BasicGraphicsScene.cpp b/src/BasicGraphicsScene.cpp index 84bf9a31..91bebfc1 100644 --- a/src/BasicGraphicsScene.cpp +++ b/src/BasicGraphicsScene.cpp @@ -3,14 +3,20 @@ #include "AbstractNodeGeometry.hpp" #include "ConnectionGraphicsObject.hpp" #include "ConnectionIdUtils.hpp" +#include "DataFlowGraphModel.hpp" #include "DefaultConnectionPainter.hpp" #include "DefaultHorizontalNodeGeometry.hpp" #include "DefaultNodePainter.hpp" #include "DefaultVerticalNodeGeometry.hpp" +#include "NodeDelegateModel.hpp" #include "NodeGraphicsObject.hpp" #include +#include +#include +#include +#include #include #include @@ -327,4 +333,31 @@ void BasicGraphicsScene::onModelReset() traverseGraphAndPopulateGraphicsObjects(); } +void BasicGraphicsScene::freezeModelAndConnections(bool isFreeze) +{ + for (QGraphicsItem *item : selectedItems()) { + if (auto n = qgraphicsitem_cast(item)) { + int portCount = graphModel().nodeData(n->nodeId(), NodeRole::OutPortCount).toInt(); + for (int i = 0; i < portCount; i++) { + auto graphConnections = graphModel().connections(n->nodeId(), + QtNodes::PortType::Out, + QtNodes::PortIndex(i)); + + for (auto const &c : graphConnections) { + if (auto *cgo = connectionGraphicsObject(c)) { + cgo->connectionState().setFrozen(isFreeze); + cgo->update(); + } + } + } + + if (auto *dfModel = dynamic_cast(&graphModel())) { + if (auto *delegate = dfModel->delegateModel(n->nodeId())) { + delegate->setFrozenState(isFreeze); + } + } + } + } +} + } // namespace QtNodes diff --git a/src/DataFlowGraphModel.cpp b/src/DataFlowGraphModel.cpp index fa5655cd..275d7639 100644 --- a/src/DataFlowGraphModel.cpp +++ b/src/DataFlowGraphModel.cpp @@ -444,6 +444,9 @@ bool DataFlowGraphModel::setPortData( switch (role) { case PortRole::Data: if (portType == PortType::In) { + if (model->frozen()) + return false; + model->setInData(value.value>(), portIndex); // Triggers repainting on the scene. diff --git a/src/DataFlowGraphicsScene.cpp b/src/DataFlowGraphicsScene.cpp index 32970608..b232164a 100644 --- a/src/DataFlowGraphicsScene.cpp +++ b/src/DataFlowGraphicsScene.cpp @@ -26,7 +26,6 @@ #include #include - namespace QtNodes { DataFlowGraphicsScene::DataFlowGraphicsScene(DataFlowGraphModel &graphModel, QObject *parent) @@ -191,4 +190,15 @@ bool DataFlowGraphicsScene::load() return true; } +void DataFlowGraphicsScene::updateConnectionGraphics( + const std::unordered_set &connections, bool state) +{ + for (auto const &c : connections) { + if (auto *cgo = connectionGraphicsObject(c)) { + cgo->connectionState().setFrozen(state); + cgo->update(); + } + } +} + } // namespace QtNodes diff --git a/src/DefaultConnectionPainter.cpp b/src/DefaultConnectionPainter.cpp index a7079ebd..d9c11333 100644 --- a/src/DefaultConnectionPainter.cpp +++ b/src/DefaultConnectionPainter.cpp @@ -9,7 +9,6 @@ #include - namespace QtNodes { QPainterPath DefaultConnectionPainter::cubicPath(ConnectionGraphicsObject const &connection) const @@ -27,11 +26,12 @@ QPainterPath DefaultConnectionPainter::cubicPath(ConnectionGraphicsObject const return cubic; } -void DefaultConnectionPainter::drawSketchLine(QPainter *painter, ConnectionGraphicsObject const &cgo) const +void DefaultConnectionPainter::drawSketchLine(QPainter *painter, + ConnectionGraphicsObject const &cgo) const { ConnectionState const &state = cgo.connectionState(); - if (state.requiresPort()) { + if (state.requiresPort() || state.frozen()) { auto const &connectionStyle = QtNodes::StyleCollection::connectionStyle(); QPen pen; @@ -49,7 +49,8 @@ void DefaultConnectionPainter::drawSketchLine(QPainter *painter, ConnectionGraph } } -void DefaultConnectionPainter::drawHoveredOrSelected(QPainter *painter, ConnectionGraphicsObject const &cgo) const +void DefaultConnectionPainter::drawHoveredOrSelected(QPainter *painter, + ConnectionGraphicsObject const &cgo) const { bool const hovered = cgo.connectionState().hovered(); bool const selected = cgo.isSelected(); @@ -74,11 +75,12 @@ void DefaultConnectionPainter::drawHoveredOrSelected(QPainter *painter, Connecti } } -void DefaultConnectionPainter::drawNormalLine(QPainter *painter, ConnectionGraphicsObject const &cgo) const +void DefaultConnectionPainter::drawNormalLine(QPainter *painter, + ConnectionGraphicsObject const &cgo) const { ConnectionState const &state = cgo.connectionState(); - if (state.requiresPort()) + if (state.requiresPort() || state.frozen()) return; // colors @@ -132,6 +134,7 @@ void DefaultConnectionPainter::drawNormalLine(QPainter *painter, ConnectionGraph painter->setBrush(Qt::NoBrush); QColor cOut = normalColorOut; + if (selected) cOut = cOut.darker(200); p.setColor(cOut); @@ -200,7 +203,8 @@ void DefaultConnectionPainter::paint(QPainter *painter, ConnectionGraphicsObject painter->drawEllipse(cgo.in(), pointRadius, pointRadius); } -QPainterPath DefaultConnectionPainter::getPainterStroke(ConnectionGraphicsObject const &connection) const +QPainterPath DefaultConnectionPainter::getPainterStroke( + ConnectionGraphicsObject const &connection) const { auto cubic = cubicPath(connection); diff --git a/src/GraphicsView.cpp b/src/GraphicsView.cpp index c587f081..750d86fd 100644 --- a/src/GraphicsView.cpp +++ b/src/GraphicsView.cpp @@ -2,6 +2,8 @@ #include "BasicGraphicsScene.hpp" #include "ConnectionGraphicsObject.hpp" +#include "DataFlowGraphModel.hpp" +#include "NodeDelegateModel.hpp" #include "NodeGraphicsObject.hpp" #include "StyleCollection.hpp" #include "UndoCommands.hpp" @@ -23,7 +25,10 @@ #include using QtNodes::BasicGraphicsScene; +using QtNodes::DataFlowGraphModel; using QtNodes::GraphicsView; +using QtNodes::NodeDelegateModel; +using QtNodes::NodeGraphicsObject; GraphicsView::GraphicsView(QWidget *parent) : QGraphicsView(parent) @@ -75,8 +80,7 @@ QAction *GraphicsView::deleteSelectionAction() const void GraphicsView::setScene(BasicGraphicsScene *scene) { QGraphicsView::setScene(scene); - if (!scene) - { + if (!scene) { // Clear actions. delete _clearSelectionAction; delete _deleteSelectionAction; @@ -186,7 +190,8 @@ void GraphicsView::contextMenuEvent(QContextMenuEvent *event) return; } - if (!nodeScene()) return; + if (!nodeScene()) + return; auto const scenePos = mapToScene(event->pos()); @@ -291,14 +296,16 @@ void GraphicsView::setupScale(double scale) void GraphicsView::onDeleteSelectedObjects() { - if (!nodeScene()) return; + if (!nodeScene()) + return; nodeScene()->undoStack().push(new DeleteCommand(nodeScene())); } void GraphicsView::onDuplicateSelectedObjects() { - if (!nodeScene()) return; + if (!nodeScene()) + return; QPointF const pastePosition = scenePastePosition(); @@ -308,14 +315,16 @@ void GraphicsView::onDuplicateSelectedObjects() void GraphicsView::onCopySelectedObjects() { - if (!nodeScene()) return; + if (!nodeScene()) + return; nodeScene()->undoStack().push(new CopyCommand(nodeScene())); } void GraphicsView::onPasteObjects() { - if (!nodeScene()) return; + if (!nodeScene()) + return; QPointF const pastePosition = scenePastePosition(); nodeScene()->undoStack().push(new PasteCommand(nodeScene(), pastePosition)); @@ -360,7 +369,8 @@ void GraphicsView::mouseMoveEvent(QMouseEvent *event) { QGraphicsView::mouseMoveEvent(event); - if (!scene()) return; + if (!scene()) + return; if (scene()->mouseGrabberItem() == nullptr && event->buttons() == Qt::LeftButton) { // Make sure shift is not being pressed