Skip to content

[codex] Stabilize diversity VFO flag placement#3880

Merged
ten9876 merged 2 commits into
mainfrom
codex/fix-diversity-vfo-flag-flip
Jun 28, 2026
Merged

[codex] Stabilize diversity VFO flag placement#3880
ten9876 merged 2 commits into
mainfrom
codex/fix-diversity-vfo-flag-flip

Conversation

@rfoust

@rfoust rfoust commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes the diversity-receive VFO flag instability by making attached A/H diversity pair placement authoritative over transient screen position and split-pair deconfliction. The pair now keeps stable left/right flag sides, updates both member overlays together during tune/drag paths, suppresses stale radio echoes during fast drag, and resolves overlap with nearby ordinary slice flags by active-group z-order instead of pushing flags to a lower row.

Constitution principle honored

Principle XI — Fixes Are Demonstrated. The fix was validated with focused tests plus automation-bridge captures against a live A/H diversity pair with an additional slice on the same panadapter.

Test plan

  • Local build passes (cmake --build build --target vfo_flag_placement_test AetherSDR -j8)
  • Behavior verified on a real radio if applicable
  • Existing tests pass (CI)
  • Reproduction steps documented if user-reported bug

Additional validation:

  • git diff --check
  • ctest --test-dir build -R '^vfo_flag_placement_test$' --output-on-failure
  • Agent automation bridge: live A/H diversity pair plus B slice on pan 0x40000000; selected B and A through slice select, captured visible panadapter screenshots, confirmed flags remain on the normal row and active group owns overlap z-order
  • Agent automation bridge: TX idle with transmitting=false, mox=false, tuning=false

Checklist

  • Commits are signed (docs/COMMIT-SIGNING.md)
  • No new flat-key AppSettings calls — use nested-JSON-under-one-key (Principle V)
  • Code is clean-room — not decompiled, disassembled, or reverse-engineered from a proprietary binary (Principle IV)
  • All meter UI uses MeterSmoother (AGENTS.md convention; no new meter UI added)
  • Documentation updated if user-visible behavior changed (not needed; bugfix only)
  • Security-sensitive changes reference a GHSA if applicable (not applicable)

Generated with OpenAI Codex.

@rfoust rfoust self-assigned this Jun 28, 2026
@rfoust rfoust marked this pull request as ready for review June 28, 2026 12:56
@rfoust rfoust requested review from a team as code owners June 28, 2026 12:56
Copilot AI review requested due to automatic review settings June 28, 2026 12:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Stabilizes VFO flag placement for diversity-receive A/H pairs by making pair side-locking and overlay updates authoritative (vs. transient screen position), adding short “echo hold” windows during fast drag to suppress stale radio echoes, and using z-order to resolve overlap with nearby slice flags.

Changes:

  • Add diversity metadata to slice overlays and use it to lock left/right flag sides for attached diversity pairs (plus active-group z-order handling).
  • Update tune/drag paths to push frequency changes to both member overlays together and suppress stale pan/center echoes during fast drag.
  • Extend the VFO flag placement test coverage for edge/locking behavior and diversity ordering.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/vfo_flag_placement_test.cpp Adds regression tests for new placement/ordering behavior.
src/models/SliceModel.cpp Emits diversityChanged when diversity role/index fields change (not just on/off).
src/gui/VfoWidget.h Introduces reusable FlagPlacement + placement helper and diversity ordering key.
src/gui/VfoWidget.cpp Refactors flag positioning to use the shared placement helper.
src/gui/SpectrumWidget.h Extends overlay metadata with diversity fields; adds z-order helper; adds VFO-drag echo hold state.
src/gui/SpectrumWidget.cpp Implements diversity-aware direction assignment, hit-testing exclusions, z-order handling, and drag echo suppression.
src/gui/MainWindow.h Tracks slice-drag target/echo-hold state for overlay suppression during drag.
src/gui/MainWindow.cpp Centralizes “push slice freq to overlay(s)” including diversity partner updates; threads diversity metadata into overlays.
src/gui/MainWindow_Wiring.cpp Integrates drag/tuning overlay updates + echo-hold suppression into wiring paths; updates diversityChanged handling.
src/gui/MainWindow_Controllers.cpp Routes controller-driven tuning updates through the unified overlay push path.

