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.

190 line
4.8 KiB

  1. #include "item.h"
  2. #include "connection.h"
  3. #include "myscene.h"
  4. #include <QMenu>
  5. #include <QPainter>
  6. #include <QStyleOptionGraphicsItem>
  7. #include <QGraphicsSceneContextMenuEvent>
  8. Item::Item(const QString &type, QGraphicsItem *parent)
  9. : QGraphicsObject(parent), type_(type), registerId_("")
  10. {
  11. setFlags(QGraphicsItem::ItemIsMovable |
  12. QGraphicsItem::ItemIsSelectable |
  13. QGraphicsItem::ItemSendsGeometryChanges);
  14. }
  15. QRectF Item::boundingRect() const
  16. {
  17. return QRectF(-22, -12, 44, 32);
  18. }
  19. QPointF Item::anchorPos(AnchorType type) const
  20. {
  21. // 对于"按钮"和"指示灯"类型,返回无效坐标
  22. if (type_ == "按钮" || type_ == "指示灯") {
  23. return QPointF(std::numeric_limits<qreal>::quiet_NaN(),
  24. std::numeric_limits<qreal>::quiet_NaN());
  25. }
  26. // 其他类型正常返回连接点位置
  27. return mapToScene(type == Left ? QPointF(-18, 0) : QPointF(18, 0));
  28. }
  29. void Item::addConnection(Connection* conn)
  30. {
  31. // 对于"按钮"和"指示灯"类型,不允许添加连接
  32. if (type_ == "按钮" || type_ == "指示灯")
  33. {
  34. return;
  35. }
  36. if (!connections_.contains(conn))
  37. {
  38. connections_.append(conn);
  39. }
  40. }
  41. void Item::removeConnection(Connection* conn)
  42. {
  43. connections_.removeAll(conn);
  44. }
  45. QList<Connection *> Item::connections()
  46. {
  47. return connections_;
  48. }
  49. QString Item::itemType()
  50. {
  51. return type_;
  52. }
  53. bool Item::setRegisterId(const QString &id)
  54. {
  55. if(registerId_.isEmpty())
  56. {
  57. registerId_ = id;
  58. return true;
  59. }
  60. return false;
  61. }
  62. void Item::setRegisterValue(const QString &registerId, quint16 value)
  63. {
  64. if (registerId_ == registerId)
  65. {
  66. registerValue_ = value;
  67. update(); // 触发重绘
  68. }
  69. }
  70. QStringList Item::resetRegister()
  71. {
  72. QStringList unboundRegs;
  73. if (!registerId_.isEmpty()) {
  74. unboundRegs << registerId_;
  75. registerId_.clear();
  76. registerValue_ = 0;
  77. update();
  78. }
  79. return unboundRegs;
  80. }
  81. void Item::MenuActions(QMenu *menu)
  82. {
  83. menu->addAction("复制");
  84. menu->addAction("删除");
  85. menu->addAction("对象");
  86. menu->addAction("重置");
  87. }
  88. void Item::addMenuActions(QMenu *menu)
  89. {
  90. Q_UNUSED(menu);
  91. }
  92. void Item::handleMenuAction(QAction *action)
  93. {
  94. if (action->text() == "复制") {
  95. emit requestCopy(this);
  96. }
  97. if (action->text() == "删除") {
  98. emit requestDelete(this);
  99. }
  100. if (action->text() == "对象"){
  101. emit requestBindRegister(this);
  102. }
  103. if (action->text() == "重置"){
  104. emit requestReset(this);
  105. }
  106. }
  107. QVariant Item::itemChange(GraphicsItemChange change, const QVariant &value)
  108. {
  109. // if (change == QGraphicsItem::ItemPositionChange) {
  110. // for (Connection* conn : connections_)
  111. // conn->updatePosition();
  112. // }
  113. // if (change == ItemPositionChange && scene()) {
  114. // // 获取场景(确保是 GridScene)
  115. // if (auto myScene = dynamic_cast<MyScene*>(scene())) {
  116. // if (myScene->getSnapToGrid()) {
  117. // // 获取网格大小
  118. // int gridSize = myScene->getGridSize();
  119. // // 对齐到网格
  120. // QPointF newPos = value.toPointF();
  121. // qreal xV = qRound(newPos.x() / gridSize) * gridSize;
  122. // qreal yV = qRound(newPos.y() / gridSize) * gridSize;
  123. // return QPointF(xV, yV);
  124. // }
  125. // }
  126. // }
  127. // 处理位置即将改变事件(网格对齐)
  128. if (change == ItemPositionChange && scene()) {
  129. QPointF newPos = value.toPointF();
  130. // 检查是否启用网格对齐
  131. if (auto myScene = dynamic_cast<MyScene*>(scene())) {
  132. if (myScene->getSnapToGrid()) {
  133. int gridSize = myScene->getGridSize();
  134. // 计算对齐位置
  135. qreal xV = qRound(newPos.x() / gridSize) * gridSize;
  136. qreal yV = qRound(newPos.y() / gridSize) * gridSize;
  137. // 返回对齐后的位置
  138. return QPointF(xV, yV);
  139. }
  140. }
  141. }
  142. // 处理位置已改变事件(更新连线)
  143. else if (change == QGraphicsItem::ItemPositionHasChanged) {
  144. // 使用范围for循环安全遍历(防止在更新过程中连接被修改)
  145. QList<Connection*> connectionsCopy = connections_;
  146. for (Connection* conn : connectionsCopy) {
  147. if (connections_.contains(conn)) { // 确保连接仍然存在
  148. conn->updatePosition();
  149. }
  150. }
  151. }
  152. return QGraphicsObject::itemChange(change, value);
  153. }
  154. void Item::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
  155. {
  156. QMenu menu;
  157. // 创建菜单
  158. MenuActions(&menu);
  159. addMenuActions(&menu);
  160. // 执行菜单
  161. QAction *selected = menu.exec(event->screenPos());
  162. // 处理菜单动作
  163. if (selected) {
  164. handleMenuAction(selected);
  165. }
  166. }