diff --git a/src/Airmap/AirMapFlightPlanManager.cc b/src/Airmap/AirMapFlightPlanManager.cc index 157af8eff5ceca902d6cbe9a43377afea866137e..3e2d21877cd4eab0094dd844d3dd595c4b2c7f6e 100644 --- a/src/Airmap/AirMapFlightPlanManager.cc +++ b/src/Airmap/AirMapFlightPlanManager.cc @@ -142,7 +142,7 @@ AirMapFlightPlanManager::_createFlightPlan() qCDebug(AirMapManagerLog) << "Flight End: " << _flightEndTime; //-- Not Yet - return; + //return; if (_pilotID == "") { //-- Need to get the pilot id before uploading the flight plan @@ -190,6 +190,7 @@ AirMapFlightPlanManager::_uploadFlightPlan() if (_state != State::FlightUpload) return; FlightPlans::Create::Parameters params; params.max_altitude = _flight.maxAltitude; + params.min_altitude = 0.0; params.buffer = 2.f; params.latitude = _flight.takeoffCoord.latitude(); params.longitude = _flight.takeoffCoord.longitude(); @@ -400,6 +401,10 @@ AirMapFlightPlanManager::_pollBriefing() _advisories.endReset(); _valid = true; //-- Collect Rulesets + _rulesViolation.clearAndDeleteContents(); + _rulesInfo.clearAndDeleteContents(); + _rulesReview.clearAndDeleteContents(); + _rulesFollowing.clearAndDeleteContents(); for(const auto& ruleset : briefing.evaluation.rulesets) { AirMapRuleSet* pRuleSet = new AirMapRuleSet(this); pRuleSet->_id = QString::fromStdString(ruleset.id); @@ -412,13 +417,33 @@ AirMapFlightPlanManager::_pollBriefing() pRule->_features.append(pFeature); } pRuleSet->_rules.append(pRule); + //-- Rules separated by status for presentation + switch(rule.status) { + case RuleSet::Rule::Status::conflicting: + _rulesViolation.append(new AirMapRule(rule, this)); + break; + case RuleSet::Rule::Status::not_conflicting: + _rulesFollowing.append(new AirMapRule(rule, this)); + break; + case RuleSet::Rule::Status::missing_info: + _rulesInfo.append(new AirMapRule(rule, this)); + break; + case RuleSet::Rule::Status::informational: + _rulesReview.append(new AirMapRule(rule, this)); + break; + default: + break; + } } //-- Sort rules by relevance order + pRuleSet->_rules.beginReset(); std::sort(pRuleSet->_rules.objectList()->begin(), pRuleSet->_rules.objectList()->end(), rules_sort); + pRuleSet->_rules.endReset(); _rulesets.append(pRuleSet); qCDebug(AirMapManagerLog) << "Adding briefing ruleset" << pRuleSet->id(); } emit advisoryChanged(); + emit rulesChanged(); //-- Evaluate briefing status bool rejected = false; bool accepted = false; @@ -512,7 +537,7 @@ AirMapFlightPlanManager::_missionChanged() _createFlightPlan(); } else { //-- Plan is being modified - // _updateFlightPlan(); + //_updateFlightPlan(); } } } diff --git a/src/Airmap/AirMapFlightPlanManager.h b/src/Airmap/AirMapFlightPlanManager.h index ac4639c2d417132a61f847fcf1c5da7463fc0234..008bbef9bc93305922d8fd1193d9e425bf0a1749 100644 --- a/src/Airmap/AirMapFlightPlanManager.h +++ b/src/Airmap/AirMapFlightPlanManager.h @@ -39,6 +39,11 @@ public: QGCGeoBoundingCube* missionArea () override { return &_flight.bc; } AirspaceAdvisoryProvider::AdvisoryColor airspaceColor () override { return _airspaceColor; } + QmlObjectListModel* rulesViolation () override { return &_rulesViolation; } + QmlObjectListModel* rulesInfo () override { return &_rulesInfo; } + QmlObjectListModel* rulesReview () override { return &_rulesReview; } + QmlObjectListModel* rulesFollowing () override { return &_rulesFollowing; } + void startFlightPlanning (PlanMasterController* planController) override; void setFlightStartTime (QDateTime start) override; void setFlightEndTime (QDateTime end) override; @@ -91,6 +96,10 @@ private: QDateTime _flightEndTime; QmlObjectListModel _advisories; QmlObjectListModel _rulesets; + QmlObjectListModel _rulesViolation; + QmlObjectListModel _rulesInfo; + QmlObjectListModel _rulesReview; + QmlObjectListModel _rulesFollowing; AirspaceAdvisoryProvider::AdvisoryColor _airspaceColor; AirspaceFlightPlanProvider::PermitStatus _flightPermitStatus = AirspaceFlightPlanProvider::PermitNone; diff --git a/src/Airmap/AirspaceControl.qml b/src/Airmap/AirspaceControl.qml index fdaec4af5dd9efb37b7f652e7eebe0f6eafbc2a1..2ab105a54ba4b0064fb63a81bd6e109364ebf188 100644 --- a/src/Airmap/AirspaceControl.qml +++ b/src/Airmap/AirspaceControl.qml @@ -28,6 +28,7 @@ Item { property color _textColor: qgcPal.text property bool _colapsed: !QGroundControl.airspaceManager.airspaceVisible property var _flightPermit: QGroundControl.airspaceManager.flightPlan.flightPermitStatus + property bool _dirty: false readonly property real _radius: ScreenTools.defaultFontPixelWidth * 0.5 readonly property color _colorOrange: "#d75e0d" @@ -551,8 +552,12 @@ Item { width: mainWindow.width height: mainWindow.height color: Qt.rgba(0,0,0,0.1) - property real flickHeight: ScreenTools.defaultFontPixelHeight * 22 - property real flickWidth: ScreenTools.defaultFontPixelWidth * 40 + property real flickHeight: ScreenTools.defaultFontPixelHeight * 22 + property real flickWidth: ScreenTools.defaultFontPixelWidth * 40 + Component.onCompleted: { + _dirty = false + mainWindow.disableToolbar() + } MouseArea { anchors.fill: parent hoverEnabled: true @@ -645,7 +650,10 @@ Item { iconSource: "qrc:/airmap/expand.svg" anchors.right: parent.right anchors.left: parent.left - onClicked: datePicker.visible = true + onClicked: { + _dirty = true + datePicker.visible = true + } } Item { anchors.right: parent.right @@ -668,6 +676,9 @@ Item { maximumValue: 95 // 96 blocks of 15 minutes in 24 hours anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter + onValueChanged: { + _dirty = true + } Component.onCompleted: { var today = new Date() var val = (((today.getHours() * 60) + today.getMinutes()) * (96/1440)) + 1 @@ -737,46 +748,97 @@ Item { color: qgcPal.windowShade anchors.right: parent.right anchors.left: parent.left - height: dateRect.height + height: authCol.height + ScreenTools.defaultFontPixelHeight Column { id: authCol - spacing: ScreenTools.defaultFontPixelHeight * 0.25 + spacing: ScreenTools.defaultFontPixelHeight * 0.5 anchors.margins: ScreenTools.defaultFontPixelWidth anchors.right: parent.right anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter QGCLabel { text: qsTr("Federal Aviation Administration") + visible: _flightPermit !== AirspaceFlightPlanProvider.PermitNone } QGCLabel { text: qsTr("Automatic authorization to fly in controlled airspace") + visible: _flightPermit !== AirspaceFlightPlanProvider.PermitNone font.pointSize: ScreenTools.smallFontPointSize } + Rectangle { + anchors.right: parent.right + anchors.left: parent.left + height: label.height + (ScreenTools.defaultFontPixelHeight * 0.5) + color: { + if(_flightPermit == AirspaceFlightPlanProvider.PermitPending) + return _colorOrange + if(_flightPermit == AirspaceFlightPlanProvider.PermitAccepted) + return _colorGreen + if(_flightPermit == AirspaceFlightPlanProvider.PermitRejected) + return _colorRed + return _colorGray + } + QGCLabel { + id: label + color: _colorWhite + text: { + if(_flightPermit === AirspaceFlightPlanProvider.PermitPending) + return qsTr("Authorization Pending") + if(_flightPermit === AirspaceFlightPlanProvider.PermitAccepted) + return qsTr("Authorization Accepted") + if(_flightPermit === AirspaceFlightPlanProvider.PermitRejected) + return qsTr("Authorization Rejected") + return qsTr("Authorization Unknown") + } + anchors.centerIn: parent + } + } } } Item { width: 1; height: ScreenTools.defaultFontPixelHeight * 0.25; } QGCLabel { text: qsTr("Rules & Compliance") } + ExclusiveGroup { id: ruleGroup } ComplianceRules { text: qsTr("Rules you may be violating") + rules: violationRules + visible: violationRules && violationRules.count + color: _colorRed + exclusiveGroup: ruleGroup anchors.right: parent.right anchors.left: parent.left + property var violationRules: QGroundControl.airspaceManager.flightPlan.rulesViolation } ComplianceRules { text: qsTr("Rules needing more information") + rules: infoRules + color: _colorOrange + visible: infoRules && infoRules.count + exclusiveGroup: ruleGroup anchors.right: parent.right anchors.left: parent.left + property var infoRules: QGroundControl.airspaceManager.flightPlan.rulesInfo } ComplianceRules { text: qsTr("Rules you should review") + rules: reviewRules + color: _colorYellow + visible: reviewRules && reviewRules.count + exclusiveGroup: ruleGroup anchors.right: parent.right anchors.left: parent.left + property var reviewRules: QGroundControl.airspaceManager.flightPlan.rulesReview } ComplianceRules { text: qsTr("Rules you are following") + rules: followRules + color: _colorGreen + visible: followRules && followRules.count + exclusiveGroup: ruleGroup anchors.right: parent.right anchors.left: parent.left + property var followRules: QGroundControl.airspaceManager.flightPlan.rulesFollowing } } } @@ -792,7 +854,7 @@ Item { backRadius: 4 heightFactor: 0.3333 showBorder: true - enabled: _flightPermit !== AirspaceFlightPlanProvider.PermitNone + enabled: _flightPermit !== AirspaceFlightPlanProvider.PermitNone && _dirty width: ScreenTools.defaultFontPixelWidth * 12 onClicked: { //-- TODO: Update Plan @@ -839,9 +901,6 @@ Item { visible = false; } } - Component.onCompleted: { - mainWindow.disableToolbar() - } } } } diff --git a/src/Airmap/ComplianceRules.qml b/src/Airmap/ComplianceRules.qml index 08a49fde0513a90d1bca467d01bb0577e791bbc2..fe8d4aec604ddce49d484b38e411e299bccc2751 100644 --- a/src/Airmap/ComplianceRules.qml +++ b/src/Airmap/ComplianceRules.qml @@ -13,27 +13,36 @@ import QGroundControl.SettingsManager 1.0 Item { id: _root - height: ScreenTools.defaultFontPixelHeight * 2 - property alias text: title.text - readonly property color _colorOrange: "#d75e0d" - readonly property color _colorYellow: "#d7c61d" - readonly property color _colorRed: "#aa1200" - readonly property color _colorGreen: "#125f00" + height: checked ? (header.height + content.height) : header.height + property var rules: null + property color color: "white" + property alias text: title.text + property bool checked: false + property ExclusiveGroup exclusiveGroup: null + onExclusiveGroupChanged: { + if (exclusiveGroup) { + exclusiveGroup.bindCheckable(_root) + } + } QGCPalette { id: qgcPal colorGroupEnabled: enabled } Rectangle { - anchors.fill: parent + id: header + height: ScreenTools.defaultFontPixelHeight * 2 color: qgcPal.windowShade + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.left } Row { spacing: ScreenTools.defaultFontPixelWidth * 2 - anchors.verticalCenter: parent.verticalCenter + anchors.fill: header Rectangle { - height: _root.height + height: parent.height width: ScreenTools.defaultFontPixelWidth * 0.75 - color: _colorGreen + color: _root.color } QGCLabel { id: title @@ -41,14 +50,75 @@ Item { } } QGCColoredImage { - source: "qrc:/airmap/expand.svg" + source: checked ? "qrc:/airmap/colapse.svg" : "qrc:/airmap/expand.svg" height: ScreenTools.defaultFontPixelHeight width: height color: qgcPal.text fillMode: Image.PreserveAspectFit sourceSize.height: height - anchors.right: parent.right + anchors.right: header.right anchors.rightMargin: ScreenTools.defaultFontPixelWidth - anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenter: header.verticalCenter + } + MouseArea { + anchors.fill: header + onClicked: { + _root.checked = !_root.checked + } + } + Rectangle { + id: content + color: qgcPal.window + visible: checked + height: ScreenTools.defaultFontPixelHeight * 10 + anchors.top: header.bottom + anchors.right: parent.right + anchors.left: parent.left + anchors.margins: ScreenTools.defaultFontPixelWidth + Flickable { + clip: true + anchors.fill: parent + contentHeight: rulesetCol.height + flickableDirection: Flickable.VerticalFlick + Column { + id: rulesetCol + spacing: ScreenTools.defaultFontPixelHeight * 0.25 + anchors.right: parent.right + anchors.left: parent.left + Repeater { + model: _root.rules ? _root.rules : [] + delegate: Item { + height: ruleCol.height + anchors.right: parent.right + anchors.left: parent.left + anchors.margins: ScreenTools.defaultFontPixelWidth + Column { + id: ruleCol + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + anchors.right: parent.right + anchors.left: parent.left + Item { width: 1; height: ScreenTools.defaultFontPixelHeight * 0.25; } + QGCLabel { + text: object.shortText !== "" ? object.shortText : qsTr("Rule") + anchors.right: parent.right + anchors.left: parent.left + wrapMode: Text.WordWrap + } + QGCLabel { + text: object.description + visible: object.description !== "" + font.pointSize: ScreenTools.smallFontPointSize + anchors.right: parent.right + anchors.left: parent.left + wrapMode: Text.WordWrap + anchors.rightMargin: ScreenTools.defaultFontPixelWidth * 0.5 + anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 0.5 + } + } + } + } + Item { width: 1; height: ScreenTools.defaultFontPixelHeight * 0.25; } + } + } } } diff --git a/src/AirspaceManagement/AirspaceFlightPlanProvider.h b/src/AirspaceManagement/AirspaceFlightPlanProvider.h index fdef3e9df07b05b1f99d6f55d16ce06e4f1ae04b..2ce0e284fed45463d5d387968e747998c3af2d40 100644 --- a/src/AirspaceManagement/AirspaceFlightPlanProvider.h +++ b/src/AirspaceManagement/AirspaceFlightPlanProvider.h @@ -49,6 +49,11 @@ public: Q_PROPERTY(QGCGeoBoundingCube* missionArea READ missionArea NOTIFY missionAreaChanged) Q_PROPERTY(AirspaceAdvisoryProvider::AdvisoryColor airspaceColor READ airspaceColor NOTIFY advisoryChanged) + Q_PROPERTY(QmlObjectListModel* rulesViolation READ rulesViolation NOTIFY rulesChanged) + Q_PROPERTY(QmlObjectListModel* rulesInfo READ rulesInfo NOTIFY rulesChanged) + Q_PROPERTY(QmlObjectListModel* rulesReview READ rulesReview NOTIFY rulesChanged) + Q_PROPERTY(QmlObjectListModel* rulesFollowing READ rulesFollowing NOTIFY rulesChanged) + virtual PermitStatus flightPermitStatus () const { return PermitNone; } virtual QDateTime flightStartTime () const = 0; virtual QDateTime flightEndTime () const = 0; @@ -58,6 +63,11 @@ public: virtual QmlObjectListModel* ruleSets () = 0; ///< List of AirspaceRuleSet virtual AirspaceAdvisoryProvider::AdvisoryColor airspaceColor () = 0; ///< Aispace overall color + virtual QmlObjectListModel* rulesViolation () = 0; ///< List of AirspaceRule in violation + virtual QmlObjectListModel* rulesInfo () = 0; ///< List of AirspaceRule need more information + virtual QmlObjectListModel* rulesReview () = 0; ///< List of AirspaceRule should review + virtual QmlObjectListModel* rulesFollowing () = 0; ///< List of AirspaceRule following + virtual void setFlightStartTime (QDateTime start) = 0; virtual void setFlightEndTime (QDateTime end) = 0; virtual void startFlightPlanning (PlanMasterController* planController) = 0; @@ -68,4 +78,5 @@ signals: void flightEndTimeChanged (); void advisoryChanged (); void missionAreaChanged (); + void rulesChanged (); };