Commit 15b2bde0 authored by Gus Grubba's avatar Gus Grubba

WIP: Create polygon instead of lineString for flight plan

Remove delete flights and add "End" active flight instead
Work on flight geometry (flight list)
parent 845e8068
......@@ -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<LifetimeChecker> 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<LifetimeChecker> 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<AirMapFlightInfo*>(_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<AirMapRule*>(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<AirMapRulesetsManager*>(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<LifetimeChecker> 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<AirMapRulesetsManager*>(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<LifetimeChecker> 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) {
......
......@@ -19,6 +19,7 @@
#include <QGeoCoordinate>
#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;
......
......@@ -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()
}
......
......@@ -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<AirspaceFlightInfo*>(a);
AirspaceFlightInfo* bb = qobject_cast<AirspaceFlightInfo*>(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)
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment