|
- #ifndef PLCDOCUMENT_H
- #define PLCDOCUMENT_H
-
- #include "basedocument.h"
- #include "plcitems.h"
- #include <QGraphicsScene>
- #include <QGraphicsView>
- #include <QGraphicsLineItem>
- #include <QGraphicsRectItem>
- #include <QGraphicsEllipseItem>
- #include <QMap>
- #include <QSet>
- #include <QVector>
- #include <QDragEnterEvent>
- #include <QDragMoveEvent>
- #include <QDropEvent>
- #include <QMimeData>
- #include <QPair>
-
- const int DEFAULT_ROWS = 11;
- const int DEFAULT_COLUMNS = 24;
- const int DEFAULT_CELL_SIZE = 70;
-
- class PLCItem;
- class ConnectionLine;
-
- class PLCDocument : public BaseDocument
- {
- Q_OBJECT
- public:
- enum TerminalType
- {
- NoTerminal = 0,
- LeftTerminal,
- RightTerminal,
- RowTerminal
- };
-
- enum ConnectionSourceType
- {
- ConnectionNone, // 无连接
- ConnectionFromItem, // 起点是元件的端子
- ConnectionFromRowTerminal // 起点是行触点
- };
-
- explicit PLCDocument(QWidget *parent = nullptr);
- ~PLCDocument() override;
-
- QString title() const override;
- QGraphicsView *view() const { return m_view; }
- QGraphicsScene *scene() const { return m_scene; }
-
- bool saveToFile(const QString &filePath) override;
- bool loadFromFile(const QString &filePath) override;
-
- void createPLCItem(const QString &type, const QPointF &pos);
- void startConnection(PLCItem *startItem, TerminalType startTerminal);
- void startConnectionFromRowTerminal(int row);
- void clearCurrentConnection();
- bool tryEndConnection(PLCItem *endItem, TerminalType endTerminal);
- void setSimulationRunning(bool running);
- void resetSimulation();
- void setCurrentTool(const QString &tool) { m_currentTool = tool; }
-
- int rowCount() const { return m_rows; }
- int columnCount() const { return m_columns; }
- int cellSize() const { return m_cellSize; }
-
- QPointF snapToCellCenter(const QPointF &pos) const;
- QPointF constrainToTable(const QPointF &pos) const;
-
- void setTitle(const QString &title) { m_title = title; }
-
- void deleteSelectedItems();
- void copySelectedItem();
- void pasteItem();
-
- protected:
- bool eventFilter(QObject *obj, QEvent *event) override;
- void keyPressEvent(QKeyEvent* event) override;
-
- private slots:
- void handleSceneChanged();
- void onRowTerminalConnection();
-
- private:
- QList<ConnectionLine*> findConnectionsUnderItem(PLCItem* item) const;
- bool lineIntersectsRect(const QLineF& line, const QRectF& rect) const;
- bool splitConnection(ConnectionLine* originalLine, PLCItem* insertItem);
- bool isPointOnLineSegment(const QPointF& point, const QLineF& line) const;
- void createRealTable();
- TerminalType whichTerminal(const QPointF& scenePos, PLCItem* item) const;
- bool isTerminalUsed(PLCItem* item, TerminalType terminal) const;
- void handleItemPositionChange(PLCItem *item);
- bool isCellOccupied(int col, int row, PLCItem* excludeItem) const;
- void updateConnections();
- void createContextMenu(QPoint globalPos);
- PLCItem* createItemByType(PLCItem::ItemType type);
- void removeInvalidConnectionsForItem(PLCItem* movedItem);
- QList<PLCItem*> allPLCItems() const;
-
- // 新增:获取元件在连线上的位置比例(0-1)
- qreal getPositionRatioOnLine(PLCItem* item, ConnectionLine* line) const;
-
- QGraphicsScene *m_scene;
- QGraphicsView *m_view;
- QString m_currentTool;
- ConnectionSourceType m_connectionSourceType = ConnectionNone;
- PLCItem *m_connectionStartItem = nullptr;
- TerminalType m_startTerminal = NoTerminal;
- int m_connectionStartRow = -1;
- QGraphicsLineItem *m_tempLine = nullptr;
- QList<ConnectionLine*> m_connections;
- QMap<PLCItem*, QMap<TerminalType, bool>> terminalConnections;
- bool m_simulationRunning = false;
- QSet<PLCItem*> m_activeItems;
- int m_rows = DEFAULT_ROWS;
- int m_columns = DEFAULT_COLUMNS;
- int m_cellSize = DEFAULT_CELL_SIZE;
- QGraphicsRectItem* m_tableFrame = nullptr;
- QVector<QGraphicsLineItem*> m_horizontalLines;
- QVector<QGraphicsLineItem*> m_verticalLines;
- QString m_title;
- QVector<QGraphicsEllipseItem*> m_rowTerminals;
- QMap<QGraphicsEllipseItem*, int> m_rowTerminalMap;
- QMap<PLCItem*, QPointF> m_lastValidPositions;
- QSet<PLCItem*> m_processingItems;
- bool m_loadingFile = false;
-
- PLCItem* m_copiedItem = nullptr;
- };
-
- class ConnectionLine : public QGraphicsLineItem
- {
- public:
- ConnectionLine(
- PLCItem *startItem, PLCDocument::TerminalType startTerminal,
- PLCItem *endItem, PLCDocument::TerminalType endTerminal,
- QGraphicsItem *parent = nullptr
- );
-
- void updatePosition();
-
- PLCItem* startItem() const { return m_startItem; }
- PLCItem* endItem() const { return m_endItem; }
- PLCDocument::TerminalType startTerminal() const { return m_startTerminal; }
- PLCDocument::TerminalType endTerminal() const { return m_endTerminal; }
- void setRowTerminalTargetRow(int row) { m_rowTerminalTargetRow = row; }
- int rowTerminalTargetRow() const { return m_rowTerminalTargetRow; }
- void setRowTerminalSourceRow(int row) { m_rowTerminalSourceRow = row; }
- int rowTerminalSourceRow() const { return m_rowTerminalSourceRow; }
- void setStartTerminalPoint(const QPointF& point) { m_startTerminalPoint = point; }
- void setEndTerminalPoint(const QPointF& point) { m_endTerminalPoint = point; }
-
- // 新增:设置这条连线是否正在被处理
- void setProcessing(bool processing) { m_processing = processing; }
- bool isProcessing() const { return m_processing; }
-
- private:
- PLCItem *m_startItem;
- PLCDocument::TerminalType m_startTerminal;
- PLCItem *m_endItem;
- PLCDocument::TerminalType m_endTerminal;
- QPointF m_startTerminalPoint;
- QPointF m_endTerminalPoint;
- int m_rowTerminalTargetRow = -1;
- int m_rowTerminalSourceRow = -1;
- bool m_processing = false; // 用于防止递归处理
- };
-
- #endif // PLCDOCUMENT_H
|