Core Concepts ============= Understanding QtNodes' architecture helps you make the right design decisions for your application. Model-View Architecture ----------------------- QtNodes follows Qt's Model-View pattern. Your data (the **Model**) is separate from its visualization (the **View**). .. image:: /_static/diagrams/architecture-diagram.png :alt: Model-View architecture diagram :align: center :width: 600px .. SCREENSHOT NEEDED: architecture-diagram.png Create a simple diagram showing: +------------------+ +----------------------+ | AbstractGraph | ------> | BasicGraphicsScene | | Model | | (QGraphicsScene) | +------------------+ +----------------------+ ^ | | v Your Data +----------------------+ (nodes, connections, | GraphicsView | positions, etc.) | (QGraphicsView) | +----------------------+ Use boxes and arrows. Can be created in any diagramming tool. Size: ~600px wide **Benefits of this separation:** - Run graph logic without any GUI (headless mode) - Multiple views of the same data - Clear ownership: you own your data, the library owns the visuals - Easy testing of graph logic Nodes and Connections --------------------- Graphs consist of **nodes** and **connections**. .. image:: /_static/screenshots/node-anatomy.png :alt: Anatomy of a node :align: center :width: 400px **Node identification:** - Each node has a unique ``NodeId`` (unsigned integer) - You generate IDs in your model via ``newNodeId()`` - The library never creates or manages IDs for you **Connections:** - A ``ConnectionId`` links an output port to an input port - Contains: ``outNodeId``, ``outPortIndex``, ``inNodeId``, ``inPortIndex`` - Connections are directional: data flows from Out to In .. code-block:: cpp // A connection from Node 1, Port 0 -> Node 2, Port 0 ConnectionId conn{ .outNodeId = 1, .outPortIndex = 0, .inNodeId = 2, .inPortIndex = 0 }; The Two Programming Models -------------------------- QtNodes supports two distinct approaches: .. list-table:: :widths: 50 50 :header-rows: 1 * - **Simple Graph Model** - **Data Flow Model** * - You subclass ``AbstractGraphModel`` - You use ``DataFlowGraphModel`` + delegates * - You store all graph data yourself - Library manages node instances for you * - No automatic data propagation - Data flows automatically through connections * - Full control, more code - Less code, follows conventions * - ``BasicGraphicsScene`` - ``DataFlowGraphicsScene`` **Choose Simple Graph Model when:** - You have existing graph data structures to wrap - You need custom graph semantics - You don't need data to flow between nodes **Choose Data Flow Model when:** - Building visual programming tools - Nodes process inputs and produce outputs - You want automatic data propagation NodeRole and PortRole --------------------- The model provides data about nodes and ports through **roles** (similar to Qt's ``ItemDataRole``). **NodeRole** -- Information about a node: .. code-block:: cpp // Get node position QPointF pos = model.nodeData(nodeId, NodeRole::Position).toPointF(); // Set node caption model.setNodeData(nodeId, NodeRole::Caption, "My Node"); Key roles: ``Type``, ``Position``, ``Caption``, ``InPortCount``, ``OutPortCount``, ``Widget`` **PortRole** -- Information about a port: .. code-block:: cpp // Get port data type auto type = model.portData(nodeId, PortType::In, 0, PortRole::DataType); Key roles: ``Data``, ``DataType``, ``Caption``, ``ConnectionPolicyRole`` See :doc:`/guide/graph-models` for the complete role reference. Graphics Object Hierarchy ------------------------- When visualized, each model element becomes a graphics object: .. code-block:: text GraphicsView (QGraphicsView) └── BasicGraphicsScene (QGraphicsScene) ├── NodeGraphicsObject (for each node) │ └── Embedded QWidget (optional) └── ConnectionGraphicsObject (for each connection) **Painters** control how objects are drawn: - ``AbstractNodePainter`` → ``DefaultNodePainter`` - ``AbstractConnectionPainter`` → ``DefaultConnectionPainter`` You can replace these with custom painters for different visual styles. Data Flow Deep Dive ------------------- In the data flow model, delegates handle node-specific logic: .. image:: /_static/diagrams/dataflow-diagram.png :alt: Data flow between nodes :align: center :width: 500px .. SCREENSHOT NEEDED: dataflow-diagram.png Show data flowing through connected nodes: [Source Node] --> [Operator Node] --> [Display Node] | | | "emits data" "receives, processes, "receives, emits result" displays" Use arrows showing dataUpdated signal flow. Size: ~500px wide **The flow:** 1. Source node calls ``emit dataUpdated(portIndex)`` 2. ``DataFlowGraphModel`` catches this signal 3. It calls ``outData(port)`` on the source delegate 4. It calls ``setInData(data, port)`` on all connected delegates 5. Connected nodes process and may emit their own ``dataUpdated`` Next Steps ---------- - :doc:`/guide/graph-models` -- Implement your own graph model - :doc:`/guide/data-flow` -- Use the data flow pattern - :doc:`/examples/index` -- Study working examples