From a2986ccf77e5411411e10ddcd05dc74ff20f2585 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Thu, 30 Jul 2026 09:02:12 -0700 Subject: [PATCH] fix(CorridorScanComplexItem): emit specifiesCoordinateChanged when polyline validity changes --- src/MissionManager/CorridorScanComplexItem.cc | 15 ++++++++ src/MissionManager/CorridorScanComplexItem.h | 2 ++ .../CorridorScanComplexItemTest.cc | 35 +++++++++++++++++++ .../CorridorScanComplexItemTest.h | 1 + 4 files changed, 53 insertions(+) diff --git a/src/MissionManager/CorridorScanComplexItem.cc b/src/MissionManager/CorridorScanComplexItem.cc index 4f905b5d5ff6..3b6ac7eab0c6 100644 --- a/src/MissionManager/CorridorScanComplexItem.cc +++ b/src/MissionManager/CorridorScanComplexItem.cc @@ -32,9 +32,14 @@ CorridorScanComplexItem::CorridorScanComplexItem(PlanMasterController* masterCon connect(&_corridorPolyline, &QGCMapPolyline::pathChanged, this, &CorridorScanComplexItem::_rebuildCorridorPolygon); connect(&_corridorWidthFact, &Fact::valueChanged, this, &CorridorScanComplexItem::_rebuildCorridorPolygon); + connect(&_corridorPolyline, &QGCMapPolyline::countChanged, this, &CorridorScanComplexItem::_updateSpecifiesCoordinate); + connect(&_corridorPolyline, &QGCMapPolyline::isValidChanged, this, &CorridorScanComplexItem::_updateWizardMode); connect(&_corridorPolyline, &QGCMapPolyline::traceModeChanged, this, &CorridorScanComplexItem::_updateWizardMode); + // Anchor the cache to current state so correctness doesn't depend on constructor ordering + _updateSpecifiesCoordinate(); + if (!kmlOrShpFile.isEmpty()) { _corridorPolyline.loadKMLOrSHPFile(kmlOrShpFile); _corridorPolyline.setDirty(false); @@ -153,6 +158,16 @@ bool CorridorScanComplexItem::specifiesCoordinate(void) const return _corridorPolyline.count() > 1; } +// specifiesCoordinate() depends on polyline count, so the NOTIFY signal must be emitted when it flips +void CorridorScanComplexItem::_updateSpecifiesCoordinate(void) +{ + const bool newSpecifiesCoordinate = specifiesCoordinate(); + if (newSpecifiesCoordinate != _specifiesCoordinate) { + _specifiesCoordinate = newSpecifiesCoordinate; + emit specifiesCoordinateChanged(); + } +} + void CorridorScanComplexItem::setCoordinate(const QGeoCoordinate& coordinate) { if (!coordinate.isValid() || !_entryCoordinate.isValid() || _corridorPolyline.count() < 2) { diff --git a/src/MissionManager/CorridorScanComplexItem.h b/src/MissionManager/CorridorScanComplexItem.h index 5d25fd347157..5d974ae9255c 100644 --- a/src/MissionManager/CorridorScanComplexItem.h +++ b/src/MissionManager/CorridorScanComplexItem.h @@ -63,6 +63,7 @@ private slots: void _polylineDirtyChanged (bool dirty); void _rebuildCorridorPolygon (void); void _updateWizardMode (void); + void _updateSpecifiesCoordinate (void); // Overrides from TransectStyleComplexItem void _rebuildTransectsPhase1 (void) final; @@ -81,6 +82,7 @@ private slots: QMap _metaDataMap; SettingsFact _corridorWidthFact; + bool _specifiesCoordinate = false; static constexpr const char* _jsonEntryPointKey = "EntryPoint"; }; diff --git a/test/MissionManager/CorridorScanComplexItemTest.cc b/test/MissionManager/CorridorScanComplexItemTest.cc index 6c299db2cd4e..46cfc3ebc483 100644 --- a/test/MissionManager/CorridorScanComplexItemTest.cc +++ b/test/MissionManager/CorridorScanComplexItemTest.cc @@ -57,6 +57,41 @@ void CorridorScanComplexItemTest::_testDirty() _corridorItem->setDirty(false); } +void CorridorScanComplexItemTest::_testSpecifiesCoordinateChanged() +{ + // Fresh item with an empty polyline so we can watch the 1 -> 2 vertex transition + CorridorScanComplexItem* item = new CorridorScanComplexItem(planController(), false /* flyView */, QString() /* kmlOrShpFile */); + + MultiSignalSpy spy; + QVERIFY(spy.init(item, QStringList{QStringLiteral("specifiesCoordinateChanged")})); + + QVERIFY(!item->specifiesCoordinate()); + + item->corridorPolyline()->appendVertex(_polyLineVertices[0]); + QVERIFY(!item->specifiesCoordinate()); + QVERIFY(spy.noneEmitted()); + + item->corridorPolyline()->appendVertex(_polyLineVertices[1]); + QVERIFY(item->specifiesCoordinate()); + QVERIFY(spy.emittedOnce("specifiesCoordinateChanged")); + + spy.clearAllSignals(); + item->corridorPolyline()->appendVertex(_polyLineVertices[2]); + QVERIFY(item->specifiesCoordinate()); + QVERIFY(spy.noneEmitted()); + + // Unrelated corridor rebuild triggers must not emit spuriously + spy.clearAllSignals(); + changeFactValue(item->corridorWidth()); + QVERIFY(spy.noneEmitted()); + + // true -> false transition when the polyline is cleared + spy.clearAllSignals(); + item->corridorPolyline()->clear(); + QVERIFY(!item->specifiesCoordinate()); + QVERIFY(spy.emittedOnce("specifiesCoordinateChanged")); +} + void CorridorScanComplexItemTest::_waitForReadyForSave() { QVERIFY_TRUE_WAIT(_corridorItem->readyForSaveState() == CorridorScanComplexItem::ReadyForSave, diff --git a/test/MissionManager/CorridorScanComplexItemTest.h b/test/MissionManager/CorridorScanComplexItemTest.h index 7a409fc6297f..bcc94d090279 100644 --- a/test/MissionManager/CorridorScanComplexItemTest.h +++ b/test/MissionManager/CorridorScanComplexItemTest.h @@ -22,6 +22,7 @@ class CorridorScanComplexItemTest : public TransectStyleComplexItemTestBase private slots: void _testDirty(); + void _testSpecifiesCoordinateChanged(); void _testPathChanges(); void _testItemGeneration(); void _testItemCount();