Skip to content

Centralize LOCKED tune-feedback timer on SliceModel (single source of truth) #2983

Description

@ten9876

Context

PR #2905 added LOCKED visual feedback to the VFO and RX applet frequency displays when a tune attempt is blocked by the slice lock. Each widget currently has its own `m_lockedFrequencyTimer` (single-shot, 500ms). When `SliceModel::tuneBlockedByLock()` fires, both widgets start independent timers and both display "LOCKED" simultaneously.

Visually unified (they clear within a frame of each other), but it's two timers and two state bools tracking the same UX concept.

Proposed refactor

Move the feedback timing and "is feedback active" state to `SliceModel` itself, so a single source of truth drives every consumer.

Sketch

```cpp
// SliceModel.h
signals:
void tuneBlockedByLock(); // existing — kept for one-shot reaction
void lockedFeedbackActive(bool on); // new — drives visual state

private:
QTimer m_lockedFeedbackTimer; // 500ms single-shot
bool m_lockedFeedbackActive{false};
```

The two emit signals:

  • `tuneBlockedByLock` (existing) — fired on every blocked attempt; consumers that just want a one-shot reaction (e.g. status bar message — see #ISSUE_NEW_2 from this set) connect here.
  • `lockedFeedbackActive(bool)` — true on first block, false when 500ms elapses without another. Consumers that want to render a sustained "LOCKED" overlay connect here.

VfoWidget and RxApplet then:

  • Drop their per-widget timer + bool
  • Connect to `lockedFeedbackActive` and use that as the gate for the LOCKED string in `updateFreqLabel()`

Why this is worth doing

  • One state variable for "is feedback active right now" — no risk of widgets drifting out of sync
  • Future consumers (spectrum-widget VFO marker? hardware controller LED? status bar?) connect to one signal, not two
  • Simpler clean-up: `setSlice()` only needs to drop one connection per widget instead of resetting per-widget state

Why it can wait

The current implementation works correctly. The two timers always start within microseconds of each other and clear within a frame. UX is unified in practice; this is structural polish, not a bug fix.

Effort

~1 hour: refactor SliceModel, drop per-widget timer state in both widgets, run existing manual tests for the LOCKED-feedback paths.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    GUIUser interfaceenhancementImprovement to existing featuremaintainer-reviewRequires maintainer review before any action is takenpriority: lowLow priority

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions