diff --git a/src/Airmap/AirMapFlightPlanManager.cc b/src/Airmap/AirMapFlightPlanManager.cc index 7752f75a5978d7f8c167e4aaaf468edf6e3b0516..5d0413debbdf0d70f8b866718ab0cdb357fa0c74 100644 --- a/src/Airmap/AirMapFlightPlanManager.cc +++ b/src/Airmap/AirMapFlightPlanManager.cc @@ -56,9 +56,20 @@ AirMapFlightInfo::AirMapFlightInfo(const airmap::Flight& flight, QObject *parent : AirspaceFlightInfo(parent) , _flight(flight) { - //-- TODO: Load bounding box geometry - - + //-- Load bounding box geometry + const Geometry& geometry = flight.geometry; + if(geometry.type() == Geometry::Type::polygon) { + const Geometry::Polygon& polygon = geometry.details_for_polygon(); + for (const auto& vertex : polygon.outer_ring.coordinates) { + QGeoCoordinate coord; + if (vertex.altitude) { + coord = QGeoCoordinate(vertex.latitude, vertex.longitude, vertex.altitude.get()); + } else { + coord = QGeoCoordinate(vertex.latitude, vertex.longitude); + } + _boundingBox.append(QVariant::fromValue(coord)); + } + } } //----------------------------------------------------------------------------- @@ -75,6 +86,30 @@ AirMapFlightInfo::startTime() return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.start_time)).toString("yyyy MM dd - hh:mm:ss"); } +//----------------------------------------------------------------------------- +QDateTime +AirMapFlightInfo::qStartTime() +{ + return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.start_time)); +} + +//----------------------------------------------------------------------------- +bool +AirMapFlightInfo::active() +{ + QDateTime end = QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.end_time)); + QDateTime now = QDateTime::currentDateTime(); + return end > now; +} + +//----------------------------------------------------------------------------- +void +AirMapFlightInfo::setEndFlight(DateTime end) +{ + _flight.end_time = end; + emit activeChanged(); +} + //----------------------------------------------------------------------------- QString AirMapFlightInfo::endTime() @@ -88,9 +123,6 @@ AirMapFlightPlanManager::AirMapFlightPlanManager(AirMapSharedState& shared, QObj , _shared(shared) { connect(&_pollTimer, &QTimer::timeout, this, &AirMapFlightPlanManager::_pollBriefing); - //-- Set some valid, initial start/end time - _flightStartTime = QDateTime::currentDateTime().addSecs(10 * 60); - _flightEndTime = _flightStartTime.addSecs(30 * 60); } //----------------------------------------------------------------------------- @@ -104,12 +136,14 @@ AirMapFlightPlanManager::~AirMapFlightPlanManager() void AirMapFlightPlanManager::setFlightStartTime(QDateTime start) { - if(_flightStartTime != start) { + quint64 startt = start.toUTC().toMSecsSinceEpoch(); + if(_flightPlan.start_time != airmap::from_milliseconds_since_epoch(airmap::Milliseconds{(long long)startt})) { //-- Can't start in the past if(start < QDateTime::currentDateTime()) { start = QDateTime::currentDateTime().addSecs(5 * 60); + startt = start.toUTC().toMSecsSinceEpoch(); } - _flightStartTime = start; + _flightPlan.start_time = airmap::from_milliseconds_since_epoch(airmap::Milliseconds{(long long)startt}); emit flightStartTimeChanged(); } } @@ -118,16 +152,32 @@ AirMapFlightPlanManager::setFlightStartTime(QDateTime start) void AirMapFlightPlanManager::setFlightEndTime(QDateTime end) { - if(_flightEndTime != end) { + quint64 endt = end.toUTC().toMSecsSinceEpoch(); + if(_flightPlan.end_time != airmap::from_milliseconds_since_epoch(airmap::Milliseconds{(long long)endt})) { //-- End has to be after start - if(end < _flightStartTime) { - end = _flightStartTime.addSecs(30 * 60); + if(end < flightStartTime()) { + end = flightStartTime().addSecs(30 * 60); + endt = end.toUTC().toMSecsSinceEpoch(); } - _flightEndTime = end; + _flightPlan.end_time = airmap::from_milliseconds_since_epoch(airmap::Milliseconds{(long long)endt}); emit flightEndTimeChanged(); } } +//----------------------------------------------------------------------------- +QDateTime +AirMapFlightPlanManager::flightStartTime() const +{ + return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flightPlan.start_time)); +} + +//----------------------------------------------------------------------------- +QDateTime +AirMapFlightPlanManager::flightEndTime() const +{ + return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flightPlan.end_time)); +} + //----------------------------------------------------------------------------- void AirMapFlightPlanManager::startFlightPlanning(PlanMasterController *planController) @@ -145,7 +195,7 @@ AirMapFlightPlanManager::startFlightPlanning(PlanMasterController *planControlle //-- TODO: Check if there is an ongoing flight plan and do something about it (Delete it?) /* - * if(!_flightPlan.isEmpty()) { + * if(!flightPlanID().isEmpty()) { * do something; * } */ @@ -161,7 +211,7 @@ AirMapFlightPlanManager::startFlightPlanning(PlanMasterController *planControlle void AirMapFlightPlanManager::submitFlightPlan() { - if(_flightPlan.isEmpty()) { + if(flightPlanID().isEmpty()) { qCWarning(AirMapManagerLog) << "Submit flight with no flight plan."; return; } @@ -169,13 +219,15 @@ AirMapFlightPlanManager::submitFlightPlan() _state = State::FlightSubmit; FlightPlans::Submit::Parameters params; params.authorization = _shared.loginToken().toStdString(); - params.id = _flightPlan.toStdString(); + params.id = flightPlanID().toStdString(); std::weak_ptr isAlive(_instance); _shared.client()->flight_plans().submit(params, [this, isAlive](const FlightPlans::Submit::Result& result) { if (!isAlive.lock()) return; if (_state != State::FlightSubmit) return; if (result) { - _flightId = QString::fromStdString(result.value().flight_id.get()); + _flightPlan = result.value(); + _flightId = QString::fromStdString(_flightPlan.flight_id.get()); + _state = State::Idle; _pollBriefing(); } else { QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : ""); @@ -207,30 +259,10 @@ AirMapFlightPlanManager::updateFlightPlan() //----------------------------------------------------------------------------- void -AirMapFlightPlanManager::deleteSelectedFlights() +AirMapFlightPlanManager::endFlight(QString flightID) { - qCDebug(AirMapManagerLog) << "Delete flights"; - _flightsToDelete.clear(); - for(int i = 0; i < _flightList.count(); i++) { - AirspaceFlightInfo* pInfo = _flightList.get(i); - if(pInfo && pInfo->selected()) { - _flightsToDelete << pInfo->flightID(); - } - } - if(_flightsToDelete.count()) { - deleteFlight(QString()); - } -} - -//----------------------------------------------------------------------------- -void -AirMapFlightPlanManager::deleteFlight(QString flightID) -{ - qCDebug(AirMapManagerLog) << "Delete flight"; - if(!flightID.isEmpty()) { - _flightsToDelete.clear(); - _flightsToDelete << flightID; - } + qCDebug(AirMapManagerLog) << "End flight"; + _flightToEnd = flightID; if (_pilotID == "") { //-- Need to get the pilot id qCDebug(AirMapManagerLog) << "Getting pilot ID"; @@ -247,7 +279,7 @@ AirMapFlightPlanManager::deleteFlight(QString flightID) _pilotID = QString::fromStdString(result.value().id); qCDebug(AirMapManagerLog) << "Got Pilot ID:"<<_pilotID; _state = State::Idle; - _deleteFlight(); + _endFlight(); } else { _state = State::Idle; QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : ""); @@ -257,58 +289,47 @@ AirMapFlightPlanManager::deleteFlight(QString flightID) }); }); } else { - _deleteFlight(); + _endFlight(); } } //----------------------------------------------------------------------------- void -AirMapFlightPlanManager::_deleteFlight() +AirMapFlightPlanManager::_endFlight() { - if(_flightsToDelete.count() < 1) { - qCDebug(AirMapManagerLog) << "Delete non existing flight"; + if(_flightToEnd.isEmpty()) { + qCDebug(AirMapManagerLog) << "End non existing flight"; return; } - qCDebug(AirMapManagerLog) << "Delete Flight. State:" << (int)_state; + qCDebug(AirMapManagerLog) << "End Flight. State:" << (int)_state; if(_state != State::Idle) { - QTimer::singleShot(100, this, &AirMapFlightPlanManager::_deleteFlight); + QTimer::singleShot(100, this, &AirMapFlightPlanManager::_endFlight); return; } - int idx = _flightList.findFlightPlanID(_flightsToDelete.last()); - if(idx >= 0) { - AirspaceFlightInfo* pInfo = _flightList.get(idx); - if(pInfo) { - pInfo->setBeingDeleted(true); - } - } - qCDebug(AirMapManagerLog) << "Deleting flight:" << _flightsToDelete.last(); - _state = State::FlightDelete; + qCDebug(AirMapManagerLog) << "Ending flight:" << _flightToEnd; + _state = State::FlightEnd; std::weak_ptr isAlive(_instance); - FlightPlans::Delete::Parameters params; + Flights::EndFlight::Parameters params; params.authorization = _shared.loginToken().toStdString(); - params.id = _flightsToDelete.last().toStdString(); - //-- Delete flight plan - _shared.client()->flight_plans().delete_(params, [this, isAlive](const FlightPlans::Delete::Result& result) { + params.id = _flightToEnd.toStdString(); + //-- End flight + _shared.client()->flights().end_flight(params, [this, isAlive](const Flights::EndFlight::Result& result) { if (!isAlive.lock()) return; - if (_state != State::FlightDelete) return; + if (_state != State::FlightEnd) return; if (result) { - qCDebug(AirMapManagerLog) << "Flight deleted"; - _flightList.remove(_flightsToDelete.last()); + qCDebug(AirMapManagerLog) << "Flight Ended"; + int idx = _flightList.findFlightID(_flightToEnd); + if(idx >= 0) { + AirMapFlightInfo* pInfo = qobject_cast(_flightList.get(idx)); + if(pInfo) { + pInfo->setEndFlight(result.value().end_time); + } + } } else { QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : ""); - emit error("Flight deletion failed", QString::fromStdString(result.error().message()), description); - AirspaceFlightInfo* pFlight = _flightList.get(_flightList.findFlightPlanID(_flightsToDelete.last())); - if(pFlight) { - pFlight->setBeingDeleted(false); - } - } - _flightsToDelete.removeLast(); - //-- Keep at it until all flights are deleted - // TODO: This is ineficient. These whole airmapd transactions need to be moved into a separate - // worker thread. - if(_flightsToDelete.count()) { - QTimer::singleShot(10, this, &AirMapFlightPlanManager::_deleteFlight); + emit error("End flight failed", QString::fromStdString(result.error().message()), description); } + _flightToEnd.clear(); _state = State::Idle; }); } @@ -332,15 +353,6 @@ AirMapFlightPlanManager::_collectFlightDtata() _flight.coords = bc.polygon2D(); _flight.bc = bc; emit missionAreaChanged(); - //-- Flight Date/Time - if(_flightStartTime.isNull() || _flightStartTime < QDateTime::currentDateTime()) { - _flightStartTime = QDateTime::currentDateTime().addSecs(5 * 60); - emit flightStartTimeChanged(); - } - if(_flightEndTime.isNull() || _flightEndTime < _flightStartTime) { - _flightEndTime = _flightStartTime.addSecs(30 * 60); - emit flightEndTimeChanged(); - } return true; } @@ -358,8 +370,8 @@ AirMapFlightPlanManager::_createFlightPlan() qCDebug(AirMapManagerLog) << "About to create flight plan"; qCDebug(AirMapManagerLog) << "Takeoff: " << _flight.takeoffCoord; qCDebug(AirMapManagerLog) << "Bounding box:" << _flight.bc.pointNW << _flight.bc.pointSE; - qCDebug(AirMapManagerLog) << "Flight Start:" << _flightStartTime; - qCDebug(AirMapManagerLog) << "Flight End: " << _flightEndTime; + qCDebug(AirMapManagerLog) << "Flight Start:" << flightStartTime().toString(); + qCDebug(AirMapManagerLog) << "Flight End: " << flightEndTime().toString(); //-- Not Yet //return; @@ -420,8 +432,8 @@ AirMapFlightPlanManager::_uploadFlightPlan() params.latitude = _flight.takeoffCoord.latitude(); params.longitude = _flight.takeoffCoord.longitude(); params.pilot.id = _pilotID.toStdString(); - quint64 start = _flightStartTime.toUTC().toMSecsSinceEpoch(); - quint64 end = _flightEndTime.toUTC().toMSecsSinceEpoch(); + quint64 start = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch(); + quint64 end = start + 60 * 30 * 1000; params.start_time = airmap::from_milliseconds_since_epoch(airmap::Milliseconds{(long long)start}); params.end_time = airmap::from_milliseconds_since_epoch(airmap::Milliseconds{(long long)end}); //-- Rules @@ -433,6 +445,7 @@ AirMapFlightPlanManager::_uploadFlightPlan() if(ruleSet && ruleSet->selected()) { params.rulesets.push_back(ruleSet->id().toStdString()); //-- Features within each rule + /* for(int r = 0; r < ruleSet->rules()->count(); r++) { AirMapRule* rule = qobject_cast(ruleSet->rules()->get(r)); if(rule) { @@ -462,18 +475,19 @@ AirMapFlightPlanManager::_uploadFlightPlan() } } } + */ } } } - //-- Geometry: LineString - Geometry::LineString lineString; + //-- Geometry: polygon + Geometry::Polygon polygon; for (const auto& qcoord : _flight.coords) { Geometry::Coordinate coord; coord.latitude = qcoord.latitude(); coord.longitude = qcoord.longitude(); - lineString.coordinates.push_back(coord); + polygon.outer_ring.coordinates.push_back(coord); } - params.geometry = Geometry(lineString); + params.geometry = Geometry(polygon); params.authorization = login_token.toStdString(); //-- Create flight plan _shared.client()->flight_plans().create_by_polygon(params, [this, isAlive](const FlightPlans::Create::Result& result) { @@ -481,8 +495,8 @@ AirMapFlightPlanManager::_uploadFlightPlan() if (_state != State::FlightUpload) return; _state = State::Idle; if (result) { - _flightPlan = QString::fromStdString(result.value().id); - qCDebug(AirMapManagerLog) << "Flight plan created:" << _flightPlan; + _flightPlan = result.value(); + qCDebug(AirMapManagerLog) << "Flight plan created:" << flightPlanID(); _pollBriefing(); } else { QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : ""); @@ -512,8 +526,34 @@ AirMapFlightPlanManager::_updateFlightPlan() qCDebug(AirMapManagerLog) << "Takeoff: " << _flight.takeoffCoord; qCDebug(AirMapManagerLog) << "Bounding box:" << _flight.bc.pointNW << _flight.bc.pointSE; - qCDebug(AirMapManagerLog) << "Flight Start:" << _flightStartTime; - qCDebug(AirMapManagerLog) << "Flight End: " << _flightEndTime; + qCDebug(AirMapManagerLog) << "Flight Start:" << flightStartTime().toString(); + qCDebug(AirMapManagerLog) << "Flight End: " << flightEndTime().toString(); + + //-- Update local instance of the flight plan + _flightPlan.altitude_agl.max = _flight.maxAltitude; + _flightPlan.altitude_agl.min = 0.0f; + _flightPlan.buffer = 2.f; + _flightPlan.takeoff.latitude = _flight.takeoffCoord.latitude(); + _flightPlan.takeoff.longitude = _flight.takeoffCoord.longitude(); + //-- Geometry: polygon + Geometry::Polygon polygon; + for (const auto& qcoord : _flight.coords) { + Geometry::Coordinate coord; + coord.latitude = qcoord.latitude(); + coord.longitude = qcoord.longitude(); + polygon.outer_ring.coordinates.push_back(coord); + } + _flightPlan.geometry = Geometry(polygon); + + //-- Rules + /* + AirMapRulesetsManager* pRulesMgr = dynamic_cast(qgcApp()->toolbox()->airspaceManager()->ruleSets()); + if(pRulesMgr) { + foreach(QString ruleset, pRulesMgr->rulesetsIDs()) { + params.flight_plan.rulesets.push_back(ruleset.toStdString()); + } + } + */ _state = State::FlightUpdate; std::weak_ptr isAlive(_instance); @@ -522,42 +562,14 @@ AirMapFlightPlanManager::_updateFlightPlan() if (_state != State::FlightUpdate) return; FlightPlans::Update::Parameters params = {}; params.authorization = login_token.toStdString(); - params.flight_plan.id = _flightPlan.toStdString(); - params.flight_plan.pilot.id = _pilotID.toStdString(); - params.flight_plan.altitude_agl.max = _flight.maxAltitude; - params.flight_plan.altitude_agl.min = 0.0f; - params.flight_plan.buffer = 2.f; - params.flight_plan.takeoff.latitude = _flight.takeoffCoord.latitude(); - params.flight_plan.takeoff.longitude = _flight.takeoffCoord.longitude(); - quint64 start = _flightStartTime.toUTC().toMSecsSinceEpoch(); - quint64 end = _flightEndTime.toUTC().toMSecsSinceEpoch(); - params.flight_plan.start_time = airmap::from_milliseconds_since_epoch(airmap::Milliseconds{(long long)start}); - params.flight_plan.end_time = airmap::from_milliseconds_since_epoch(airmap::Milliseconds{(long long)end}); - //-- Rules - /* - AirMapRulesetsManager* pRulesMgr = dynamic_cast(qgcApp()->toolbox()->airspaceManager()->ruleSets()); - if(pRulesMgr) { - foreach(QString ruleset, pRulesMgr->rulesetsIDs()) { - params.flight_plan.rulesets.push_back(ruleset.toStdString()); - } - } - */ - //-- Geometry: LineString - Geometry::LineString lineString; - for (const auto& qcoord : _flight.coords) { - Geometry::Coordinate coord; - coord.latitude = qcoord.latitude(); - coord.longitude = qcoord.longitude(); - lineString.coordinates.push_back(coord); - } - params.flight_plan.geometry = Geometry(lineString); + params.flight_plan = _flightPlan; //-- Update flight plan _shared.client()->flight_plans().update(params, [this, isAlive](const FlightPlans::Update::Result& result) { if (!isAlive.lock()) return; if (_state != State::FlightUpdate) return; _state = State::Idle; if (result) { - qCDebug(AirMapManagerLog) << "Flight plan updated:" << _flightPlan; + qCDebug(AirMapManagerLog) << "Flight plan updated:" << flightPlanID(); _pollBriefing(); } else { QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : ""); @@ -599,7 +611,7 @@ AirMapFlightPlanManager::_pollBriefing() _state = State::FlightPolling; FlightPlans::RenderBriefing::Parameters params; params.authorization = _shared.loginToken().toStdString(); - params.id = _flightPlan.toStdString(); + params.id = flightPlanID().toStdString(); std::weak_ptr isAlive(_instance); _shared.client()->flight_plans().render_briefing(params, [this, isAlive](const FlightPlans::RenderBriefing::Result& result) { if (!isAlive.lock()) return; @@ -743,7 +755,7 @@ AirMapFlightPlanManager::_missionChanged() } //-- Creating a new flight plan? if(_state == State::Idle) { - if(_flightPlan.isEmpty()) { + if(flightPlanID().isEmpty()) { _createFlightPlan(); } else { //-- Plan is being modified @@ -828,8 +840,9 @@ AirMapFlightPlanManager::_loadFlightList() for (const auto& flight : response.flights) { AirMapFlightInfo* pFlight = new AirMapFlightInfo(flight, this); _flightList.append(pFlight); - qCDebug(AirMapManagerLog) << "Found:" << pFlight->flightID() << pFlight->flightPlanID(); + qCDebug(AirMapManagerLog) << "Found:" << pFlight->flightID() << pFlight->flightPlanID() << pFlight->endTime(); } + _flightList.sortStartFlight(); emit flightListChanged(); } else { if(!result) { diff --git a/src/Airmap/AirMapFlightPlanManager.h b/src/Airmap/AirMapFlightPlanManager.h index 782cfb18f41f5d2d8dbbed427b5e16bfac7acd42..6a65a2034665d18ec29292ba072bb78d1004f44a 100644 --- a/src/Airmap/AirMapFlightPlanManager.h +++ b/src/Airmap/AirMapFlightPlanManager.h @@ -19,6 +19,7 @@ #include #include "airmap/flight.h" +#include "airmap/flight_plan.h" class PlanMasterController; @@ -49,11 +50,14 @@ public: QString createdTime () override; QString startTime () override; QString endTime () override; + QDateTime qStartTime () override; QGeoCoordinate takeOff () override { return QGeoCoordinate(_flight.latitude, _flight.longitude);} - QmlObjectListModel* boundingBox () override { return &_boundingBox; } + QVariantList boundingBox () override { return _boundingBox; } + bool active () override; + void setEndFlight (airmap::DateTime end); private: airmap::Flight _flight; - QmlObjectListModel _boundingBox; + QVariantList _boundingBox; }; //----------------------------------------------------------------------------- @@ -66,8 +70,8 @@ public: ~AirMapFlightPlanManager (); PermitStatus flightPermitStatus () const override { return _flightPermitStatus; } - QDateTime flightStartTime () const override { return _flightStartTime; } - QDateTime flightEndTime () const override { return _flightEndTime; } + QDateTime flightStartTime () const override; + QDateTime flightEndTime () const override; bool valid () override { return _valid; } QmlObjectListModel* advisories () override { return &_advisories; } QmlObjectListModel* ruleSets () override { return &_rulesets; } @@ -84,6 +88,7 @@ public: QmlObjectListModel* authorizations () override { return &_authorizations; } AirspaceFlightModel*flightList () override { return &_flightList; } bool loadingFlightList () override { return _loadingFlightList; } + QString flightPlanID () {return QString::fromStdString(_flightPlan.id); } void updateFlightPlan () override; void submitFlightPlan () override; @@ -91,9 +96,7 @@ public: void setFlightStartTime (QDateTime start) override; void setFlightEndTime (QDateTime end) override; void loadFlightList (QDateTime startTime, QDateTime endTime) override; - void deleteFlight (QString flightID) override; - - void deleteSelectedFlights() override; + void endFlight (QString flightID) override; signals: void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); @@ -101,7 +104,7 @@ signals: private slots: void _pollBriefing (); void _missionChanged (); - void _deleteFlight (); + void _endFlight (); void _uploadFlightPlan (); void _updateFlightPlan (); void _loadFlightList (); @@ -116,7 +119,7 @@ private: GetPilotID, FlightUpload, FlightUpdate, - FlightDelete, + FlightEnd, FlightSubmit, FlightPolling, LoadFlightList, @@ -138,15 +141,12 @@ private: State _state = State::Idle; AirMapSharedState& _shared; QTimer _pollTimer; ///< timer to poll for approval check - QString _flightPlan; ///< Current flight plan QString _flightId; ///< Current flight ID, not necessarily accepted yet QString _pilotID; ///< Pilot ID in the form "auth0|abc123" - QStringList _flightsToDelete; + QString _flightToEnd; PlanMasterController* _planController = nullptr; bool _valid = false; bool _loadingFlightList = false; - QDateTime _flightStartTime; - QDateTime _flightEndTime; QmlObjectListModel _advisories; QmlObjectListModel _rulesets; QmlObjectListModel _rulesViolation; @@ -158,6 +158,7 @@ private: AirspaceFlightModel _flightList; QDateTime _rangeStart; QDateTime _rangeEnd; + airmap::FlightPlan _flightPlan; AirspaceAdvisoryProvider::AdvisoryColor _airspaceColor; AirspaceFlightPlanProvider::PermitStatus _flightPermitStatus = AirspaceFlightPlanProvider::PermitNone; diff --git a/src/Airmap/AirmapSettings.qml b/src/Airmap/AirmapSettings.qml index 241ae8f4f9f74ea3dab1980bf97838a9307e0454..7f99b3ea5df145515664325942801d0ad951c3e3 100644 --- a/src/Airmap/AirmapSettings.qml +++ b/src/Airmap/AirmapSettings.qml @@ -294,18 +294,6 @@ QGCView { onPressed: { mouse.accepted = true; } onReleased: { mouse.accepted = true; } } - function updateSelection() { - //-- Clear selection - for(var i = 0; i < _flightList.count; i++) { - var o = _flightList.get(i) - if (o) o.selected = false - } - //-- Flag selected flights - tableView.selection.forEach(function(rowIndex){ - var o = _flightList.get(rowIndex) - if (o) o.selected = true - }) - } //--------------------------------------------------------- //-- Flight List RowLayout { @@ -315,8 +303,19 @@ QGCView { anchors.top: parent.top anchors.bottom: parent.bottom model: _flightList - selectionMode: SelectionMode.MultiSelection + selectionMode: SelectionMode.SingleSelection Layout.fillWidth: true + onCurrentRowChanged: { + map.fitViewportToMapItems() + var o = _flightList.get(tableView.currentRow) + if(o) { + console.log(o.boundingBox.count) + console.log(o.boundingBox) + console.log(o.flightID) + } else { + console.log('No bounding box') + } + } TableViewColumn { title: qsTr("No") width: ScreenTools.defaultFontPixelWidth * 3 @@ -331,7 +330,7 @@ QGCView { } TableViewColumn { title: qsTr("Created") - width: ScreenTools.defaultFontPixelWidth * 20 + width: ScreenTools.defaultFontPixelWidth * 18 horizontalAlignment: Text.AlignHCenter delegate : Text { horizontalAlignment: Text.AlignHCenter @@ -346,7 +345,7 @@ QGCView { } TableViewColumn { title: qsTr("Flight Start") - width: ScreenTools.defaultFontPixelWidth * 20 + width: ScreenTools.defaultFontPixelWidth * 18 horizontalAlignment: Text.AlignHCenter delegate : Text { horizontalAlignment: Text.AlignHCenter @@ -359,15 +358,30 @@ QGCView { font.pixelSize: ScreenTools.smallFontPointSize } } + TableViewColumn { + title: qsTr("Flight End") + width: ScreenTools.defaultFontPixelWidth * 18 + horizontalAlignment: Text.AlignHCenter + delegate : Text { + horizontalAlignment: Text.AlignHCenter + text: { + var o = _flightList.get(styleData.row) + return o ? o.endTime : "" + } + color: tableView.currentRow === styleData.row ? qgcPal.colorBlue : "black" + font.family: ScreenTools.fixedFontFamily + font.pixelSize: ScreenTools.smallFontPointSize + } + } TableViewColumn { title: qsTr("State") - width: ScreenTools.defaultFontPixelWidth * 22 + width: ScreenTools.defaultFontPixelWidth * 8 horizontalAlignment: Text.AlignHCenter delegate : Text { horizontalAlignment: Text.AlignHCenter text: { var o = _flightList.get(styleData.row) - return o ? (o.beingDeleted ? qsTr("Deleting") : qsTr("Valid")) : qsTr("Unknown") + return o ? (o.active ? qsTr("Active") : qsTr("Completed")) : qsTr("Unknown") } color: tableView.currentRow === styleData.row ? qgcPal.colorBlue : "black" font.family: ScreenTools.fixedFontFamily @@ -491,40 +505,21 @@ QGCView { } } QGCButton { - text: qsTr("Select All") - backRadius: 4 - heightFactor: 0.3333 - showBorder: true - width: _buttonWidth - enabled: _flightList.count > 0 - anchors.horizontalCenter: parent.horizontalCenter - onClicked: { - tableView.selection.selectAll() - } - } - QGCButton { - text: qsTr("Select None") + text: qsTr("End Selected") backRadius: 4 heightFactor: 0.3333 showBorder: true width: _buttonWidth - enabled: _flightList.count > 0 - anchors.horizontalCenter: parent.horizontalCenter - onClicked: { - tableView.selection.clear() + enabled: { + var o = _flightList.get(tableView.currentRow) + return o && o.active } - } - QGCButton { - text: qsTr("Delete Selected") - backRadius: 4 - heightFactor: 0.3333 - showBorder: true - width: _buttonWidth - enabled: tableView.selection.count > 0 anchors.horizontalCenter: parent.horizontalCenter onClicked: { - flightListRoot.updateSelection(); - QGroundControl.airspaceManager.flightPlan.deleteSelectedFlights() + var o = _flightList.get(tableView.currentRow) + if(o) { + QGroundControl.airspaceManager.flightPlan.endFlight(o.flightID) + } } } QGCButton { @@ -539,7 +534,7 @@ QGCView { } } QGCLabel { - text: _flightList.count > 0 ? tableView.selection.count + '/' + _flightList.count + qsTr(" Flights Selected") : qsTr("No Flights Loaded") + text: _flightList.count > 0 ? _flightList.count + qsTr(" Flights Loaded") : qsTr("No Flights Loaded") anchors.horizontalCenter: parent.horizontalCenter } QGCLabel { @@ -578,6 +573,20 @@ QGCView { } } } + MapItemView { + model: { + var o = _flightList.get(tableView.currentRow) + if(o) { + return o.boundingBox + } + return [] + } + delegate: MapPolygon { + path: object + color: Qt.rgba(1,0,0,0.2) + border.color: Qt.rgba(1,1,1,0.65) + } + } Component.onCompleted: { updateActiveMapType() } diff --git a/src/AirspaceManagement/AirspaceFlightPlanProvider.cc b/src/AirspaceManagement/AirspaceFlightPlanProvider.cc index ec6985677098a46233b630d8b9071f3e6aa480d4..574523eb4c14c02bda79ea7497576ecfc403dc4e 100644 --- a/src/AirspaceManagement/AirspaceFlightPlanProvider.cc +++ b/src/AirspaceManagement/AirspaceFlightPlanProvider.cc @@ -20,8 +20,6 @@ AirspaceFlightAuthorization::AirspaceFlightAuthorization(QObject *parent) //----------------------------------------------------------------------------- AirspaceFlightInfo::AirspaceFlightInfo(QObject *parent) : QObject(parent) - , _beingDeleted(false) - , _selected(false) { } @@ -50,10 +48,10 @@ AirspaceFlightModel::get(int index) //----------------------------------------------------------------------------- int -AirspaceFlightModel::findFlightPlanID(QString flightPlanID) +AirspaceFlightModel::findFlightID(QString flightID) { for(int i = 0; i < _flightEntries.count(); i++) { - if(_flightEntries[i]->flightPlanID() == flightPlanID) { + if(_flightEntries[i]->flightID() == flightID) { return i; } } @@ -80,9 +78,9 @@ AirspaceFlightModel::append(AirspaceFlightInfo* object) //----------------------------------------------------------------------------- void -AirspaceFlightModel::remove(const QString& flightPlanID) +AirspaceFlightModel::remove(const QString& flightID) { - remove(findFlightPlanID(flightPlanID)); + remove(findFlightID(flightID)); } //----------------------------------------------------------------------------- @@ -118,6 +116,26 @@ AirspaceFlightModel::clear(void) } } +//----------------------------------------------------------------------------- +static bool +flight_sort(QObject* a, QObject* b) +{ + AirspaceFlightInfo* aa = qobject_cast(a); + AirspaceFlightInfo* bb = qobject_cast(b); + if(!aa || !bb) return false; + return aa->qStartTime() > bb->qStartTime(); +} + +//----------------------------------------------------------------------------- +void +AirspaceFlightModel::sortStartFlight() +{ + beginResetModel(); + std::sort(_flightEntries.begin(), _flightEntries.end(), flight_sort); + endResetModel(); +} + + //----------------------------------------------------------------------------- AirspaceFlightInfo* AirspaceFlightModel::operator[](int index) diff --git a/src/AirspaceManagement/AirspaceFlightPlanProvider.h b/src/AirspaceManagement/AirspaceFlightPlanProvider.h index 1c27679c51fe03a66121b4c504f778a60945b727..f62fee3c5d1bba2f5bec62acf570a3f4fb767f04 100644 --- a/src/AirspaceManagement/AirspaceFlightPlanProvider.h +++ b/src/AirspaceManagement/AirspaceFlightPlanProvider.h @@ -68,30 +68,21 @@ public: Q_PROPERTY(QString startTime READ startTime CONSTANT) Q_PROPERTY(QString endTime READ endTime CONSTANT) Q_PROPERTY(QGeoCoordinate takeOff READ takeOff CONSTANT) - Q_PROPERTY(QmlObjectListModel* boundingBox READ boundingBox CONSTANT) - Q_PROPERTY(bool beingDeleted READ beingDeleted WRITE setBeingDeleted NOTIFY beingDeletedChanged) - Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged) + Q_PROPERTY(QVariantList boundingBox READ boundingBox CONSTANT) + Q_PROPERTY(bool active READ active NOTIFY activeChanged) virtual QString flightID () = 0; virtual QString flightPlanID () = 0; virtual QString createdTime () = 0; virtual QString startTime () = 0; + virtual QDateTime qStartTime () = 0; virtual QString endTime () = 0; virtual QGeoCoordinate takeOff () = 0; - virtual QmlObjectListModel* boundingBox () = 0; - - virtual bool beingDeleted () { return _beingDeleted; } - virtual void setBeingDeleted (bool val) { _beingDeleted = val; emit beingDeletedChanged(); } - virtual bool selected () { return _selected; } - virtual void setSelected (bool sel) { _selected = sel; emit selectedChanged(); } + virtual QVariantList boundingBox () = 0; + virtual bool active () = 0; signals: - void selectedChanged (); - void beingDeletedChanged (); - -protected: - bool _beingDeleted; - bool _selected; + void activeChanged (); }; //----------------------------------------------------------------------------- @@ -109,13 +100,14 @@ public: Q_PROPERTY(int count READ count NOTIFY countChanged) Q_INVOKABLE AirspaceFlightInfo* get (int index); - Q_INVOKABLE int findFlightPlanID (QString flightPlanID); + Q_INVOKABLE int findFlightID (QString flightID); - int count (void) const; + int count () const; void append (AirspaceFlightInfo *entry); - void remove (const QString& flightPlanID); + void remove (const QString& flightID); void remove (int index); - void clear (void); + void clear (); + void sortStartFlight (); AirspaceFlightInfo* operator[] (int i); @@ -175,8 +167,7 @@ public: Q_INVOKABLE virtual void submitFlightPlan () = 0; Q_INVOKABLE virtual void updateFlightPlan () = 0; Q_INVOKABLE virtual void loadFlightList (QDateTime startTime, QDateTime endTime) = 0; - Q_INVOKABLE virtual void deleteFlight (QString flighPlanID) = 0; - Q_INVOKABLE virtual void deleteSelectedFlights () = 0; + Q_INVOKABLE virtual void endFlight (QString flighID) = 0; virtual PermitStatus flightPermitStatus () const { return PermitNone; } virtual QDateTime flightStartTime () const = 0;