From 4d68c05c12439d58247ac53d3d599e6bb9315867 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Mon, 10 Feb 2025 11:42:18 -0800 Subject: [PATCH 1/2] Add new DropPanel control support --- custom-example/qgroundcontrol.qrc | 1 + qgroundcontrol.qrc | 1 + src/QmlControls/DropPanel.qml | 192 ++++++------------ .../QGroundControl/Controls/qmldir | 1 + src/QmlControls/ToolStrip.qml | 2 +- src/QmlControls/ToolStripDropPanel.qml | 162 +++++++++++++++ 6 files changed, 232 insertions(+), 127 deletions(-) create mode 100644 src/QmlControls/ToolStripDropPanel.qml diff --git a/custom-example/qgroundcontrol.qrc b/custom-example/qgroundcontrol.qrc index 0a717639462f..57d510f1eb37 100644 --- a/custom-example/qgroundcontrol.qrc +++ b/custom-example/qgroundcontrol.qrc @@ -193,6 +193,7 @@ ../src/PlanView/TakeoffItemMapVisual.qml ../src/QmlControls/ToolIndicatorPage.qml ../src/QmlControls/ToolStrip.qml + ../src/QmlControls/ToolStripDropPanel.qml ../src/QmlControls/ToolStripHoverButton.qml ../src/PlanView/TransectStyleComplexItemEditor.qml ../src/PlanView/TransectStyleComplexItemStats.qml diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 1a689064d3d4..ef613f923fb3 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -196,6 +196,7 @@ src/PlanView/TakeoffItemMapVisual.qml src/QmlControls/ToolIndicatorPage.qml src/QmlControls/ToolStrip.qml + src/QmlControls/ToolStripDropPanel.qml src/QmlControls/ToolStripHoverButton.qml src/PlanView/TransectStyleComplexItemEditor.qml src/PlanView/TransectStyleComplexItemStats.qml diff --git a/src/QmlControls/DropPanel.qml b/src/QmlControls/DropPanel.qml index 472966c54ef4..5b3928731874 100644 --- a/src/QmlControls/DropPanel.qml +++ b/src/QmlControls/DropPanel.qml @@ -9,154 +9,94 @@ import QtQuick import QtQuick.Controls +import QtQuick.Layouts import QGroundControl import QGroundControl.ScreenTools import QGroundControl.Palette -Item { - id: _root - visible: false - - signal clicked() - property real radius: ScreenTools.isMobile ? ScreenTools.defaultFontPixelHeight * 1.75 : ScreenTools.defaultFontPixelHeight * 1.25 - property real viewportMargins: 0 - property var toolStrip - - // Should be an enum but that get's into the whole problem of creating a singleton which isn't worth the effort - readonly property int dropLeft: 1 - readonly property int dropRight: 2 - readonly property int dropUp: 3 - readonly property int dropDown: 4 - - readonly property real _arrowBaseHeight: radius // Height of vertical side of arrow - readonly property real _arrowPointWidth: radius * 0.666 // Distance from vertical side to point - readonly property real _dropMargin: ScreenTools.defaultFontPixelWidth - - property var _dropEdgeTopPoint - property alias _dropDownComponent: panelLoader.sourceComponent - property real _viewportMaxTop: 0 - property real _viewportMaxBottom: parent.parent.height - parent.y - property real _viewportMaxHeight: _viewportMaxBottom - _viewportMaxTop - property var _dropPanelCancel - property var _parentButton - - function show(panelEdgeTopPoint, panelComponent, parentButton) { - _parentButton = parentButton - _dropEdgeTopPoint = panelEdgeTopPoint - _dropDownComponent = panelComponent - _calcPositions() - visible = true - _dropPanelCancel = dropPanelCancelComponent.createObject(toolStrip.parent) - } - - function hide() { - if (_dropPanelCancel) { - _dropPanelCancel.destroy() - _parentButton.checked = false - visible = false - _dropDownComponent = undefined +/// Drop panel that displays positioned next to the specified click position. +/// By default the panel drops to the right of the click position. If there isn't +/// enough room to the right then the panel will drop to the left. +Popup { + id: _root + padding: _innerMargin + leftPadding: _dropRight ? _innerMargin + _arrowPointWidth : _innerMargin + rightPadding: _dropRight ? _innerMargin : _innerMargin + _arrowPointWidth + modal: true + focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + clip: false + + property var sourceComponent // Component to display within the popup + property var clickRect: Qt.rect(0, 0, 0, 0) // Rectangle of clicked item - used to position drop down + property var dropViewPort: Qt.rect(0, 0, parent.width, parent.height) // Available viewport for dropdown + + property var _qgcPal: QGroundControl.globalPalette + property real _innerMargin: ScreenTools.defaultFontPixelWidth * 0.5 // Margin between content and rectanglular portion of background + property real _arrowPointWidth: ScreenTools.defaultFontPixelWidth * 2 // Distance from vertical side to point + property real _arrowPointPositionY: height / 2 + property bool _dropRight: true + + onAboutToShow: { + // Panel defaults to dropping to the right of click position + _root.x = clickRect.x + clickRect.width + + // If there isn't room to the right then we switch to drop to the left + if (_root.x + _root.width > dropViewPort.x + dropViewPort.width) { + _dropRight = false + _root.x = clickRect.x - _root.width } - } - - function _calcPositions() { - var panelComponentWidth = panelLoader.item.width - var panelComponentHeight = panelLoader.item.height - - dropDownItem.width = panelComponentWidth + (_dropMargin * 2) + _arrowPointWidth - dropDownItem.height = panelComponentHeight + (_dropMargin * 2) - - dropDownItem.x = _dropEdgeTopPoint.x + _dropMargin - dropDownItem.y = _dropEdgeTopPoint.y -(dropDownItem.height / 2) + radius - - // Validate that dropdown is within viewport - dropDownItem.y = Math.min(dropDownItem.y + dropDownItem.height, _viewportMaxBottom) - dropDownItem.height - dropDownItem.y = Math.max(dropDownItem.y, _viewportMaxTop) - - // Adjust height to not exceed viewport bounds - dropDownItem.height = Math.min(dropDownItem.height, _viewportMaxHeight - dropDownItem.y) - - // Arrow points - arrowCanvas.arrowPoint.y = (_dropEdgeTopPoint.y + radius) - dropDownItem.y - arrowCanvas.arrowPoint.x = 0 - arrowCanvas.arrowBase1.x = _arrowPointWidth - arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseHeight / 2) - arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x - arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseHeight - arrowCanvas.requestPaint() - } // function - _calcPositions - QGCPalette { id: qgcPal } + // Default position of panel is vertically centered on click position + _root.y = clickRect.y + (clickRect.height / 2) + _root.y -= _root.height / 2 - Component { - // Overlay which is used to cancel the panel when the user clicks away - id: dropPanelCancelComponent + // Make sure panel is within viewport + let originRootY = _root.y + _root.y = Math.max(_root.y, dropViewPort.y) + _root.y = Math.min(_root.y, dropViewPort.y + dropViewPort.height - _root.height) - MouseArea { - anchors.fill: parent - z: toolStrip.z - 1 - onClicked: dropPanel.hide() - } + // Adjust arrow position back to point at click position + _arrowPointPositionY += originRootY - _root.y } - // This item is sized to hold the entirety of the drop panel including the arrow point - Item { - id: dropDownItem + background: Item { + implicitWidth: contentItem.implicitWidth + _innerMargin * 2 + _arrowPointWidth + implicitHeight: contentItem.implicitHeight + _innerMargin * 2 - DeadMouseArea { - anchors.fill: parent + Rectangle { + x: _dropRight ? _arrowPointWidth : 0 + radius: ScreenTools.defaultFontPixelHeight / 2 + width: parent.implicitWidth - _arrowPointWidth + height: parent.implicitHeight + color: _qgcPal.window } + // Arrowhead Canvas { - id: arrowCanvas - anchors.fill: parent - - property point arrowPoint: Qt.point(0, 0) - property point arrowBase1: Qt.point(0, 0) - property point arrowBase2: Qt.point(0, 0) - + x: _dropRight ? 0 : parent.width - _arrowPointWidth + y: _arrowPointPositionY - _arrowPointWidth + width: _arrowPointWidth + height: _arrowPointWidth * 2 + onPaint: { - var panelX = _arrowPointWidth - var panelY = 0 - var panelWidth = parent.width - _arrowPointWidth - var panelHeight = parent.height - var context = getContext("2d") context.reset() context.beginPath() - - context.moveTo(panelX, panelY) // top left - context.lineTo(panelX + panelWidth, panelY) // top right - context.lineTo(panelX + panelWidth, panelX + panelHeight) // bottom right - context.lineTo(panelX, panelY + panelHeight) // bottom left - context.lineTo(arrowBase2.x, arrowBase2.y) - context.lineTo(arrowPoint.x, arrowPoint.y) - context.lineTo(arrowBase1.x, arrowBase1.y) - context.lineTo(panelX, panelY) // top left - + context.moveTo(_dropRight ? 0 : _arrowPointWidth, _arrowPointWidth) + context.lineTo(_dropRight ? _arrowPointWidth : 0, 0) + context.lineTo(_dropRight ? _arrowPointWidth : 0, _arrowPointWidth * 2) context.closePath() - context.fillStyle = qgcPal.windowShade + context.fillStyle = _qgcPal.window context.fill() } - } // Canvas - arrowCanvas - - QGCFlickable { - id: panelItemFlickable - anchors.margins: _dropMargin - anchors.leftMargin: _dropMargin + _arrowPointWidth - anchors.fill: parent - flickableDirection: Flickable.VerticalFlick - contentWidth: panelLoader.width - contentHeight: panelLoader.height - - Loader { - id: panelLoader - - onHeightChanged: _calcPositions() - onWidthChanged: _calcPositions() + } + } - property var dropPanel: _root - } + contentItem: SettingsGroupLayout { + Loader { + sourceComponent: _root.sourceComponent } - } // Item - dropDownItem + } } diff --git a/src/QmlControls/QGroundControl/Controls/qmldir b/src/QmlControls/QGroundControl/Controls/qmldir index 1c366fe526fa..28ce27c4828e 100644 --- a/src/QmlControls/QGroundControl/Controls/qmldir +++ b/src/QmlControls/QGroundControl/Controls/qmldir @@ -117,6 +117,7 @@ SurveyMapVisuals 1.0 SurveyMapVisuals.qml TerrainStatus 1.0 TerrainStatus.qml ToolIndicatorPage 1.0 ToolIndicatorPage.qml ToolStrip 1.0 ToolStrip.qml +ToolStripDropPanel 1.0 ToolStripDropPanel.qml ToolStripHoverButton 1.0 ToolStripHoverButton.qml TransectStyleComplexItemEditor 1.0 TransectStyleComplexItemEditor.qml TransectStyleComplexItemStats 1.0 TransectStyleComplexItemStats.qml diff --git a/src/QmlControls/ToolStrip.qml b/src/QmlControls/ToolStrip.qml index daf07f7d637f..5b2e5ebdf3a8 100644 --- a/src/QmlControls/ToolStrip.qml +++ b/src/QmlControls/ToolStrip.qml @@ -102,7 +102,7 @@ Rectangle { } } - DropPanel { + ToolStripDropPanel { id: dropPanel toolStrip: _root } diff --git a/src/QmlControls/ToolStripDropPanel.qml b/src/QmlControls/ToolStripDropPanel.qml new file mode 100644 index 000000000000..472966c54ef4 --- /dev/null +++ b/src/QmlControls/ToolStripDropPanel.qml @@ -0,0 +1,162 @@ +/**************************************************************************** + * + * (c) 2009-2020 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick +import QtQuick.Controls + +import QGroundControl +import QGroundControl.ScreenTools +import QGroundControl.Palette + +Item { + id: _root + visible: false + + signal clicked() + property real radius: ScreenTools.isMobile ? ScreenTools.defaultFontPixelHeight * 1.75 : ScreenTools.defaultFontPixelHeight * 1.25 + property real viewportMargins: 0 + property var toolStrip + + // Should be an enum but that get's into the whole problem of creating a singleton which isn't worth the effort + readonly property int dropLeft: 1 + readonly property int dropRight: 2 + readonly property int dropUp: 3 + readonly property int dropDown: 4 + + readonly property real _arrowBaseHeight: radius // Height of vertical side of arrow + readonly property real _arrowPointWidth: radius * 0.666 // Distance from vertical side to point + readonly property real _dropMargin: ScreenTools.defaultFontPixelWidth + + property var _dropEdgeTopPoint + property alias _dropDownComponent: panelLoader.sourceComponent + property real _viewportMaxTop: 0 + property real _viewportMaxBottom: parent.parent.height - parent.y + property real _viewportMaxHeight: _viewportMaxBottom - _viewportMaxTop + property var _dropPanelCancel + property var _parentButton + + function show(panelEdgeTopPoint, panelComponent, parentButton) { + _parentButton = parentButton + _dropEdgeTopPoint = panelEdgeTopPoint + _dropDownComponent = panelComponent + _calcPositions() + visible = true + _dropPanelCancel = dropPanelCancelComponent.createObject(toolStrip.parent) + } + + function hide() { + if (_dropPanelCancel) { + _dropPanelCancel.destroy() + _parentButton.checked = false + visible = false + _dropDownComponent = undefined + } + } + + function _calcPositions() { + var panelComponentWidth = panelLoader.item.width + var panelComponentHeight = panelLoader.item.height + + dropDownItem.width = panelComponentWidth + (_dropMargin * 2) + _arrowPointWidth + dropDownItem.height = panelComponentHeight + (_dropMargin * 2) + + dropDownItem.x = _dropEdgeTopPoint.x + _dropMargin + dropDownItem.y = _dropEdgeTopPoint.y -(dropDownItem.height / 2) + radius + + // Validate that dropdown is within viewport + dropDownItem.y = Math.min(dropDownItem.y + dropDownItem.height, _viewportMaxBottom) - dropDownItem.height + dropDownItem.y = Math.max(dropDownItem.y, _viewportMaxTop) + + // Adjust height to not exceed viewport bounds + dropDownItem.height = Math.min(dropDownItem.height, _viewportMaxHeight - dropDownItem.y) + + // Arrow points + arrowCanvas.arrowPoint.y = (_dropEdgeTopPoint.y + radius) - dropDownItem.y + arrowCanvas.arrowPoint.x = 0 + arrowCanvas.arrowBase1.x = _arrowPointWidth + arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseHeight / 2) + arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x + arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseHeight + arrowCanvas.requestPaint() + } // function - _calcPositions + + QGCPalette { id: qgcPal } + + Component { + // Overlay which is used to cancel the panel when the user clicks away + id: dropPanelCancelComponent + + MouseArea { + anchors.fill: parent + z: toolStrip.z - 1 + onClicked: dropPanel.hide() + } + } + + // This item is sized to hold the entirety of the drop panel including the arrow point + Item { + id: dropDownItem + + DeadMouseArea { + anchors.fill: parent + } + + Canvas { + id: arrowCanvas + anchors.fill: parent + + property point arrowPoint: Qt.point(0, 0) + property point arrowBase1: Qt.point(0, 0) + property point arrowBase2: Qt.point(0, 0) + + onPaint: { + var panelX = _arrowPointWidth + var panelY = 0 + var panelWidth = parent.width - _arrowPointWidth + var panelHeight = parent.height + + var context = getContext("2d") + context.reset() + context.beginPath() + + context.moveTo(panelX, panelY) // top left + context.lineTo(panelX + panelWidth, panelY) // top right + context.lineTo(panelX + panelWidth, panelX + panelHeight) // bottom right + context.lineTo(panelX, panelY + panelHeight) // bottom left + context.lineTo(arrowBase2.x, arrowBase2.y) + context.lineTo(arrowPoint.x, arrowPoint.y) + context.lineTo(arrowBase1.x, arrowBase1.y) + context.lineTo(panelX, panelY) // top left + + context.closePath() + context.fillStyle = qgcPal.windowShade + context.fill() + } + } // Canvas - arrowCanvas + + QGCFlickable { + id: panelItemFlickable + anchors.margins: _dropMargin + anchors.leftMargin: _dropMargin + _arrowPointWidth + anchors.fill: parent + flickableDirection: Flickable.VerticalFlick + contentWidth: panelLoader.width + contentHeight: panelLoader.height + + Loader { + id: panelLoader + + onHeightChanged: _calcPositions() + onWidthChanged: _calcPositions() + + property var dropPanel: _root + } + } + } // Item - dropDownItem +} From 532bac92d2f137edea7b4c1a50ca0cd0d34c3f17 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Mon, 10 Feb 2025 11:42:34 -0800 Subject: [PATCH 2/2] Switch to new DropPanel control --- src/FlightDisplay/FlyViewMap.qml | 267 +++++++++++++---------------- src/PlanView/MissionItemEditor.qml | 143 +++++++++------ src/PlanView/PlanView.qml | 2 +- 3 files changed, 204 insertions(+), 208 deletions(-) diff --git a/src/FlightDisplay/FlyViewMap.qml b/src/FlightDisplay/FlyViewMap.qml index 5aabb6db1018..f4ca80762f96 100644 --- a/src/FlightDisplay/FlyViewMap.qml +++ b/src/FlightDisplay/FlyViewMap.qml @@ -500,10 +500,12 @@ FlightMap { MouseArea { anchors.fill: parent onClicked: (position) => { - var roiEditMenu = popupMenuComponent.createObject(_root, { coord: roiLocationItem.coordinate, contentItemComponent: roiEditMenuComponent }) - var clickPoint = mapToItem(_root, position.x, position.y) - roiEditMenu.setPosition(clickPoint.x, clickPoint.y) - roiEditMenu.open() + position = Qt.point(position.x, position.y) + var clickCoord = _root.toCoordinate(position, false /* clipToViewPort */) + // For some strange reason using mainWindow in mapToItem doesn't work, so we use globals.parent instead which also gets us mainWindow + position = mapToItem(globals.parent, position) + var dropPanel = roiEditDropPanelComponent.createObject(mainWindow, { clickRect: Qt.rect(position.x, position.y, 0, 0) }) + dropPanel.open() } } @@ -542,171 +544,129 @@ FlightMap { } Component { - id: popupMenuComponent - - Popup { - id: mapClickMenu - modal: true - - property var coord - property var contentItemComponent - - function setPosition(mouseX, mouseY) { - var newX = mouseX - var newY = mouseY - - // Filtering coordinates - if (newX + mapClickMenu.width > _root.width) { - newX = _root.width - mapClickMenu.width - } - if (newY + mapClickMenu.height > _root.height) { - newY = _root.height - mapClickMenu.height - } - - // Set coordiantes - x = newX - y = newY - } - - background: Rectangle { - radius: ScreenTools.defaultFontPixelHeight * 0.5 - color: qgcPal.window - border.color: qgcPal.text - } - - contentItem: Loader { - sourceComponent: contentItemComponent + id: roiEditPositionDialogComponent - property var mapClickCoord: mapClickMenu.coord - property var popup: mapClickMenu + EditPositionDialog { + title: qsTr("Edit ROI Position") + coordinate: roiLocationItem.coordinate + onCoordinateChanged: { + roiLocationItem.coordinate = coordinate + _activeVehicle.guidedModeROI(coordinate) } } } Component { - id: mapClickMenuComponent - - ColumnLayout { - id: mainLayout - spacing: ScreenTools.defaultFontPixelWidth / 2 - - QGCButton { - Layout.fillWidth: true - text: qsTr("Go to location") - visible: globals.guidedControllerFlyView.showGotoLocation - onClicked: { - if (popup.opened) { - popup.close() + id: roiEditDropPanelComponent + + DropPanel { + id: roiEditDropPanel + + sourceComponent: Component { + ColumnLayout { + spacing: ScreenTools.defaultFontPixelWidth / 2 + + QGCButton { + Layout.fillWidth: true + text: qsTr("Cancel ROI") + onClicked: { + _activeVehicle.stopGuidedModeROI() + roiEditDropPanel.close() + } } - gotoLocationItem.show(mapClickCoord) - globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionGoto, mapClickCoord, gotoLocationItem) - } - } - QGCButton { - Layout.fillWidth: true - text: qsTr("Orbit at location") - visible: globals.guidedControllerFlyView.showOrbit - onClicked: { - if (popup.opened) { - popup.close() + QGCButton { + Layout.fillWidth: true + text: qsTr("Edit Position") + onClicked: { + roiEditPositionDialogComponent.createObject(mainWindow, { showSetPositionFromVehicle: false }).open() + roiEditDropPanel.close() + } } - orbitMapCircle.show(mapClickCoord) - globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionOrbit, mapClickCoord, orbitMapCircle) } } + } + } - QGCButton { - Layout.fillWidth: true - text: qsTr("ROI at location") - visible: globals.guidedControllerFlyView.showROI - onClicked: { - if (popup.opened) { - popup.close() + Component { + id: mapClickDropPanelComponent + + DropPanel { + id: mapClickDropPanel + + property var mapClickCoord + + sourceComponent: Component { + ColumnLayout { + spacing: ScreenTools.defaultFontPixelWidth / 2 + + QGCButton { + Layout.fillWidth: true + text: qsTr("Go to location") + visible: globals.guidedControllerFlyView.showGotoLocation + onClicked: { + mapClickDropPanel.close() + gotoLocationItem.show(mapClickCoord) + globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionGoto, mapClickCoord, gotoLocationItem) + } } - globals.guidedControllerFlyView.executeAction(globals.guidedControllerFlyView.actionROI, mapClickCoord, 0, false) - } - } - QGCButton { - Layout.fillWidth: true - text: qsTr("Set home here") - visible: globals.guidedControllerFlyView.showSetHome - onClicked: { - if (popup.opened) { - popup.close() + QGCButton { + Layout.fillWidth: true + text: qsTr("Orbit at location") + visible: globals.guidedControllerFlyView.showOrbit + onClicked: { + mapClickDropPanel.close() + orbitMapCircle.show(mapClickCoord) + globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionOrbit, mapClickCoord, orbitMapCircle) + } } - globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetHome, mapClickCoord) - } - } - QGCButton { - Layout.fillWidth: true - text: qsTr("Set Estimator Origin") - visible: globals.guidedControllerFlyView.showSetEstimatorOrigin - onClicked: { - if (popup.opened) { - popup.close() + QGCButton { + Layout.fillWidth: true + text: qsTr("ROI at location") + visible: globals.guidedControllerFlyView.showROI + onClicked: { + mapClickDropPanel.close() + globals.guidedControllerFlyView.executeAction(globals.guidedControllerFlyView.actionROI, mapClickCoord, 0, false) + } } - globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetEstimatorOrigin, mapClickCoord) - } - } - QGCButton { - Layout.fillWidth: true - text: qsTr("Set Heading") - visible: globals.guidedControllerFlyView.showChangeHeading - onClicked: { - if (popup.opened) { - popup.close() + QGCButton { + Layout.fillWidth: true + text: qsTr("Set home here") + visible: globals.guidedControllerFlyView.showSetHome + onClicked: { + mapClickDropPanel.close() + globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetHome, mapClickCoord) + } } - globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionChangeHeading, mapClickCoord) - } - } - - ColumnLayout { - spacing: 0 - QGCLabel { text: qsTr("Lat: %1").arg(mapClickCoord.latitude.toFixed(6)) } - QGCLabel { text: qsTr("Lon: %1").arg(mapClickCoord.longitude.toFixed(6)) } - } - } - } - - Component { - id: roiEditPositionDialogComponent - EditPositionDialog { - title: qsTr("Edit ROI Position") - coordinate: roiLocationItem.coordinate - onCoordinateChanged: { - roiLocationItem.coordinate = coordinate - _activeVehicle.guidedModeROI(coordinate) - } - } - } + QGCButton { + Layout.fillWidth: true + text: qsTr("Set Estimator Origin") + visible: globals.guidedControllerFlyView.showSetEstimatorOrigin + onClicked: { + mapClickDropPanel.close() + globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetEstimatorOrigin, mapClickCoord) + } + } - Component { - id: roiEditMenuComponent - - ColumnLayout { - id: mainLayout - spacing: ScreenTools.defaultFontPixelWidth / 2 - - QGCButton { - Layout.fillWidth: true - text: qsTr("Cancel ROI") - onClicked: { - _activeVehicle.stopGuidedModeROI() - popup.close() - } - } + QGCButton { + Layout.fillWidth: true + text: qsTr("Set Heading") + visible: globals.guidedControllerFlyView.showChangeHeading + onClicked: { + mapClickDropPanel.close() + globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionChangeHeading, mapClickCoord) + } + } - QGCButton { - Layout.fillWidth: true - text: qsTr("Edit Position") - onClicked: { - roiEditPositionDialogComponent.createObject(mainWindow, { showSetPositionFromVehicle: false }).open() - popup.close() + ColumnLayout { + spacing: 0 + QGCLabel { text: qsTr("Lat: %1").arg(mapClickCoord.latitude.toFixed(6)) } + QGCLabel { text: qsTr("Lon: %1").arg(mapClickCoord.longitude.toFixed(6)) } + } } } } @@ -714,13 +674,16 @@ FlightMap { onMapClicked: (position) => { if (!globals.guidedControllerFlyView.guidedUIVisible && - (globals.guidedControllerFlyView.showGotoLocation || globals.guidedControllerFlyView.showOrbit || globals.guidedControllerFlyView.showROI || globals.guidedControllerFlyView.showSetHome || globals.guidedControllerFlyView.showSetEstimatorOrigin)) { + (globals.guidedControllerFlyView.showGotoLocation || globals.guidedControllerFlyView.showOrbit || globals.guidedControllerFlyView.showROI || globals.guidedControllerFlyView.showSetHome || globals.guidedControllerFlyView.showSetEstimatorOrigin)) { orbitMapCircle.hide() gotoLocationItem.hide() - var clickCoord = _root.toCoordinate(Qt.point(position.x, position.y), false /* clipToViewPort */) - var mapClickMenu = popupMenuComponent.createObject(_root, { coord: clickCoord, contentItemComponent: mapClickMenuComponent }) - mapClickMenu.setPosition(position.x, position.y) - mapClickMenu.open() + + position = Qt.point(position.x, position.y) + var clickCoord = _root.toCoordinate(position, false /* clipToViewPort */) + // For some strange reason using mainWindow in mapToItem doesn't work, so we use globals.parent instead which also gets us mainWindow + position = _root.mapToItem(globals.parent, position) + var dropPanel = mapClickDropPanelComponent.createObject(mainWindow, { mapClickCoord: clickCoord, clickRect: Qt.rect(position.x, position.y, 0, 0) }) + dropPanel.open() } } diff --git a/src/PlanView/MissionItemEditor.qml b/src/PlanView/MissionItemEditor.qml index e0f362a2a02f..726f177300d5 100644 --- a/src/PlanView/MissionItemEditor.qml +++ b/src/PlanView/MissionItemEditor.qml @@ -181,81 +181,114 @@ Rectangle { } } - QGCColoredImage { - id: hamburger - anchors.margins: _margin - anchors.right: parent.right - anchors.verticalCenter: topRowLayout.verticalCenter - width: _hamburgerSize - height: _hamburgerSize - sourceSize.height: _hamburgerSize - source: "qrc:/qmlimages/Hamburger.svg" - visible: missionItem.isCurrentItem && missionItem.sequenceNumber !== 0 - color: qgcPal.text + Component { + id: hamburgerMenuDropPanelComponent - QGCMouseArea { - fillItem: hamburger - onClicked: { - currentItemScope.focus = true - hamburgerMenu.popup() - } + DropPanel { + id: hamburgerMenuDropPanel - QGCMenu { - id: hamburgerMenu + sourceComponent: Component { + ColumnLayout { + spacing: ScreenTools.defaultFontPixelHeight / 2 - QGCMenuItem { - text: qsTr("Move to vehicle position") - enabled: _activeVehicle && missionItem.specifiesCoordinate - onTriggered: missionItem.coordinate = _activeVehicle.coordinate + QGCButton { + Layout.fillWidth: true + text: qsTr("Move to vehicle position") + enabled: _activeVehicle && missionItem.specifiesCoordinate - property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle - } + onClicked: { + missionItem.coordinate = _activeVehicle.coordinate + hamburgerMenuDropPanel.close() + } - QGCMenuItem { - text: qsTr("Move to previous item position") - enabled: _missionController.previousCoordinate.isValid - onTriggered: missionItem.coordinate = _missionController.previousCoordinate - } + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + } - QGCMenuItem { - text: qsTr("Edit position...") - enabled: missionItem.specifiesCoordinate - onTriggered: editPositionDialog.createObject(mainWindow).open() - } + QGCButton { + Layout.fillWidth: true + text: qsTr("Move to previous item position") + enabled: _missionController.previousCoordinate.isValid + onClicked: { + missionItem.coordinate = _missionController.previousCoordinate + hamburgerMenuDropPanel.close() + } + } - QGCMenuSeparator { - //visible: missionItem.isSimpleItem && !_waypointsOnlyMode - } + QGCButton { + Layout.fillWidth: true + text: qsTr("Edit position...") + enabled: missionItem.specifiesCoordinate + onClicked: { + editPositionDialog.createObject(mainWindow).open() + hamburgerMenuDropPanel.close() + } + } - QGCMenuItem { - text: qsTr("Show all values") - visible: QGroundControl.corePlugin.showAdvancedUI - checkable: true - checked: missionItem.isSimpleItem ? missionItem.rawEdit : false - enabled: missionItem.isSimpleItem && !_waypointsOnlyMode + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: qgcPal.groupBorder + } + + QGCCheckBoxSlider { + Layout.fillWidth: true + text: qsTr("Show all values") + visible: QGroundControl.corePlugin.showAdvancedUI + checked: missionItem.isSimpleItem ? missionItem.rawEdit : false + enabled: missionItem.isSimpleItem && !_waypointsOnlyMode - onTriggered: { - if (missionItem.rawEdit) { - if (missionItem.friendlyEditAllowed) { + onClicked: { + missionItem.rawEdit = checked + if (missionItem.rawEdit && !missionItem.friendlyEditAllowed) { missionItem.rawEdit = false - } else { + checked = false mainWindow.showMessageDialog(qsTr("Mission Edit"), qsTr("You have made changes to the mission item which cannot be shown in Simple Mode")) } - } else { - missionItem.rawEdit = true + hamburgerMenuDropPanel.close() } - checked = missionItem.rawEdit } - } - QGCMenuItem { - text: qsTr("Item #%1").arg(missionItem.sequenceNumber) - enabled: false + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: qgcPal.groupBorder + } + + QGCLabel { + text: qsTr("Item #%1").arg(missionItem.sequenceNumber) + enabled: false + } } } } } + + QGCColoredImage { + id: hamburger + anchors.margins: _margin + anchors.right: parent.right + anchors.verticalCenter: topRowLayout.verticalCenter + width: _hamburgerSize + height: _hamburgerSize + sourceSize.height: _hamburgerSize + source: "qrc:/qmlimages/Hamburger.svg" + visible: missionItem.isCurrentItem && missionItem.sequenceNumber !== 0 + color: qgcPal.text + + QGCMouseArea { + fillItem: hamburger + onClicked: (position) => { + currentItemScope.focus = true + position = Qt.point(position.x, position.y) + // For some strange reason using mainWindow in mapToItem doesn't work, so we use globals.parent instead which also gets us mainWindow + position = mapToItem(globals.parent, position) + var dropPanel = hamburgerMenuDropPanelComponent.createObject(mainWindow, { clickRect: Qt.rect(position.x, position.y, 0, 0) }) + dropPanel.open() + } + } + } + /* QGCLabel { id: notReadyForSaveLabel diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index bc25e8317544..12cc2e3a27a3 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -910,7 +910,7 @@ Item { UTMSPStateStorage.currentStateIndex = 0}}) } - //- ToolStrip DropPanel Components + //- ToolStrip ToolStripDropPanel Components Component { id: centerMapDropPanel