From 3bc2c3a040b78c15f4cb54a1c20ee8cc8cf4c3b6 Mon Sep 17 00:00:00 2001 From: Valentin Platzgummer Date: Thu, 21 Mar 2019 18:58:03 +0100 Subject: [PATCH] Fly Area Editor added --- qgroundcontrol.qrc | 2 + src/MissionManager/WimaFlyArea.cc | 41 +++- src/MissionManager/WimaFlyArea.h | 20 +- .../QGroundControl.Controls.qmldir | 1 + src/WimaView/FlyAreaEditor.qml | 48 +++++ src/WimaView/FlyAreaItemEditor.qml | 151 +++++++++++++++ src/WimaView/WimaView.qml | 178 +++++++++--------- 7 files changed, 336 insertions(+), 105 deletions(-) create mode 100644 src/WimaView/FlyAreaEditor.qml create mode 100644 src/WimaView/FlyAreaItemEditor.qml diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 79c89f87d..7c317e544 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -211,6 +211,8 @@ src/WimaView/WimaToolBar.qml src/WimaView/WimaView.qml src/WimaView/FlyAreaPolygonMapVisual.qml + src/WimaView/FlyAreaEditor.qml + src/WimaView/FlyAreaItemEditor.qml src/Settings/APMMavlinkStreamRate.SettingsGroup.json diff --git a/src/MissionManager/WimaFlyArea.cc b/src/MissionManager/WimaFlyArea.cc index 90a418095..920f191f2 100644 --- a/src/MissionManager/WimaFlyArea.cc +++ b/src/MissionManager/WimaFlyArea.cc @@ -22,20 +22,47 @@ void WimaFlyArea::_init() _polygons = new QmlObjectListModel(this); } -void WimaFlyArea::append_WimaFlyArea() + + +void WimaFlyArea::appendFlyAreaPolygon() { QGCMapPolygon *newPolygon = new QGCMapPolygon(); - newPolygon->setInteractive(true); - - for (int i = 0; i < _polygons->count(); i++) { - QGCMapPolygon* polygon = qobject_cast(_polygons->get(i)); - polygon->setInteractive(false); - } _polygons->append(newPolygon); + int index = _polygons->count()-1; + setCurrentPolygon(index); emit polygonsChanged(); } +void WimaFlyArea::removeFlyAreaPolygon(int index) +{ + if(index >= 0 && index < _polygons->count()) { + _polygons->removeAt(index); + + emit polygonsChanged(); + } +} +void WimaFlyArea::setCurrentPolygon(int index) +{ + if(index >= 0 && index < _polygons->count()) { + + if(index == _currentPolygonIndex){ + return; + } + + for (int i = 0; i < _polygons->count(); i++) { + QGCMapPolygon* polygon = qobject_cast(_polygons->get(i)); + polygon->setInteractive(false); + } + + _currentPolygonIndex = index; + _currentPolygonItem = qobject_cast(_polygons->get(index)); + _currentPolygonItem->setInteractive(true); + + emit currentPolygonItemChanged(_currentPolygonItem); + emit currentPolygonIndexChanged(index); + } +} diff --git a/src/MissionManager/WimaFlyArea.h b/src/MissionManager/WimaFlyArea.h index 9ea9ecc2d..f9f44e030 100644 --- a/src/MissionManager/WimaFlyArea.h +++ b/src/MissionManager/WimaFlyArea.h @@ -16,12 +16,18 @@ public: - Q_PROPERTY(QmlObjectListModel *polygons READ polygons NOTIFY polygonsChanged) + Q_PROPERTY(QmlObjectListModel *polygons READ polygons NOTIFY polygonsChanged) + Q_PROPERTY(QGCMapPolygon *currentPolygonItem READ currentPolygonItem NOTIFY currentPolygonItemChanged) + Q_PROPERTY(int currentPolygonIndex READ currentPolygonIndex NOTIFY currentPolygonIndexChanged) - Q_INVOKABLE void append_WimaFlyArea(); + Q_INVOKABLE void appendFlyAreaPolygon(); + Q_INVOKABLE void removeFlyAreaPolygon(int index); + Q_INVOKABLE void setCurrentPolygon(int index); // Property Accessors - QmlObjectListModel * polygons (void) { return _polygons;} + QmlObjectListModel * polygons (void) { return _polygons;} + QGCMapPolygon * currentPolygonItem (void) { return _currentPolygonItem;} + int currentPolygonIndex (void) { return _currentPolygonIndex;} // Methodes @@ -29,13 +35,19 @@ public: signals: void polygonsChanged(void); + void currentPolygonItemChanged(QGCMapPolygon * polygon); + void currentPolygonIndexChanged(int index); public slots: private: + + + QmlObjectListModel* _polygons; - QGCMapPolygon* _isCurrentPolygon; + QGCMapPolygon* _currentPolygonItem; + int _currentPolygonIndex; }; diff --git a/src/QmlControls/QGroundControl.Controls.qmldir b/src/QmlControls/QGroundControl.Controls.qmldir index d3fe378e1..4043d987e 100644 --- a/src/QmlControls/QGroundControl.Controls.qmldir +++ b/src/QmlControls/QGroundControl.Controls.qmldir @@ -84,3 +84,4 @@ VehicleRotationCal 1.0 VehicleRotationCal.qml VehicleSummaryRow 1.0 VehicleSummaryRow.qml ViewWidget 1.0 ViewWidget.qml FlyAreaPolygonMapVisual 1.0 FlyAreaPolygonMapVisual.qml +FlyAreaItemEditor 1.0 FlyAreaItemEditor.qml diff --git a/src/WimaView/FlyAreaEditor.qml b/src/WimaView/FlyAreaEditor.qml new file mode 100644 index 000000000..15da55f10 --- /dev/null +++ b/src/WimaView/FlyAreaEditor.qml @@ -0,0 +1,48 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Dialogs 1.2 +import QtQuick.Extras 1.4 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Vehicle 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.FlightMap 1.0 + +// Editor for Survery mission items +Rectangle { + id: _root + height: visible ? (editorColumn.height + (_margin * 2)) : 0 + width: availableWidth + color: qgcPal.windowShadeDark + radius: _radius + + // The following properties must be available up the hierarchy chain + //property real availableWidth ///< Width for control + //property var missionItem ///< Mission Item for editor + + property real _margin: ScreenTools.defaultFontPixelWidth / 2 + property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 10.5 + property var _vehicle: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle : QGroundControl.multiVehicleManager.offlineEditingVehicle + property real _cameraMinTriggerInterval: missionItem.cameraCalc.minTriggerInterval.rawValue + + + + QGCPalette { id: qgcPal; colorGroupEnabled: true } + + Column { + id: editorColumn + anchors.margins: _margin + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + + + + } // Column +} // Rectangle diff --git a/src/WimaView/FlyAreaItemEditor.qml b/src/WimaView/FlyAreaItemEditor.qml new file mode 100644 index 000000000..07ece3ee5 --- /dev/null +++ b/src/WimaView/FlyAreaItemEditor.qml @@ -0,0 +1,151 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Dialogs 1.2 +import QtQml 2.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Vehicle 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 + + +/// Fly Area edit control +Rectangle { + id: _root + height: editorLoader.visible ? (editorLoader.y + editorLoader.height + (_margin * 2)) : (commandPicker.y + commandPicker.height + _margin / 2) + color: _currentItem ? qgcPal.missionItemEditor : qgcPal.windowShade + radius: _radius + + property var map ///< Map control + property var masterController + property var missionItem ///< MissionItem associated with this editor + property bool readOnly ///< true: read only view, false: full editing view + property var rootQgcView + property var flyArea + + signal clicked + signal remove + + property var _masterController: masterController + property var _missionController: _masterController.missionController + property bool _currentItem: flyArea.currentPolygonIndex === index + property color _outerTextColor: _currentItem ? qgcPal.primaryButtonText : qgcPal.text + property bool _noMissionItemsAdded: ListView.view.model.count === 1 + property real _sectionSpacer: ScreenTools.defaultFontPixelWidth / 2 // spacing between section headings + + readonly property real _editFieldWidth: Math.min(width - _margin * 2, ScreenTools.defaultFontPixelWidth * 12) + readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2 + readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2 + readonly property real _hamburgerSize: commandPicker.height + readonly property bool _waypointsOnlyMode: QGroundControl.corePlugin.options.missionWaypointsOnly + + QGCPalette { + id: qgcPal + colorGroupEnabled: enabled + } + + FocusScope { + id: currentItemScope + anchors.fill: parent + + MouseArea { + anchors.fill: parent + onClicked: { + currentItemScope.focus = true + _root.clicked() + } + } + } + + + + QGCLabel { + id: label + anchors.verticalCenter: commandPicker.verticalCenter + anchors.leftMargin: _margin + anchors.left: parent.left + text: index+1 + color: _outerTextColor + } + + QGCColoredImage { + id: hamburger + anchors.rightMargin: ScreenTools.defaultFontPixelWidth + anchors.right: parent.right + anchors.verticalCenter: commandPicker.verticalCenter + width: _hamburgerSize + height: _hamburgerSize + sourceSize.height: _hamburgerSize + source: "qrc:/qmlimages/Hamburger.svg" + visible: flyArea.currentPolygonIndex === index + color: qgcPal.text + } + + QGCMouseArea { + fillItem: hamburger + visible: hamburger.visible + onClicked: { + currentItemScope.focus = true + hamburgerMenu.popup() + } + + Menu { + id: hamburgerMenu + + MenuItem { + text: qsTr("Insert Fly Area") + onTriggered: flyArea.appendFlyAreaPolygon() + } + MenuItem { + text: qsTr("Delete") + onTriggered: remove() + } + } + } + + QGCButton { + id: commandPicker + anchors.topMargin: _margin / 2 + anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2 + anchors.rightMargin: ScreenTools.defaultFontPixelWidth + anchors.left: label.right + anchors.top: parent.top + visible: !commandPicker.visible + text: missionItem.commandName + + Component { + id: commandDialog + + MissionCommandDialog { + missionItem: _root.missionItem + } + } + + //onClicked: qgcView.showDialog(commandDialog, qsTr("Select Mission Command"), qgcView.showDialogDefaultWidth, StandardButton.Cancel) + } + + QGCLabel { + id: commandLabel + anchors.fill: parent + verticalAlignment: Text.AlignVCenter + text: "Fly Area" + color: _outerTextColor + } + + Loader { + id: editorLoader + anchors.leftMargin: _margin + anchors.topMargin: _margin + anchors.left: parent.left + anchors.top: commandPicker.bottom + source: "FlyAreaEditor.qml" + visible: _currentItem + + property var masterController: _masterController + property real availableWidth: _root.width - (_margin * 2) ///< How wide the editor should be + property var editorRoot: _root + } +} // Rectangle diff --git a/src/WimaView/WimaView.qml b/src/WimaView/WimaView.qml index fff8bd9cc..3919e04c3 100644 --- a/src/WimaView/WimaView.qml +++ b/src/WimaView/WimaView.qml @@ -57,8 +57,6 @@ QGCView { property var _flyArea: wimaController.flyArea property var _planMasterController: masterController property var _missionController: _planMasterController.missionController - property var _geoFenceController: _planMasterController.geoFenceController - property var _rallyPointController: _planMasterController.rallyPointController property var _visualItems: _missionController.visualItems property bool _lightWidgetBorders: editorMap.isSatelliteMap property bool _addWaypointOnClick: false @@ -70,8 +68,7 @@ QGCView { property var _appSettings: QGroundControl.settingsManager.appSettings readonly property int _layerMission: 1 - readonly property int _layerGeoFence: 2 - readonly property int _layerRallyPoints: 3 + readonly property int _layerFlyArea: 2 readonly property string _armedVehicleUploadPrompt: qsTr("Vehicle is currently armed. Do you want to upload the mission to the vehicle?") Component.onCompleted: { @@ -79,24 +76,6 @@ QGCView { toolbar.currentMissionItem = Qt.binding(function () { return _missionController.currentPlanViewItem }) } - function addComplexItem(complexItemName) { - var coordinate = editorMap.center - coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) - coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces) - coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces) - insertComplexMissionItem(complexItemName, coordinate, _missionController.visualItems.count) - } - - function insertComplexMissionItem(complexItemName, coordinate, index) { - var sequenceNumber = _missionController.insertComplexMissionItem(complexItemName, coordinate, index) - _missionController.setCurrentPlanViewIndex(sequenceNumber, true) - } - - function insertComplexMissionItemFromKMLOrSHP(complexItemName, file, index) { - var sequenceNumber = _missionController.insertComplexMissionItemFromKMLOrSHP(complexItemName, file, index) - _missionController.setCurrentPlanViewIndex(sequenceNumber, true) - } - function updateAirspace(reset) { if(_airspaceEnabled) { var coordinateNW = editorMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */) @@ -142,18 +121,6 @@ QGCView { } } - Component { - id: applyNewAltitude - - QGCViewMessage { - message: qsTr("You have changed the default altitude for mission items. Would you like to apply that altitude to all the items in the current mission?") - - function accept() { - hideDialog() - _missionController.applyDefaultMissionAltitude() - } - } - } Component { id: activeMissionUploadDialogComponent @@ -190,7 +157,7 @@ QGCView { Connections { target: QGroundControl.airspaceManager - onAirspaceVisibleChanged: {oolStrip + onAirspaceVisibleChanged: { planControlColapsed = QGroundControl.airspaceManager.airspaceVisible } } @@ -303,23 +270,7 @@ QGCView { id: _mapTypeButtonsExclusiveGroup } - /// Inserts a new simple mission item - /// @param coordinate Location to insert item - /// @param index Insert item at this index - function insertSimpleMissionItem(coordinate, index) { - var sequenceNumber = _missionController.insertSimpleMissionItem(coordinate, index) - _missionController.setCurrentPlanViewIndex(sequenceNumber, true) - } - /// Inserts a new ROI mission item - /// @param coordinate Location to insert item - /// @param index Insert item at this index - function insertROIMissionItem(coordinate, index) { - var sequenceNumber = _missionController.insertROIMissionItem(coordinate, index) - _missionController.setCurrentPlanViewIndex(sequenceNumber, true) - _addROIOnClick = false - toolStrip.uncheckAll() - } property int _moveDialogMissionItemIndex @@ -496,7 +447,8 @@ QGCView { return } - var coordinate = editorMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */) + //var coordinate = editorMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */) + /* coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces) coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces) @@ -510,12 +462,7 @@ QGCView { insertROIMissionItem(coordinate, _missionController.visualItems.count) } break - case _layerRallyPoints: - if (_rallyPointController.supported) { - _rallyPointController.addPoint(coordinate) - } - break - } + }*/ } } @@ -562,6 +509,7 @@ QGCView { } } + /* GeoFenceMapVisuals { map: editorMap myGeoFenceController: _geoFenceController @@ -575,7 +523,7 @@ QGCView { myRallyPointController: _rallyPointController interactive: _editingLayer == _layerRallyPoints planView: true - } + }*/ // Airspace overlap support MapItemView { @@ -626,18 +574,15 @@ QGCView { }, { name: qsTr("Fly Area"), - iconSource: "/qmlimages/Target.svg", - toggle: true + iconSource: "/qmlimages/Target.svg" }, - { + { name: qsTr("No Fly"), - iconSource: "/qmlimages/noFlyArea.svg", - toggle: true + iconSource: "/qmlimages/noFlyArea.svg" }, { name: qsTr("Calculate"), - iconSource: "/qmlimages/calculate.svg", - toggle: true + iconSource: "/res/gear-white.svg" }, /*{ name: _singleComplexItem ? _missionController.complexMissionItemNames[0] : qsTr("Pattern"), @@ -662,7 +607,7 @@ QGCView { onClicked: { switch (index) { case 1: - _flyArea.append_WimaFlyArea(); + _flyArea.appendFlyAreaPolygon(); console.log("polygon count: ", _flyArea.polygons.count) //addComplexItem(_missionController.complexMissionItemNames[2]) /*_addWaypointOnClick = checked @@ -690,6 +635,8 @@ QGCView { } } } + + //----------------------------------------------------------- // Right pane for mission editing controls Rectangle { @@ -808,34 +755,24 @@ QGCView { case planElementMission: _editingLayer = _layerMission break - case planElementGeoFence: - _editingLayer = _layerGeoFence - break - case planElementRallyPoints: - _editingLayer = _layerRallyPoints + case planElementFlyArea: + _editingLayer = _layerFlyArea break } } } QGCRadioButton { - id: planElementMission + id: planElementFlyArea exclusiveGroup: planElementSelectorGroup - text: qsTr("Mission") + text: qsTr("Fly Area") checked: true visible: QGroundControl.corePlugin.options.enablePlanViewSelector anchors.verticalCenter: parent.verticalCenter } QGCRadioButton { - id: planElementGeoFence - exclusiveGroup: planElementSelectorGroup - text: qsTr("Fence") - visible: QGroundControl.corePlugin.options.enablePlanViewSelector - anchors.verticalCenter: parent.verticalCenter - } - QGCRadioButton { - id: planElementRallyPoints + id: planElementMission exclusiveGroup: planElementSelectorGroup - text: qsTr("Rally") + text: qsTr("Mission") visible: QGroundControl.corePlugin.options.enablePlanViewSelector anchors.verticalCenter: parent.verticalCenter } @@ -845,6 +782,49 @@ QGCView { } } //------------------------------------------------------- + // Fly Area Item Editor + Item { + id: flyAreaItemEditor + anchors.left: parent.left + anchors.right: parent.right + anchors.top: rightControls.bottom + anchors.topMargin: ScreenTools.defaultFontPixelHeight * 0.5 + anchors.bottom: parent.bottom + anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 0.25 + visible: _editingLayer == _layerFlyArea && !planControlColapsed + QGCListView { + id: flyAreaItemEditorListView + anchors.fill: parent + spacing: ScreenTools.defaultFontPixelHeight / 4 + orientation: ListView.Vertical + model: _flyArea.polygons + cacheBuffer: Math.max(height * 2, 0) + clip: true + currentIndex: _flyArea.currentPolygonIndex + highlightMoveDuration: 250 + visible: _editingLayer == _layerFlyArea && !planControlColapsed + //-- List Elements + delegate: FlyAreaItemEditor { + map: editorMap + masterController: _planMasterController + flyArea: _flyArea + missionItem: object + width: parent.width + readOnly: false + rootQgcView: _qgcView + onClicked: _flyArea.setCurrentPolygon(index) + onRemove: { + var removeIndex = index + _flyArea.removeFlyAreaPolygon(removeIndex) + if (removeIndex >= _flyArea.polygons.count) { + removeIndex-- + } + _flyArea.setCurrentPolygon(removeIndex) + } + } + } + } + //------------------------------------------------------- // Mission Item Editor Item { id: missionItemEditor @@ -888,6 +868,7 @@ QGCView { } } } + /* // GeoFence Editor GeoFenceEditor { anchors.top: rightControls.bottom @@ -919,6 +900,7 @@ QGCView { rallyPoint: _rallyPointController.currentRallyPoint controller: _rallyPointController } + */ } MapScale { @@ -1200,7 +1182,6 @@ QGCView { radius: 10 border.color: "black" border.width: 2 - color: "green" z:100 @@ -1208,23 +1189,32 @@ QGCView { id: debugTextTitle anchors.top: parent.top x: (parent.width - width)/2 - text: qsTr("Debug Messages") + text: qsTr("Debug Messages:") } - Column { + Rectangle { id: debugMessageText - Repeater{ - model: _flyArea.polygons - delegate: Rectangle{ - color: "lightsteelblue" - radius: 5 - Text { - text: object.interactive + anchors.margins: 50 + color: "darkgreen" + radius: 10 + Column { + anchors.fill: parent + Repeater{ + model: _flyArea.polygons + delegate: Rectangle{ + height: 25 + color: "lightsteelblue" + radius: 5 + Text { + text: object.interactive + } + } } - } } } + + } } // QGCVIew -- 2.22.0