From e4a84fd997c815771ad7e7e809482af12aafefa1 Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 7 Oct 2026 21:44:13 +0200 Subject: [PATCH] chatgui: verify latched PTT ownership and channel reset --- tools/chatgui/src/radiopanel.cpp | 4 +-- tools/chatgui/tests/test_radio_panel.cpp | 33 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/tools/chatgui/src/radiopanel.cpp b/tools/chatgui/src/radiopanel.cpp index 7e130d15..a4c9cdf5 100644 --- a/tools/chatgui/src/radiopanel.cpp +++ b/tools/chatgui/src/radiopanel.cpp @@ -59,7 +59,7 @@ RadioPanel::RadioPanel(QWidget* parent) : QWidget(parent) { row->addWidget(m_ptt); auto* engine = RadioAudioEngine::instance(); connect(m_ptt, &QPushButton::pressed, this, [this, engine]() { - if (m_pttLatched) setPttLatched(false, "button-pressed"); + if (m_pttLatched) { setPttLatched(false, "button-pressed"); updateState(); } else engine->talkBegin(); }); connect(m_ptt, &QPushButton::released, this, [this, engine]() { @@ -85,6 +85,7 @@ bool RadioPanel::eventFilter(QObject* watched, QEvent* event) { auto* mouse = static_cast(event); if (mouse->button() == Qt::LeftButton && m_ptt->rect().contains(mouse->pos())) { setPttLatched(true, "double-click"); + updateState(); return true; } } @@ -100,7 +101,6 @@ void RadioPanel::setPttLatched(bool latched, const char* reason) { latched ? "latched (click to release)" : "latch released", (unsigned long long)engine->groupId(), reason); if (latched) engine->talkBegin(); else engine->talkEnd(); - updateState(); } void RadioPanel::updateState() { diff --git a/tools/chatgui/tests/test_radio_panel.cpp b/tools/chatgui/tests/test_radio_panel.cpp index da8e1d50..19666719 100644 --- a/tools/chatgui/tests/test_radio_panel.cpp +++ b/tools/chatgui/tests/test_radio_panel.cpp @@ -153,6 +153,39 @@ int main(int argc, char** argv) { engine->setHotkeyTalking(false); await([&]() { return !engine->isTransmitting(); }); REQUIRE(!selfSpeaking()); + // Реальная последовательность double-click: первый click, второе нажатие DoubleClick, release. + auto latchPtt = [&]() { + QTest::mouseClick(ptt, Qt::LeftButton); + QTest::mouseDClick(ptt, Qt::LeftButton); + QTest::mouseRelease(ptt, Qt::LeftButton); + REQUIRE(engine->isTalking()); + await([&]() { return engine->isTransmitting(); }); + }; + latchPtt(); + engine->setHotkeyTalking(true); + engine->setHotkeyTalking(false); + REQUIRE(engine->isTalking()); // Отпускание хоткея не снимает фиксацию кнопки. + QTest::mousePress(ptt, Qt::LeftButton); + REQUIRE(!engine->isTalking()); // Следующий click отпускает уже на нажатии. + QTest::mouseRelease(ptt, Qt::LeftButton); + await([&]() { return !engine->isTransmitting(); }); + latchPtt(); + engine->setHotkeyTalking(true); + QTest::mouseClick(ptt, Qt::LeftButton); + REQUIRE(engine->isTalking()); // Снятие фиксации не отпускает зажатый хоткей. + engine->setHotkeyTalking(false); + await([&]() { return !engine->isTransmitting(); }); + latchPtt(); + REQUIRE(engine->start(8) == 0); + await([&]() { return engine->captureAvailable(); }); + REQUIRE(!engine->isTalking() && !engine->isTransmitting()); + REQUIRE(engine->start(7) == 0); + await([&]() { return engine->captureAvailable(); }); + QTest::mousePress(ptt, Qt::LeftButton); + REQUIRE(engine->isTalking()); // После смены канала снова работает обычное удержание. + QTest::mouseRelease(ptt, Qt::LeftButton); + REQUIRE(!engine->isTalking()); + qInfo("radio panel: double-click latch, click release, independent hotkey and channel reset PASS"); REQUIRE(engine->applySettings({{"radio_vad_threshold", 65}, {"radio_vad_hangover_ms", 400}, {"radio_vad_compressor_max_gain_db", 30}, {"radio_compressor_max_gain_db", 6}})); await([&]() { return !engine->settingsBusy(); });