You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
5.0 KiB

  1. #ifndef PLCDOCUMENT_H
  2. #define PLCDOCUMENT_H
  3. #include "basedocument.h"
  4. #include "plcitems.h"
  5. #include <QGraphicsScene>
  6. #include <QGraphicsView>
  7. #include <QGraphicsLineItem>
  8. #include <QGraphicsRectItem>
  9. #include <QGraphicsEllipseItem>
  10. #include <QMap>
  11. #include <QSet>
  12. #include <QVector>
  13. #include <QDragEnterEvent>
  14. #include <QDragMoveEvent>
  15. #include <QDropEvent>
  16. #include <QMimeData>
  17. #include <QPair>
  18. const int DEFAULT_ROWS = 11;
  19. const int DEFAULT_COLUMNS = 15;
  20. const int DEFAULT_CELL_SIZE = 70;
  21. class PLCItem;
  22. class ConnectionLine;
  23. class PLCDocument : public BaseDocument
  24. {
  25. Q_OBJECT
  26. public:
  27. enum TerminalType {
  28. NoTerminal = 0,
  29. LeftTerminal,
  30. RightTerminal,
  31. RowTerminal
  32. };
  33. enum ConnectionSourceType {
  34. ConnectionNone, // 无连接
  35. ConnectionFromItem, // 起点是元件的端子
  36. ConnectionFromRowTerminal // 起点是行触点
  37. };
  38. explicit PLCDocument(QWidget *parent = nullptr);
  39. ~PLCDocument() override;
  40. QString title() const override;
  41. QGraphicsView *view() const { return m_view; }
  42. QGraphicsScene *scene() const { return m_scene; }
  43. bool saveToFile(const QString &filePath) override;
  44. bool loadFromFile(const QString &filePath) override;
  45. void createPLCItem(const QString &type, const QPointF &pos);
  46. void startConnection(PLCItem *startItem, TerminalType startTerminal);
  47. void startConnectionFromRowTerminal(int row);
  48. void clearCurrentConnection();
  49. bool tryEndConnection(PLCItem *endItem, TerminalType endTerminal);
  50. void setSimulationRunning(bool running);
  51. void resetSimulation();
  52. void setCurrentTool(const QString &tool) { m_currentTool = tool; }
  53. int rowCount() const { return m_rows; }
  54. int columnCount() const { return m_columns; }
  55. int cellSize() const { return m_cellSize; }
  56. QPointF snapToCellCenter(const QPointF &pos) const;
  57. QPointF constrainToTable(const QPointF &pos) const;
  58. void setTitle(const QString &title) { m_title = title; }
  59. protected:
  60. bool eventFilter(QObject *obj, QEvent *event) override;
  61. void resizeEvent(QResizeEvent *event) override;
  62. private slots:
  63. void handleSceneChanged();
  64. void onRowTerminalConnection();
  65. private:
  66. void createRealTable();
  67. //void clearTable();
  68. TerminalType whichTerminal(const QPointF& scenePos, PLCItem* item) const;
  69. bool isTerminalUsed(PLCItem* item, TerminalType terminal) const;
  70. void handleItemPositionChange(PLCItem *item);
  71. bool isCellOccupied(int col, int row, PLCItem* excludeItem) const;
  72. void updateConnections();
  73. void createContextMenu(QPoint globalPos);
  74. PLCItem* createItemByType(PLCItem::ItemType type);
  75. void removeInvalidConnectionsForItem(PLCItem* movedItem);
  76. QList<PLCItem*> allPLCItems() const;
  77. QGraphicsScene *m_scene;
  78. QGraphicsView *m_view;
  79. QString m_currentTool;
  80. ConnectionSourceType m_connectionSourceType = ConnectionNone;
  81. PLCItem *m_connectionStartItem = nullptr;
  82. TerminalType m_startTerminal = NoTerminal;
  83. int m_connectionStartRow = -1;
  84. QGraphicsLineItem *m_tempLine = nullptr;
  85. QList<ConnectionLine*> m_connections;
  86. QMap<PLCItem*, QMap<TerminalType, bool>> terminalConnections;
  87. bool m_simulationRunning = false;
  88. QSet<PLCItem*> m_activeItems;
  89. int m_rows = DEFAULT_ROWS;
  90. int m_columns = DEFAULT_COLUMNS;
  91. int m_cellSize = DEFAULT_CELL_SIZE;
  92. QGraphicsRectItem* m_tableFrame = nullptr;
  93. QVector<QGraphicsLineItem*> m_horizontalLines;
  94. QVector<QGraphicsLineItem*> m_verticalLines;
  95. QString m_title;
  96. QVector<QGraphicsEllipseItem*> m_rowTerminals;
  97. QMap<QGraphicsEllipseItem*, int> m_rowTerminalMap;
  98. QMap<PLCItem*, QPointF> m_lastValidPositions;
  99. QSet<PLCItem*> m_processingItems;
  100. bool m_loadingFile = false;
  101. };
  102. class ConnectionLine : public QGraphicsLineItem
  103. {
  104. public:
  105. ConnectionLine(
  106. PLCItem *startItem, PLCDocument::TerminalType startTerminal,
  107. PLCItem *endItem, PLCDocument::TerminalType endTerminal,
  108. QGraphicsItem *parent = nullptr
  109. );
  110. void updatePosition();
  111. PLCItem* startItem() const { return m_startItem; }
  112. PLCItem* endItem() const { return m_endItem; }
  113. PLCDocument::TerminalType startTerminal() const { return m_startTerminal; }
  114. PLCDocument::TerminalType endTerminal() const { return m_endTerminal; }
  115. void setRowTerminalTargetRow(int row) { m_rowTerminalTargetRow = row; }
  116. int rowTerminalTargetRow() const { return m_rowTerminalTargetRow; }
  117. void setRowTerminalSourceRow(int row) { m_rowTerminalSourceRow = row; }
  118. int rowTerminalSourceRow() const { return m_rowTerminalSourceRow; }
  119. void setStartTerminalPoint(const QPointF& point) { m_startTerminalPoint = point; }
  120. void setEndTerminalPoint(const QPointF& point) { m_endTerminalPoint = point; }
  121. private:
  122. PLCItem *m_startItem;
  123. PLCDocument::TerminalType m_startTerminal;
  124. PLCItem *m_endItem;
  125. PLCDocument::TerminalType m_endTerminal;
  126. QPointF m_startTerminalPoint;
  127. QPointF m_endTerminalPoint;
  128. int m_rowTerminalTargetRow = -1;
  129. int m_rowTerminalSourceRow = -1;
  130. };
  131. #endif // PLCDOCUMENT_H