From 46284c4ed5acebb16b9f3d781238cd2a6af5b78e Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 25 Aug 2026 10:30:00 +0300 Subject: [PATCH] =?UTF-8?q?fix(ui):=20SETUP=20=D0=B7=D0=B0=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D1=82,=20=D0=BF=D0=BE=D0=BA=D0=B0=20=D1=83=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B9=D1=81=D1=82=D0=B2=D0=BE=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Почти всё в окне настроек — свойства КОНКРЕТНОГО радио: они грузятся и сохраняются по его MAC (у AD936x — по серийному номеру). До подключения MAC неизвестен, и правки уезжали бы в чужую секцию конфига — ровно так когда-то оборачивался старт по AutoStart с нулевым MAC (66c9fa6). Проще не пускать оператора внутрь, чем потом объяснять, куда делись настройки. Кнопка создаётся выключенной и отпирается в ветке rfDevice, то есть после удачного Connect. TFlatButton уже умеет рисовать выключенное состояние (приглушённые текст и рамка), так что запрет виден, а не выглядит поломкой; на кнопке подсказка, почему она заперта. Гейт продублирован внутри BtnSettingsClick: туда приходит не только мышь, но и ПКМ по кнопке TX-профиля (BtnTXProfileMouseDown → ShowTransmitPage), и этот путь открывал бы диалог в обход запертой кнопки. ★После Stop обратно не запираем: FDevConnected означает «устройство известно», а не «сеть жива» (он и не сбрасывается в StopAndDisconnect), а править настройки между сеансами законно. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01M37eCTZZ9aqppKWkZRxXkP --- MainForm.pas | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/MainForm.pas b/MainForm.pas index 423c017..89b445e 100644 --- a/MainForm.pas +++ b/MainForm.pas @@ -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);