| 1309 | } |
| 1310 | |
| 1311 | void RcxController::handleNodeClick(RcxEditor* source, int line, |
| 1312 | uint64_t nodeId, |
| 1313 | Qt::KeyboardModifiers mods) { |
| 1314 | bool ctrl = mods & Qt::ControlModifier; |
| 1315 | bool shift = mods & Qt::ShiftModifier; |
| 1316 | |
| 1317 | // Compute effective selection ID: footers use nodeId | kFooterIdBit |
| 1318 | auto effectiveId = [this](int ln, uint64_t nid) -> uint64_t { |
| 1319 | if (ln >= 0 && ln < m_lastResult.meta.size() && |
| 1320 | m_lastResult.meta[ln].lineKind == LineKind::Footer) |
| 1321 | return nid | kFooterIdBit; |
| 1322 | return nid; |
| 1323 | }; |
| 1324 | |
| 1325 | uint64_t selId = effectiveId(line, nodeId); |
| 1326 | |
| 1327 | if (!ctrl && !shift) { |
| 1328 | m_selIds.clear(); |
| 1329 | m_selIds.insert(selId); |
| 1330 | m_anchorLine = line; |
| 1331 | } else if (ctrl && !shift) { |
| 1332 | if (m_selIds.contains(selId)) |
| 1333 | m_selIds.remove(selId); |
| 1334 | else |
| 1335 | m_selIds.insert(selId); |
| 1336 | m_anchorLine = line; |
| 1337 | } else if (shift && !ctrl) { |
| 1338 | if (m_anchorLine < 0) { |
| 1339 | m_selIds.clear(); |
| 1340 | m_selIds.insert(selId); |
| 1341 | m_anchorLine = line; |
| 1342 | } else { |
| 1343 | m_selIds.clear(); |
| 1344 | int from = qMin(m_anchorLine, line); |
| 1345 | int to = qMax(m_anchorLine, line); |
| 1346 | for (int i = from; i <= to && i < m_lastResult.meta.size(); i++) { |
| 1347 | uint64_t nid = m_lastResult.meta[i].nodeId; |
| 1348 | if (nid != 0 && nid != kCommandRowId) m_selIds.insert(effectiveId(i, nid)); |
| 1349 | } |
| 1350 | } |
| 1351 | } else { // Ctrl+Shift |
| 1352 | if (m_anchorLine < 0) { |
| 1353 | m_selIds.insert(selId); |
| 1354 | m_anchorLine = line; |
| 1355 | } else { |
| 1356 | int from = qMin(m_anchorLine, line); |
| 1357 | int to = qMax(m_anchorLine, line); |
| 1358 | for (int i = from; i <= to && i < m_lastResult.meta.size(); i++) { |
| 1359 | uint64_t nid = m_lastResult.meta[i].nodeId; |
| 1360 | if (nid != 0 && nid != kCommandRowId) m_selIds.insert(effectiveId(i, nid)); |
| 1361 | } |
| 1362 | } |
| 1363 | } |
| 1364 | |
| 1365 | applySelectionOverlays(); |
| 1366 | updateCommandRow(); |
| 1367 | |
| 1368 | if (m_selIds.size() == 1) { |
no test coverage detected