|
- #include "plcdocument.h"
- #include "plcitems.h"
- #include <QPainter>
- #include <QPen>
- #include <QBrush>
- #include <QMenu>
- #include <QAction>
- #include <QGraphicsSceneMouseEvent>
- #include <QJsonDocument>
- #include <QJsonObject>
- #include <QJsonArray>
- #include <QFile>
- #include <QFileInfo>
- #include <QVBoxLayout>
- #include <QMessageBox>
- #include <QInputDialog>
- #include <QDragEnterEvent>
- #include <QDragMoveEvent>
- #include <QCursor>
- #include <QDropEvent>
- #include <QMimeData>
- #include <cmath>
- #include <QResizeEvent>
- #include <QDebug>
- #include <QGraphicsItem>
- #include <QSet>
- #include <QMap>
- #include <QPointer>
- #include <QScrollArea>
- #include <QKeyEvent>
-
- PLCDocument::PLCDocument(QWidget *parent)
- : BaseDocument(PLC, parent)
- , m_rows(DEFAULT_ROWS)
- , m_columns(DEFAULT_COLUMNS)
- , m_cellSize(DEFAULT_CELL_SIZE)
- {
- m_scene = new QGraphicsScene(this);
- m_scene->setSceneRect(0, 0, m_columns * m_cellSize, m_rows * m_cellSize);
-
- m_view = new QGraphicsView(m_scene, this);
- m_view->setRenderHint(QPainter::Antialiasing);
- m_view->setDragMode(QGraphicsView::RubberBandDrag);
- m_view->setMouseTracking(true);
- m_view->viewport()->installEventFilter(this);
- m_view->setAlignment(Qt::AlignLeft | Qt::AlignTop);
-
- QScrollArea *scrollArea = new QScrollArea(this);
- scrollArea->setWidget(m_view);
- scrollArea->setWidgetResizable(true);
-
- auto layout = new QVBoxLayout(this);
- layout->setContentsMargins(0, 0, 0, 0);
- layout->addWidget(scrollArea);
- setLayout(layout);
- m_view->setAcceptDrops(true);
- createRealTable();
-
- connect(m_scene, &QGraphicsScene::selectionChanged, this, [this]()
- {
- auto items = m_scene->selectedItems();
- if (items.size() == 1 && dynamic_cast<PLCItem*>(items.first()))
- {
- clearCurrentConnection();
- }
- });
-
- connect(m_scene, &QGraphicsScene::changed, this, &PLCDocument::handleSceneChanged);
- }
-
- PLCDocument::~PLCDocument()
- {
- qDeleteAll(m_connections);
- m_copiedItem = nullptr;
- }
-
- QString PLCDocument::title() const {
- return "PLC文档";
- }
-
- void PLCDocument::createRealTable()
- {
- QRectF tableRect(0, 0, m_columns * m_cellSize, m_rows * m_cellSize);
- m_tableFrame = new QGraphicsRectItem(tableRect);
- m_tableFrame->setPen(QPen(Qt::black, 2));
- m_tableFrame->setBrush(QBrush(QColor(228, 255, 202)));
- m_tableFrame->setZValue(-10);
- m_scene->addItem(m_tableFrame);
-
- for (int col = 0; col <= m_columns; col++) {
- int x = col * m_cellSize;
- QGraphicsLineItem* line = new QGraphicsLineItem(x, 0, x, m_rows * m_cellSize);
- line->setPen(QPen(Qt::darkGray, 1));
- line->setZValue(-9);
- m_scene->addItem(line);
- m_verticalLines.append(line);
- }
-
- for (int row = 0; row <= m_rows; row++) {
- int y = row * m_cellSize;
- QGraphicsLineItem* line = new QGraphicsLineItem(0, y, m_columns * m_cellSize, y);
- line->setPen(QPen(Qt::darkGray, 1));
- line->setZValue(-9);
- m_scene->addItem(line);
- m_horizontalLines.append(line);
- }
-
- for (int row = 0; row < m_rows; row++)
- {
- const int terminalSize = 15;
- QPointF terminalPos(0, row * m_cellSize + m_cellSize / 2.0 - terminalSize / 2);
-
- QGraphicsEllipseItem* terminal = new QGraphicsEllipseItem(
- terminalPos.x(), terminalPos.y(), terminalSize, terminalSize);
-
- terminal->setFlag(QGraphicsItem::ItemIsSelectable, true);
- terminal->setFlag(QGraphicsItem::ItemIsFocusable, true);
- terminal->setAcceptHoverEvents(true);
- terminal->setVisible(true);
-
- m_scene->addItem(terminal);
- m_rowTerminals.append(terminal);
- m_rowTerminalMap[terminal] = row;
- }
- }
-
- QPointF PLCDocument::snapToCellCenter(const QPointF& pos) const
- {
- int col = static_cast<int>(std::floor(pos.x() / m_cellSize));
- int row = static_cast<int>(std::floor(pos.y() / m_cellSize));
-
- col = qBound(0, col, m_columns - 1);
- row = qBound(0, row, m_rows - 1);
-
- return QPointF(col * m_cellSize + m_cellSize / 2.0,
- row * m_cellSize + m_cellSize / 2.0);
- }
-
- QPointF PLCDocument::constrainToTable(const QPointF &pos) const
- {
- int col = static_cast<int>(std::floor(pos.x() / m_cellSize));
- int row = static_cast<int>(std::floor(pos.y() / m_cellSize));
-
- col = qBound(0, col, m_columns - 1);
- row = qBound(0, row, m_rows - 1);
-
- return QPointF(col * m_cellSize + m_cellSize / 2.0,
- row * m_cellSize + m_cellSize / 2.0);
- }
-
- bool PLCDocument::eventFilter(QObject *obj, QEvent *event)
- {
- if (obj == m_view->viewport())
- {
- if (event->type() == QEvent::DragEnter) {
- QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent*>(event);
- if (dragEvent->mimeData()->hasText()) {
- dragEvent->acceptProposedAction();
- return true;
- }
- }
- else if (event->type() == QEvent::DragMove) {
- QDragMoveEvent *dragEvent = static_cast<QDragMoveEvent*>(event);
- if(dragEvent->mimeData()->hasText()) {
- dragEvent->acceptProposedAction();
- return true;
- }
- }
- else if (event->type() == QEvent::Drop) {
- QDropEvent *dropEvent = static_cast<QDropEvent*>(event);
- const QMimeData *mimeData = dropEvent->mimeData();
- if (mimeData->hasText()) {
- QPoint viewportPos = m_view->viewport()->mapFromParent(dropEvent->pos());
- QPointF scenePos = m_view->mapToScene(viewportPos);
- QPointF cellCenter = snapToCellCenter(scenePos);
-
- QSet<int> occupiedCells;
- for (QGraphicsItem* item : m_scene->items()) {
- if (PLCItem* plcItem = dynamic_cast<PLCItem*>(item)) {
- int col = static_cast<int>(plcItem->x() / m_cellSize);
- int row = static_cast<int>(plcItem->y() / m_cellSize);
- occupiedCells.insert(col * 1000 + row);
- }
- }
-
- int col = static_cast<int>(cellCenter.x() / m_cellSize);
- int row = static_cast<int>(cellCenter.y() / m_cellSize);
- int cellKey = col * 1000 + row;
-
- if (occupiedCells.contains(cellKey)) {
- bool found = false;
- for (int offset = 1; offset < m_columns; offset++) {
- int newCol = col + offset;
- if (newCol < m_columns) {
- int newKey = newCol * 1000 + row;
- if (!occupiedCells.contains(newKey)) {
- cellCenter = QPointF(newCol * m_cellSize + m_cellSize / 2.0,
- row * m_cellSize + m_cellSize / 2.0);
- found = true;
- break;
- }
- }
- }
- if (!found) {
- for (int offset = 1; offset < m_rows; offset++) {
- int newRow = row + offset;
- if (newRow < m_rows) {
- int newKey = col * 1000 + newRow;
- if (!occupiedCells.contains(newKey)) {
- cellCenter = QPointF(col * m_cellSize + m_cellSize / 2.0,
- newRow * m_cellSize + m_cellSize / 2.0);
- found = true;
- break;
- }
- }
- }
- }
- }
-
- QString toolType = mimeData->text();
- createPLCItem(toolType, cellCenter);
- m_currentTool.clear();
- dropEvent->acceptProposedAction();
- return true;
- }
- }
- }
-
- if (obj != m_view->viewport()) {
- return QWidget::eventFilter(obj, event);
- }
-
- if (event->type() == QEvent::MouseMove && m_tempLine) {
- QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
- QPointF scenePos = m_view->mapToScene(mouseEvent->pos());
- QPointF cellCenter = snapToCellCenter(scenePos);
-
- if (m_connectionSourceType != ConnectionNone) {
- if (m_connectionSourceType == ConnectionFromItem && m_connectionStartItem) {
- if (m_startTerminal == LeftTerminal) {
- QPointF startPos = m_connectionStartItem->leftTerminal();
- QLineF line(startPos, cellCenter);
- m_tempLine->setLine(line);
- } else if (m_startTerminal == RightTerminal) {
- QPointF startPos = m_connectionStartItem->rightTerminal();
- QLineF line(startPos, cellCenter);
- m_tempLine->setLine(line);
- }
- } else if (m_connectionSourceType == ConnectionFromRowTerminal) {
- QPointF startPos(0, (m_connectionStartRow + 0.5) * m_cellSize);
- QLineF line(startPos, cellCenter);
- m_tempLine->setLine(line);
- }
- }
- }
- if (event->type() == QEvent::MouseButtonPress) {
- QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
-
- if (mouseEvent->button() == Qt::RightButton) {
- createContextMenu(mouseEvent->globalPos());
- return true;
- }
-
- if (mouseEvent->button() == Qt::LeftButton) {
- QPointF scenePos = m_view->mapToScene(mouseEvent->pos());
-
- QGraphicsEllipseItem* clickedRowTerminal = nullptr;
- int rowTerminalIndex = -1;
- for (auto terminal : m_rowTerminals) {
- QPointF localPos = terminal->mapFromScene(scenePos);
- if (terminal->contains(localPos)) {
- clickedRowTerminal = terminal;
- rowTerminalIndex = m_rowTerminalMap[terminal];
- break;
- }
- }
-
- if (clickedRowTerminal) {
- if (m_connectionSourceType != ConnectionNone) {
- if (tryEndConnection(nullptr, RowTerminal)) {
- return true;
- }
- } else {
- startConnectionFromRowTerminal(rowTerminalIndex);
- return true;
- }
- }
-
- QPointF cellCenter = snapToCellCenter(scenePos);
- QGraphicsItem *clickedItem = m_scene->itemAt(cellCenter, m_view->transform());
- PLCItem *plcItem = dynamic_cast<PLCItem*>(clickedItem);
-
- if (!m_currentTool.isEmpty()) {
- QSet<int> occupiedCells;
- for (QGraphicsItem* item : m_scene->items()) {
- if (PLCItem* existingItem = dynamic_cast<PLCItem*>(item)) {
- int col = static_cast<int>(existingItem->x() / m_cellSize);
- int row = static_cast<int>(existingItem->y() / m_cellSize);
- occupiedCells.insert(col * 1000 + row);
- }
- }
-
- int col = static_cast<int>(cellCenter.x() / m_cellSize);
- int row = static_cast<int>(cellCenter.y() / m_cellSize);
- int cellKey = col * 1000 + row;
-
- if (!occupiedCells.contains(cellKey)) {
- createPLCItem(m_currentTool, cellCenter);
- m_currentTool.clear();
- return true;
- } else {
- QMessageBox::warning(this, "位置被占用", "此单元格已被占用,请选择其他位置。");
- return true;
- }
- }
-
- if (plcItem) {
- TerminalType clickedTerminal = whichTerminal(scenePos, plcItem);
-
- if (m_connectionSourceType != ConnectionNone) {
- if (clickedTerminal != NoTerminal) {
- if (tryEndConnection(plcItem, clickedTerminal)) {
- return true;
- }
- }
- } else {
- if (clickedTerminal != NoTerminal && !isTerminalUsed(plcItem, clickedTerminal))
- {
- startConnection(plcItem, clickedTerminal);
- return true;
- }
- }
- }
- }
- }
-
- return QWidget::eventFilter(obj, event);
- }
-
- void PLCDocument::startConnectionFromRowTerminal(int row)
- {
- clearCurrentConnection();
-
- m_connectionSourceType = ConnectionFromRowTerminal;
- m_connectionStartRow = row;
-
- m_tempLine = new QGraphicsLineItem;
- m_tempLine->setPen(QPen(Qt::blue, 2, Qt::DashLine));
-
- QPointF startPos(0, (row + 0.5) * m_cellSize);
- m_tempLine->setLine(QLineF(startPos, startPos));
- m_scene->addItem(m_tempLine);
- }
-
- PLCDocument::TerminalType PLCDocument::whichTerminal(const QPointF& scenePos, PLCItem* item) const
- {
- const qreal terminalRadius = 20.0;
-
- QPointF leftTerminal = item->leftTerminal();
- qreal dxLeft = scenePos.x() - leftTerminal.x();
- qreal dyLeft = scenePos.y() - leftTerminal.y();
- qreal distLeft = std::sqrt(dxLeft*dxLeft + dyLeft*dyLeft);
-
- if (distLeft <= terminalRadius) {
- return LeftTerminal;
- }
-
- QPointF rightTerminal = item->rightTerminal();
- qreal dxRight = scenePos.x() - rightTerminal.x();
- qreal dyRight = scenePos.y() - rightTerminal.y();
- qreal distRight = std::sqrt(dxRight*dxRight + dyRight*dyRight);
-
- if (distRight <= terminalRadius) {
- return RightTerminal;
- }
-
- return NoTerminal;
- }
-
- bool PLCDocument::isTerminalUsed(PLCItem* item, TerminalType terminal) const
- {
- if (item->itemType() == PLCItem::Coil && terminal == RightTerminal)
- {
- return true;
- }
- for (ConnectionLine* line : m_connections) {
- if (line->startItem() == item && line->startTerminal() == terminal) {
- return true;
- }
- if (line->endItem() == item && line->endTerminal() == terminal) {
- return true;
- }
- }
-
- return false;
- }
-
- void PLCDocument::startConnection(PLCItem *startItem, TerminalType startTerminal)
- {
- clearCurrentConnection();
-
- m_connectionSourceType = ConnectionFromItem;
- m_connectionStartItem = startItem;
- m_startTerminal = startTerminal;
-
- m_tempLine = new QGraphicsLineItem;
- m_tempLine->setPen(QPen(Qt::blue, 2, Qt::DashLine));
-
- QPointF startPos;
- if (startTerminal == LeftTerminal) {
- startPos = startItem->leftTerminal();
- } else if (startTerminal == RightTerminal) {
- startPos = startItem->rightTerminal();
- }
-
- m_tempLine->setLine(QLineF(startPos, startPos));
- m_scene->addItem(m_tempLine);
- }
-
- bool PLCDocument::tryEndConnection(PLCItem *endItem, TerminalType endTerminal)
- {
- if (m_connectionSourceType == ConnectionFromRowTerminal) {
- if (endTerminal != LeftTerminal) {
- QMessageBox::warning(this, "连线错误", "行触点只能连接到元件的左端子");
- clearCurrentConnection();
- return false;
- }
-
- int endRow = static_cast<int>(endItem->y() / m_cellSize);
- if (endRow != m_connectionStartRow) {
- QMessageBox::warning(this, "连线错误", "行触点只能连接到同一行元件的左端子");
- clearCurrentConnection();
- return false;
- }
-
- if (isTerminalUsed(endItem, LeftTerminal)) {
- QMessageBox::warning(this, "连线错误", "该元件的左端子已被使用");
- clearCurrentConnection();
- return false;
- }
-
- ConnectionLine *connection = new ConnectionLine(
- nullptr, RowTerminal,
- endItem, LeftTerminal
- );
- connection->setStartTerminalPoint(QPointF(0, (m_connectionStartRow + 0.5) * m_cellSize));
- connection->setRowTerminalSourceRow(m_connectionStartRow);
-
- m_scene->addItem(connection);
- m_connections.append(connection);
-
- terminalConnections[endItem][LeftTerminal] = true;
-
- clearCurrentConnection();
- setModified(true);
- return true;
- }
-
- if (endTerminal == RowTerminal) {
- if (m_startTerminal != LeftTerminal) {
- QMessageBox::warning(this, "连线错误", "行触点只能连接到元件的左端子");
- clearCurrentConnection();
- return false;
- }
-
- int startRow = static_cast<int>(m_connectionStartItem->y() / m_cellSize);
- ConnectionLine *connection = new ConnectionLine(
- m_connectionStartItem, m_startTerminal,
- nullptr, RowTerminal
- );
- connection->setEndTerminalPoint(QPointF(0, (startRow + 0.5) * m_cellSize));
- connection->setRowTerminalTargetRow(startRow);
-
- m_scene->addItem(connection);
- m_connections.append(connection);
-
- terminalConnections[m_connectionStartItem][m_startTerminal] = true;
-
- clearCurrentConnection();
- setModified(true);
- return true;
- }
-
- if (m_connectionSourceType == ConnectionFromItem && m_connectionStartItem) {
- if (endItem == m_connectionStartItem && endTerminal == m_startTerminal) {
- clearCurrentConnection();
- return false;
- }
-
- int startCol = static_cast<int>(m_connectionStartItem->pos().x() / m_cellSize);
- int endCol = static_cast<int>(endItem->pos().x() / m_cellSize);
-
- if (m_startTerminal == LeftTerminal)
- {
- if (endTerminal != RightTerminal)
- {
- QMessageBox::warning(this, "连线错误", "左端子只能连接到其他元件的右端子");
- clearCurrentConnection();
- return false;
- }
- if (startCol <= endCol)
- {
- QMessageBox::warning(this, "连线错误", "左端子只能连接到左边元件的右端子");
- clearCurrentConnection();
- return false;
- }
- } else if (m_startTerminal == RightTerminal)
- {
- if (endTerminal != LeftTerminal) {
- QMessageBox::warning(this, "连线错误", "右端子只能连接到其他元件的左端子");
- clearCurrentConnection();
- return false;
- }
- if (startCol >= endCol) {
- QMessageBox::warning(this, "连线错误", "右端子只能连接到右边元件的左端子");
- clearCurrentConnection();
- return false;
- }
- }
-
- if (isTerminalUsed(endItem, endTerminal)) {
- QMessageBox::warning(this, "连线错误", "该端子已被使用");
- clearCurrentConnection();
- return false;
- }
-
- ConnectionLine *connection = new ConnectionLine(
- m_connectionStartItem, m_startTerminal,
- endItem, endTerminal
- );
-
- m_scene->addItem(connection);
- m_connections.append(connection);
-
- terminalConnections[m_connectionStartItem][m_startTerminal] = true;
- terminalConnections[endItem][endTerminal] = true;
-
- clearCurrentConnection();
- setModified(true);
- return true;
- }
-
- return false;
- }
-
- void PLCDocument::clearCurrentConnection()
- {
- if (m_tempLine) {
- m_scene->removeItem(m_tempLine);
- delete m_tempLine;
- m_tempLine = nullptr;
- }
- m_connectionSourceType = ConnectionNone;
- m_connectionStartItem = nullptr;
- m_startTerminal = NoTerminal;
- m_connectionStartRow = -1;
- }
-
- void PLCDocument::createPLCItem(const QString &type, const QPointF &pos)
- {
- PLCItem *item = nullptr;
-
- if (type == "常开") {
- item = new NormallyOpenItem;
- } else if (type == "常闭") {
- item = new NormallyClosedItem;
- } else if (type == "大于") {
- item = new GreaterThanItem;
- } else if (type == "大于等于") {
- item = new GreaterEqualItem;
- } else if (type == "小于") {
- item = new LessThanItem;
- } else if (type == "小于等于") {
- item = new LessEqualItem;
- } else if (type == "等于") {
- item = new EqualItem;
- } else if (type == "线圈") {
- item = new CoilItem;
- }
-
- if (item) {
- QPointF constrainedPos = constrainToTable(pos);
- item->setPos(constrainedPos);
- m_scene->addItem(item);
- setModified(true);
-
- terminalConnections[item][LeftTerminal] = false;
- terminalConnections[item][RightTerminal] = false;
-
- m_lastValidPositions[item] = constrainedPos;
-
- connect(item, &PLCItem::stateChanged, this, [this, item](bool active) {
- if (m_simulationRunning) {
- if (active) {
- m_activeItems.insert(item);
- } else {
- m_activeItems.remove(item);
- }
- updateConnections();
- }
- });
- }
- }
-
- void PLCDocument::handleSceneChanged()
- {
- for (auto* connection : qAsConst(m_connections))
- {
- connection->updatePosition();
- }
-
- if (m_tempLine && m_connectionSourceType != ConnectionNone)
- {
- QPointF cursorPos = m_view->mapFromGlobal(QCursor::pos());
- QPointF scenePos = m_view->mapToScene(cursorPos.toPoint());
- QLineF line = m_tempLine->line();
- line.setP2(scenePos);
- m_tempLine->setLine(line);
- }
-
- for (QGraphicsItem *item : m_scene->items())
- {
- if (PLCItem *plcItem = dynamic_cast<PLCItem*>(item))
- {
- handleItemPositionChange(plcItem);
- }
- }
- }
-
- QList<PLCItem*> PLCDocument::allPLCItems() const
- {
- QList<PLCItem*> items;
- for (QGraphicsItem *item : m_scene->items()) {
- if (PLCItem *plcItem = dynamic_cast<PLCItem*>(item)) {
- items.append(plcItem);
- }
- }
- return items;
- }
-
- bool PLCDocument::isCellOccupied(int col, int row, PLCItem* excludeItem) const
- {
- for (PLCItem* item : allPLCItems()) {
- if (item == excludeItem) continue;
-
- int itemCol = static_cast<int>(item->x() / m_cellSize);
- int itemRow = static_cast<int>(item->y() / m_cellSize);
-
- if (itemCol == col && itemRow == row) {
- return true;
- }
- }
- return false;
- }
-
- // 计算元件在连线上的位置比例(0-1)
- qreal PLCDocument::getPositionRatioOnLine(PLCItem* item, ConnectionLine* line) const
- {
- if (!item || !line) return -1;
-
- QLineF lineSeg = line->line();
- QPointF itemPos = item->pos();
-
- // 计算投影比例
- qreal dx = lineSeg.dx();
- qreal dy = lineSeg.dy();
- qreal lengthSquared = dx*dx + dy*dy;
-
- if (lengthSquared == 0) return 0;
-
- qreal t = ((itemPos.x() - lineSeg.p1().x()) * dx +
- (itemPos.y() - lineSeg.p1().y()) * dy) / lengthSquared;
-
- return qBound(0.0, t, 1.0);
- }
-
- void PLCDocument::handleItemPositionChange(PLCItem *item)
- {
- if (!item) return;
-
- if (m_loadingFile) {
- QPointF newPos = constrainToTable(item->pos());
- item->setPos(newPos);
- m_lastValidPositions[item] = newPos;
- return;
- }
-
- if (m_processingItems.contains(item)) {
- return;
- }
- m_processingItems.insert(item);
-
- QPointF newPos = constrainToTable(item->pos());
- int newCol = static_cast<int>(newPos.x() / m_cellSize);
- int newRow = static_cast<int>(newPos.y() / m_cellSize);
-
- if (isCellOccupied(newCol, newRow, item))
- {
- if (m_lastValidPositions.contains(item))
- {
- item->setPos(m_lastValidPositions[item]);
- QMessageBox::warning(this, "移动失败", "无法移动,该单元格已被占用");
- }
- }
- else
- {
- int oldCol = static_cast<int>(m_lastValidPositions[item].x() / m_cellSize);
- item->setPos(newPos);
- m_lastValidPositions[item] = newPos;
-
- if (newCol != oldCol) {
- removeInvalidConnectionsForItem(item);
- }
-
- // 获取要拆分的连线并排序
- QList<ConnectionLine*> connectionsToSplit = findConnectionsUnderItem(item);
-
- // 按元件在连线上的位置排序,确保从左到右处理
- std::sort(connectionsToSplit.begin(), connectionsToSplit.end(),
- [this, item](ConnectionLine* a, ConnectionLine* b) {
- return getPositionRatioOnLine(item, a) < getPositionRatioOnLine(item, b);
- });
-
- // 处理每条连线
- for (ConnectionLine* line : connectionsToSplit) {
- if (m_connections.contains(line) && !line->isProcessing()) {
- splitConnection(line, item);
- }
- }
-
- // 更新所有连接位置
- for (ConnectionLine *line : m_connections) {
- if (line) {
- line->updatePosition();
- }
- }
- }
-
- m_processingItems.remove(item);
- }
-
- //QList<ConnectionLine*> PLCDocument::findConnectionsUnderItem(PLCItem* item) const
- //{
- // QList<ConnectionLine*> result;
- // if (!item) return result;
-
- // QRectF itemRect = item->boundingRect();
- // itemRect.adjust(-2, -2, 2, 2);
- // QPolygonF itemPolygon = QPolygonF(itemRect).translated(item->pos());
-
- // foreach (ConnectionLine* line, m_connections) {
- // if (!line || line->isProcessing()) continue;
-
- // QLineF lineGeometry = line->line();
- // QRectF lineRect(lineGeometry.p1(), lineGeometry.p2());
- // lineRect.adjust(-10, -10, 10, 10);
-
- // if (itemPolygon.intersects(lineRect)) {
- // result.append(line);
- // }
- // }
- // return result;
- //}
-
- // 在PLCDocument类的splitConnection函数中,修改逻辑以支持行触点连线的插入
- bool PLCDocument::splitConnection(ConnectionLine* originalLine, PLCItem* insertItem)
- {
- if (!originalLine || !insertItem || originalLine->isProcessing()) {
- return false;
- }
-
- originalLine->setProcessing(true);
-
- PLCItem* originalStart = originalLine->startItem();
- TerminalType originalStartTerminal = originalLine->startTerminal();
- PLCItem* originalEnd = originalLine->endItem();
- TerminalType originalEndTerminal = originalLine->endTerminal();
-
- // 保存原始行触点信息
- int sourceRow = originalLine->rowTerminalSourceRow();
- int targetRow = originalLine->rowTerminalTargetRow();
-
- PLCItem* logicalInput = originalStart;
- TerminalType inputTerminal = originalStartTerminal;
- PLCItem* logicalOutput = originalEnd;
- TerminalType outputTerminal = originalEndTerminal;
-
- // 标准化方向时同步交换行触点信息
- if ((originalStartTerminal == LeftTerminal && originalEndTerminal == RightTerminal) ||
- (originalStartTerminal == LeftTerminal && originalEndTerminal == RowTerminal))
- {
- std::swap(logicalInput, logicalOutput);
- std::swap(inputTerminal, outputTerminal);
- std::swap(sourceRow, targetRow); // 同步交换行号
- }
-
- // 位置有效性校验
- int inputCol = (inputTerminal == RowTerminal) ? 0 :
- static_cast<int>(logicalInput->x() / m_cellSize);
-
- int outputCol = (outputTerminal == RowTerminal) ? 0 :
- static_cast<int>(logicalOutput->x() / m_cellSize);
-
- int insertCol = static_cast<int>(insertItem->x() / m_cellSize);
-
- // 统一位置验证逻辑
- bool isBetween = (insertCol > qMin(inputCol, outputCol)) &&
- (insertCol < qMax(inputCol, outputCol));
-
- if (!isBetween) {
- originalLine->setProcessing(false);
- return false;
- }
-
- // 检查端子可用性
- if (isTerminalUsed(insertItem, LeftTerminal) ||
- isTerminalUsed(insertItem, RightTerminal))
- {
- originalLine->setProcessing(false);
- return false;
- }
-
- // 创建新连线
- ConnectionLine* line1 = new ConnectionLine(
- logicalInput, inputTerminal,
- insertItem, LeftTerminal
- );
-
- // 保留行触点源信息
- if (inputTerminal == RowTerminal) {
- line1->setStartTerminalPoint(QPointF(0, (sourceRow + 0.5) * m_cellSize));
- line1->setRowTerminalSourceRow(sourceRow);
- }
-
- ConnectionLine* line2 = new ConnectionLine(
- insertItem, RightTerminal,
- logicalOutput, outputTerminal
- );
-
- // 保留行触点目标信息
- if (outputTerminal == RowTerminal) {
- line2->setEndTerminalPoint(QPointF(0, (targetRow + 0.5) * m_cellSize));
- line2->setRowTerminalTargetRow(targetRow);
- }
-
- // 添加新连线
- m_scene->addItem(line1);
- m_scene->addItem(line2);
- m_connections.append(line1);
- m_connections.append(line2);
-
- // 更新端子状态
- terminalConnections[insertItem][LeftTerminal] = true;
- terminalConnections[insertItem][RightTerminal] = true;
-
- // 移除原连线
- m_connections.removeAll(originalLine);
- m_scene->removeItem(originalLine);
- delete originalLine;
-
- setModified(true);
- originalLine->setProcessing(false);
- return true;
- }
-
-
- // 补充:确保行触点连线能被检测为"需要拆分的连线"(扩展findConnectionsUnderItem)
- QList<ConnectionLine*> PLCDocument::findConnectionsUnderItem(PLCItem* item) const
- {
- QList<ConnectionLine*> result;
- if (!item) return result;
-
- // 元件的边界框(扩大检测范围,确保行触点连线也能被检测)
- QRectF itemRect = item->boundingRect();
- itemRect.adjust(-5, -5, 5, 5); // 扩大边界框,提高检测灵敏度
- QPolygonF itemPolygon = QPolygonF(itemRect).translated(item->pos());
-
- foreach (ConnectionLine* line, m_connections) {
- if (!line || line->isProcessing()) continue;
-
- // 行触点连线的特殊处理:起点是(0, row),终点是元件左端子
- QLineF lineGeometry = line->line();
- QRectF lineRect = QRectF(lineGeometry.p1(), lineGeometry.p2()).normalized();
- lineRect.adjust(-10, -10, 10, 10); // 扩大连线的检测范围
-
- // 检查元件是否与连线相交(包括行触点连线)
- if (itemPolygon.intersects(lineRect)) {
- result.append(line);
- }
- }
- return result;
- }
-
- void PLCDocument::removeInvalidConnectionsForItem(PLCItem* movedItem)
- {
- if (!movedItem || m_connections.isEmpty()) return;
- if (m_cellSize <= 0) {
- qWarning() << "Invalid cell size!";
- return;
- }
-
- int movedCol = static_cast<int>(movedItem->x() / m_cellSize);
- QSet<ConnectionLine*> connectionsToRemove;
- bool shouldRemoveAll = false;
-
- for (ConnectionLine* line : m_connections) {
- if (!line) continue;
-
- PLCItem* otherItem = nullptr;
- TerminalType movedTerminal = NoTerminal;
- TerminalType otherTerminal = NoTerminal;
-
- if (line->startItem() == movedItem) {
- otherItem = line->endItem();
- movedTerminal = line->startTerminal();
- otherTerminal = line->endTerminal();
- } else if (line->endItem() == movedItem) {
- otherItem = line->startItem();
- movedTerminal = line->endTerminal();
- otherTerminal = line->startTerminal();
- } else {
- continue;
- }
-
- if (!otherItem) continue;
-
- int otherCol = static_cast<int>(otherItem->x() / m_cellSize);
-
- if (movedTerminal == LeftTerminal && otherTerminal == RightTerminal) {
- if (movedCol <= otherCol) {
- shouldRemoveAll = true;
- break;
- }
- } else if (movedTerminal == RightTerminal && otherTerminal == LeftTerminal) {
- if (movedCol >= otherCol) {
- shouldRemoveAll = true;
- break;
- }
- }
- }
-
- if (shouldRemoveAll) {
- for (ConnectionLine* line : m_connections) {
- if (!line) continue;
- if (line->startItem() == movedItem || line->endItem() == movedItem) {
- connectionsToRemove.insert(line);
- }
- }
- }
-
- for (ConnectionLine* line : connectionsToRemove) {
- if (!line) continue;
-
- if (line->startItem()) {
- terminalConnections[line->startItem()].remove(line->startTerminal());
- }
- if (line->endItem()) {
- terminalConnections[line->endItem()].remove(line->endTerminal());
- }
-
- if (m_scene && line->scene() == m_scene) {
- m_scene->removeItem(line);
- }
-
- if (m_connections.contains(line)) {
- m_connections.removeAll(line);
- }
- delete line;
- }
-
- if (!connectionsToRemove.isEmpty()) {
- setModified(true);
- }
- }
-
- void PLCDocument::setSimulationRunning(bool running)
- {
- m_simulationRunning = running;
- if (!running) {
- resetSimulation();
- }
- }
-
- void PLCDocument::resetSimulation()
- {
- m_activeItems.clear();
- for (QGraphicsItem *item : m_scene->items()) {
- if (PLCItem *plcItem = dynamic_cast<PLCItem*>(item)) {
- plcItem->setState(false);
- }
- }
- terminalConnections.clear();
- updateConnections();
- }
-
- void PLCDocument::updateConnections()
- {
- for (ConnectionLine *line : m_connections) {
- PLCItem *start = line->startItem();
- PLCItem *end = line->endItem();
-
- if (line->endTerminal() == RowTerminal || line->startTerminal() == RowTerminal) {
- line->setPen(QPen(Qt::green, 2));
- continue;
- }
-
- if (m_activeItems.contains(start) && m_activeItems.contains(end)) {
- line->setPen(QPen(Qt::green, 2));
- } else {
- line->setPen(QPen(Qt::black, 1));
- }
- }
- }
-
- void PLCDocument::deleteSelectedItems()
- {
- QList<QGraphicsItem*> selected = m_scene->selectedItems();
- if (selected.isEmpty()) return;
-
- QList<PLCItem*> itemsToDelete;
- QList<ConnectionLine*> linesToDelete;
- QSet<ConnectionLine*> connectionsToDelete;
-
- for (QGraphicsItem* item : selected) {
- if (PLCItem* plcItem = dynamic_cast<PLCItem*>(item)) {
- itemsToDelete.append(plcItem);
- } else if (ConnectionLine* line = dynamic_cast<ConnectionLine*>(item)) {
- linesToDelete.append(line);
- }
- }
-
- for (ConnectionLine* line : m_connections) {
- if (line->startItem() && itemsToDelete.contains(line->startItem())) {
- connectionsToDelete.insert(line);
- }
- if (line->endItem() && itemsToDelete.contains(line->endItem())) {
- connectionsToDelete.insert(line);
- }
- }
-
- for (ConnectionLine* line : linesToDelete) {
- connectionsToDelete.insert(line);
- }
-
- for (ConnectionLine* line : connectionsToDelete) {
- if (!line) continue;
-
- if (line->startItem()) {
- terminalConnections[line->startItem()].remove(line->startTerminal());
- }
- if (line->endItem()) {
- terminalConnections[line->endItem()].remove(line->endTerminal());
- }
-
- if (m_scene && m_scene->items().contains(line)) {
- m_scene->removeItem(line);
- }
-
- m_connections.removeAll(line);
- delete line;
- }
-
- for (PLCItem* item : itemsToDelete) {
- terminalConnections.remove(item);
- m_lastValidPositions.remove(item);
- m_scene->removeItem(item);
- delete item;
- }
-
- setModified(true);
- }
-
- void PLCDocument::copySelectedItem()
- {
- QList<QGraphicsItem*> selected = m_scene->selectedItems();
- if (selected.size() != 1) return;
-
- if (PLCItem* item = dynamic_cast<PLCItem*>(selected.first())) {
- m_copiedItem = item;
- }
- }
-
- void PLCDocument::pasteItem()
- {
- if (!m_copiedItem) return;
- QPointF pastePos = snapToCellCenter(m_view->mapToScene(m_view->viewport()->mapFromGlobal(QCursor::pos())));
- pastePos.setX(pastePos.x() - 70);
- pastePos.setY(pastePos.y() - 70);
-
- int col = static_cast<int>(pastePos.x() / m_cellSize);
- int row = static_cast<int>(pastePos.y() / m_cellSize);
- if (isCellOccupied(col, row, nullptr))
- {
- QMessageBox::warning(this, "粘贴失败", "目标单元格已被占用");
- return;
- }
-
- PLCItem* newItem = createItemByType(m_copiedItem->itemType());
- if (!newItem) return;
- newItem->setPos(pastePos);
- newItem->setName(m_copiedItem->name() + "_副本");
- m_scene->addItem(newItem);
-
- terminalConnections[newItem][LeftTerminal] = false;
- terminalConnections[newItem][RightTerminal] = false;
- m_lastValidPositions[newItem] = pastePos;
- setModified(true);
- }
-
- void PLCDocument::keyPressEvent(QKeyEvent* event)
- {
- if (event->key() == Qt::Key_Delete)
- {
- deleteSelectedItems();
- event->accept();
- return;
- }
- BaseDocument::keyPressEvent(event);
- }
-
- void PLCDocument::createContextMenu(QPoint globalPos)
- {
- QMenu menu(this);
-
- QAction* deleteAction = menu.addAction("删除");
- QAction* copyAction = menu.addAction("复制");
- QAction* pasteAction = menu.addAction("粘贴");
-
- QList<QGraphicsItem*> selected = m_scene->selectedItems();
- deleteAction->setEnabled(!selected.isEmpty());
- copyAction->setEnabled(selected.size() == 1&&dynamic_cast<PLCItem*>(selected.first()));
- pasteAction->setEnabled(m_copiedItem != nullptr);
-
- connect(deleteAction, &QAction::triggered, this, &PLCDocument::deleteSelectedItems);
- connect(copyAction, &QAction::triggered, this, &PLCDocument::copySelectedItem);
- connect(pasteAction, &QAction::triggered, this, &PLCDocument::pasteItem);
-
- menu.addSeparator();
-
- QAction *tableGridAction = menu.addAction("隐藏/显示网格");
- connect(tableGridAction, &QAction::triggered, this, [this]() {
- for (auto line : m_horizontalLines)
- {
- line->setVisible(!line->isVisible());
- }
- for (auto line : m_verticalLines)
- {
- line->setVisible(!line->isVisible());
- }
- });
-
- menu.exec(globalPos + QPoint(10, 10));
- }
-
- void PLCDocument::onRowTerminalConnection()
- {
- QList<QGraphicsItem*> selected = m_scene->selectedItems();
- if (selected.size() != 1) return;
-
- PLCItem* item = dynamic_cast<PLCItem*>(selected.first());
- if (!item) return;
-
- int itemRow = static_cast<int>(item->y() / m_cellSize);
- int itemCol = static_cast<int>(item->x() / m_cellSize);
- if (itemCol != 0) {
- QMessageBox::warning(this, "连接错误", "只有最左侧列的元件可以连接到行触点");
- return;
- }
-
- if (isTerminalUsed(item, LeftTerminal)) {
- QMessageBox::warning(this, "连接失败", "该元件的左端子已被使用");
- return;
- }
-
- ConnectionLine* connection = new ConnectionLine(
- item, LeftTerminal,
- nullptr, RowTerminal
- );
-
- connection->setRowTerminalTargetRow(itemRow);
- connection->setEndTerminalPoint(QPointF(0, (itemRow + 0.5) * m_cellSize));
- connection->updatePosition();
-
- m_scene->addItem(connection);
- m_connections.append(connection);
-
- terminalConnections[item][LeftTerminal] = true;
-
- setModified(true);
- }
-
- PLCItem* PLCDocument::createItemByType(PLCItem::ItemType type)
- {
- switch (type) {
- case PLCItem::NormallyOpen: return new NormallyOpenItem;
- case PLCItem::NormallyClosed: return new NormallyClosedItem;
- case PLCItem::GreaterThan: return new GreaterThanItem;
- case PLCItem::GreaterEqual: return new GreaterEqualItem;
- case PLCItem::LessThan: return new LessThanItem;
- case PLCItem::LessEqual: return new LessEqualItem;
- case PLCItem::Equal: return new EqualItem;
- case PLCItem::Coil: return new CoilItem;
- default:
- qWarning() << "未知的PLC元件类型:" << type;
- return nullptr;
- }
- }
-
- bool PLCDocument::saveToFile(const QString &filePath)
- {
- QFile file(filePath);
- if (!file.open(QIODevice::WriteOnly)) {
- QMessageBox::warning(this, "保存失败", "无法打开文件进行写入:" + filePath);
- return false;
- }
-
- QJsonObject docObject;
- docObject["type"] = "PLCDocument";
-
- docObject["table_rows"] = m_rows;
- docObject["table_columns"] = m_columns;
- docObject["table_cell_size"] = m_cellSize;
-
- QJsonArray itemsArray;
- for (QGraphicsItem *item : m_scene->items()) {
- if (PLCItem *plcItem = dynamic_cast<PLCItem*>(item)) {
- QJsonObject itemObj;
- itemObj["type"] = static_cast<int>(plcItem->itemType());
- int col = static_cast<int>(plcItem->x() / m_cellSize);
- int row = static_cast<int>(plcItem->y() / m_cellSize);
- itemObj["col"] = col;
- itemObj["row"] = row;
- itemObj["name"] = plcItem->name();
- itemObj["active"] = plcItem->isActive();
- itemsArray.append(itemObj);
- }
- }
- docObject["items"] = itemsArray;
-
- QJsonArray connectionsArray;
- for (ConnectionLine *line : m_connections) {
- QJsonObject connObj;
-
- if (line->startItem()) {
- int startCol = static_cast<int>(line->startItem()->pos().x() / m_cellSize);
- int startRow = static_cast<int>(line->startItem()->pos().y() / m_cellSize);
- connObj["startCol"] = startCol;
- connObj["startRow"] = startRow;
- } else if (line->startTerminal() == RowTerminal) {
- connObj["startRowTerminal"] = line->rowTerminalSourceRow();
- }
- connObj["startTerminal"] = static_cast<int>(line->startTerminal());
-
- connObj["endTerminal"] = static_cast<int>(line->endTerminal());
- if (line->endTerminal() == RowTerminal) {
- connObj["endRowTerminal"] = line->rowTerminalTargetRow();
- } else if (line->endItem()) {
- int endCol = static_cast<int>(line->endItem()->pos().x() / m_cellSize);
- int endRow = static_cast<int>(line->endItem()->pos().y() / m_cellSize);
- connObj["endCol"] = endCol;
- connObj["endRow"] = endRow;
- }
-
- connectionsArray.append(connObj);
- }
- docObject["connections"] = connectionsArray;
-
- QJsonDocument doc(docObject);
- file.write(doc.toJson());
- file.close();
-
- setFilePath(filePath);
- setModified(false);
- return true;
- }
-
- bool PLCDocument::loadFromFile(const QString &filePath)
- {
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly)) {
- QMessageBox::warning(this, "打开失败", "无法打开文件:" + filePath);
- return false;
- }
-
- QByteArray data = file.readAll();
- file.close();
-
- QJsonParseError parseError;
- QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
- if (parseError.error != QJsonParseError::NoError) {
- QMessageBox::warning(this, "文件格式错误", "JSON解析错误: " + parseError.errorString());
- return false;
- }
-
- if (doc.isNull() || !doc.isObject()) {
- QMessageBox::warning(this, "文件格式错误", "不是有效的PLC文档");
- return false;
- }
-
- QJsonObject docObject = doc.object();
- if (docObject["type"].toString() != "PLCDocument") {
- QMessageBox::warning(this, "文件类型错误", "不是有效的PLC文档");
- return false;
- }
-
- m_rows = docObject["table_rows"].toInt(DEFAULT_ROWS);
- m_columns = docObject["table_columns"].toInt(DEFAULT_COLUMNS);
- m_cellSize = docObject["table_cell_size"].toInt(DEFAULT_CELL_SIZE);
-
- setSimulationRunning(false);
-
- m_scene->blockSignals(true);
-
- for (auto conn : m_connections) {
- m_scene->removeItem(conn);
- delete conn;
- }
- m_connections.clear();
-
- QList<QGraphicsItem*> allItems = m_scene->items();
- for (QGraphicsItem* item : allItems) {
- if (dynamic_cast<PLCItem*>(item) || dynamic_cast<ConnectionLine*>(item)) {
- m_scene->removeItem(item);
- delete item;
- }
- }
-
- m_activeItems.clear();
- terminalConnections.clear();
- clearCurrentConnection();
-
- createRealTable();
-
- QMap<QPair<int, int>, PLCItem*> itemMap;
- QJsonArray itemsArray = docObject["items"].toArray();
- for (const QJsonValue &itemValue : itemsArray) {
- QJsonObject itemObj = itemValue.toObject();
- PLCItem::ItemType type = static_cast<PLCItem::ItemType>(itemObj["type"].toInt());
- int col = itemObj["col"].toInt();
- int row = itemObj["row"].toInt();
- QString name = itemObj["name"].toString();
- bool active = itemObj["active"].toBool();
-
- col = qBound(0, col, m_columns - 1);
- row = qBound(0, row, m_rows - 1);
-
- PLCItem *item = createItemByType(type);
- if (item) {
- QPointF pos(col * m_cellSize + m_cellSize / 2.0,
- row * m_cellSize + m_cellSize / 2.0);
- item->setPos(pos);
- item->setName(name);
- item->setState(active);
- m_scene->addItem(item);
-
- itemMap.insert(qMakePair(col, row), item);
-
- if (active) {
- m_activeItems.insert(item);
- }
-
- terminalConnections[item][LeftTerminal] = false;
- terminalConnections[item][RightTerminal] = false;
-
- connect(item, &PLCItem::stateChanged, this, [this, item](bool active) {
- if (m_simulationRunning) {
- if (active) m_activeItems.insert(item);
- else m_activeItems.remove(item);
- updateConnections();
- }
- });
- }
- }
-
- QJsonArray connectionsArray = docObject["connections"].toArray();
- for (const QJsonValue &connValue : connectionsArray) {
- QJsonObject connObj = connValue.toObject();
-
- TerminalType startTerminal = static_cast<TerminalType>(connObj["startTerminal"].toInt());
- TerminalType endTerminal = static_cast<TerminalType>(connObj["endTerminal"].toInt());
-
- PLCItem *startItem = nullptr;
- PLCItem *endItem = nullptr;
-
- if (connObj.contains("startRowTerminal")) {
- int startRow = connObj["startRowTerminal"].toInt();
- ConnectionLine *line = new ConnectionLine(
- nullptr, RowTerminal,
- endItem, endTerminal
- );
- line->setStartTerminalPoint(QPointF(0, (startRow + 0.5) * m_cellSize));
- line->setRowTerminalSourceRow(startRow);
- m_scene->addItem(line);
- m_connections.append(line);
- }
- else if (connObj.contains("startCol") && connObj.contains("startRow")) {
- int startCol = connObj["startCol"].toInt();
- int startRow = connObj["startRow"].toInt();
- startItem = itemMap.value(qMakePair(startCol, startRow));
-
- if (endTerminal == RowTerminal && connObj.contains("endRowTerminal")) {
- int endRow = connObj["endRowTerminal"].toInt();
- ConnectionLine *line = new ConnectionLine(
- startItem, startTerminal,
- nullptr, RowTerminal
- );
- line->setEndTerminalPoint(QPointF(0, (endRow + 0.5) * m_cellSize));
- line->setRowTerminalTargetRow(endRow);
- m_scene->addItem(line);
- m_connections.append(line);
- }
- else if (connObj.contains("endCol") && connObj.contains("endRow")) {
- int endCol = connObj["endCol"].toInt();
- int endRow = connObj["endRow"].toInt();
- endItem = itemMap.value(qMakePair(endCol, endRow));
-
- if (startItem && endItem) {
- ConnectionLine *line = new ConnectionLine(
- startItem, startTerminal,
- endItem, endTerminal
- );
- m_scene->addItem(line);
-
- m_connections.append(line);
- }
- }
- }
- }
-
- for (ConnectionLine* line : m_connections) {
- if (line->startItem()) {
- terminalConnections[line->startItem()][line->startTerminal()] = true;
- }
- if (line->endItem()) {
- terminalConnections[line->endItem()][line->endTerminal()] = true;
- }
- }
-
- m_scene->blockSignals(false);
- handleSceneChanged();
-
- setFilePath(filePath);
- setModified(false);
-
- return true;
- }
-
- ConnectionLine::ConnectionLine(
- PLCItem *startItem, PLCDocument::TerminalType startTerminal,
- PLCItem *endItem, PLCDocument::TerminalType endTerminal,
- QGraphicsItem *parent
- ) : QGraphicsLineItem(parent)
- , m_startItem(startItem)
- , m_startTerminal(startTerminal)
- , m_endItem(endItem)
- , m_endTerminal(endTerminal)
- , m_rowTerminalTargetRow(-1)
- , m_rowTerminalSourceRow(-1)
- , m_processing(false)
- {
- setFlag(QGraphicsItem::ItemIsSelectable, true);
- setPen(QPen(Qt::black, 1));
- setZValue(-1);
- updatePosition();
- }
-
- void ConnectionLine::updatePosition()
- {
- QPointF startPoint;
- if (m_startItem) {
- if (m_startTerminal == PLCDocument::LeftTerminal) {
- startPoint = m_startItem->leftTerminal();
- } else if (m_startTerminal == PLCDocument::RightTerminal) {
- startPoint = m_startItem->rightTerminal();
- }
- } else if (!m_startTerminalPoint.isNull()) {
- startPoint = m_startTerminalPoint;
- }
-
- QPointF endPoint;
- if (m_endItem) {
- if (m_endTerminal == PLCDocument::LeftTerminal) {
- endPoint = m_endItem->leftTerminal();
- } else if (m_endTerminal == PLCDocument::RightTerminal) {
- endPoint = m_endItem->rightTerminal();
- }
- } else if (!m_endTerminalPoint.isNull()) {
- endPoint = m_endTerminalPoint;
- }
-
- if (!startPoint.isNull() && !endPoint.isNull()) {
- setLine(QLineF(startPoint, endPoint));
- }
- }
|