potato/src/gui/PipeWireGraphModel.h
2026-01-27 15:24:29 -07:00

91 lines
4.1 KiB
C++

#pragma once
#include "pipewire/pipewirecontroller.h"
#include <QtNodes/AbstractGraphModel>
#include <QPointF>
#include <QSize>
#include <QHash>
#include <QString>
#include <QJsonObject>
#include <QJsonArray>
#include <cstdint>
#include <unordered_map>
#include <unordered_set>
class PipeWireGraphModel : public QtNodes::AbstractGraphModel
{
Q_OBJECT
public:
explicit PipeWireGraphModel(Potato::PipeWireController *controller, QObject *parent = nullptr);
QtNodes::NodeId newNodeId() override;
std::unordered_set<QtNodes::NodeId> allNodeIds() const override;
std::unordered_set<QtNodes::ConnectionId> allConnectionIds(QtNodes::NodeId const nodeId) const override;
std::unordered_set<QtNodes::ConnectionId> connections(QtNodes::NodeId nodeId,
QtNodes::PortType portType,
QtNodes::PortIndex portIndex) const override;
bool connectionExists(QtNodes::ConnectionId const connectionId) const override;
QtNodes::NodeId addNode(QString const nodeType = QString()) override;
bool connectionPossible(QtNodes::ConnectionId const connectionId) const override;
void addConnection(QtNodes::ConnectionId const connectionId) override;
bool nodeExists(QtNodes::NodeId const nodeId) const override;
QVariant nodeData(QtNodes::NodeId nodeId, QtNodes::NodeRole role) const override;
bool setNodeData(QtNodes::NodeId nodeId, QtNodes::NodeRole role, QVariant value) override;
QVariant portData(QtNodes::NodeId nodeId,
QtNodes::PortType portType,
QtNodes::PortIndex portIndex,
QtNodes::PortRole role) const override;
bool setPortData(QtNodes::NodeId nodeId,
QtNodes::PortType portType,
QtNodes::PortIndex portIndex,
QVariant const &value,
QtNodes::PortRole role = QtNodes::PortRole::Data) override;
bool deleteConnection(QtNodes::ConnectionId const connectionId) override;
bool deleteNode(QtNodes::NodeId const nodeId) override;
QJsonObject saveNode(QtNodes::NodeId const) const override;
void loadNode(QJsonObject const &) override;
QtNodes::NodeId addPipeWireNode(const Potato::NodeInfo &node);
void removePipeWireNode(uint32_t nodeId);
bool addPipeWireConnection(const Potato::LinkInfo &link, QtNodes::ConnectionId *connectionId);
void removePipeWireConnection(uint32_t linkId);
bool findConnectionForLink(uint32_t linkId, QtNodes::ConnectionId &connectionId) const;
const Potato::NodeInfo *nodeInfo(QtNodes::NodeId nodeId) const;
bool connectionIdForLink(const Potato::LinkInfo &link, QtNodes::ConnectionId &connectionId) const;
void reset();
void loadLayout();
void saveLayout() const;
void saveLayoutAs(const QString &path) const;
void autoArrange();
void resetLayout();
QString defaultLayoutPath() const;
void setViewState(double scale, const QPointF &center);
bool viewState(double &scale, QPointF &center) const;
private:
QtNodes::ConnectionId connectionFromPipeWire(const Potato::LinkInfo &link, bool *ok) const;
bool findPortIndex(const Potato::NodeInfo &node, uint32_t portId, QtNodes::PortType type, QtNodes::PortIndex &index) const;
QString portLabel(const Potato::PortInfo &port) const;
QPointF nextPosition() const;
QString layoutFilePath() const;
void updateLayoutForNode(QtNodes::NodeId nodeId, QPointF position);
void writeLayoutToFile(const QString &path) const;
void applyLayoutData(const QJsonArray &nodes);
Potato::PipeWireController *m_controller = nullptr;
QtNodes::NodeId m_nextNodeId = 1;
std::unordered_map<QtNodes::NodeId, Potato::NodeInfo> m_nodes;
std::unordered_map<uint32_t, QtNodes::NodeId> m_pwToNode;
std::unordered_set<QtNodes::ConnectionId> m_connections;
std::unordered_map<uint32_t, QtNodes::ConnectionId> m_linkIdToConnection;
std::unordered_map<QtNodes::NodeId, QPointF> m_positions;
QHash<QString, QPointF> m_layoutByStableId;
QPointF m_viewCenter = QPointF(0, 0);
double m_viewScale = 1.0;
bool m_hasViewState = false;
};