diagrams-fable-qt/src/core/NetworkModel.h
Ilya Ashikhmin 26905a4ba0 feat(core): add network model with typed ports, relations and grouped properties
Data-driven node types (SVG + port config) loaded from JSON, relation-based
connection validation, and a property system supporting string, int, float,
enum, catalogue item(s), color and value-list types grouped by category.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 23:14:11 +02:00

76 lines
2.5 KiB
C++

#pragma once
#include "TypeRegistry.h"
#include "Types.h"
#include <QHash>
#include <QObject>
namespace diag {
// The document model: nodes placed on the canvas and edges connecting their
// ports. All edits are signalled so views stay in sync. Pure Qt Core/Gui —
// usable headless in tests.
class NetworkModel : public QObject {
Q_OBJECT
public:
explicit NetworkModel(TypeRegistry* registry = nullptr, QObject* parent = nullptr);
TypeRegistry* registry() const { return m_registry; }
// --- nodes ---
QUuid addNode(const QString& typeId, QPointF pos, QUuid id = {});
void removeNode(QUuid id); // cascades to attached edges
void moveNode(QUuid id, QPointF pos);
const Node* node(QUuid id) const;
QList<QUuid> nodeIds() const;
const NodeType* nodeTypeOf(QUuid id) const;
// --- edges ---
bool canConnect(QUuid nodeA, const QString& portA, QUuid nodeB, const QString& portB,
QString* reason = nullptr) const;
QUuid addEdge(QUuid fromNode, const QString& fromPort, QUuid toNode, const QString& toPort,
QUuid id = {});
void removeEdge(QUuid id);
const Edge* edge(QUuid id) const;
QList<QUuid> edgeIds() const;
QList<QUuid> edgesOfNode(QUuid nodeId) const;
int connectionCount(QUuid nodeId, const QString& portId) const;
// --- properties (values fall back to the spec default when unset) ---
void setNodeProperty(QUuid id, const QString& key, const QVariant& value);
QVariant nodeProperty(QUuid id, const QString& key) const;
void setEdgeProperty(QUuid id, const QString& key, const QVariant& value);
QVariant edgeProperty(QUuid id, const QString& key) const;
// Solver results (does not go through the undo stack).
void setEdgeFlow(QUuid id, double rate);
// Scene position of a port (node pos + relative port pos * size).
QPointF portScenePos(QUuid nodeId, const QString& portId) const;
void clear();
signals:
void nodeAdded(QUuid id);
void nodeRemoved(QUuid id);
void nodeMoved(QUuid id);
void nodeChanged(QUuid id);
void edgeAdded(QUuid id);
void edgeRemoved(QUuid id);
void edgeChanged(QUuid id);
void flowChanged(QUuid id);
void modelReset();
private:
static QVariant defaultFor(const QList<PropertySpec>& specs, const QString& key);
TypeRegistry* m_registry;
QHash<QUuid, Node> m_nodes;
QHash<QUuid, Edge> m_edges;
QList<QUuid> m_nodeOrder; // stable iteration/serialization order
QList<QUuid> m_edgeOrder;
};
} // namespace diag