Browse Source

Handling Date/Time

Flight management with date range, delete flights.
QGC4.4
Gus Grubba 7 years ago
parent
commit
51a6792a00
  1. 216
      src/Airmap/AirMapFlightPlanManager.cc
  2. 26
      src/Airmap/AirMapFlightPlanManager.h
  3. 4
      src/Airmap/AirMapManager.cc
  4. 201
      src/Airmap/AirmapSettings.qml
  5. 38
      src/AirspaceManagement/AirspaceFlightPlanProvider.cc
  6. 18
      src/AirspaceManagement/AirspaceFlightPlanProvider.h
  7. 2
      src/FactSystem/FactControls/FactTextField.qml

216
src/Airmap/AirMapFlightPlanManager.cc

@ -36,6 +36,27 @@ AirMapFlightInfo::AirMapFlightInfo(const airmap::Flight& flight, QObject *parent @@ -36,6 +36,27 @@ AirMapFlightInfo::AirMapFlightInfo(const airmap::Flight& flight, QObject *parent
}
//-----------------------------------------------------------------------------
QString
AirMapFlightInfo::createdTime()
{
return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.created_at)).toString("yyyy MM dd - hh:mm:ss");
}
//-----------------------------------------------------------------------------
QString
AirMapFlightInfo::startTime()
{
return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.start_time)).toString("yyyy MM dd - hh:mm:ss");
}
//-----------------------------------------------------------------------------
QString
AirMapFlightInfo::endTime()
{
return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.end_time)).toString("yyyy MM dd - hh:mm:ss");
}
//-----------------------------------------------------------------------------
AirMapFlightPlanManager::AirMapFlightPlanManager(AirMapSharedState& shared, QObject *parent)
: AirspaceFlightPlanProvider(parent)
, _shared(shared)
@ -160,6 +181,113 @@ AirMapFlightPlanManager::updateFlightPlan() @@ -160,6 +181,113 @@ AirMapFlightPlanManager::updateFlightPlan()
}
//-----------------------------------------------------------------------------
void
AirMapFlightPlanManager::deleteSelectedFlightPlans()
{
qCDebug(AirMapManagerLog) << "Delete flight plan";
_flightsToDelete.clear();
for(int i = 0; i < _flightList.count(); i++) {
AirspaceFlightInfo* pInfo = _flightList.get(i);
if(pInfo && pInfo->selected()) {
_flightsToDelete << pInfo->flightPlanID();
}
}
if(_flightsToDelete.count()) {
deleteFlightPlan(QString());
}
}
//-----------------------------------------------------------------------------
void
AirMapFlightPlanManager::deleteFlightPlan(QString flightPlanID)
{
qCDebug(AirMapManagerLog) << "Delete flight plan";
if(!flightPlanID.isEmpty()) {
_flightsToDelete.clear();
_flightsToDelete << flightPlanID;
}
if (_pilotID == "") {
//-- Need to get the pilot id
qCDebug(AirMapManagerLog) << "Getting pilot ID";
_state = State::GetPilotID;
std::weak_ptr<LifetimeChecker> isAlive(_instance);
_shared.doRequestWithLogin([this, isAlive](const QString& login_token) {
if (!isAlive.lock()) return;
Pilots::Authenticated::Parameters params;
params.authorization = login_token.toStdString();
_shared.client()->pilots().authenticated(params, [this, isAlive](const Pilots::Authenticated::Result& result) {
if (!isAlive.lock()) return;
if (_state != State::GetPilotID) return;
if (result) {
_pilotID = QString::fromStdString(result.value().id);
qCDebug(AirMapManagerLog) << "Got Pilot ID:"<<_pilotID;
_state = State::Idle;
_deleteFlightPlan();
} else {
_state = State::Idle;
QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
emit error("Failed to get pilot ID", QString::fromStdString(result.error().message()), description);
return;
}
});
});
} else {
_deleteFlightPlan();
}
}
//-----------------------------------------------------------------------------
void
AirMapFlightPlanManager::_deleteFlightPlan()
{
if(_flightsToDelete.count() < 1) {
qCDebug(AirMapManagerLog) << "Delete non existing flight plan";
return;
}
if(_state != State::Idle) {
QTimer::singleShot(100, this, &AirMapFlightPlanManager::_deleteFlightPlan);
return;
}
int idx = _flightList.findFlightPlanID(_flightsToDelete.last());
if(idx >= 0) {
AirspaceFlightInfo* pInfo = _flightList.get(idx);
if(pInfo) {
pInfo->setBeingDeleted(true);
}
}
qCDebug(AirMapManagerLog) << "Deleting flight plan:" << _flightsToDelete.last();
_state = State::FlightDelete;
std::weak_ptr<LifetimeChecker> isAlive(_instance);
FlightPlans::Delete::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) {
if (!isAlive.lock()) return;
if (_state != State::FlightDelete) return;
if (result) {
qCDebug(AirMapManagerLog) << "Flight plan deleted";
_flightList.remove(_flightsToDelete.last());
} else {
QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
emit error("Flight Plan 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::_deleteFlightPlan);
}
_state = State::Idle;
});
}
//-----------------------------------------------------------------------------
bool
AirMapFlightPlanManager::_collectFlightDtata()
{
@ -250,6 +378,10 @@ void @@ -250,6 +378,10 @@ void
AirMapFlightPlanManager::_uploadFlightPlan()
{
qCDebug(AirMapManagerLog) << "Uploading flight plan";
if(_state != State::Idle) {
QTimer::singleShot(100, this, &AirMapFlightPlanManager::_uploadFlightPlan);
return;
}
_state = State::FlightUpload;
std::weak_ptr<LifetimeChecker> isAlive(_instance);
_shared.doRequestWithLogin([this, isAlive](const QString& login_token) {
@ -262,16 +394,10 @@ AirMapFlightPlanManager::_uploadFlightPlan() @@ -262,16 +394,10 @@ AirMapFlightPlanManager::_uploadFlightPlan()
params.latitude = _flight.takeoffCoord.latitude();
params.longitude = _flight.takeoffCoord.longitude();
params.pilot.id = _pilotID.toStdString();
/*
TODO: Convert this to fucking boost
quint64 start = _flightStartTime.toUTC().toMSecsSinceEpoch();
quint64 end = _flightEndTime.toUTC().toMSecsSinceEpoch();
*/
params.start_time = Clock::universal_time() + Minutes{5};
params.end_time = Clock::universal_time() + Hours{2};
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
AirMapRulesetsManager* pRulesMgr = dynamic_cast<AirMapRulesetsManager*>(qgcApp()->toolbox()->airspaceManager()->ruleSets());
if(pRulesMgr) {
@ -345,12 +471,16 @@ AirMapFlightPlanManager::_updateFlightPlan() @@ -345,12 +471,16 @@ AirMapFlightPlanManager::_updateFlightPlan()
// little to do with those used when creating it.
qCDebug(AirMapManagerLog) << "Updating flight plan";
if(_state != State::Idle) {
QTimer::singleShot(100, this, &AirMapFlightPlanManager::_updateFlightPlan);
return;
}
//-- Get flight data
if(!_collectFlightDtata()) {
return;
}
qCDebug(AirMapManagerLog) << "About to update the flight plan";
qCDebug(AirMapManagerLog) << "Takeoff: " << _flight.takeoffCoord;
qCDebug(AirMapManagerLog) << "Bounding box:" << _flight.bc.pointNW << _flight.bc.pointSE;
qCDebug(AirMapManagerLog) << "Flight Start:" << _flightStartTime;
@ -370,16 +500,10 @@ AirMapFlightPlanManager::_updateFlightPlan() @@ -370,16 +500,10 @@ AirMapFlightPlanManager::_updateFlightPlan()
params.flight_plan.buffer = 2.f;
params.flight_plan.takeoff.latitude = _flight.takeoffCoord.latitude();
params.flight_plan.takeoff.longitude = _flight.takeoffCoord.longitude();
/*
TODO: Convert this to fucking boost
quint64 start = _flightStartTime.toUTC().toMSecsSinceEpoch();
quint64 end = _flightEndTime.toUTC().toMSecsSinceEpoch();
*/
params.flight_plan.start_time = Clock::universal_time() + Minutes{5};
params.flight_plan.end_time = Clock::universal_time() + Hours{2};
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());
@ -568,36 +692,6 @@ AirMapFlightPlanManager::_pollBriefing() @@ -568,36 +692,6 @@ AirMapFlightPlanManager::_pollBriefing()
//-----------------------------------------------------------------------------
void
AirMapFlightPlanManager::_deleteFlightPlan()
{
if(_flightPlan.isEmpty()) {
qCDebug(AirMapManagerLog) << "Delete non existing flight plan";
return;
}
qCDebug(AirMapManagerLog) << "Deleting flight plan";
_state = State::FlightDelete;
std::weak_ptr<LifetimeChecker> isAlive(_instance);
FlightPlans::Delete::Parameters params;
params.authorization = _shared.loginToken().toStdString();
params.id = _flightPlan.toStdString();
//-- Delete flight plan
_shared.client()->flight_plans().delete_(params, [this, isAlive](const FlightPlans::Delete::Result& result) {
if (!isAlive.lock()) return;
if (_state != State::FlightDelete) return;
if (result) {
_flightPlan.clear();
qCDebug(AirMapManagerLog) << "Flight plan deleted";
_state = State::Idle;
} else {
_state = State::Idle;
QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
emit error("Flight Plan deletion failed", QString::fromStdString(result.error().message()), description);
}
});
}
//-----------------------------------------------------------------------------
void
AirMapFlightPlanManager::_missionChanged()
{
//-- Are we enabled?
@ -621,9 +715,16 @@ AirMapFlightPlanManager::_missionChanged() @@ -621,9 +715,16 @@ AirMapFlightPlanManager::_missionChanged()
//-----------------------------------------------------------------------------
void
AirMapFlightPlanManager::loadFlightList()
AirMapFlightPlanManager::loadFlightList(QDateTime startTime, QDateTime endTime)
{
qCDebug(AirMapManagerLog) << "Search flights";
//-- TODO: This is not checking if the state is Idle. Again, these need to
// queued up and handled by a worker thread.
qCDebug(AirMapManagerLog) << "Preparing load flight list";
_loadingFlightList = true;
emit loadingFlightListChanged();
_rangeStart = startTime;
_rangeEnd = endTime;
qCDebug(AirMapManagerLog) << "List flights from:" << _rangeStart.toString("yyyy MM dd - hh:mm:ss") << "to" << _rangeEnd.toString("yyyy MM dd - hh:mm:ss");
if (_pilotID == "") {
//-- Need to get the pilot id
qCDebug(AirMapManagerLog) << "Getting pilot ID";
@ -645,6 +746,8 @@ AirMapFlightPlanManager::loadFlightList() @@ -645,6 +746,8 @@ AirMapFlightPlanManager::loadFlightList()
_state = State::Idle;
QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
emit error("Failed to get pilot ID", QString::fromStdString(result.error().message()), description);
_loadingFlightList = false;
emit loadingFlightListChanged();
return;
}
});
@ -658,6 +761,11 @@ AirMapFlightPlanManager::loadFlightList() @@ -658,6 +761,11 @@ AirMapFlightPlanManager::loadFlightList()
void
AirMapFlightPlanManager::_loadFlightList()
{
qCDebug(AirMapManagerLog) << "Load flight list";
if(_state != State::Idle) {
QTimer::singleShot(100, this, &AirMapFlightPlanManager::_loadFlightList);
return;
}
_flightList.clear();
emit flightListChanged();
_state = State::LoadFlightList;
@ -667,8 +775,13 @@ AirMapFlightPlanManager::_loadFlightList() @@ -667,8 +775,13 @@ AirMapFlightPlanManager::_loadFlightList()
if (_state != State::LoadFlightList) return;
Flights::Search::Parameters params;
params.authorization = login_token.toStdString();
params.limit = 60;
quint64 start = _rangeStart.toUTC().toMSecsSinceEpoch();
quint64 end = _rangeEnd.toUTC().toMSecsSinceEpoch();
params.start_after = airmap::from_milliseconds_since_epoch(airmap::Milliseconds{(long long)start});
params.start_before = airmap::from_milliseconds_since_epoch(airmap::Milliseconds{(long long)end});
params.limit = 250;
params.pilot_id = _pilotID.toStdString();
qCDebug(AirMapManagerLog) << "List flights from:" << _rangeStart.toUTC().toString("yyyy MM dd - hh:mm:ss") << "to" << _rangeEnd.toUTC().toString("yyyy MM dd - hh:mm:ss");
_shared.client()->flights().search(params, [this, isAlive](const Flights::Search::Result& result) {
if (!isAlive.lock()) return;
if (_state != State::LoadFlightList) return;
@ -686,6 +799,9 @@ AirMapFlightPlanManager::_loadFlightList() @@ -686,6 +799,9 @@ AirMapFlightPlanManager::_loadFlightList()
emit error("Flight search failed", QString::fromStdString(result.error().message()), description);
}
}
_state = State::Idle;
_loadingFlightList = false;
emit loadingFlightListChanged();
});
});
}

