| 534 | } |
| 535 | |
| 536 | void ClientChainWidget::mouseMoveEvent(QMouseEvent* ev) |
| 537 | { |
| 538 | if (m_pressIndex < 0 || !(ev->buttons() & Qt::LeftButton)) { |
| 539 | // Hover → update cursor over interactive boxes. |
| 540 | const int idx = hitTest(ev->position()); |
| 541 | setCursor((idx > 0 && !m_boxes[idx].isEndpoint) |
| 542 | ? Qt::PointingHandCursor : Qt::ArrowCursor); |
| 543 | QWidget::mouseMoveEvent(ev); |
| 544 | return; |
| 545 | } |
| 546 | // Distinguish drag from click — require ~6 px of movement. |
| 547 | if ((ev->position().toPoint() - m_pressPos).manhattanLength() < 6) return; |
| 548 | |
| 549 | const auto& b = m_boxes[m_pressIndex]; |
| 550 | auto* drag = new QDrag(this); |
| 551 | auto* mime = new QMimeData; |
| 552 | mime->setData(kMimeFormat, |
| 553 | QByteArray::number(static_cast<int>(b.stage))); |
| 554 | drag->setMimeData(mime); |
| 555 | |
| 556 | // Drag pixmap — snapshot the box so the user sees what they're moving. |
| 557 | QPixmap pix(b.rect.size().toSize()); |
| 558 | pix.fill(Qt::transparent); |
| 559 | { |
| 560 | QPainter pp(&pix); |
| 561 | pp.setRenderHint(QPainter::Antialiasing, true); |
| 562 | pp.setBrush(kBgActive()); |
| 563 | pp.setPen(QPen(kBorderActive(), 1.0)); |
| 564 | pp.drawRoundedRect(QRectF(0, 0, pix.width() - 1, pix.height() - 1), |
| 565 | kRadius, kRadius); |
| 566 | QFont f = pp.font(); |
| 567 | f.setPixelSize(9); |
| 568 | f.setBold(true); |
| 569 | pp.setFont(f); |
| 570 | pp.setPen(kTextLabel()); |
| 571 | pp.drawText(pix.rect(), Qt::AlignCenter, stageLabel(b.stage)); |
| 572 | } |
| 573 | drag->setPixmap(pix); |
| 574 | drag->setHotSpot(QPoint(pix.width() / 2, pix.height() / 2)); |
| 575 | |
| 576 | m_pressIndex = -1; |
| 577 | drag->exec(Qt::MoveAction); |
| 578 | m_dropIndex = -1; |
| 579 | update(); |
| 580 | } |
| 581 | |
| 582 | void ClientChainWidget::mouseReleaseEvent(QMouseEvent* ev) |
| 583 | { |
nothing calls this directly
no test coverage detected