Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi Vehicle Panel Overhaul #11970

Merged
merged 1 commit into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions qgroundcontrol.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
<file alias="QGroundControl/Controls/MissionItemIndexLabel.qml">src/QmlControls/MissionItemIndexLabel.qml</file>
<file alias="QGroundControl/Controls/MissionItemMapVisual.qml">src/PlanView/MissionItemMapVisual.qml</file>
<file alias="QGroundControl/Controls/MissionItemStatus.qml">src/PlanView/MissionItemStatus.qml</file>
<file alias="QGroundControl/Controls/MvPanelPage.qml">src/QmlControls/MvPanelPage.qml</file>
<file alias="QGroundControl/Controls/OfflineMapButton.qml">src/QmlControls/OfflineMapButton.qml</file>
<file alias="QGroundControl/Controls/OfflineMapEditor.qml">src/QtLocationPlugin/QMLControl/OfflineMapEditor.qml</file>
<file alias="QGroundControl/Controls/OfflineMapInfo.qml">src/UI/preferences/OfflineMapInfo.qml</file>
Expand Down Expand Up @@ -161,12 +162,14 @@
<file alias="QGroundControl/Controls/QGCMenuSeparator.qml">src/QmlControls/QGCMenuSeparator.qml</file>
<file alias="QGroundControl/Controls/QGCMouseArea.qml">src/QmlControls/QGCMouseArea.qml</file>
<file alias="QGroundControl/Controls/QGCMovableItem.qml">src/QmlControls/QGCMovableItem.qml</file>
<file alias="QGroundControl/Controls/QGCPageIndicator.qml">src/QmlControls/QGCPageIndicator.qml</file>
<file alias="QGroundControl/Controls/QGCPopupDialog.qml">src/QmlControls/QGCPopupDialog.qml</file>
<file alias="QGroundControl/Controls/PipView.qml">src/QmlControls/PipView.qml</file>
<file alias="QGroundControl/Controls/PipState.qml">src/QmlControls/PipState.qml</file>
<file alias="QGroundControl/Controls/QGCRadioButton.qml">src/QmlControls/QGCRadioButton.qml</file>
<file alias="QGroundControl/Controls/QGCSimpleMessageDialog.qml">src/QmlControls/QGCSimpleMessageDialog.qml</file>
<file alias="QGroundControl/Controls/QGCSlider.qml">src/QmlControls/QGCSlider.qml</file>
<file alias="QGroundControl/Controls/QGCSwipeView.qml">src/QmlControls/QGCSwipeView.qml</file>
<file alias="QGroundControl/Controls/QGCSwitch.qml">src/QmlControls/QGCSwitch.qml</file>
<file alias="QGroundControl/Controls/QGCTabBar.qml">src/QmlControls/QGCTabBar.qml</file>
<file alias="QGroundControl/Controls/QGCTabButton.qml">src/QmlControls/QGCTabButton.qml</file>
Expand Down Expand Up @@ -342,6 +345,7 @@
<file alias="Viewer3D/Models3D/Line3D.qml">src/Viewer3D/Viewer3DQml/Models3D/Line3D.qml</file>
<file alias="Viewer3D/Models3D/Viewer3DVehicleItems.qml">src/Viewer3D/Viewer3DQml/Models3D/Viewer3DVehicleItems.qml</file>
<file alias="Viewer3D/Viewer3DProgressBar.qml">src/Viewer3D/Viewer3DQml/Viewer3DProgressBar.qml</file>
<file alias="QGroundControl/FlightDisplay/FlyViewTopRightPanel.qml">src/FlightDisplay/FlyViewTopRightPanel.qml</file>
</qresource>
<qresource prefix="/FirstRunPromptDialogs">
<file alias="UnitsFirstRunPrompt.qml">src/FirstRunPromptDialogs/UnitsFirstRunPrompt.qml</file>
Expand Down
31 changes: 1 addition & 30 deletions src/FlightDisplay/FlyViewTopRightColumnLayout.qml
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,6 @@ import QGroundControl.ScreenTools
ColumnLayout {
width: _rightPanelWidth

RowLayout {
id: multiVehiclePanelSelector
Layout.alignment: Qt.AlignTop
spacing: ScreenTools.defaultFontPixelWidth
visible: QGroundControl.multiVehicleManager.vehicles.count > 1 && QGroundControl.corePlugin.options.flyView.showMultiVehicleList

QGCMapPalette { id: mapPal; lightColors: true }

QGCRadioButton {
id: singleVehicleRadio
text: qsTr("Single")
checked: _showSingleVehicleUI
onClicked: _showSingleVehicleUI = true
textColor: mapPal.text
}

QGCRadioButton {
text: qsTr("Multi-Vehicle")
textColor: mapPal.text
onClicked: _showSingleVehicleUI = false
}
}

TerrainProgress {
Layout.alignment: Qt.AlignTop
Layout.preferredWidth: _rightPanelWidth
Expand All @@ -54,7 +31,7 @@ ColumnLayout {
Loader {
id: photoVideoControlLoader
Layout.alignment: Qt.AlignTop | Qt.AlignRight
sourceComponent: globals.activeVehicle && _showSingleVehicleUI ? photoVideoControlComponent : undefined
sourceComponent: globals.activeVehicle ? photoVideoControlComponent : undefined

property real rightEdgeCenterInset: visible ? parent.width - x : 0

Expand All @@ -65,10 +42,4 @@ ColumnLayout {
}
}
}

MultiVehicleList {
Layout.preferredWidth: _rightPanelWidth
Layout.fillHeight: true
visible: !_showSingleVehicleUI
}
}
252 changes: 252 additions & 0 deletions src/FlightDisplay/FlyViewTopRightPanel.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
/****************************************************************************
*
* (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
import QtQuick.Layouts

import QGroundControl
import QGroundControl.FactSystem
import QGroundControl.FactControls
import QGroundControl.Controls
import QGroundControl.FlightDisplay
import QGroundControl.FlightMap
import QGroundControl.Palette
import QGroundControl.ScreenTools


Rectangle {
id: topRightPanel
width: contentWidth
height: Math.max(contentHeight, minimumHeight)
color: qgcPal.toolbarBackground
radius: ScreenTools.defaultFontPixelHeight / 2
visible: !QGroundControl.videoManager.fullScreen && _multipleVehicles && _settingEnableMVPanel
clip: true

property bool _settingEnableMVPanel: QGroundControl.settingsManager.appSettings.enableMultiVehiclePanel.value
property bool _multipleVehicles: QGroundControl.multiVehicleManager.vehicles.count > 1
property var vehicles: QGroundControl.multiVehicleManager.vehicles
property var selectedVehicles: QGroundControl.multiVehicleManager.selectedVehicles
property real contentWidth: Math.max(
multiVehicleList.implicitWidth,
swipeViewContainer.implicitWidth
) + ScreenTools.defaultFontPixelHeight
property real contentHeight: Math.min(
maximumHeight,
topRightPanelColumnLayout.implicitHeight + topRightPanelColumnLayout.spacing * ( topRightPanelColumnLayout.children.length - 1)
)
property real minimumHeight: selectedVehiclesLabel.height + swipeViewContainer.height
property real maximumHeight

QGCPalette { id: qgcPal }

ColumnLayout {
id: topRightPanelColumnLayout
anchors.fill: parent
anchors.margins: ScreenTools.defaultFontPixelHeight / 2
spacing: ScreenTools.defaultFontPixelHeight / 2

QGCLabel {
id: selectedVehiclesLabel
text: {
let ids = Array.from({length: selectedVehicles.count}, (_, i) =>
selectedVehicles.get(i).id
).sort((a, b) => a - b)
.join(", ")
return qsTr("Selected: ") + ids
}
}

MultiVehicleList {
id: multiVehicleList
Layout.fillWidth: true
Layout.fillHeight: true
implicitHeight: multiVehicleList.innerColumnHeight * vehicles.count - _margins * 3

Rectangle {
anchors.fill: parent
visible: topRightPanel.height === maximumHeight

Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 0
height: 1
color: QGroundControl.globalPalette.groupBorder
}

gradient: Gradient {
orientation: Gradient.Vertical
GradientStop { position: 0.00; color: topRightPanel.color }
GradientStop { position: 0.05; color: "transparent" }

GradientStop { position: 0.95; color: "transparent" }
GradientStop { position: 1.00; color: topRightPanel.color }
}

Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: 0
height: 1
color: QGroundControl.globalPalette.groupBorder
}
}

}

Rectangle {
id: swipeViewContainer
Layout.fillWidth: true
implicitHeight: swipePages.implicitHeight
implicitWidth: swipePages.implicitWidth
color: "transparent"

QGCSwipeView {
id: swipePages
anchors.fill: parent
spacing: ScreenTools.defaultFontPixelHeight
implicitHeight: Math.max(buttonsPage.implicitHeight, photoVideoPage.implicitHeight)
implicitWidth: Math.max(buttonsPage.implicitWidth, photoVideoPage.implicitWidth)

MvPanelPage {
id: buttonsPage
implicitHeight: buttonsColumnLayout.implicitHeight + ScreenTools.defaultFontPixelHeight * 2
implicitWidth: buttonsColumnLayout.implicitWidth + ScreenTools.defaultFontPixelHeight * 2

ColumnLayout {
id: buttonsColumnLayout
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: ScreenTools.defaultFontPixelHeight / 2
implicitHeight: Math.max(selectionRowLayout.height, actionRowLayout.height) + ScreenTools.defaultFontPixelHeight * 2
implicitWidth: Math.max(selectionRowLayout.width, actionRowLayout.width) + ScreenTools.defaultFontPixelHeight * 4

QGCLabel {
text: qsTr("Multi Vehicle Selection")
Layout.alignment: Qt.AlignHCenter
}

RowLayout {
id: selectionRowLayout
Layout.alignment: Qt.AlignHCenter

QGCButton {
text: qsTr("Select All")
enabled: multiVehicleList.selectedVehicles && multiVehicleList.selectedVehicles.count !== QGroundControl.multiVehicleManager.vehicles.count
onClicked: multiVehicleList.selectAll()
}

QGCButton {
text: qsTr("Deselect All")
enabled: multiVehicleList.selectedVehicles && multiVehicleList.selectedVehicles.count > 0
onClicked: multiVehicleList.deselectAll()
}

}


QGCLabel {
text: qsTr("Multi Vehicle Actions")
Layout.alignment: Qt.AlignHCenter
}

RowLayout {
id: actionRowLayout
Layout.alignment: Qt.AlignHCenter

QGCButton {
text: qsTr("Arm")
enabled: multiVehicleList.armAvailable()
onClicked: _guidedController.confirmAction(_guidedController.actionMVArm)
Layout.preferredWidth: ScreenTools.defaultFontPixelHeight * 2.75
leftPadding: 0
rightPadding: 0
}

QGCButton {
text: qsTr("Disarm")
enabled: multiVehicleList.disarmAvailable()
onClicked: _guidedController.confirmAction(_guidedController.actionMVDisarm)
Layout.preferredWidth: ScreenTools.defaultFontPixelHeight * 2.75
leftPadding: 0
rightPadding: 0
}

QGCButton {
text: qsTr("Start")
enabled: multiVehicleList.startAvailable()
onClicked: _guidedController.confirmAction(_guidedController.actionMVStartMission)
Layout.preferredWidth: ScreenTools.defaultFontPixelHeight * 2.75
leftPadding: 0
rightPadding: 0
}

QGCButton {
text: qsTr("Pause")
enabled: multiVehicleList.pauseAvailable()
onClicked: _guidedController.confirmAction(_guidedController.actionMVPause)
Layout.preferredWidth: ScreenTools.defaultFontPixelHeight * 2.75
leftPadding: 0
rightPadding: 0
}
}
}
} // Page 1

MvPanelPage {

id: photoVideoPage
implicitHeight: photoVideoControlLoader.implicitHeight + ScreenTools.defaultFontPixelHeight * 2
implicitWidth: photoVideoControlLoader.implicitWidth + ScreenTools.defaultFontPixelHeight * 2

// We use a Loader to load the photoVideoControlComponent only when the active vehicle is not null
// This make it easier to implement PhotoVideoControl without having to check for the mavlink camera
// to be null all over the place

Loader {
id: photoVideoControlLoader
anchors.horizontalCenter: parent.horizontalCenter
sourceComponent: globals.activeVehicle ? photoVideoControlComponent : undefined

property real rightEdgeCenterInset: visible ? parent.width - x : 0

Component {
id: photoVideoControlComponent

PhotoVideoControl {
}
}
}
} // Page 2
} // QGCSwipeView

QGCPageIndicator {
id: pageIndicator
count: swipePages.count
currentIndex: swipePages.currentIndex
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: ScreenTools.defaultFontPixelHeight / 4

delegate: Rectangle {
height: ScreenTools.defaultFontPixelHeight / 2
width: height
radius: width / 2
color: model.index === pageIndicator.currentIndex ? qgcPal.text : qgcPal.button
opacity: model.index === pageIndicator.currentIndex ? 0.9 : 0.3
}
}
}
}
}

20 changes: 17 additions & 3 deletions src/FlightDisplay/FlyViewWidgetLayer.qml
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,38 @@ Item {
leftEdgeTopInset: toolStrip.leftEdgeTopInset
leftEdgeCenterInset: toolStrip.leftEdgeCenterInset
leftEdgeBottomInset: virtualJoystickMultiTouch.visible ? virtualJoystickMultiTouch.leftEdgeBottomInset : parentToolInsets.leftEdgeBottomInset
rightEdgeTopInset: topRightColumnLayout.rightEdgeTopInset
rightEdgeCenterInset: topRightColumnLayout.rightEdgeCenterInset
rightEdgeTopInset: topRightPanel.rightEdgeTopInset
rightEdgeCenterInset: topRightPanel.rightEdgeCenterInset
rightEdgeBottomInset: bottomRightRowLayout.rightEdgeBottomInset
topEdgeLeftInset: toolStrip.topEdgeLeftInset
topEdgeCenterInset: mapScale.topEdgeCenterInset
topEdgeRightInset: topRightColumnLayout.topEdgeRightInset
topEdgeRightInset: topRightPanel.topEdgeRightInset
bottomEdgeLeftInset: virtualJoystickMultiTouch.visible ? virtualJoystickMultiTouch.bottomEdgeLeftInset : parentToolInsets.bottomEdgeLeftInset
bottomEdgeCenterInset: bottomRightRowLayout.bottomEdgeCenterInset
bottomEdgeRightInset: virtualJoystickMultiTouch.visible ? virtualJoystickMultiTouch.bottomEdgeRightInset : bottomRightRowLayout.bottomEdgeRightInset
}

FlyViewTopRightPanel {
id: topRightPanel
anchors.top: parent.top
anchors.right: parent.right
anchors.topMargin: _layoutMargin
anchors.rightMargin: _layoutMargin
maximumHeight: parent.height - (bottomRightRowLayout.height + _margins * 5)

property real topEdgeRightInset: height + _layoutMargin
property real rightEdgeTopInset: width + _layoutMargin
property real rightEdgeCenterInset: rightEdgeTopInset
}

FlyViewTopRightColumnLayout {
id: topRightColumnLayout
anchors.margins: _layoutMargin
anchors.top: parent.top
anchors.bottom: bottomRightRowLayout.top
anchors.right: parent.right
spacing: _layoutSpacing
visible: !topRightPanel.visible

property real topEdgeRightInset: childrenRect.height + _layoutMargin
property real rightEdgeTopInset: width + _layoutMargin
Expand Down
Loading
Loading