fix(ui): SETUP заперт, пока устройство не подключено

Почти всё в окне настроек — свойства КОНКРЕТНОГО радио: они грузятся и
сохраняются по его MAC (у AD936x — по серийному номеру). До подключения MAC
неизвестен, и правки уезжали бы в чужую секцию конфига — ровно так когда-то
оборачивался старт по AutoStart с нулевым MAC (66c9fa6). Проще не пускать
оператора внутрь, чем потом объяснять, куда делись настройки.

Кнопка создаётся выключенной и отпирается в ветке rfDevice, то есть после
удачного Connect. TFlatButton уже умеет рисовать выключенное состояние
(приглушённые текст и рамка), так что запрет виден, а не выглядит поломкой;
на кнопке подсказка, почему она заперта.

Гейт продублирован внутри BtnSettingsClick: туда приходит не только мышь, но и
ПКМ по кнопке TX-профиля (BtnTXProfileMouseDown → ShowTransmitPage), и этот
путь открывал бы диалог в обход запертой кнопки.

★После Stop обратно не запираем: FDevConnected означает «устройство известно»,
а не «сеть жива» (он и не сбрасывается в StopAndDisconnect), а править настройки
между сеансами законно.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M37eCTZZ9aqppKWkZRxXkP
This commit is contained in:
2026-08-25 10:30:00 +03:00
co-authored by Claude Opus 5
parent f99443620a
commit 46284c4ed5
+24
View File
@@ -679,6 +679,7 @@ type
procedure DeactivateXvtr;
// -------------------------------------------------------------------------
procedure BtnSettingsClick(Sender: TObject);
procedure UpdateSetupButton; // SETUP заперт, пока не знаем устройство
// Семантические обработчики событий флагов (роутинг по FPan.CurSliceId).
// Коллекция/раскладка/диспетчер флагов — в TPanafallPanel.
procedure OnModeFilterSelect(Mode: Integer; FilterBW: Integer);
@@ -1861,6 +1862,7 @@ begin
FCATAdapter.ApplySettings(FController.FLoadedGlobal);
ApplySliceSlotAudio;
RelabelBands; // HF ↔ VHF/UHF подписи под тип бэкенда
UpdateSetupButton; // MAC/серийник известны — SETUP открылся
ApplyBackendCapsToUI; // пресеты sample rate + гейтинг полей
RebuildXvtrButtons;
PushXvtrToWeb;
@@ -2044,6 +2046,8 @@ begin
BtnDiscover := MakeBtn(PanelToolbar, 'DISCOVER', X, 3, 80, BTN_H, BtnDiscoverClick);
BtnStartStop := MakeBtn(PanelToolbar, 'START', X+84, 3, 76, BTN_H, BtnStartStopClick);
BtnSettings := MakeBtn(PanelToolbar, 'SETUP', X+164, 3, 66, BTN_H, BtnSettingsClick);
// SETUP отпирается только после подключения — см. UpdateSetupButton.
UpdateSetupButton;
// DX живёт в блоке RX левой панели, рядом с CTUN (см. ниже): споты — часть
// приёмного вида, а не глобальная команда уровня DISCOVER/START/SETUP.
@@ -9717,10 +9721,30 @@ begin
if FreqDispB <> nil then FreqDispB.MaxFreq := hi;
end;
procedure TMainForm.UpdateSetupButton;
// Почти всё в окне настроек — свойства КОНКРЕТНОГО устройства: они и грузятся,
// и сохраняются по его MAC (у AD936x — по серийному номеру). Пока устройство не
// подключено, MAC неизвестен, и правки уезжали бы в чужую секцию конфига —
// ровно этим когда-то оборачивался старт по AutoStart с нулевым MAC. Поэтому
// SETUP заперт до первого удачного Connect. ★После Stop не запираем обратно:
// FDevConnected означает «устройство известно», а не «сеть жива», и настройки
// между сеансами править законно.
begin
if BtnSettings = nil then Exit;
BtnSettings.Enabled := (FController <> nil) and FController.FDevConnected;
BtnSettings.ShowHint := True;
if BtnSettings.Enabled then
BtnSettings.Hint := ''
else
BtnSettings.Hint := 'Connect a radio first — settings are stored per device';
end;
procedure TMainForm.BtnSettingsClick(Sender: TObject);
var
SF: TSettingsForm;
begin
// Гейт не только для мыши: сюда же приходит ПКМ по кнопке TX-профиля.
if (BtnSettings <> nil) and (not BtnSettings.Enabled) then Exit;
if not Assigned(FSettingsForm) then
begin
SF := TSettingsForm.Create(Self);