I've reviewed all 48 open issues. None of them cover pop-in/pop-out or detachable/floating panel windowing for panadapters or the Radio Panel. The closest issues are #152 (multi-panadapter support, which is about creating multiple pans) and the general GUI work in #56, but neither touches detachable/floating window behavior. No duplicate exists — here's your new issue:
GitHub Issue
Title: feat: Pop-out / pop-in and free-drag positioning for panadapters and Radio Panel (SmartSDR parity)
## What
Add the ability to **pop out** any panadapter panel or the Radio Panel (the
main VFO/applet strip) into its own independent, freely-positionable
top-level window, and **pop it back in** (dock it) to the main AetherSDR
window — mirroring SmartSDR's pop-out/pop-in behavior exactly.
While popped out, each panel:
- Becomes a standalone borderless (or thin-framed) `QWidget` window with
its own title bar / drag handle
- Can be freely dragged to any screen position, including a second monitor
- Retains full live functionality (spectrum updates, click-to-tune, applet
controls, etc.)
- Remembers its last screen position and restore state across restarts
(persisted via `AppSettings`)
A **pop-in** button (or double-click on the drag handle) re-docks the panel
back to its original slot in the main window layout.
## Why
Multi-monitor ham radio operating is extremely common. Operators frequently
want:
- The **panadapter on one monitor**, the **VFO/applet controls on another**
- Multiple panadapters spread across monitors (especially relevant once
issue #152 multi-pan lands)
- A compact "heads down" Radio Panel on a small secondary display while
the spectrum occupies a large primary display
Currently, AetherSDR locks all panels into a single `QMainWindow` splitter.
This forces operators to choose between a large spectrum and enough room for
controls — there is no escape. SmartSDR for Windows solves this cleanly with
its pop-out system; AetherSDR needs parity.
## How Other Clients Do It
### SmartSDR for Windows (reference implementation)
SmartSDR uses a pop-out/pop-in model that is the direct target for this
feature:
- Every panadapter has a **pop-out icon** (↗ arrow) in its top-right corner.
Clicking it detaches the panadapter into a standalone floating window.
- The **Radio Panel** (VFO strip + applets) has a corresponding pop-out
control.
- Floating windows have a thin custom title bar with a **pop-in button**
(↙ arrow) to re-dock.
- Windows can be dragged freely across monitors.
- Position is remembered per-radio, per-panadapter-ID across sessions.
- During pop-out, the slot in the main window either collapses or shows a
placeholder/ghost.
### SDR# (SDRSharp)
Uses a **plugin panel docking** system where panels can be undocked from
the side rail into floating `Form` windows. Less polished than SmartSDR but
same concept.
### GQRX
Uses Qt's built-in `QDockWidget` for the control panels, which provides
free float + re-dock. The spectrum itself is not detachable in GQRX, but
the dock widget pattern is the standard Qt approach for this class of
feature.
## Suggested Behavior
### Pop-out trigger
- A small **↗ pop-out button** appears in the top-right corner of each
`PanadapterApplet` header bar (and in the Radio Panel's drag/title zone).
- Keyboard shortcut: e.g. `Ctrl+Shift+P` for focused panadapter,
`Ctrl+Shift+R` for Radio Panel (exact shortcuts TBD).
### Popped-out state
┌──────────────────────────────────────┐
│ ≡ Panadapter 1 [14.225 MHz / 40m] │ ↙ │ ✕ │ ← custom drag handle
├──────────────────────────────────────┤
│ │
│ [live SpectrumWidget] │
│ │
└──────────────────────────────────────┘
- The popped-out window is a `QWidget` with `Qt::Window | Qt::FramelessWindowHint`
(or a thin custom frame).
- Custom drag handle at top: click-drag moves the window, ↙ button re-docks,
✕ closes (which should pop-in, not destroy the panadapter).
- The `SpectrumWidget` (or Radio Panel widget) is **re-parented**, not cloned —
the same live widget moves into the floating window. No duplication of VITA-49
routing or signal connections needed.
### Main window while panel is popped out
- The vacated slot in the `PanadapterStack` QSplitter collapses to zero height
(or shows a thin placeholder strip with the pan name and a ↗ "re-open"
button).
- The main window remains fully functional for all other panels.
### Pop-in (re-docking)
- Clicking ↙ in the floating window re-parents the widget back into the
`PanadapterStack` at its original index.
- The placeholder strip in the main window expands back to the previous size.
- If the original slot no longer exists (pan was deleted while floating), the
widget is destroyed gracefully.
### Persistence (`AppSettings`)
PanPopOut_0x40000000_IsFloating = True
PanPopOut_0x40000000_X = 1920
PanPopOut_0x40000000_Y = 100
PanPopOut_0x40000000_Width = 960
PanPopOut_0x40000000_Height = 600
RadioPanelPopOut_IsFloating = False
On launch, AetherSDR restores floating state before the first paint so there
is no visible "snap" of windows jumping around.
### Radio Panel pop-out
The same mechanism applies to the Radio Panel (the `MainWindow` center pane
containing `VfoWidget`, mode selector, `AppletPanel`, etc.). This lets the
operator move the entire control surface to a secondary monitor while the
spectrum stays on the primary.
## Protocol Hints
No FlexLib/SmartSDR protocol involvement — this is **purely a client-side
Qt windowing feature**. The radio is unaware of window positions.
The relevant Qt classes are:
| Class | Role |
|-------|------|
| `QWidget::setParent(nullptr)` + `show()` | Re-parent widget as top-level window |
| `QWidget::setParent(container)` + `show()` | Re-parent widget back into layout |
| `Qt::Window \| Qt::FramelessWindowHint` | Create borderless floating window |
| `QSplitter` | Already used in `PanadapterStack` — handles collapse on re-parent |
| `AppSettings` | Persist geometry and floating state |
> ⚠️ **Re-parenting caveat:** Qt re-parenting destroys and re-creates the
> native window handle. On X11/Wayland, OpenGL contexts (if any) must be
> re-initialized. `SpectrumWidget` currently uses `QPainter`/`QPixmap` — no
> OpenGL — so re-parenting should be safe. Verify this assumption before
> implementing.
> ⚠️ **Wayland note:** `Qt::FramelessWindowHint` behaves differently under
> Wayland compositors; window positioning via `move()` may be ignored. May
> need `QWindow::setPosition()` workaround or fallback to decorated windows
> on Wayland. Test on both X11 and Wayland (KDE/GNOME).
## Implementation Sketch
```cpp
// PanadapterApplet.h — add pop-out support
class PanadapterApplet : public QWidget {
// ...
QPushButton* m_popOutBtn{};
QWidget* m_floatingWindow{}; // nullptr when docked
int m_stackIndex{-1}; // slot in PanadapterStack
public slots:
void popOut();
void popIn();
};
void PanadapterApplet::popOut() {
m_stackIndex = parentWidget() ? /* record splitter index */ : -1;
setParent(nullptr);
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
auto& s = AppSettings::instance();
int x = s.value("PanPopOut_" + m_panId + "_X", "100").toInt();
int y = s.value("PanPopOut_" + m_panId + "_Y", "100").toInt();
move(x, y);
show();
s.setValue("PanPopOut_" + m_panId + "_IsFloating", "True");
}
Labels
feature · GUI · spectrum · priority: medium
---
No duplicate found in the open issues — this is a fresh feature request ready to paste into GitHub. The only tangentially related open work is **#152** (multi-panadapter), so you may want to cross-link the two issues since pop-out becomes especially useful once multiple pans are available.
I've reviewed all 48 open issues. None of them cover pop-in/pop-out or detachable/floating panel windowing for panadapters or the Radio Panel. The closest issues are #152 (multi-panadapter support, which is about creating multiple pans) and the general GUI work in #56, but neither touches detachable/floating window behavior. No duplicate exists — here's your new issue:
GitHub Issue
Title:
feat: Pop-out / pop-in and free-drag positioning for panadapters and Radio Panel (SmartSDR parity)┌──────────────────────────────────────┐
│ ≡ Panadapter 1 [14.225 MHz / 40m] │ ↙ │ ✕ │ ← custom drag handle
├──────────────────────────────────────┤
│ │
│ [live SpectrumWidget] │
│ │
└──────────────────────────────────────┘
PanPopOut_0x40000000_IsFloating = True
PanPopOut_0x40000000_X = 1920
PanPopOut_0x40000000_Y = 100
PanPopOut_0x40000000_Width = 960
PanPopOut_0x40000000_Height = 600
RadioPanelPopOut_IsFloating = False
Labels
feature·GUI·spectrum·priority: medium