| 755 | } |
| 756 | |
| 757 | void RcxController::removeNode(int nodeIdx) { |
| 758 | if (nodeIdx < 0 || nodeIdx >= m_doc->tree.nodes.size()) return; |
| 759 | const Node& node = m_doc->tree.nodes[nodeIdx]; |
| 760 | uint64_t nodeId = node.id; |
| 761 | uint64_t parentId = node.parentId; |
| 762 | |
| 763 | // Compute size of deleted node/subtree |
| 764 | int deletedSize = (node.kind == NodeKind::Struct || node.kind == NodeKind::Array) |
| 765 | ? m_doc->tree.structSpan(node.id) : node.byteSize(); |
| 766 | int deletedEnd = node.offset + deletedSize; |
| 767 | |
| 768 | // Find siblings after this node and compute offset adjustments |
| 769 | QVector<cmd::OffsetAdj> adjs; |
| 770 | if (parentId != 0) { // only adjust if not root-level |
| 771 | auto siblings = m_doc->tree.childrenOf(parentId); |
| 772 | for (int si : siblings) { |
| 773 | if (si == nodeIdx) continue; |
| 774 | auto& sib = m_doc->tree.nodes[si]; |
| 775 | if (sib.offset >= deletedEnd) { |
| 776 | adjs.append({sib.id, sib.offset, sib.offset - deletedSize}); |
| 777 | } |
| 778 | } |
| 779 | } |
| 780 | |
| 781 | // Collect subtree |
| 782 | QVector<int> indices = m_doc->tree.subtreeIndices(nodeId); |
| 783 | QVector<Node> subtree; |
| 784 | for (int i : indices) |
| 785 | subtree.append(m_doc->tree.nodes[i]); |
| 786 | |
| 787 | m_doc->undoStack.push(new RcxCommand(this, |
| 788 | cmd::Remove{nodeId, subtree, adjs})); |
| 789 | } |
| 790 | |
| 791 | void RcxController::toggleCollapse(int nodeIdx) { |
| 792 | if (nodeIdx < 0 || nodeIdx >= m_doc->tree.nodes.size()) return; |
nothing calls this directly
no test coverage detected