26
src/Airmap/AirMapFlightPlanManager.h

@ -29,10 +29,10 @@ class AirMapFlightInfo : public AirspaceFlightInfo @@ -29,10 +29,10 @@ class AirMapFlightInfo : public AirspaceFlightInfo
public:
AirMapFlightInfo (const airmap::Flight& flight, QObject *parent = nullptr);
QString flightID () override { return QString::fromStdString(_flight.id); }
QString flightPlanID () override { return QString::fromStdString(_flight.flight_plan_id.get()); }
QString createdTime () override { return QDateTime::currentDateTime().toString(Qt::SystemLocaleShortDate); } //-- TODO: Need to get rid of boost first
QString startTime () override { return QDateTime::currentDateTime().toString(Qt::SystemLocaleShortDate); } //-- TODO: Need to get rid of boost first
QString endTime () override { return QDateTime::currentDateTime().toString(Qt::SystemLocaleShortDate); } //-- TODO: Need to get rid of boost first
QString flightPlanID () override { return _flight.flight_plan_id ? QString::fromStdString(_flight.flight_plan_id.get()) : QString(); }
QString createdTime () override;
QString startTime () override;
QString endTime () override;
QGeoCoordinate takeOff () override { return QGeoCoordinate(_flight.latitude, _flight.longitude);}
QmlObjectListModel* boundingBox () override { return &_boundingBox; }
private:
@ -66,13 +66,17 @@ public: @@ -66,13 +66,17 @@ public:
QmlObjectListModel* rulesFollowing () override { return &_rulesFollowing; }
QmlObjectListModel* briefFeatures () override { return &_briefFeatures; }
AirspaceFlightModel*flightList () override { return &_flightList; }
bool loadingFlightList () override { return _loadingFlightList; }
void updateFlightPlan () override;
void submitFlightPlan () override;
void startFlightPlanning (PlanMasterController* planController) override;
void setFlightStartTime (QDateTime start) override;
void setFlightEndTime (QDateTime end) override;
void loadFlightList () override;
void loadFlightList (QDateTime startTime, QDateTime endTime) override;
void deleteFlightPlan (QString flightPlanID) override;
void deleteSelectedFlightPlans() override;
signals:
void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
@ -80,14 +84,14 @@ signals: @@ -80,14 +84,14 @@ signals:
private slots:
void _pollBriefing ();
void _missionChanged ();
private:
void _deleteFlightPlan ();
void _uploadFlightPlan ();
void _updateFlightPlan ();
void _loadFlightList ();
private:
void _createFlightPlan ();
void _deleteFlightPlan ();
bool _collectFlightDtata ();
void _loadFlightList ();
private:
enum class State {
@ -121,8 +125,10 @@ private: @@ -121,8 +125,10 @@ private:
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;
PlanMasterController* _planController = nullptr;
bool _valid = false;
bool _loadingFlightList = false;
QDateTime _flightStartTime;
QDateTime _flightEndTime;
QmlObjectListModel _advisories;
@ -133,6 +139,8 @@ private: @@ -133,6 +139,8 @@ private:
QmlObjectListModel _rulesFollowing;
QmlObjectListModel _briefFeatures;
AirspaceFlightModel _flightList;
QDateTime _rangeStart;
QDateTime _rangeEnd;
AirspaceAdvisoryProvider::AdvisoryColor _airspaceColor;
AirspaceFlightPlanProvider::PermitStatus _flightPermitStatus = AirspaceFlightPlanProvider::PermitNone;

4
src/Airmap/AirMapManager.cc

@ -37,8 +37,8 @@ AirMapManager::AirMapManager(QGCApplication* app, QGCToolbox* toolbox) @@ -37,8 +37,8 @@ AirMapManager::AirMapManager(QGCApplication* app, QGCToolbox* toolbox)
{
_logger = std::make_shared<qt::Logger>();
qt::register_types(); // TODO: still needed?
_logger->logging_category().setEnabled(QtDebugMsg, false);
_logger->logging_category().setEnabled(QtInfoMsg, false);
_logger->logging_category().setEnabled(QtDebugMsg, true);
_logger->logging_category().setEnabled(QtInfoMsg, true);
_logger->logging_category().setEnabled(QtWarningMsg, true);
_dispatchingLogger = std::make_shared<qt::DispatchingLogger>(_logger);
connect(&_shared, &AirMapSharedState::error, this, &AirMapManager::_error);

201
src/Airmap/AirmapSettings.qml

@ -125,6 +125,7 @@ QGCView { @@ -125,6 +125,7 @@ QGCView {
QGCLabel { text: qsTr("Email:") }
FactTextField {
fact: _loginEmailFact
width: _editFieldWidth
enabled: _airMapEnabled
visible: _loginEmailFact.visible
property Fact _loginEmailFact: QGroundControl.settingsManager.airMapSettings.loginEmail
@ -132,6 +133,7 @@ QGCView { @@ -132,6 +133,7 @@ QGCView {
QGCLabel { text: qsTr("Password:") }
FactTextField {
fact: _loginPasswordFact
width: _editFieldWidth
enabled: _airMapEnabled
visible: _loginPasswordFact.visible
property Fact _loginPasswordFact: QGroundControl.settingsManager.airMapSettings.loginPassword
@ -225,13 +227,13 @@ QGCView { @@ -225,13 +227,13 @@ QGCView {
rowSpacing: ScreenTools.defaultFontPixelWidth * 0.25
anchors.centerIn: parent
QGCLabel { text: qsTr("API Key:") }
FactTextField { fact: QGroundControl.settingsManager.airMapSettings.apiKey; }
FactTextField { fact: QGroundControl.settingsManager.airMapSettings.apiKey; width: _editFieldWidth; }
QGCLabel { text: qsTr("Client ID:") }
FactTextField { fact: QGroundControl.settingsManager.airMapSettings.clientID; }
FactTextField { fact: QGroundControl.settingsManager.airMapSettings.clientID; width: _editFieldWidth; }
QGCLabel { text: qsTr("User Name:") }
FactTextField { fact: QGroundControl.settingsManager.airMapSettings.userName; }
FactTextField { fact: QGroundControl.settingsManager.airMapSettings.userName; width: _editFieldWidth; }
QGCLabel { text: qsTr("Password:") }
FactTextField { fact: QGroundControl.settingsManager.airMapSettings.password; echoMode: TextInput.Password }
FactTextField { fact: QGroundControl.settingsManager.airMapSettings.password; width: _editFieldWidth; echoMode: TextInput.Password }
}
}
//-----------------------------------------------------------------
@ -284,15 +286,7 @@ QGCView { @@ -284,15 +286,7 @@ QGCView {
height: _qgcView.height
color: qgcPal.window
property var _flightList: QGroundControl.airspaceManager.flightPlan.flightList
Component.onCompleted: {
QGroundControl.airspaceManager.flightPlan.loadFlightList()
}
Connections {
target: _flightList
onCountChanged: {
tableView.resizeColumnsToContents()
}
}
property real _mapWidth: ScreenTools.defaultFontPixelWidth * 40
MouseArea {
anchors.fill: parent
hoverEnabled: true
@ -300,6 +294,18 @@ QGCView { @@ -300,6 +294,18 @@ 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 {
@ -312,6 +318,18 @@ QGCView { @@ -312,6 +318,18 @@ QGCView {
selectionMode: SelectionMode.MultiSelection
Layout.fillWidth: true
TableViewColumn {
title: qsTr("No")
width: ScreenTools.defaultFontPixelWidth * 3
horizontalAlignment: Text.AlignHCenter
delegate : Text {
horizontalAlignment: Text.AlignHCenter
text: (styleData.row + 1)
color: tableView.currentRow === styleData.row ? qgcPal.colorBlue : "black"
font.family: ScreenTools.fixedFontFamily
font.pixelSize: ScreenTools.smallFontPointSize
}
}
TableViewColumn {
title: qsTr("Created")
width: ScreenTools.defaultFontPixelWidth * 20
horizontalAlignment: Text.AlignHCenter
@ -321,6 +339,9 @@ QGCView { @@ -321,6 +339,9 @@ QGCView {
var o = _flightList.get(styleData.row)
return o ? o.createdTime : ""
}
color: tableView.currentRow === styleData.row ? qgcPal.colorBlue : "black"
font.family: ScreenTools.fixedFontFamily
font.pixelSize: ScreenTools.smallFontPointSize
}
}
TableViewColumn {
@ -333,33 +354,126 @@ QGCView { @@ -333,33 +354,126 @@ QGCView {
var o = _flightList.get(styleData.row)
return o ? o.startTime : ""
}
color: tableView.currentRow === styleData.row ? qgcPal.colorBlue : "black"
font.family: ScreenTools.fixedFontFamily
font.pixelSize: ScreenTools.smallFontPointSize
}
}
TableViewColumn {
title: qsTr("Take Off")
title: qsTr("State")
width: ScreenTools.defaultFontPixelWidth * 22
horizontalAlignment: Text.AlignHCenter
delegate : Text {
horizontalAlignment: Text.AlignHCenter
text: {
var o = _flightList.get(styleData.row)
return o ? o.takeOff.latitude.toFixed(6) + ', ' + o.takeOff.longitude.toFixed(6) : ""
return o ? (o.beingDeleted ? qsTr("Deleting") : qsTr("Valid")) : qsTr("Unknown")
}
color: tableView.currentRow === styleData.row ? qgcPal.colorBlue : "black"
font.family: ScreenTools.fixedFontFamily
font.pixelSize: ScreenTools.smallFontPointSize
}
}
}
Item {
width: map.width
width: flightListRoot._mapWidth
height: parent.height
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
QGCLabel {
id: loadingLabel
text: qsTr("Loading Flight List")
visible: QGroundControl.airspaceManager.flightPlan.loadingFlightList
anchors.centerIn: parent
}
QGCColoredImage {
id: busyIndicator
height: ScreenTools.defaultFontPixelHeight * 2.5
width: height
source: "/qmlimages/MapSync.svg"
sourceSize.height: height
fillMode: Image.PreserveAspectFit
mipmap: true
smooth: true
color: qgcPal.colorGreen
visible: loadingLabel.visible
anchors.top: loadingLabel.bottom
anchors.topMargin: ScreenTools.defaultFontPixelHeight
anchors.horizontalCenter: parent.horizontalCenter
RotationAnimation on rotation {
loops: Animation.Infinite
from: 360
to: 0
duration: 740
running: busyIndicator.visible
}
}
Column {
spacing: ScreenTools.defaultFontPixelHeight
spacing: ScreenTools.defaultFontPixelHeight * 0.75
visible: !QGroundControl.airspaceManager.flightPlan.loadingFlightList
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
text: qsTr("Flight List")
anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle {
color: qgcPal.window
border.color: qgcPal.globalTheme === QGCPalette.Dark ? Qt.rgba(1,1,1,0.25) : Qt.rgba(0,0,0,0.25)
border.width: 1
radius: 4
width: _mapWidth - (ScreenTools.defaultFontPixelWidth * 2)
height: rangeCol.height + (ScreenTools.defaultFontPixelHeight * 2)
Column {
id: rangeCol
anchors.centerIn: parent
spacing: ScreenTools.defaultFontPixelHeight * 0.5
QGCLabel {
text: qsTr("Range")
anchors.horizontalCenter: parent.horizontalCenter
}
Row {
spacing: ScreenTools.defaultFontPixelWidth * 2
anchors.horizontalCenter: parent.horizontalCenter
Column {
spacing: ScreenTools.defaultFontPixelHeight * 0.5
QGCButton {
text: qsTr("From")
backRadius: 4
heightFactor: 0.3333
showBorder: true
width: _buttonWidth * 0.5
onClicked: fromPicker.visible = true
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
anchors.horizontalCenter: parent.horizontalCenter
text: fromPicker.selectedDate.toLocaleDateString(Qt.locale())
}
}
Rectangle {
width: 1
height: parent.height
color: qgcPal.globalTheme === QGCPalette.Dark ? Qt.rgba(1,1,1,0.25) : Qt.rgba(0,0,0,0.25)
}
Column {
spacing: ScreenTools.defaultFontPixelHeight * 0.5
QGCButton {
text: qsTr("To")
backRadius: 4
heightFactor: 0.3333
showBorder: true
width: _buttonWidth * 0.5
onClicked: toPicker.visible = true
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
anchors.horizontalCenter: parent.horizontalCenter
text: toPicker.selectedDate.toLocaleDateString(Qt.locale())
}
}
}
}
}
QGCButton {
text: qsTr("Refresh")
backRadius: 4
@ -369,7 +483,11 @@ QGCView { @@ -369,7 +483,11 @@ QGCView {
enabled: true
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
QGroundControl.airspaceManager.flightPlan.loadFlightList()
var start = fromPicker.selectedDate
var end = toPicker.selectedDate
start.setHours(0,0,0,0)
end.setHours(23,59,59,0)
QGroundControl.airspaceManager.flightPlan.loadFlightList(start, end)
}
}
QGCButton {
@ -402,20 +520,11 @@ QGCView { @@ -402,20 +520,11 @@ QGCView {
heightFactor: 0.3333
showBorder: true
width: _buttonWidth
enabled: false
enabled: tableView.selection.count > 0
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
//-- 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
})
//TODO:
flightListRoot.updateSelection();
QGroundControl.airspaceManager.flightPlan.deleteSelectedFlightPlans()
}
}
QGCButton {
@ -429,9 +538,21 @@ QGCView { @@ -429,9 +538,21 @@ QGCView {
panelLoader.sourceComponent = null
}
}
QGCLabel {
text: _flightList.count > 0 ? tableView.selection.count + '/' + _flightList.count + qsTr(" Flights Selected") : qsTr("No Flights Loaded")
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: qsTr("Flight Area")
text: qsTr("A maximum of 250 flights were loaded")
color: qgcPal.colorOrange
font.pixelSize: ScreenTools.smallFontPointSize
visible: _flightList.count >= 250
anchors.horizontalCenter: parent.horizontalCenter
}
}
QGCLabel {
text: qsTr("Flight Area ") + (tableView.currentRow + 1)
visible: !QGroundControl.airspaceManager.flightPlan.loadingFlightList && _flightList.count > 0 && tableView.currentRow >= 0
anchors.bottom: map.top
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 0.25
anchors.horizontalCenter: parent.horizontalCenter
@ -446,6 +567,7 @@ QGCView { @@ -446,6 +567,7 @@ QGCView {
center: QGroundControl.flightMapPosition
gesture.acceptedGestures: MapGestureArea.PinchGesture
plugin: Plugin { name: "QGroundControl" }
visible: !QGroundControl.airspaceManager.flightPlan.loadingFlightList && _flightList.count > 0 && tableView.currentRow >= 0
function updateActiveMapType() {
var settings = QGroundControl.settingsManager.flightMapSettings
var fullMapName = settings.mapProvider.enumStringValue + " " + settings.mapType.enumStringValue
@ -470,6 +592,23 @@ QGCView { @@ -470,6 +592,23 @@ QGCView {
}
}
Calendar {
id: fromPicker
anchors.centerIn: parent
visible: false;
onClicked: {
visible = false;
}
}
Calendar {
id: toPicker
anchors.centerIn: parent
visible: false;
minimumDate: fromPicker.selectedDate
onClicked: {
visible = false;
}
}
}
}
}

38
src/AirspaceManagement/AirspaceFlightPlanProvider.cc

@ -7,12 +7,14 @@ @@ -7,12 +7,14 @@
*
****************************************************************************/
#include "AirspaceManager.h"
#include "AirspaceFlightPlanProvider.h"
#include <QQmlEngine>
//-----------------------------------------------------------------------------
AirspaceFlightInfo::AirspaceFlightInfo(QObject *parent)
: QObject(parent)
, _beingDeleted(false)
, _selected(false)
{
}
@ -42,6 +44,18 @@ AirspaceFlightModel::get(int index) @@ -42,6 +44,18 @@ AirspaceFlightModel::get(int index)
//-----------------------------------------------------------------------------
int
AirspaceFlightModel::findFlightPlanID(QString flightPlanID)
{
for(int i = 0; i < _flightEntries.count(); i++) {
if(_flightEntries[i]->flightPlanID() == flightPlanID) {
return i;
}
}
return -1;
}
//-----------------------------------------------------------------------------
int
AirspaceFlightModel::count() const
{
return _flightEntries.count();
@ -60,6 +74,30 @@ AirspaceFlightModel::append(AirspaceFlightInfo* object) @@ -60,6 +74,30 @@ AirspaceFlightModel::append(AirspaceFlightInfo* object)
//-----------------------------------------------------------------------------
void
AirspaceFlightModel::remove(const QString& flightPlanID)
{
remove(findFlightPlanID(flightPlanID));
}
//-----------------------------------------------------------------------------
void
AirspaceFlightModel::remove(int index)
{
if (index >= 0 && index < _flightEntries.count()) {
beginRemoveRows(QModelIndex(), index, index);
AirspaceFlightInfo* entry = _flightEntries[index];
if(entry) {
qCDebug(AirspaceManagementLog) << "Deleting flight plan" << entry->flightPlanID();
entry->deleteLater();
}
_flightEntries.removeAt(index);
endRemoveRows();
emit countChanged();
}
}
//-----------------------------------------------------------------------------
void
AirspaceFlightModel::clear(void)
{
if(!_flightEntries.isEmpty()) {

18
src/AirspaceManagement/AirspaceFlightPlanProvider.h

@ -38,6 +38,7 @@ public: @@ -38,6 +38,7 @@ public:
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)
virtual QString flightID () = 0;
@ -48,13 +49,17 @@ public: @@ -48,13 +49,17 @@ public:
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(); }
signals:
void selectedChanged ();
void beingDeletedChanged ();
protected:
bool _beingDeleted;
bool _selected;
};
@ -71,10 +76,14 @@ public: @@ -71,10 +76,14 @@ public:
AirspaceFlightModel(QObject *parent = 0);
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_INVOKABLE AirspaceFlightInfo* get(int index);
Q_INVOKABLE AirspaceFlightInfo* get (int index);
Q_INVOKABLE int findFlightPlanID (QString flightPlanID);
int count (void) const;
void append (AirspaceFlightInfo *entry);
void remove (const QString& flightPlanID);
void remove (int index);
void clear (void);
AirspaceFlightInfo*
@ -124,11 +133,14 @@ public: @@ -124,11 +133,14 @@ public:
Q_PROPERTY(QmlObjectListModel* rulesFollowing READ rulesFollowing NOTIFY rulesChanged)
Q_PROPERTY(QmlObjectListModel* briefFeatures READ briefFeatures NOTIFY rulesChanged)
Q_PROPERTY(AirspaceFlightModel* flightList READ flightList NOTIFY flightListChanged)
Q_PROPERTY(bool loadingFlightList READ loadingFlightList NOTIFY loadingFlightListChanged)
//-- TODO: This will submit the current flight plan in memory.
Q_INVOKABLE virtual void submitFlightPlan () = 0;
Q_INVOKABLE virtual void updateFlightPlan () = 0;
Q_INVOKABLE virtual void loadFlightList () = 0;
Q_INVOKABLE virtual void loadFlightList (QDateTime startTime, QDateTime endTime) = 0;
Q_INVOKABLE virtual void deleteFlightPlan (QString flighPlanID) = 0;
Q_INVOKABLE virtual void deleteSelectedFlightPlans () = 0;
virtual PermitStatus flightPermitStatus () const { return PermitNone; }
virtual QDateTime flightStartTime () const = 0;
@ -145,6 +157,7 @@ public: @@ -145,6 +157,7 @@ public:
virtual QmlObjectListModel* rulesFollowing () = 0; ///< List of AirspaceRule following
virtual QmlObjectListModel* briefFeatures () = 0; ///< List of AirspaceRule in violation
virtual AirspaceFlightModel*flightList () = 0; ///< List of AirspaceFlightInfo
virtual bool loadingFlightList () = 0;
virtual void setFlightStartTime (QDateTime start) = 0;
virtual void setFlightEndTime (QDateTime end) = 0;
@ -158,4 +171,5 @@ signals: @@ -158,4 +171,5 @@ signals:
void missionAreaChanged ();
void rulesChanged ();
void flightListChanged ();
void loadingFlightListChanged ();
};

2
src/FactSystem/FactControls/FactTextField.qml

@ -32,7 +32,7 @@ QGCTextField { @@ -32,7 +32,7 @@ QGCTextField {
}
if (typeof qgcView !== 'undefined' && qgcView) {
var errorString = fact.validate(text, false /* convertOnly */)
if (errorString == "") {
if (errorString === "") {
fact.value = text
} else {
_validateString = text

Loading…
Cancel
Save