| 6562 | } |
| 6563 | |
| 6564 | void SpectrumWidget::mouseMoveEvent(QMouseEvent* ev) |
| 6565 | { |
| 6566 | PerfInputScope perfScope("mouseMove"); |
| 6567 | if (PerfTelemetry::instance().enabled()) { |
| 6568 | const qint64 nowNs = PerfTelemetry::nowNs(); |
| 6569 | if (m_lastMouseMoveNs > 0) { |
| 6570 | PerfTelemetry::instance().recordMouseMoveGap( |
| 6571 | static_cast<double>(nowNs - m_lastMouseMoveNs) / 1000000.0); |
| 6572 | } |
| 6573 | m_lastMouseMoveNs = nowNs; |
| 6574 | } |
| 6575 | const auto dragStatePublisher = makeScopeExit([this] { publishPerfDragState(); }); |
| 6576 | (void)dragStatePublisher; |
| 6577 | |
| 6578 | const int chromeH = freqScaleH() + DIVIDER_H; |
| 6579 | const int contentH = height() - chromeH; |
| 6580 | const int specH = static_cast<int>(contentH * m_spectrumFrac); |
| 6581 | const int y = static_cast<int>(ev->position().y()); |
| 6582 | const int mx = static_cast<int>(ev->position().x()); |
| 6583 | const QPoint mousePos = ev->position().toPoint(); |
| 6584 | Qt::CursorShape sliceCursorShape = Qt::ArrowCursor; |
| 6585 | const bool overSliceCursorTarget = sliceCursorShapeAt(mousePos, sliceCursorShape); |
| 6586 | if (!anyDragActive()) { |
| 6587 | if (overSliceCursorTarget) { |
| 6588 | setVfoCursorOverride(sliceCursorShape); |
| 6589 | } else { |
| 6590 | clearVfoCursorOverride(); |
| 6591 | } |
| 6592 | } |
| 6593 | |
| 6594 | // Let child widgets (overlay menu buttons) own the pointer while hovered so |
| 6595 | // their tooltips are not killed by SpectrumWidget's QToolTip::hideText() calls. |
| 6596 | // Slice passband/edge zones are still owned by the spectrum because their |
| 6597 | // cursor advertises the drag action before click. (#2355) |
| 6598 | if (!anyDragActive() && childAt(mousePos) && !overSliceCursorTarget) { |
| 6599 | ev->ignore(); |
| 6600 | return; |
| 6601 | } |
| 6602 | |
| 6603 | // TNF drag |
| 6604 | if (m_draggingTnfId >= 0) { |
| 6605 | const double newFreq = xToMhz(mx); |
| 6606 | const int dy = static_cast<int>(ev->position().y()) - m_tnfDragStartPos.y(); |
| 6607 | const double widthScale = std::pow(2.0, static_cast<double>(-dy) / 48.0); |
| 6608 | const int newWidthHz = std::clamp( |
| 6609 | static_cast<int>(std::lround(static_cast<double>(m_dragTnfOrigWidthHz) * widthScale)), |
| 6610 | 10, 12000); |
| 6611 | for (auto& t : m_tnfMarkers) { |
| 6612 | if (t.id == m_draggingTnfId) { |
| 6613 | t.freqMhz = newFreq; |
| 6614 | t.widthHz = newWidthHz; |
| 6615 | break; |
| 6616 | } |
| 6617 | } |
| 6618 | if (!qFuzzyCompare(newFreq + 1.0, m_dragTnfLastFreq + 1.0)) { |
| 6619 | m_dragTnfLastFreq = newFreq; |
| 6620 | emit tnfMoveRequested(m_draggingTnfId, newFreq); |
| 6621 | } |
nothing calls this directly
no test coverage detected