Comment thread src/gui/MainWindow_Wiring.cpp
Comment thread src/gui/MainWindow_Wiring.cpp Outdated
Comment on lines +576 to +580
const bool activeDiversityPartner = [this, s]() {
SliceModel* active = m_radioModel.slice(m_activeSliceId);
if (!active || active == s || !active->diversity() || !s->diversity()) {
return false;
}

@aethersdr-agent aethersdr-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, @rfoust — solid, well-structured fix. The extraction of the flag-placement geometry into a pure, testable VfoWidget::placementForMarker(...) / diversityPairOrderKey(...) and the consolidation of the three near-identical direction-assignment blocks (GPU repositionVfoFlags, software paintEvent, and vfoFlagOnLeftForSlice) into the shared assign*Directions helpers is a real readability win and removes a known drift hazard between those paths. Null-handling looks careful throughout (pushSliceFrequencyToOverlays, applyActiveVfoZOrder, and overlaysAreAttachedDiversityPair all guard their pointers), and the SliceModel change to emit diversityChanged on any of child/parent/diversity/index transitioning (not just the diversity bool) is more correct. CI is green across build/macos/windows/CodeQL.

A couple of points, both echoing Copilot — I verified both against the diff and agree they're worth addressing:

1. Stale displayMhz capture in the drag-echo singleShot (MainWindow_Wiring.cpp:619-633) — valid, minor. The lambda captures displayMhz by value at schedule time, but its own guard reads the live m_sliceDragTargetMhz. If the drag advances before the singleShot(0) runs, the lambda pushes the older captured frequency — a momentary backward nudge, which is exactly the snap-back class this PR is suppressing. A following echo would correct it, so it's transient, but since you already read the member in the guard, just read it for the push too:

QTimer::singleShot(0, this, [this, sliceId]() {
    const double displayMhz = m_sliceDragTargetMhz;
    if (displayMhz <= 0.0) return;
    if (!m_sliceDragInProgress
        && QDateTime::currentMSecsSinceEpoch() >= m_sliceDragEchoHoldUntilMs) return;
    if (SliceModel* slice = m_radioModel.slice(sliceId))
        pushSliceFrequencyToOverlays(slice, displayMhz);
});

2. Duplicated diversity-pair detection — valid, maintainability. The same "are these two an attached A/H diversity pair?" check now exists in four spots with slightly different shapes: sameDiversityReceivePair() (MainWindow.cpp, file-static), the activeDiversityPartner and dragDiversityPartner lambdas (MainWindow_Wiring.cpp), and overlaysAreAttachedDiversityPair() (SpectrumWidget.cpp, over overlays). The two Wiring lambdas are byte-for-byte identical apart from the slice they test, and they replicate sameDiversityReceivePair exactly. Since pairing rules for diversity_index/roles have already changed once, this is a real drift risk. The slice-based copies could collapse to one shared bool isSameDiversityReceivePair(const SliceModel*, const SliceModel*) reused at all three call sites; the overlay variant necessarily stays separate (overlays carry no panId).

Neither is blocking. Nice work, and the focused test additions for the geometry and ordering helpers are appreciated.


🤖 aethersdr-agent · cost: $2.2082 · model: claude-opus-4-8

@rfoust

rfoust commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the review feedback in e9a1f74:

  • The deferred drag overlay update now reads the live m_sliceDragTargetMhz inside the singleShot callback before pushing overlays, so it cannot reapply an older captured drag frequency.
  • The duplicated slice-based diversity-pair checks in MainWindow_Wiring.cpp now reuse MainWindow::isSameDiversityReceivePair(...), which is also used by pushSliceFrequencyToOverlays(...).

Local validation rerun:

  • git diff --check
  • cmake --build build --target vfo_flag_placement_test AetherSDR -j8
  • ctest --test-dir build -R '^vfo_flag_placement_test$' --output-on-failure

@ten9876 ten9876 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Reviewed the current head (e9a1f74):

  • Solid follow-on to #3866 — extracts flag geometry into pure, testable placementForMarker()/diversityPairOrderKey() and consolidates the three direction-assignment blocks into shared assign*Directions helpers, removing the drift hazard between the GPU/software/vfoFlagOnLeftForSlice paths.
  • Diversity pair placement is now authoritative (stable L/R sides), both overlays update together, stale echoes suppressed during fast drag, and overlap resolves by active-group z-order rather than pushing flags to a lower row. SliceModel emitting diversityChanged on any child/parent/diversity/index transition is more correct.
  • Both review notes addressed in e9a1f74: the drag-echo singleShot reads the live m_sliceDragTargetMhz (no stale-capture backward nudge — verified), and the duplicated pair detection is collapsed into a shared isSameDiversityReceivePair() helper used at all slice-based call sites.
  • Not a keying path (Principle VI N/A); vfo_flag_placement_test extended for the geometry + ordering helpers. CI green on all 6.

Thanks @rfoust — clean fix.

@ten9876 ten9876 merged commit bf71afd into main Jun 28, 2026
6 checks passed
@ten9876 ten9876 deleted the codex/fix-diversity-vfo-flag-flip branch June 28, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants