| 568 | } |
| 569 | |
| 570 | void ClientRxChainWidget::paintEvent(QPaintEvent*) |
| 571 | { |
| 572 | rebuildLayout(); |
| 573 | |
| 574 | QPainter p(this); |
| 575 | p.setRenderHint(QPainter::Antialiasing, true); |
| 576 | p.fillRect(rect(), AetherSDR::ThemeManager::instance().color("color.background.0")); |
| 577 | |
| 578 | if (m_boxes.isEmpty()) return; |
| 579 | |
| 580 | // Connectors — same snake-aware logic as ClientChainWidget. |
| 581 | auto drawArrowHead = [&](QPointF tip, QPointF from) { |
| 582 | const QPointF dir = tip - from; |
| 583 | const qreal len = std::hypot(dir.x(), dir.y()); |
| 584 | if (len < 0.01) return; |
| 585 | const QPointF u(dir.x() / len, dir.y() / len); |
| 586 | const QPointF perp(-u.y(), u.x()); |
| 587 | QPainterPath head; |
| 588 | head.moveTo(tip); |
| 589 | head.lineTo(tip.x() - u.x() * kArrowTip + perp.x() * kArrowTip, |
| 590 | tip.y() - u.y() * kArrowTip + perp.y() * kArrowTip); |
| 591 | head.lineTo(tip.x() - u.x() * kArrowTip - perp.x() * kArrowTip, |
| 592 | tip.y() - u.y() * kArrowTip - perp.y() * kArrowTip); |
| 593 | head.closeSubpath(); |
| 594 | p.setBrush(kConnector()); |
| 595 | p.setPen(Qt::NoPen); |
| 596 | p.drawPath(head); |
| 597 | }; |
| 598 | |
| 599 | p.setPen(QPen(kConnector(), 2.0)); |
| 600 | for (int i = 0; i + 1 < m_boxes.size(); ++i) { |
| 601 | const QRectF a = m_boxes[i].rect; |
| 602 | const QRectF b = m_boxes[i + 1].rect; |
| 603 | const bool sameRow = qFuzzyCompare(a.center().y(), b.center().y()); |
| 604 | if (sameRow) { |
| 605 | const bool rtl = a.center().x() > b.center().x(); |
| 606 | QPointF from, to; |
| 607 | if (rtl) { |
| 608 | from = QPointF(a.left(), a.center().y()); |
| 609 | to = QPointF(b.right() + 1, b.center().y()); |
| 610 | } else { |
| 611 | from = QPointF(a.right(), a.center().y()); |
| 612 | to = QPointF(b.left() - 1, b.center().y()); |
| 613 | } |
| 614 | p.setPen(QPen(kConnector(), 2.0)); |
| 615 | p.drawLine(from, to); |
| 616 | drawArrowHead(to, from); |
| 617 | } else { |
| 618 | const bool turnRight = a.center().x() > rect().center().x(); |
| 619 | const QPointF aEdge = turnRight |
| 620 | ? QPointF(a.right(), a.center().y()) |
| 621 | : QPointF(a.left(), a.center().y()); |
| 622 | const QPointF bEdge = turnRight |
| 623 | ? QPointF(b.right(), b.center().y()) |
| 624 | : QPointF(b.left(), b.center().y()); |
| 625 | const qreal turnX = turnRight ? aEdge.x() + kTurnOffset |
| 626 | : aEdge.x() - kTurnOffset; |
| 627 | p.setPen(QPen(kConnector(), 2.0)); |
nothing calls this directly
no test coverage detected