Commit 6794e035 authored by DoinLakeFlyer's avatar DoinLakeFlyer

parent d95cb35f
...@@ -194,12 +194,16 @@ ...@@ -194,12 +194,16 @@
<file alias="QGroundControl/FlightDisplay/FlightDisplayViewMap.qml">src/FlightDisplay/FlightDisplayViewMap.qml</file> <file alias="QGroundControl/FlightDisplay/FlightDisplayViewMap.qml">src/FlightDisplay/FlightDisplayViewMap.qml</file>
<file alias="QGroundControl/FlightDisplay/FlightDisplayViewVideo.qml">src/FlightDisplay/FlightDisplayViewVideo.qml</file> <file alias="QGroundControl/FlightDisplay/FlightDisplayViewVideo.qml">src/FlightDisplay/FlightDisplayViewVideo.qml</file>
<file alias="QGroundControl/FlightDisplay/FlightDisplayViewWidgets.qml">src/FlightDisplay/FlightDisplayViewWidgets.qml</file> <file alias="QGroundControl/FlightDisplay/FlightDisplayViewWidgets.qml">src/FlightDisplay/FlightDisplayViewWidgets.qml</file>
<file alias="QGroundControl/FlightDisplay/FlyViewAirspaceIndicator.qml">src/FlightDisplay/FlyViewAirspaceIndicator.qml</file>
<file alias="QGroundControl/FlightDisplay/FlyViewMissionCompleteDialog.qml">src/FlightDisplay/FlyViewMissionCompleteDialog.qml</file>
<file alias="QGroundControl/FlightDisplay/FlyViewPreFlightChecklistPopup.qml">src/FlightDisplay/FlyViewPreFlightChecklistPopup.qml</file>
<file alias="QGroundControl/FlightDisplay/FlyViewToolStrip.qml">src/FlightDisplay/FlyViewToolStrip.qml</file> <file alias="QGroundControl/FlightDisplay/FlyViewToolStrip.qml">src/FlightDisplay/FlyViewToolStrip.qml</file>
<file alias="QGroundControl/FlightDisplay/GuidedActionConfirm.qml">src/FlightDisplay/GuidedActionConfirm.qml</file> <file alias="QGroundControl/FlightDisplay/GuidedActionConfirm.qml">src/FlightDisplay/GuidedActionConfirm.qml</file>
<file alias="QGroundControl/FlightDisplay/GuidedActionList.qml">src/FlightDisplay/GuidedActionList.qml</file> <file alias="QGroundControl/FlightDisplay/GuidedActionList.qml">src/FlightDisplay/GuidedActionList.qml</file>
<file alias="QGroundControl/FlightDisplay/GuidedActionsController.qml">src/FlightDisplay/GuidedActionsController.qml</file> <file alias="QGroundControl/FlightDisplay/GuidedActionsController.qml">src/FlightDisplay/GuidedActionsController.qml</file>
<file alias="QGroundControl/FlightDisplay/GuidedAltitudeSlider.qml">src/FlightDisplay/GuidedAltitudeSlider.qml</file> <file alias="QGroundControl/FlightDisplay/GuidedAltitudeSlider.qml">src/FlightDisplay/GuidedAltitudeSlider.qml</file>
<file alias="QGroundControl/FlightDisplay/MultiVehicleList.qml">src/FlightDisplay/MultiVehicleList.qml</file> <file alias="QGroundControl/FlightDisplay/MultiVehicleList.qml">src/FlightDisplay/MultiVehicleList.qml</file>
<file alias="QGroundControl/FlightDisplay/MultiVehiclePanel.qml">src/FlightDisplay/MultiVehiclePanel.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightBatteryCheck.qml">src/FlightDisplay/PreFlightBatteryCheck.qml</file> <file alias="QGroundControl/FlightDisplay/PreFlightBatteryCheck.qml">src/FlightDisplay/PreFlightBatteryCheck.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightGPSCheck.qml">src/FlightDisplay/PreFlightGPSCheck.qml</file> <file alias="QGroundControl/FlightDisplay/PreFlightGPSCheck.qml">src/FlightDisplay/PreFlightGPSCheck.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightRCCheck.qml">src/FlightDisplay/PreFlightRCCheck.qml</file> <file alias="QGroundControl/FlightDisplay/PreFlightRCCheck.qml">src/FlightDisplay/PreFlightRCCheck.qml</file>
......
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
* *
****************************************************************************/ ****************************************************************************/
import QtQuick 2.11 import QtQuick 2.12
import QtQuick.Controls 2.4 import QtQuick.Controls 2.4
import QtQuick.Dialogs 1.3 import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.11 import QtQuick.Layouts 1.12
import QtLocation 5.3 import QtLocation 5.3
import QtPositioning 5.3 import QtPositioning 5.3
...@@ -39,17 +39,14 @@ Item { ...@@ -39,17 +39,14 @@ Item {
} }
} }
property bool activeVehicleJoystickEnabled: activeVehicle ? activeVehicle.joystickEnabled : false
property bool mainIsMap: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey, true) : true property bool mainIsMap: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey, true) : true
property bool isBackgroundDark: mainIsMap ? (mainWindow.flightDisplayMap ? mainWindow.flightDisplayMap.isSatelliteMap : true) : true property bool isBackgroundDark: mainIsMap ? (mainWindow.flightDisplayMap ? mainWindow.flightDisplayMap.isSatelliteMap : true) : true
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _missionController: _planController.missionController property var _missionController: _planController.missionController
property var _geoFenceController: _planController.geoFenceController property var _geoFenceController: _planController.geoFenceController
property var _rallyPointController: _planController.rallyPointController property var _rallyPointController: _planController.rallyPointController
property bool _isPipVisible: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false property bool _isPipVisible: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false
property bool _useChecklist: QGroundControl.settingsManager.appSettings.useChecklist.rawValue && QGroundControl.corePlugin.options.preFlightChecklistUrl.toString().length
property bool _enforceChecklist: _useChecklist && QGroundControl.settingsManager.appSettings.enforceChecklist.rawValue
property bool _checklistComplete: activeVehicle && (activeVehicle.checkListState === Vehicle.CheckListPassed)
property real _margins: ScreenTools.defaultFontPixelWidth / 2 property real _margins: ScreenTools.defaultFontPixelWidth / 2
property real _pipSize: mainWindow.width * 0.2 property real _pipSize: mainWindow.width * 0.2
property alias _guidedController: guidedActionsController property alias _guidedController: guidedActionsController
...@@ -64,20 +61,6 @@ Item { ...@@ -64,20 +61,6 @@ Item {
readonly property string _mainIsMapKey: "MainFlyWindowIsMap" readonly property string _mainIsMapKey: "MainFlyWindowIsMap"
readonly property string _PIPVisibleKey: "IsPIPVisible" readonly property string _PIPVisibleKey: "IsPIPVisible"
Timer {
id: checklistPopupTimer
interval: 1000
repeat: false
onTriggered: {
if (visible && !_checklistComplete) {
checklistDropPanel.open()
}
else {
checklistDropPanel.close()
}
}
}
function setStates() { function setStates() {
QGroundControl.saveBoolGlobalSetting(_mainIsMapKey, mainIsMap) QGroundControl.saveBoolGlobalSetting(_mainIsMapKey, mainIsMap)
if(mainIsMap) { if(mainIsMap) {
...@@ -110,29 +93,9 @@ Item { ...@@ -110,29 +93,9 @@ Item {
return true; return true;
} }
function showPreflightChecklistIfNeeded () { // Signal routing
if (activeVehicle && !_checklistComplete && _enforceChecklist) {
checklistPopupTimer.restart()
}
}
Connections {
target: _missionController
onResumeMissionUploadFail: guidedActionsController.confirmAction(guidedActionsController.actionResumeMissionUploadFail)
}
Connections { Connections {
target: mainWindow target: mainWindow
onArmVehicle: _guidedController.confirmAction(_guidedController.actionArm)
onDisarmVehicle: {
if (_guidedController.showEmergenyStop) {
_guidedController.confirmAction(_guidedController.actionEmergencyStop)
} else {
_guidedController.confirmAction(_guidedController.actionDisarm)
}
}
onVtolTransitionToFwdFlight: _guidedController.confirmAction(_guidedController.actionVtolTransitionToFwdFlight)
onVtolTransitionToMRFlight: _guidedController.confirmAction(_guidedController.actionVtolTransitionToMRFlight)
onFlightDisplayMapChanged: setStates() onFlightDisplayMapChanged: setStates()
} }
...@@ -140,123 +103,13 @@ Item { ...@@ -140,123 +103,13 @@ Item {
if(QGroundControl.corePlugin.options.flyViewOverlay.toString().length) { if(QGroundControl.corePlugin.options.flyViewOverlay.toString().length) {
flyViewOverlay.source = QGroundControl.corePlugin.options.flyViewOverlay flyViewOverlay.source = QGroundControl.corePlugin.options.flyViewOverlay
} }
if(QGroundControl.corePlugin.options.preFlightChecklistUrl.toString().length) {
checkList.source = QGroundControl.corePlugin.options.preFlightChecklistUrl
}
}
// The following code is used to track vehicle states for showing the mission complete dialog
property bool vehicleArmed: activeVehicle ? activeVehicle.armed : true // true here prevents pop up from showing during shutdown
property bool vehicleWasArmed: false
property bool vehicleInMissionFlightMode: activeVehicle ? (activeVehicle.flightMode === activeVehicle.missionFlightMode) : false
property bool vehicleWasInMissionFlightMode: false
property bool showMissionCompleteDialog: vehicleWasArmed && vehicleWasInMissionFlightMode &&
(_missionController.containsItems || _geoFenceController.containsItems || _rallyPointController.containsItems ||
(activeVehicle ? activeVehicle.cameraTriggerPoints.count !== 0 : false))
onVehicleArmedChanged: {
if (vehicleArmed) {
vehicleWasArmed = true
vehicleWasInMissionFlightMode = vehicleInMissionFlightMode
} else {
if (showMissionCompleteDialog) {
mainWindow.showComponentDialog(missionCompleteDialogComponent, qsTr("Flight Plan complete"), mainWindow.showDialogDefaultWidth, StandardButton.Close)
}
vehicleWasArmed = false
vehicleWasInMissionFlightMode = false
}
}
onVehicleInMissionFlightModeChanged: {
if (vehicleInMissionFlightMode && vehicleArmed) {
vehicleWasInMissionFlightMode = true
}
}
Component {
id: missionCompleteDialogComponent
QGCViewDialog {
property var activeVehicleCopy: activeVehicle
onActiveVehicleCopyChanged:
if (!activeVehicleCopy) {
hideDialog()
}
QGCFlickable {
anchors.fill: parent
contentHeight: column.height
ColumnLayout {
id: column
anchors.margins: _margins
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelHeight
QGCLabel {
Layout.fillWidth: true
text: qsTr("%1 Images Taken").arg(activeVehicle.cameraTriggerPoints.count)
horizontalAlignment: Text.AlignHCenter
visible: activeVehicle.cameraTriggerPoints.count !== 0
}
QGCButton {
Layout.fillWidth: true
text: qsTr("Remove plan from vehicle")
visible: !activeVehicle.connectionLost// && !activeVehicle.apmFirmware // ArduPilot has a bug somewhere with mission clear
onClicked: {
_planController.removeAllFromVehicle()
hideDialog()
}
}
QGCButton {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
text: qsTr("Leave plan on vehicle")
onClicked: hideDialog()
}
Rectangle {
Layout.fillWidth: true
color: qgcPal.text
height: 1
}
ColumnLayout {
Layout.fillWidth: true
spacing: ScreenTools.defaultFontPixelHeight
visible: !activeVehicle.connectionLost && _guidedController.showResumeMission
QGCButton {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
text: qsTr("Resume Mission From Waypoint %1").arg(_guidedController._resumeMissionIndex)
onClicked: {
_guidedController.executeAction(_guidedController.actionResumeMission, null, null)
hideDialog()
}
} }
QGCLabel { FlyViewMissionCompleteDialog {
Layout.fillWidth: true missionController: _missionController
wrapMode: Text.WordWrap geoFenceController: _geoFenceController
text: qsTr("Resume Mission will rebuild the current mission from the last flown waypoint and upload it to the vehicle for the next flight.") rallyPointController: _rallyPointController
} guidedController: _guidedController
}
QGCLabel {
Layout.fillWidth: true
wrapMode: Text.WordWrap
color: qgcPal.warningText
text: qsTr("If you are changing batteries for Resume Mission do not disconnect from the vehicle.")
visible: _guidedController.showResumeMission
}
}
}
}
} }
Window { Window {
...@@ -328,10 +181,9 @@ Item { ...@@ -328,10 +181,9 @@ Item {
id: _fMap id: _fMap
anchors.fill: parent anchors.fill: parent
guidedActionsController: _guidedController guidedActionsController: _guidedController
missionController: _planController planMasterController: _planController
flightWidgets: flightDisplayViewWidgets flightWidgets: flightDisplayViewWidgets
rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9 rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9
multiVehicleView: !singleVehicleView.checked
scaleState: (mainIsMap && flyViewOverlay.item) ? (flyViewOverlay.item.scaleState ? flyViewOverlay.item.scaleState : "bottomMode") : "bottomMode" scaleState: (mainIsMap && flyViewOverlay.item) ? (flyViewOverlay.item.scaleState ? flyViewOverlay.item.scaleState : "bottomMode") : "bottomMode"
Component.onCompleted: { Component.onCompleted: {
mainWindow.flightDisplayMap = _fMap mainWindow.flightDisplayMap = _fMap
...@@ -474,26 +326,14 @@ Item { ...@@ -474,26 +326,14 @@ Item {
} }
} }
Row { MultiVehiclePanel {
id: singleMultiSelector id: singleMultiSelector
anchors.topMargin: ScreenTools.toolbarHeight + _toolsMargin anchors.margins: _toolsMargin
anchors.rightMargin: _toolsMargin anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
z: _mapAndVideo.z + 4 z: _mapAndVideo.z + 4
visible: QGroundControl.multiVehicleManager.vehicles.count > 1 && QGroundControl.corePlugin.options.enableMultiVehicleList availableHeight: mainWindow.availableHeight - (anchors.margins * 2)
guidedActionsController: _guidedController
QGCRadioButton {
id: singleVehicleView
text: qsTr("Single")
checked: true
textColor: mapPal.text
}
QGCRadioButton {
text: qsTr("Multi-Vehicle")
textColor: mapPal.text
}
} }
FlightDisplayViewWidgets { FlightDisplayViewWidgets {
...@@ -506,7 +346,7 @@ Item { ...@@ -506,7 +346,7 @@ Item {
anchors.top: singleMultiSelector.visible? singleMultiSelector.bottom : undefined anchors.top: singleMultiSelector.visible? singleMultiSelector.bottom : undefined
useLightColors: isBackgroundDark useLightColors: isBackgroundDark
missionController: _missionController missionController: _missionController
visible: singleVehicleView.checked && !QGroundControl.videoManager.fullScreen visible: singleMultiSelector.singleVehiclePanel && !QGroundControl.videoManager.fullScreen
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
...@@ -521,29 +361,18 @@ Item { ...@@ -521,29 +361,18 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
} }
MultiVehicleList {
anchors.margins: _toolsMargin
anchors.top: singleMultiSelector.bottom
anchors.right: parent.right
anchors.bottom: parent.bottom
width: ScreenTools.defaultFontPixelWidth * 30
visible: !singleVehicleView.checked && !QGroundControl.videoManager.fullScreen && QGroundControl.corePlugin.options.enableMultiVehicleList
z: _mapAndVideo.z + 4
guidedActionsController: _guidedController
}
//-- Virtual Joystick //-- Virtual Joystick
Loader { Loader {
id: virtualJoystickMultiTouch id: virtualJoystickMultiTouch
z: _mapAndVideo.z + 5 z: _mapAndVideo.z + 5
width: parent.width - (_flightVideoPipControl.width / 2) width: parent.width - (_flightVideoPipControl.width / 2)
height: Math.min(mainWindow.height * 0.25, ScreenTools.defaultFontPixelWidth * 16) height: Math.min(mainWindow.height * 0.25, ScreenTools.defaultFontPixelWidth * 16)
visible: (_virtualJoystick ? _virtualJoystick.value : false) && !QGroundControl.videoManager.fullScreen && !(activeVehicle ? activeVehicle.highLatencyLink : false) visible: (_virtualJoystick ? _virtualJoystick.value : false) && !QGroundControl.videoManager.fullScreen && !(_activeVehicle ? _activeVehicle.highLatencyLink : false)
anchors.bottom: _flightVideoPipControl.top anchors.bottom: _flightVideoPipControl.top
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 2 anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 2
anchors.horizontalCenter: flightDisplayViewWidgets.horizontalCenter anchors.horizontalCenter: flightDisplayViewWidgets.horizontalCenter
source: "qrc:/qml/VirtualJoystick.qml" source: "qrc:/qml/VirtualJoystick.qml"
active: (_virtualJoystick ? _virtualJoystick.value : false) && !(activeVehicle ? activeVehicle.highLatencyLink : false) active: (_virtualJoystick ? _virtualJoystick.value : false) && !(_activeVehicle ? _activeVehicle.highLatencyLink : false)
property bool useLightColors: isBackgroundDark property bool useLightColors: isBackgroundDark
// The default behaviour is not centralized throttle // The default behaviour is not centralized throttle
...@@ -565,8 +394,10 @@ Item { ...@@ -565,8 +394,10 @@ Item {
maxHeight: parent.height - toolStrip.y + (_flightVideo.visible ? (_flightVideo.y - parent.height) : 0) maxHeight: parent.height - toolStrip.y + (_flightVideo.visible ? (_flightVideo.y - parent.height) : 0)
guidedActionsController: _guidedController guidedActionsController: _guidedController
guidedActionList: _guidedList guidedActionList: _guidedList
preFlightCheckList: checklistDropPanel usePreFlightChecklist: preFlightChecklistPopup.useChecklist
visible: (activeVehicle ? activeVehicle.guidedModeSupported : true) && !QGroundControl.videoManager.fullScreen visible: (_activeVehicle ? _activeVehicle.guidedModeSupported : true) && !QGroundControl.videoManager.fullScreen
onDisplayPreFlightChecklist: preFlightChecklistPopup.open()
} }
GuidedActionsController { GuidedActionsController {
...@@ -612,84 +443,16 @@ Item { ...@@ -612,84 +443,16 @@ Item {
} }
} }
//-- Airspace Indicator FlyViewAirspaceIndicator {
Rectangle {
id: airspaceIndicator
width: airspaceRow.width + (ScreenTools.defaultFontPixelWidth * 3)
height: airspaceRow.height * 1.25
color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.95) : Qt.rgba(0,0,0,0.75)
visible: QGroundControl.airmapSupported && mainIsMap && flightPermit && flightPermit !== AirspaceFlightPlanProvider.PermitNone
radius: 3
border.width: 1
border.color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.35) : Qt.rgba(1,1,1,0.35)
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: ScreenTools.toolbarHeight + (ScreenTools.defaultFontPixelHeight * 0.25) anchors.topMargin: ScreenTools.defaultFontPixelHeight * 0.25
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
Row { show: mainIsMap
id: airspaceRow
spacing: ScreenTools.defaultFontPixelWidth
anchors.centerIn: parent
QGCLabel { text: airspaceIndicator.providerName+":"; anchors.verticalCenter: parent.verticalCenter; }
QGCLabel {
text: {
if(airspaceIndicator.flightPermit) {
if(airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitPending)
return qsTr("Approval Pending")
if(airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitAccepted || airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitNotRequired)
return qsTr("Flight Approved")
if(airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitRejected)
return qsTr("Flight Rejected")
}
return ""
}
color: {
if(airspaceIndicator.flightPermit) {
if(airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitPending)
return qgcPal.colorOrange
if(airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitAccepted || airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitNotRequired)
return qgcPal.colorGreen
}
return qgcPal.colorRed
}
anchors.verticalCenter: parent.verticalCenter;
}
}
property var flightPermit: QGroundControl.airmapSupported ? QGroundControl.airspaceManager.flightPlan.flightPermitStatus : null
property string providerName: QGroundControl.airspaceManager.providerName
}
//-- Checklist GUI
Popup {
id: checklistDropPanel
x: toolStrip.x + toolStrip.width + (ScreenTools.defaultFontPixelWidth * 2)
y: toolStrip.y
height: checkList.height
width: checkList.width
modal: true
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
background: Rectangle {
anchors.fill: parent
color: Qt.rgba(0,0,0,0)
clip: true
} }
Loader { FlyViewPreFlightChecklistPopup {
id: checkList id: preFlightChecklistPopup
anchors.centerIn: parent x: toolStrip.x + toolStrip.width + (ScreenTools.defaultFontPixelWidth * 2)
} y: toolStrip.y
property alias checkListItem: checkList.item
Connections {
target: checkList.item
onAllChecksPassedChanged: {
if (target.allChecksPassed)
{
checklistPopupTimer.restart()
}
}
}
} }
} }
...@@ -39,13 +39,13 @@ FlightMap { ...@@ -39,13 +39,13 @@ FlightMap {
property var guidedActionsController property var guidedActionsController
property var flightWidgets property var flightWidgets
property var rightPanelWidth property var rightPanelWidth
property var multiVehicleView ///< true: multi-vehicle view, false: single vehicle view property var planMasterController
property var missionController: null
property rect centerViewport: Qt.rect(0, 0, width, height) property rect centerViewport: Qt.rect(0, 0, width, height)
property var _geoFenceController: missionController.geoFenceController property var _planMasterController: planMasterController
property var _rallyPointController: missionController.rallyPointController property var _geoFenceController: planMasterController.geoFenceController
property var _rallyPointController: planMasterController.rallyPointController
property var _activeVehicleCoordinate: activeVehicle ? activeVehicle.coordinate : QtPositioning.coordinate() property var _activeVehicleCoordinate: activeVehicle ? activeVehicle.coordinate : QtPositioning.coordinate()
property real _toolButtonTopMargin: parent.height - mainWindow.height + (ScreenTools.defaultFontPixelHeight / 2) property real _toolButtonTopMargin: parent.height - mainWindow.height + (ScreenTools.defaultFontPixelHeight / 2)
property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false
...@@ -200,10 +200,10 @@ FlightMap { ...@@ -200,10 +200,10 @@ FlightMap {
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap } QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
Connections { Connections {
target: missionController target: _missionController
ignoreUnknownSignals: true ignoreUnknownSignals: true
onNewItemsFromVehicle: { onNewItemsFromVehicle: {
var visualItems = missionController.visualItems var visualItems = _missionController.visualItems
if (visualItems && visualItems.count !== 1) { if (visualItems && visualItems.count !== 1) {
mapFitFunctions.fitMapViewportToMissionItems() mapFitFunctions.fitMapViewportToMissionItems()
firstVehiclePositionReceived = true firstVehiclePositionReceived = true
...@@ -215,7 +215,7 @@ FlightMap { ...@@ -215,7 +215,7 @@ FlightMap {
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware! id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
map: mainWindow.flightDisplayMap map: mainWindow.flightDisplayMap
usePlannedHomePosition: false usePlannedHomePosition: false
planMasterController: missionController planMasterController: _planMasterController
property real leftToolWidth: toolStrip.x + toolStrip.width property real leftToolWidth: toolStrip.x + toolStrip.width
} }
...@@ -273,7 +273,7 @@ FlightMap { ...@@ -273,7 +273,7 @@ FlightMap {
PlanMapItems { PlanMapItems {
map: flightMap map: flightMap
largeMapView: mainIsMap largeMapView: mainIsMap
masterController: masterController planMasterController: _planMasterController
vehicle: _vehicle vehicle: _vehicle
property var _vehicle: object property var _vehicle: object
......
/****************************************************************************
*
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.12
import QtQuick.Controls 2.4
import QGroundControl 1.0
import QGroundControl.Airspace 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
Rectangle {
id: _root
width: airspaceRow.width + (ScreenTools.defaultFontPixelWidth * 3)
height: airspaceRow.height * 1.25
color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.95) : Qt.rgba(0,0,0,0.75)
visible: show && QGroundControl.airmapSupported && _flightPermit && _flightPermit !== AirspaceFlightPlanProvider.PermitNone
radius: 3
border.width: 1
border.color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.35) : Qt.rgba(1,1,1,0.35)
property bool show: false
property var _flightPermit: QGroundControl.airmapSupported ? QGroundControl.airspaceManager.flightPlan.flightPermitStatus : null
property string _providerName: QGroundControl.airspaceManager.providerName
QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
Row {
id: airspaceRow
spacing: ScreenTools.defaultFontPixelWidth
anchors.centerIn: parent
QGCLabel { text: _providerName+":"; anchors.verticalCenter: parent.verticalCenter; }
QGCLabel {
text: {
if(_flightPermit) {
if(_flightPermit === AirspaceFlightPlanProvider.PermitPending)
return qsTr("Approval Pending")
if(_flightPermit === AirspaceFlightPlanProvider.PermitAccepted || _flightPermit === AirspaceFlightPlanProvider.PermitNotRequired)
return qsTr("Flight Approved")
if(_flightPermit === AirspaceFlightPlanProvider.PermitRejected)
return qsTr("Flight Rejected")
}
return ""
}
color: {
if(_flightPermit) {
if(_flightPermit === AirspaceFlightPlanProvider.PermitPending)
return qgcPal.colorOrange
if(_flightPermit === AirspaceFlightPlanProvider.PermitAccepted || _flightPermit === AirspaceFlightPlanProvider.PermitNotRequired)
return qgcPal.colorGreen
}
return qgcPal.colorRed
}
anchors.verticalCenter: parent.verticalCenter;
}
}
}
/****************************************************************************
*
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.12
import QtQuick.Controls 2.4
import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.12
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
/// Dialog which shows up when a flight completes. Prompts the user for things like whether they should remove the plan from the vehicle.
Item {
visible: false
property var missionController
property var geoFenceController
property var rallyPointController
property var guidedController
// The following code is used to track vehicle states for showing the mission complete dialog
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property bool _vehicleArmed: _activeVehicle ? _activeVehicle.armed : true // true here prevents pop up from showing during shutdown
property bool _vehicleWasArmed: false
property bool _vehicleInMissionFlightMode: _activeVehicle ? (_activeVehicle.flightMode === _activeVehicle.missionFlightMode) : false
property bool _vehicleWasInMissionFlightMode: false
property bool _showMissionCompleteDialog: _vehicleWasArmed && _vehicleWasInMissionFlightMode &&
(missionController.containsItems || geoFenceController.containsItems || rallyPointController.containsItems ||
(_activeVehicle ? _activeVehicle.cameraTriggerPoints.count !== 0 : false))
on_VehicleArmedChanged: {
if (_vehicleArmed) {
_vehicleWasArmed = true
_vehicleWasInMissionFlightMode = _vehicleInMissionFlightMode
} else {
if (_showMissionCompleteDialog) {
mainWindow.showComponentDialog(missionCompleteDialogComponent, qsTr("Flight Plan complete"), mainWindow.showDialogDefaultWidth, StandardButton.Close)
}
_vehicleWasArmed = false
_vehicleWasInMissionFlightMode = false
}
}
on_VehicleInMissionFlightModeChanged: {
if (_vehicleInMissionFlightMode && _vehicleArmed) {
_vehicleWasInMissionFlightMode = true
}
}
Component {
id: missionCompleteDialogComponent
QGCViewDialog {
property var activeVehicleCopy: _activeVehicle
onActiveVehicleCopyChanged:
if (!activeVehicleCopy) {
hideDialog()
}
QGCFlickable {
anchors.fill: parent
contentHeight: column.height
ColumnLayout {
id: column
anchors.margins: _margins
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelHeight
QGCLabel {
Layout.fillWidth: true
text: qsTr("%1 Images Taken").arg(_activeVehicle.cameraTriggerPoints.count)
horizontalAlignment: Text.AlignHCenter
visible: _activeVehicle.cameraTriggerPoints.count !== 0
}
QGCButton {
Layout.fillWidth: true
text: qsTr("Remove plan from vehicle")
visible: !_activeVehicle.connectionLost// && !_activeVehicle.apmFirmware // ArduPilot has a bug somewhere with mission clear
onClicked: {
_planController.removeAllFromVehicle()
hideDialog()
}
}
QGCButton {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
text: qsTr("Leave plan on vehicle")
onClicked: hideDialog()
}
Rectangle {
Layout.fillWidth: true
color: qgcPal.text
height: 1
}
ColumnLayout {
Layout.fillWidth: true
spacing: ScreenTools.defaultFontPixelHeight
visible: !_activeVehicle.connectionLost && guidedController.showResumeMission
QGCButton {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
text: qsTr("Resume Mission From Waypoint %1").arg(guidedController._resumeMissionIndex)
onClicked: {
guidedController.executeAction(guidedController.actionResumeMission, null, null)
hideDialog()
}
}
QGCLabel {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: qsTr("Resume Mission will rebuild the current mission from the last flown waypoint and upload it to the vehicle for the next flight.")
}
}
QGCLabel {
Layout.fillWidth: true
wrapMode: Text.WordWrap
color: qgcPal.warningText
text: qsTr("If you are changing batteries for Resume Mission do not disconnect from the vehicle.")
visible: guidedController.showResumeMission
}
}
}
}
}
}
/****************************************************************************
*
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.11
import QtQuick.Controls 2.4
import QGroundControl 1.0
import QGroundControl.Vehicle 1.0
/// Popup container for preflight checklists
Popup {
id: _root
height: checkList.height
width: checkList.width
modal: true
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
background: Rectangle {
anchors.fill: parent
color: Qt.rgba(0,0,0,0)
clip: true
}
property bool useChecklist: QGroundControl.settingsManager.appSettings.useChecklist.rawValue && QGroundControl.corePlugin.options.preFlightChecklistUrl.toString().length
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property bool _enforceChecklist: useChecklist && QGroundControl.settingsManager.appSettings.enforceChecklist.rawValue
property bool _checklistComplete: _activeVehicle && (_activeVehicle.checkListState === Vehicle.CheckListPassed)
on_ActiveVehicleChanged: _showPreFlightChecklistIfNeeded()
Connections {
target: mainWindow
onShowPreFlightChecklistIfNeeded: _root._showPreFlightChecklistIfNeeded()
}
function _showPreFlightChecklistIfNeeded() {
if (_activeVehicle && !_checklistComplete && _enforceChecklist) {
popupTimer.restart()
}
}
Timer {
id: popupTimer
interval: 1000
repeat: false
onTriggered: {
// FIXME: What was the visible check in here for
if (!_checklistComplete) {
console.log("open", _root.width, _root.height)
_root.open()
} else {
_root.close()
}
}
}
Loader {
id: checkList
anchors.centerIn: parent
source: QGroundControl.corePlugin.options.preFlightChecklistUrl
}
property alias checkListItem: checkList.item
Connections {
target: checkList.item
onAllChecksPassedChanged: {
if (target.allChecksPassed) {
popupTimer.restart()
}
}
}
}
...@@ -15,7 +15,9 @@ ToolStrip { ...@@ -15,7 +15,9 @@ ToolStrip {
property var guidedActionsController property var guidedActionsController
property var guidedActionList property var guidedActionList
property var preFlightCheckList property bool usePreFlightChecklist
signal displayPreFlightChecklist
property bool _anyActionAvailable: guidedActionsController.showStartMission || guidedActionsController.showResumeMission || guidedActionsController.showChangeAlt || guidedActionsController.showLandAbort property bool _anyActionAvailable: guidedActionsController.showStartMission || guidedActionsController.showResumeMission || guidedActionsController.showChangeAlt || guidedActionsController.showLandAbort
property var _actionModel: [ property var _actionModel: [
...@@ -49,8 +51,8 @@ ToolStrip { ...@@ -49,8 +51,8 @@ ToolStrip {
{ {
name: "Checklist", name: "Checklist",
iconSource: "/qmlimages/check.svg", iconSource: "/qmlimages/check.svg",
buttonVisible: _useChecklist, buttonVisible: usePreFlightChecklist,
buttonEnabled: _useChecklist && activeVehicle && !activeVehicle.armed, buttonEnabled: usePreFlightChecklist && activeVehicle && !activeVehicle.armed,
}, },
{ {
name: guidedActionsController.takeoffTitle, name: guidedActionsController.takeoffTitle,
...@@ -91,7 +93,7 @@ ToolStrip { ...@@ -91,7 +93,7 @@ ToolStrip {
onClicked: { onClicked: {
if(index === 0) { if(index === 0) {
preFlightCheckList.open() displayPreFlightChecklist()
} else { } else {
guidedActionsController.closeAll() guidedActionsController.closeAll()
var action = model[index].action var action = model[index].action
......
...@@ -239,6 +239,40 @@ Item { ...@@ -239,6 +239,40 @@ Item {
_vehicleInMissionMode = activeVehicle ? _flightMode === activeVehicle.missionFlightMode : false // Must be last to get correct signalling for showStartMission popups _vehicleInMissionMode = activeVehicle ? _flightMode === activeVehicle.missionFlightMode : false // Must be last to get correct signalling for showStartMission popups
} }
Connections {
target: missionController
onResumeMissionUploadFail: confirmAction(actionResumeMissionUploadFail)
}
Connections {
target: mainWindow
onArmVehicleRequest: armVehicleRequest()
onDisarmVehicleRequest: disarmVehicleRequest()
onVtolTransitionToFwdFlightRequest: vtolTransitionToFwdFlightRequest()
onVtolTransitionToMRFlightRequest: vtolTransitionToMRFlightRequest()
}
function armVehicleRequest() {
confirmAction(actionArm)
}
function disarmVehicleRequest() {
if (showEmergenyStop) {
confirmAction(actionEmergencyStop)
} else {
confirmAction(actionDisarm)
}
}
function vtolTransitionToFwdFlightRequest() {
confirmAction(actionVtolTransitionToFwdFlight)
}
function vtolTransitionToMRFlightRequest() {
confirmAction(actionVtolTransitionToMRFlight)
}
function closeAll() { function closeAll() {
confirmDialog.visible = false confirmDialog.visible = false
actionList.visible = false actionList.visible = false
......
/****************************************************************************
*
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.12
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.12
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightDisplay 1.0
import QGroundControl.ScreenTools 1.0
/// Multi vehicle panel for Fly View
Item {
id: _root
width: ScreenTools.defaultFontPixelWidth * 30
height: singleVehiclePanel ? selectorRow.height : availableHeight
visible: QGroundControl.multiVehicleManager.vehicles.count > 1 && QGroundControl.corePlugin.options.enableMultiVehicleList
property alias singleVehiclePanel: singleVehicleView.checked
property real availableHeight
property var guidedActionsController
Row {
id: selectorRow
spacing: ScreenTools.defaultFontPixelWidth
QGCRadioButton {
id: singleVehicleView
text: qsTr("Single")
checked: true
textColor: mapPal.text
}
QGCRadioButton {
text: qsTr("Multi-Vehicle")
textColor: mapPal.text
}
}
MultiVehicleList {
anchors.topMargin: ScreenTools.defaultFontPixelHeight / 2
anchors.top: selectorRow.bottom
anchors.bottom: parent.bottom
width: parent.width
visible: !singleVehiclePanel && !QGroundControl.videoManager.fullScreen && QGroundControl.corePlugin.options.enableMultiVehicleList
guidedActionsController: _root.guidedActionsController
}
}
...@@ -19,7 +19,7 @@ import QGroundControl.Vehicle 1.0 ...@@ -19,7 +19,7 @@ import QGroundControl.Vehicle 1.0
Rectangle { Rectangle {
width: mainColumn.width + ScreenTools.defaultFontPixelWidth * 3 width: mainColumn.width + ScreenTools.defaultFontPixelWidth * 3
height: Math.min(availableHeight - (_verticalMargin * 2), mainColumn.height + ScreenTools.defaultFontPixelHeight) height: Math.min(mainWindow.availableHeight - (_verticalMargin * 2), mainColumn.height + ScreenTools.defaultFontPixelHeight)
color: qgcPal.windowShade color: qgcPal.windowShade
radius: 3 radius: 3
......
...@@ -22,7 +22,7 @@ Item { ...@@ -22,7 +22,7 @@ Item {
property var map ///< Map control to show items on property var map ///< Map control to show items on
property bool largeMapView ///< true: map takes up entire view, false: map is in small window property bool largeMapView ///< true: map takes up entire view, false: map is in small window
property var masterController ///< Reference to PlanMasterController for vehicle property var planMasterController ///< Reference to PlanMasterController for vehicle
property var vehicle ///< Vehicle associated with these items property var vehicle ///< Vehicle associated with these items
property var _map: map property var _map: map
......
...@@ -4,12 +4,16 @@ FlightDisplayView 1.0 FlightDisplayView.qml ...@@ -4,12 +4,16 @@ FlightDisplayView 1.0 FlightDisplayView.qml
FlightDisplayViewMap 1.0 FlightDisplayViewMap.qml FlightDisplayViewMap 1.0 FlightDisplayViewMap.qml
FlightDisplayViewVideo 1.0 FlightDisplayViewVideo.qml FlightDisplayViewVideo 1.0 FlightDisplayViewVideo.qml
FlightDisplayViewWidgets 1.0 FlightDisplayViewWidgets.qml FlightDisplayViewWidgets 1.0 FlightDisplayViewWidgets.qml
FlyViewAirspaceIndicator 1.0 FlyViewAirspaceIndicator.qml
FlyViewMissionCompleteDialog 1.0 FlyViewMissionCompleteDialog.qml
FlyViewPreFlightChecklistPopup 1.0 FlyViewPreFlightChecklistPopup.qml
FlyViewToolStrip 1.0 FlyViewToolStrip.qml FlyViewToolStrip 1.0 FlyViewToolStrip.qml
GuidedActionConfirm 1.0 GuidedActionConfirm.qml GuidedActionConfirm 1.0 GuidedActionConfirm.qml
GuidedActionList 1.0 GuidedActionList.qml GuidedActionList 1.0 GuidedActionList.qml
GuidedActionsController 1.0 GuidedActionsController.qml GuidedActionsController 1.0 GuidedActionsController.qml
GuidedAltitudeSlider 1.0 GuidedAltitudeSlider.qml GuidedAltitudeSlider 1.0 GuidedAltitudeSlider.qml
MultiVehicleList 1.0 MultiVehicleList.qml MultiVehicleList 1.0 MultiVehicleList.qml
MultiVehiclePanel 1.0 MultiVehiclePanel.qml
PreFlightBatteryCheck 1.0 PreFlightBatteryCheck.qml PreFlightBatteryCheck 1.0 PreFlightBatteryCheck.qml
PreFlightGPSCheck 1.0 PreFlightGPSCheck.qml PreFlightGPSCheck 1.0 PreFlightGPSCheck.qml
PreFlightRCCheck 1.0 PreFlightRCCheck.qml PreFlightRCCheck 1.0 PreFlightRCCheck.qml
......
...@@ -32,7 +32,7 @@ ApplicationWindow { ...@@ -32,7 +32,7 @@ ApplicationWindow {
Component.onCompleted: { Component.onCompleted: {
//-- Full screen on mobile or tiny screens //-- Full screen on mobile or tiny screens
if(ScreenTools.isMobile || Screen.height / ScreenTools.realPixelDensity < 120) { if (ScreenTools.isMobile || Screen.height / ScreenTools.realPixelDensity < 120) {
mainWindow.showFullScreen() mainWindow.showFullScreen()
} else { } else {
width = ScreenTools.isMobile ? Screen.width : Math.min(250 * Screen.pixelDensity, Screen.width) width = ScreenTools.isMobile ? Screen.width : Math.min(250 * Screen.pixelDensity, Screen.width)
...@@ -40,8 +40,10 @@ ApplicationWindow { ...@@ -40,8 +40,10 @@ ApplicationWindow {
} }
// Startup experience wizard and provide the source using QGCCorePlugin // Startup experience wizard and provide the source using QGCCorePlugin
if(QGroundControl.settingsManager.appSettings.firstTimeStart.value) { if (QGroundControl.settingsManager.appSettings.firstTimeStart.value) {
startupPopup.open() startupPopup.open()
} else {
showPreFlightChecklistIfNeeded()
} }
} }
...@@ -78,10 +80,11 @@ ApplicationWindow { ...@@ -78,10 +80,11 @@ ApplicationWindow {
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
//-- Actions //-- Actions
signal armVehicle signal armVehicleRequest
signal disarmVehicle signal disarmVehicleRequest
signal vtolTransitionToFwdFlight signal vtolTransitionToFwdFlightRequest
signal vtolTransitionToMRFlight signal vtolTransitionToMRFlightRequest
signal showPreFlightChecklistIfNeeded
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
//-- Global Scope Functions //-- Global Scope Functions
...@@ -120,9 +123,8 @@ ApplicationWindow { ...@@ -120,9 +123,8 @@ ApplicationWindow {
function showFlyView() { function showFlyView() {
if (!flightView.visible) { if (!flightView.visible) {
flightView.showPreflightChecklistIfNeeded() mainWindow.showPreFlightChecklistIfNeeded()
} }
viewSwitch(false) viewSwitch(false)
flightView.visible = true flightView.visible = true
} }
...@@ -696,17 +698,17 @@ ApplicationWindow { ...@@ -696,17 +698,17 @@ ApplicationWindow {
Popup { Popup {
id: startupPopup id: startupPopup
anchors.centerIn: parent anchors.centerIn: parent
width: Math.min(startupWizard.implicitWidth, mainWindow.width - 2 * startupPopup._horizontalSpacing) width: Math.min(startupWizard.implicitWidth, mainWindow.width - 2 * startupPopup._horizontalSpacing)
height: Math.min(startupWizard.implicitHeight, mainWindow.availableHeight - 2 * startupPopup._verticalSpacing) height: Math.min(startupWizard.implicitHeight, mainWindow.availableHeight - 2 * startupPopup._verticalSpacing)
property real _horizontalSpacing: ScreenTools.defaultFontPixelWidth * 5
property real _verticalSpacing: ScreenTools.defaultFontPixelHeight * 2
modal: true modal: true
focus: true focus: true
closePolicy: (startupWizard && startupWizard.forceKeepingOpen !== undefined && startupWizard.forceKeepingOpen) ? Popup.NoAutoClose : Popup.CloseOnEscape | Popup.CloseOnPressOutside closePolicy: (startupWizard && startupWizard.forceKeepingOpen !== undefined && startupWizard.forceKeepingOpen) ? Popup.NoAutoClose : Popup.CloseOnEscape | Popup.CloseOnPressOutside
onClosed: mainWindow.showPreFlightChecklistIfNeeded()
property real _horizontalSpacing: ScreenTools.defaultFontPixelWidth * 5
property real _verticalSpacing: ScreenTools.defaultFontPixelHeight * 2
Connections { Connections {
target: startupWizard target: startupWizard
onCloseView: startupPopup.close() onCloseView: startupPopup.close()
......
...@@ -34,9 +34,9 @@ QGCComboBox { ...@@ -34,9 +34,9 @@ QGCComboBox {
onActivated: { onActivated: {
if (index == 0) { if (index == 0) {
mainWindow.armVehicle() mainWindow.armVehicleRequest()
} else { } else {
mainWindow.disarmVehicle() mainWindow.disarmVehicleRequest()
} }
currentIndex = -1 currentIndex = -1
} }
......
...@@ -35,11 +35,11 @@ QGCComboBox { ...@@ -35,11 +35,11 @@ QGCComboBox {
onActivated: { onActivated: {
if (index == 0) { if (index == 0) {
if (_fwdFlight) { if (_fwdFlight) {
mainWindow.vtolTransitionToMRFlight() mainWindow.vtolTransitionToMRFlightRequest()
} }
} else { } else {
if (!_fwdFlight) { if (!_fwdFlight) {
mainWindow.vtolTransitionToFwdFlight() mainWindow.vtolTransitionToFwdFlightRequest()
} }
} }
currentIndex = -1 currentIndex = -1
......
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