Skip to content

fix(applet-panel): TXDSP drag silently failed due to ID mismatch (#1836)#3044

Merged
ten9876 merged 1 commit into
mainfrom
auto/fix-1836
May 24, 2026
Merged

fix(applet-panel): TXDSP drag silently failed due to ID mismatch (#1836)#3044
ten9876 merged 1 commit into
mainfrom
auto/fix-1836

Conversation

@ten9876

@ten9876 ten9876 commented May 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes #1836. Dragging the TXDSP (VUDU) tile's title bar to reorder it in the applet panel silently did nothing because the composite tile's underlying container id (tx_dsp) and its AppletEntry id (TXDSP) didn't match.

Root cause

`AppletEntry.id = "TXDSP"` is the persistence key (`Applet_TXDSP`), but the underlying `ContainerWidget` was created with id `"tx_dsp"` (used as the parent-id reference for its sub-containers). The drag MIME data is set from the container's id in `ContainerWidget.cpp:150`, so MIME `"tx_dsp"` never matched the `AppletEntry.id == "TXDSP"` lookup in `dropEvent`. `srcIdx` stayed -1, function early-returned. Silent failure.

Fix

Aliasing fallback in `AppletPanel.cpp:128-155` `dropEvent`: if the dragged id doesn't match any `AppletEntry.id` directly, walk the entries again and check whether any of their underlying `ContainerWidget` instances has that id. Catches the composite-tile case without renaming anything.

Why aliasing instead of renaming

While investigating, found that the container id `"tx_dsp"` is persisted in real user settings:

  • `<ContainerGeometry_tx_dsp>0,0,244,988</ContainerGeometry_tx_dsp>`
  • 13+ children in `ContainerTree` JSON with `"parent": "tx_dsp"`
  • The `"tx_dsp"` entry itself in `ContainerTree` with its children list

A literal rename to `"TXDSP"` would orphan every existing user's TXDSP geometry + child layout on first launch. The alias-in-dropEvent fix is regression-safe: zero migration, container m_id stays as-is, only the lookup gains a fallback.

Stats

  • 1 file, +15 / -0
  • No new flat-key AppSettings (Principle V N/A)
  • MeterSmoother N/A (no meter code)

Test plan

  • Local build clean
  • Visual confirmation by Jeremy: TXDSP drag now reorders cleanly
  • Non-composite applets (RX, EQ, etc.) still drag — fallback only triggers when direct lookup fails, so fast path unchanged
  • Pop-out + dock cycle still works — parent/child container relationship preserved (no renames)
  • CI: build + check-paths green; check-windows skipped (no MainWindow.cpp / build deps touched)

Checklist

  • No new flat-key `AppSettings`
  • All meter UI uses `MeterSmoother` (N/A)
  • Documentation updated if user-visible behavior changed (release notes will mention TXDSP reorder fix)

Closes #1836.

🤖 Generated with Claude Code

Symptom: dragging the TXDSP (VUDU) tile's title bar to reorder it in
the applet panel did nothing. No crash, no error, no log message.

Root cause: TXDSP is a composite tile — the AppletEntry registered in
m_appletOrder has id="TXDSP" (the persistence key used by
Applet_TXDSP), but the underlying ContainerWidget that backs it was
created with id="tx_dsp" (the internal container id, used as the
parent-id reference for its sub-containers and persisted via
ContainerGeometry_tx_dsp + ContainerTree JSON parent refs).

The drag MIME data is set from the container's id in
ContainerWidget::startDrag — so dragging TXDSP's title bar produces
MIME "tx_dsp", which never matches any AppletEntry.id in the
dropEvent lookup. srcIdx stays -1 and the function early-returns.
Silent failure.

Fix: add a fallback in dropEvent. If no AppletEntry matches the
dragged id directly, walk the entries again and check whether any of
their underlying ContainerWidgets has that id. That catches the
composite-tile case (tx_dsp -> TXDSP) without renaming anything.

Why aliasing instead of renaming:

The container id "tx_dsp" is persisted in real user settings:
  - ContainerGeometry_tx_dsp records the floating geometry
  - ContainerTree JSON has 13+ children with parent: "tx_dsp"
  - The tx_dsp entry itself appears in ContainerTree

Renaming the container id to "TXDSP" would require a one-shot
migration to rewrite all those keys, or every existing user would
lose their TXDSP layout on first launch with the new code. The
alias-in-dropEvent fix is regression-safe: zero migration, container
m_id stays as-is, only the lookup gains a fallback.

Verified locally: TXDSP now reorders cleanly via drag; non-composite
applets (RX, EQ, etc.) unaffected; pop-out + dock cycle still works
(parent/child container relationship preserved).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ten9876 ten9876 requested a review from jensenpat as a code owner May 24, 2026 05:29
@ten9876 ten9876 enabled auto-merge (squash) May 24, 2026 05:29

@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 the careful triage on this one, @ten9876 — the diagnosis is spot-on. I verified the chain:

  • ContainerWidget.cpp:150 sets MIME from m_id (= "tx_dsp").
  • AppletPanel.cpp:752 registers the entry as AppletEntry.id="TXDSP" wrapping the "tx_dsp" container.
  • Direct lookup at the original dropEvent only matched on AppletEntry.id, so the drag silently dropped.

The aliasing fallback is the right call. A literal rename would orphan ContainerGeometry_tx_dsp + every ContainerTree child pointing at parent: "tx_dsp" in real users' settings, and you've kept the fast path untouched for non-composite tiles. qobject_cast<ContainerWidget*> is null-safe and the c && guard handles non-container entries cleanly.

Couple of small observations, no changes requested:

  1. Drift risk. This adds a second place where the MIME-id ↔ AppletEntry-id relationship is implicit. If another composite tile is added later, whoever writes it has to remember the same alias trick works automatically — which it does here, but it's worth a one-liner in ContainerWidget::onTitleBarDragStart referencing this fallback so the contract is discoverable from both ends. Not blocking.

  2. Long-term cleanup. A follow-up could give ContainerWidget an optional "drag id" property that defaults to m_id but can be set to the owning AppletEntry.id at construction. That would let the fast path always succeed and let the fallback be deleted. Out of scope for a bug fix — just flagging if you want to file a follow-up issue.

The comment in the diff is unusually clear about the why (persistence, migration cost, regression-safety) — exactly the kind of context that ages well. Nice work tracking the persistence dependency before reaching for a rename.

LGTM from a correctness standpoint.


🤖 aethersdr-agent · cost: $4.2088 · model: claude-opus-4-7

@ten9876 ten9876 merged commit 53315ef into main May 24, 2026
5 checks passed
@ten9876 ten9876 deleted the auto/fix-1836 branch May 24, 2026 15:14
aethersdr-agent Bot added a commit that referenced this pull request May 24, 2026
…etPanel fallback (#3057). Principle IX.

Adds ContainerWidget::dragId() / setDragId() so composite tiles can declare
the drag MIME payload that matches their owning AppletEntry.id directly.
TXDSP now sets dragId("TXDSP") at the wrap site; the aliasing fallback in
AppletPanel::dropEvent (added in #3044 to fix #1836) is now dead code and
removed in this PR.

Behavior-preserving:
- Non-composite tiles: m_dragId stays empty, dragId() returns m_id —
  drag MIME unchanged.
- TXDSP: drag MIME is now "TXDSP" (matches AppletEntry.id) instead of
  "tx_dsp" (the internal container id) — fast-path lookup hits directly.
- Container persistence keys (ContainerGeometry_tx_dsp, ContainerTree
  parent refs) read m_id, not m_dragId — completely unaffected. No
  migration needed.

Net diff is negative: ~12 LOC added in ContainerWidget header, 1 line
changed in ContainerWidget.cpp, +6 lines at the TXDSP wrap site, -14
lines of fallback removed in AppletPanel::dropEvent. Pure refactor.

Blast radius: risk_score=0.275, 10 high-risk affected (top: MainWindow,
AppletPanel ctor, MainWindow::buildUI). The transitive callers reach via
AppletPanel construction; the actual API surface change is purely
additive (new method, new field with default-empty semantics), so no
caller behavior changes. The only behavior delta is the TXDSP wrap site
explicitly opting into the new dragId.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
aethersdr-agent Bot added a commit that referenced this pull request May 25, 2026
…drag MIME-set (#3056). Principle III.

Adds a brief comment in ContainerWidget::onTitleBarDragStart immediately
above the setData call, pointing future composite-tile authors at the
aliasing fallback in AppletPanel::dropEvent (added in #1836 / PR #3044).
Without the cross-reference, a future author wrapping another internal
container (e.g. an RXDSP-style composite) would touch the sender side
first, ship the same m_id != AppletEntry.id mismatch, and never know
that the receiver has a safety net catching it.

Pure documentation — no behavioral change, no symbol/signature edits.

Blast radius: comment-only edit. PreToolUse hook flagged 37 transitive
callers (risk_score=0.208, top: MainWindow ctor/buildUI, AppletPanel
ctor), but none can be affected by adding a multi-line comment inside
an existing function body.
G6PWY-Chris pushed a commit to G6PWY-Chris/AetherSDR that referenced this pull request Jun 22, 2026
…hersdr#1836) (aethersdr#3044)

## Summary

Fixes aethersdr#1836. Dragging the TXDSP (VUDU) tile's title bar to reorder it in
the applet panel silently did nothing because the composite tile's
underlying container id (`tx_dsp`) and its AppletEntry id (`TXDSP`)
didn't match.

## Root cause

\`AppletEntry.id = "TXDSP"\` is the persistence key (\`Applet_TXDSP\`),
but the underlying \`ContainerWidget\` was created with id \`"tx_dsp"\`
(used as the parent-id reference for its sub-containers). The drag MIME
data is set from the container's id in
[\`ContainerWidget.cpp:150\`](src/gui/containers/ContainerWidget.cpp#L150),
so MIME \`"tx_dsp"\` never matched the \`AppletEntry.id == "TXDSP"\`
lookup in \`dropEvent\`. \`srcIdx\` stayed -1, function early-returned.
Silent failure.

## Fix

Aliasing fallback in
[\`AppletPanel.cpp:128-155\`](src/gui/AppletPanel.cpp#L128-L155)
\`dropEvent\`: if the dragged id doesn't match any \`AppletEntry.id\`
directly, walk the entries again and check whether any of their
underlying \`ContainerWidget\` instances has that id. Catches the
composite-tile case without renaming anything.

## Why aliasing instead of renaming

While investigating, found that the container id \`"tx_dsp"\` is
persisted in real user settings:

- \`<ContainerGeometry_tx_dsp>0,0,244,988</ContainerGeometry_tx_dsp>\`
- 13+ children in \`ContainerTree\` JSON with \`"parent": "tx_dsp"\`
- The \`"tx_dsp"\` entry itself in \`ContainerTree\` with its children
list

A literal rename to \`"TXDSP"\` would orphan every existing user's TXDSP
geometry + child layout on first launch. The alias-in-dropEvent fix is
regression-safe: zero migration, container m_id stays as-is, only the
lookup gains a fallback.

## Stats

- 1 file, +15 / -0
- No new flat-key AppSettings (Principle V N/A)
- MeterSmoother N/A (no meter code)

## Test plan

- [x] Local build clean
- [x] Visual confirmation by Jeremy: TXDSP drag now reorders cleanly
- [x] Non-composite applets (RX, EQ, etc.) still drag — fallback only
triggers when direct lookup fails, so fast path unchanged
- [x] Pop-out + dock cycle still works — parent/child container
relationship preserved (no renames)
- [ ] CI: build + check-paths green; check-windows skipped (no
MainWindow.cpp / build deps touched)

## Checklist

- [x] No new flat-key \`AppSettings\`
- [x] All meter UI uses \`MeterSmoother\` (N/A)
- [x] Documentation updated if user-visible behavior changed (release
notes will mention TXDSP reorder fix)

Closes aethersdr#1836.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

TXDSP applet silently un-reorderable due to ID mismatch

1 participant