#pragma once #include #include #include #include #include #include #include #include namespace QtNodes { using NodeId = unsigned int; class BasicGraphicsScene; } // namespace QtNodes class ZoomGraphicsView; class AudioLevelMeter; class WarpGraphModel; class NodeVolumeWidget; class QLabel; class QScrollArea; class QSplitter; class QTabWidget; class QSlider; class QTimer; class QAction; class QMenu; class DeleteVirtualNodeCommand; enum class ConnectionStyleType : uint8_t { kBezier = 0, kSquare, }; class GraphEditorWidget : public QWidget { Q_OBJECT friend class DeleteVirtualNodeCommand; public: explicit GraphEditorWidget(warppipe::Client *client, QWidget *parent = nullptr); ~GraphEditorWidget() override; int nodeCount() const; int linkCount() const; void setDebugScreenshotDir(const QString &dir); bool eventFilter(QObject *obj, QEvent *event) override; Q_SIGNALS: void graphReady(); private slots: void onRefreshTimer(); void onContextMenuRequested(const QPoint &pos); void scheduleSaveLayout(); protected: virtual QAction *execMenuAction(QMenu &menu, const QPoint &screenPos); virtual QString promptTextInput(const QString &title, const QString &label, bool *ok); virtual QString chooseSaveFilePath(const QString &title, const QString &initialDir, const QString &filter); virtual QString chooseOpenFilePath(const QString &title, const QString &initialDir, const QString &filter); virtual void showWarningDialog(const QString &title, const QString &message); private: void showCanvasContextMenu(const QPoint &screenPos, const QPointF &scenePos); void showNodeContextMenu(const QPoint &screenPos, uint32_t pwNodeId, QtNodes::NodeId qtNodeId); void createVirtualNode(bool isSink, const QPointF &scenePos); void captureDebugScreenshot(const QString &event); void deleteSelection(); void copySelection(); void pasteSelection(const QPointF &offset); void duplicateSelection(); void removeDefaultActions(); void tryResolvePendingLinks(); void saveLayoutWithViewState(); void restoreViewState(); void savePreset(); void loadPreset(); void wireVolumeWidget(QtNodes::NodeId nodeId); void rebuildMixerStrips(); void updateMeters(); void rebuildNodeMeters(); void rebuildRulesList(); void showAddRuleDialog(const std::string &prefillApp = {}, const std::string &prefillBin = {}, const std::string &prefillRole = {}, const std::string &prefillTarget = {}, warppipe::RuleId editRuleId = {}, warppipe::RuleDirection prefillDirection = warppipe::RuleDirection::kPlayback, const std::string &prefillSource = {}); void setConnectionStyle(ConnectionStyleType style); void onSelectionChanged(); void updateNodeDetailsPanel(QtNodes::NodeId nodeId); void clearNodeDetailsPanel(); struct PendingPasteLink { std::string outNodeName; std::string outPortName; std::string inNodeName; std::string inPortName; }; warppipe::Client *m_client = nullptr; WarpGraphModel *m_model = nullptr; QtNodes::BasicGraphicsScene *m_scene = nullptr; ZoomGraphicsView *m_view = nullptr; QSplitter *m_splitter = nullptr; QTabWidget *m_sidebar = nullptr; QTimer *m_refreshTimer = nullptr; QTimer *m_changeTimer = nullptr; QTimer *m_saveTimer = nullptr; QString m_layoutPath; QString m_presetDir; QString m_debugScreenshotDir; bool m_graphReady = false; QJsonObject m_clipboardJson; std::vector m_pendingPasteLinks; QPointF m_lastContextMenuScenePos; QWidget *m_mixerContainer = nullptr; QScrollArea *m_mixerScroll = nullptr; std::unordered_map m_mixerStrips; QTimer *m_meterTimer = nullptr; AudioLevelMeter *m_masterMeterL = nullptr; AudioLevelMeter *m_masterMeterR = nullptr; QWidget *m_nodeMeterContainer = nullptr; QScrollArea *m_nodeMeterScroll = nullptr; struct NodeMeterRow { QWidget *widget = nullptr; AudioLevelMeter *meter = nullptr; QLabel *label = nullptr; }; std::unordered_map m_nodeMeters; QWidget *m_rulesContainer = nullptr; QScrollArea *m_rulesScroll = nullptr; ConnectionStyleType m_connectionStyle = ConnectionStyleType::kBezier; QSlider *m_zoomSensSlider = nullptr; QLabel *m_zoomSensValue = nullptr; QSlider *m_zoomMinSlider = nullptr; QLabel *m_zoomMinValue = nullptr; QSlider *m_zoomMaxSlider = nullptr; QLabel *m_zoomMaxValue = nullptr; QWidget *m_nodeDetailsContainer = nullptr; QScrollArea *m_nodeDetailsScroll = nullptr; QtNodes::NodeId m_selectedNodeId = 0; };