From 8af20fbcab6a129e99b97dce529668a77603dcdd Mon Sep 17 00:00:00 2001 From: James Turner Date: Tue, 19 May 2020 22:01:42 +0100 Subject: [PATCH] Fix for loading of FGFP plans. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Where the plan does not contain departure / arrival WPs, fire the corresponding delegate methods after load, to run the selection logic. Also, add a ‘loaded’ delegate callback, to give delegates a chance to perform validation and fix-up after all flight-plan loads. --- src/Navaids/FlightPlan.cxx | 34 +++++++++++++++++-- src/Navaids/FlightPlan.hxx | 20 +++++++---- src/Scripting/NasalPositioned.cxx | 5 +++ .../unit_tests/Navaids/test_routeManager.cxx | 2 +- .../unit_tests/Navaids/test_routeManager.hxx | 4 +-- 5 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/Navaids/FlightPlan.cxx b/src/Navaids/FlightPlan.cxx index 7da7e09d5..779bcfba2 100644 --- a/src/Navaids/FlightPlan.cxx +++ b/src/Navaids/FlightPlan.cxx @@ -334,6 +334,7 @@ void FlightPlan::setCurrentIndex(int index) lockDelegates(); _currentIndex = index; _currentWaypointChanged = true; + _didLoadFP = true; unlockDelegates(); } @@ -764,6 +765,16 @@ void FlightPlan::saveToProperties(SGPropertyNode* d) const } // of waypoint iteration } +static bool anyWaypointsWithFlag(FlightPlan* plan, WayptFlag flag) +{ + bool r = false; + plan->forEachLeg([&r, flag](FlightPlan::Leg* l) { + if (l->waypoint()->flags() && flag) { + r = true; + } + }); +} + bool FlightPlan::load(const SGPath& path) { if (!path.exists()) { @@ -787,8 +798,13 @@ bool FlightPlan::load(const SGPath& path) // a load, since we assume the flight-plan had it specified already // especially, the XML might have a SID/STAR embedded, which we don't // want to lose - _arrivalChanged = false; - _departureChanged = false; + + // however, we do want to run the normal delegate if no procedure was + // defined. We'll use the presence of waypoints tagged to decide + const bool hasArrival = anyWaypointsWithFlag(this, WPT_ARRIVAL); + const bool hasDeparture = anyWaypointsWithFlag(this, WPT_DEPARTURE); + _arrivalChanged = !hasArrival; + _departureChanged = !hasDeparture; Status = true; } else if (loadPlainTextFormat(path)) { // simple textual list of waypoints _arrivalChanged = true; @@ -1696,6 +1712,13 @@ void FlightPlan::unlockDelegates() return; } + if (_didLoadFP) { + _didLoadFP = false; + for (auto d : _delegates) { + d->loaded(); + } + } + if (_departureChanged) { _departureChanged = false; for (auto d : _delegates) { @@ -2114,5 +2137,10 @@ int FlightPlan::cruiseAltitudeFt() const { return _cruiseAltitudeFt; } - + +void FlightPlan::forEachLeg(const LegVisitor& lv) +{ + std::for_each(_legs.begin(), _legs.end(), lv); +} + } // of namespace flightgear diff --git a/src/Navaids/FlightPlan.hxx b/src/Navaids/FlightPlan.hxx index ed2c32acc..ec8902699 100644 --- a/src/Navaids/FlightPlan.hxx +++ b/src/Navaids/FlightPlan.hxx @@ -24,6 +24,8 @@ #ifndef FG_FLIGHTPLAN_HXX #define FG_FLIGHTPLAN_HXX +#include + #include #include @@ -186,6 +188,8 @@ public: virtual void currentWaypointChanged() { } virtual void endOfFlightPlan() { } + + virtual void loaded() { } protected: Delegate(); @@ -373,6 +377,9 @@ public: void addDelegate(Delegate* d); void removeDelegate(Delegate* d); + + using LegVisitor = std::function; + void forEachLeg(const LegVisitor& lv); private: friend class Leg; @@ -384,12 +391,13 @@ private: void notifyCleared(); unsigned int _delegateLock = 0; - bool _arrivalChanged, - _departureChanged, - _waypointsChanged, - _currentWaypointChanged, - _cruiseDataChanged; - + bool _arrivalChanged = false, + _departureChanged = false, + _waypointsChanged = false, + _currentWaypointChanged = false, + _cruiseDataChanged = false; + bool _didLoadFP = false; + void saveToProperties(SGPropertyNode* d) const; bool loadXmlFormat(const SGPath& path); diff --git a/src/Scripting/NasalPositioned.cxx b/src/Scripting/NasalPositioned.cxx index 79169377d..f3141d19c 100644 --- a/src/Scripting/NasalPositioned.cxx +++ b/src/Scripting/NasalPositioned.cxx @@ -2426,6 +2426,11 @@ public: { callDelegateMethod("sequence"); } + + void loaded() override + { + callDelegateMethod("loaded"); + } private: void callDelegateMethod(const char* method) diff --git a/test_suite/unit_tests/Navaids/test_routeManager.cxx b/test_suite/unit_tests/Navaids/test_routeManager.cxx index 6e3e1c1e6..e4ff46335 100644 --- a/test_suite/unit_tests/Navaids/test_routeManager.cxx +++ b/test_suite/unit_tests/Navaids/test_routeManager.cxx @@ -599,7 +599,7 @@ void RouteManagerTests::loadGPX() } // The same test as above, but for a file exported from the route manager or online -void RouteManagerTests::loadFgfp() +void RouteManagerTests::loadFGFP() { auto rm = globals->get_subsystem(); diff --git a/test_suite/unit_tests/Navaids/test_routeManager.hxx b/test_suite/unit_tests/Navaids/test_routeManager.hxx index 32686f00c..ab642bddc 100644 --- a/test_suite/unit_tests/Navaids/test_routeManager.hxx +++ b/test_suite/unit_tests/Navaids/test_routeManager.hxx @@ -41,7 +41,7 @@ class RouteManagerTests : public CppUnit::TestFixture CPPUNIT_TEST(testSequenceDiscontinuityAndResume); CPPUNIT_TEST(testHiddenWaypoints); CPPUNIT_TEST(loadGPX); - CPPUNIT_TEST(loadFgfp); + CPPUNIT_TEST(loadFGFP); CPPUNIT_TEST_SUITE_END(); @@ -65,7 +65,7 @@ public: void testSequenceDiscontinuityAndResume(); void testHiddenWaypoints(); void loadGPX(); - void loadFgfp(); + void loadFGFP(); private: GPS* m_gps = nullptr; };