5import QGroundControl.Controls
6import QGroundControl.FactControls
10 width: controlIndicatorIconGCS.width * 1.1
11 anchors.top: parent.top
12 anchors.bottom: parent.bottom
14 property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
15 property bool showIndicator: activeVehicle && activeVehicle.firstControlStatusReceived
16 property var sysidInControl: activeVehicle ? activeVehicle.sysidInControl : 0
17 property bool gcsControlStatusFlags_SystemManager: activeVehicle ? activeVehicle.gcsControlStatusFlags_SystemManager : false
18 property bool gcsControlStatusFlags_TakeoverAllowed: activeVehicle ? activeVehicle.gcsControlStatusFlags_TakeoverAllowed : false
19 property Fact requestControlAllowTakeoverFact: QGroundControl.settingsManager.flyViewSettings.requestControlAllowTakeover
20 property bool requestControlAllowTakeover: requestControlAllowTakeoverFact.rawValue
21 property bool isThisGCSinControl: sysidInControl == QGroundControl.settingsManager.mavlinkSettings.gcsMavlinkSystemID.rawValue
22 property bool sendControlRequestAllowed: activeVehicle ? activeVehicle.sendControlRequestAllowed : false
24 property var margins: ScreenTools.defaultFontPixelWidth
25 property var panelRadius: ScreenTools.defaultFontPixelWidth * 0.5
26 property var buttonHeight: height * 1.6
27 property var squareButtonPadding: ScreenTools.defaultFontPixelWidth
28 property var separatorHeight: buttonHeight * 0.9
29 property var settingsPanelVisible: false
30 property bool outdoorPalette: qgcPal.globalTheme === QGCPalette.Light
32 // Used by control request popup, when other GCS ask us for control
33 property var receivedRequestTimeoutMs: QGroundControl.settingsManager.flyViewSettings.requestControlTimeout.defaultValue // Use this as default in case something goes wrong. Usually it will be overriden on onRequestOperatorControlReceived
34 property var requestSysIdRequestingControl: 0
35 property var requestAllowTakeover: false
37 signal triggerAnimations // Used to trigger animation inside the popup component
41 // Popup prompting user to accept control from other GCS
42 function onRequestOperatorControlReceived(sysIdRequestingControl, allowTakeover, requestTimeoutSecs) {
43 // If we don't have the indicator visible ( not receiving CONTROL_STATUS ) don't proceed
44 if (!control.showIndicator) {
47 requestSysIdRequestingControl = sysIdRequestingControl
48 requestAllowTakeover = allowTakeover
49 // If request came without request timeout, use our default one
50 receivedRequestTimeoutMs = requestTimeoutSecs !== 0 ? requestTimeoutSecs * 1000 : QGroundControl.settingsManager.flyViewSettings.requestControlTimeout.defaultValue
51 // First hide current popup, in case the normal control panel is visible
52 mainWindow.closeIndicatorDrawer()
53 // When showing the popup, the component will automatically start the count down in controlRequestPopup
54 mainWindow.showIndicatorDrawer(controlRequestPopup, control)
56 // Animation to blink indicator when any related info changes
57 function onGcsControlStatusChanged() {
58 backgroundRectangle.doOpacityAnimation()
59 triggerAnimations() // Needed for animation inside the popup component
63 // Background to have animation when current system in control changes
65 id: backgroundRectangle
66 anchors.centerIn: parent
68 height: parent.height * 1.4
69 color: isThisGCSinControl ? qgcPal.colorGreen : qgcPal.text
73 function doOpacityAnimation() { opacityAnimation.restart() }
74 SequentialAnimation on opacity {
78 PropertyAnimation { to: 0.4; duration: 150 }
79 PropertyAnimation { to: 0.5; duration: 100 }
80 PropertyAnimation { to: 0.0; duration: 150 }
84 // Control request popup. Appears when other GCS requests control, so operator on this one can accept or deny it
86 id: controlRequestPopup
89 TimedProgressTracker {
90 id: requestProgressTracker
91 timeoutSeconds: receivedRequestTimeoutMs * 0.001
92 onTimeout: mainWindow.closeIndicatorDrawer()
95 Component.onCompleted: {
96 requestProgressTracker.start()
99 contentComponent: GridLayout {
105 font.pointSize: ScreenTools.defaultFontPointSize * 1.1
106 text: qsTr("GCS ") + requestSysIdRequestingControl + qsTr(" is requesting control")
111 text: qsTr("Allow <br> takeover")
113 Layout.leftMargin: margins * 2
114 Layout.alignment: Qt.AlignBottom
115 Layout.fillHeight: true
117 control.activeVehicle.requestOperatorControl(true) // Allow takeover
118 mainWindow.closeIndicatorDrawer()
119 // After allowing takeover, if other GCS does not take control within 10 seconds
120 // takeover will be set to not allowed again. Notify user about this
121 control.activeVehicle.startTimerRevertAllowTakeover()
122 mainWindow.showIndicatorDrawer(allowTakeoverExpirationPopup, control)
127 font.pointSize: ScreenTools.defaultFontPointSize * 1.1
128 text: qsTr("Ignoring automatically in ") + requestProgressTracker.progressLabel + qsTr(" seconds")
133 onClicked: mainWindow.closeIndicatorDrawer()
134 Layout.alignment: Qt.AlignHCenter
136 // Actual progress bar
139 height: ScreenTools.defaultFontPixelWidth
140 width: parent.width * requestProgressTracker.progress
141 color: qgcPal.buttonHighlight
148 // Allow takeover expiration time popup. When a request is received and takeover was allowed, this popup alerts
149 // that after vehicle::REQUEST_OPERATOR_CONTROL_ALLOW_TAKEOVER_TIMEOUT_MSECS seconds, this GCS will change back to takeover not allowed, as per mavlink specs
151 id: allowTakeoverExpirationPopup
154 // Allow takeover expiration time popup. When a request is received and takeover was allowed, this popup alerts
155 // that after vehicle::REQUEST_OPERATOR_CONTROL_ALLOW_TAKEOVER_TIMEOUT_MSECS seconds, this GCS will change back to takeover not allowed, as per mavlink specs
156 TimedProgressTracker {
157 id: revertTakeoverProgressTracker
158 timeoutSeconds: control.activeVehicle.operatorControlTakeoverTimeoutMsecs * 0.001
160 mainWindow.closeIndicatorDrawer()
163 // After accepting allow takeover after a request, we show the 10 seconds countdown after which takeover will be set again to not allowed.
164 // If during this time another GCS takes control, which is what we are expecting, remove this popup
165 property var isThisGCSinControlLocal: control.isThisGCSinControl
166 onIsThisGCSinControlLocalChanged: {
167 if (visible && !isThisGCSinControlLocal) {
168 mainWindow.closeIndicatorDrawer()
172 Component.onCompleted: {
173 revertTakeoverProgressTracker.start()
176 contentComponent: GridLayout {
182 font.pointSize: ScreenTools.defaultFontPointSize * 1.1
183 text: qsTr("Reverting back to takeover not allowed if GCS ") + requestSysIdRequestingControl +
184 qsTr(" doesn't take control in ") + revertTakeoverProgressTracker.progressLabel +
190 onClicked: mainWindow.closeIndicatorDrawer()
191 Layout.alignment: Qt.AlignHCenter
197 // Popup panel, appears when clicking top control indicator
203 TimedProgressTracker {
204 id: sendRequestProgressTracker
205 timeoutSeconds: QGroundControl.settingsManager.flyViewSettings.requestControlTimeout.rawValue
207 // If a request was sent, and we get feedback that takeover has been allowed, stop the progress tracker as the request has been granted
208 property var takeoverAllowedLocal: control.gcsControlStatusFlags_TakeoverAllowed
209 onTakeoverAllowedLocalChanged: {
210 if (takeoverAllowedLocal && sendRequestProgressTracker.running) {
211 sendRequestProgressTracker.stop()
215 Component.onCompleted: {
216 // If send control request is not allowed it means we recently sent a request, closed the popup, and opened again
217 // before the other request timeout expired. This way we can keep track of the time remaining and update UI accordingly
218 if (!sendControlRequestAllowed) {
219 // vehicle.requestOperatorControlRemainingMsecs holds the time remaining for the current request
220 startProgressTracker(control.activeVehicle.requestOperatorControlRemainingMsecs * 0.001)
224 function startProgressTracker(timeoutSeconds) {
225 sendRequestProgressTracker.timeoutSeconds = timeoutSeconds
226 sendRequestProgressTracker.start()
229 contentComponent: GridLayout {
234 text: qsTr("System in control: ")
238 text: isThisGCSinControl ? (qsTr("This GCS") + " (" + sysidInControl + ")" ) : sysidInControl
239 font.bold: isThisGCSinControl
240 color: isThisGCSinControl ? qgcPal.colorGreen : qgcPal.text
241 Layout.alignment: Qt.AlignRight
242 Layout.fillWidth: true
243 horizontalAlignment: Text.AlignRight
246 text: gcsControlStatusFlags_TakeoverAllowed ? qsTr("Takeover allowed") : qsTr("Takeover NOT allowed")
248 Layout.alignment: Qt.AlignRight
249 Layout.fillWidth: true
250 horizontalAlignment: Text.AlignRight
251 color: gcsControlStatusFlags_TakeoverAllowed ? qgcPal.colorGreen : qgcPal.text
256 Layout.preferredWidth: parent.width
257 Layout.alignment: Qt.AlignHCenter
258 color: qgcPal.windowShade
259 height: outdoorPalette ? 1 : 2
262 text: qsTr("Send Control Request:")
264 visible: !isThisGCSinControl
267 text: qsTr("Change takeover condition:")
269 visible: isThisGCSinControl
272 id: requestSentTimeoutLabel
273 text: qsTr("Request sent: ") + sendRequestProgressTracker.progressLabel
275 visible: sendRequestProgressTracker.running
278 text: qsTr("Allow takeover")
279 fact: requestControlAllowTakeoverFact
280 enabled: gcsControlStatusFlags_TakeoverAllowed || isThisGCSinControl
283 text: gcsControlStatusFlags_TakeoverAllowed ? qsTr("Adquire Control") : qsTr("Send Request")
285 var timeout = gcsControlStatusFlags_TakeoverAllowed ? 0 : QGroundControl.settingsManager.flyViewSettings.requestControlTimeout.rawValue
286 control.activeVehicle.requestOperatorControl(requestControlAllowTakeoverFact.rawValue, timeout)
288 // Start UI timeout animation
289 startProgressTracker(timeout)
292 Layout.alignment: Qt.AlignRight
293 visible: !isThisGCSinControl
294 enabled: !sendRequestProgressTracker.running
297 text: qsTr("Request Timeout (sec):")
298 visible: !isThisGCSinControl && !gcsControlStatusFlags_TakeoverAllowed
301 fact: QGroundControl.settingsManager.flyViewSettings.requestControlTimeout
302 visible: !isThisGCSinControl && !gcsControlStatusFlags_TakeoverAllowed
303 Layout.alignment: Qt.AlignRight
304 Layout.preferredWidth: ScreenTools.defaultFontPixelWidth * 7
308 onClicked: control.activeVehicle.requestOperatorControl(requestControlAllowTakeoverFact.rawValue)
309 visible: isThisGCSinControl
310 Layout.alignment: Qt.AlignRight
311 enabled: gcsControlStatusFlags_TakeoverAllowed != requestControlAllowTakeoverFact.rawValue
316 Layout.preferredWidth: parent.width
317 Layout.alignment: Qt.AlignHCenter
318 color: qgcPal.windowShade
319 height: outdoorPalette ? 1 : 2
321 LabelledFactTextField {
322 Layout.fillWidth: true
324 label: qsTr("This GCS Mavlink System ID: ")
325 fact: QGroundControl.settingsManager.mavlinkSettings.gcsMavlinkSystemID
331 // Actual top toolbar indicator
333 id: controlIndicatorIconLine
335 anchors.top: parent.top
336 anchors.bottom: parent.bottom
337 source: "/gcscontrolIndicator/gcscontrol_line.svg"
338 fillMode: Image.PreserveAspectFit
339 sourceSize.height: height
340 color: isThisGCSinControl ? qgcPal.colorGreen : qgcPal.text
343 id: controlIndicatorIconAircraft
345 anchors.top: parent.top
346 anchors.bottom: parent.bottom
347 source: "/gcscontrolIndicator/gcscontrol_device.svg"
348 fillMode: Image.PreserveAspectFit
349 sourceSize.height: height
350 color: (isThisGCSinControl || gcsControlStatusFlags_TakeoverAllowed) ? qgcPal.colorGreen : qgcPal.text
353 id: controlIndicatorIconGCS
355 anchors.top: parent.top
356 anchors.bottom: parent.bottom
357 source: "/gcscontrolIndicator/gcscontrol_gcs.svg"
358 fillMode: Image.PreserveAspectFit
359 sourceSize.height: height
362 // Current GCS in control indicator
364 id: gcsInControlIndicator
367 font.pointSize: ScreenTools.smallFontPointSize * 1.1
368 color: isThisGCSinControl ? qgcPal.colorGreen : qgcPal.text
369 anchors.bottom: parent.bottom
370 anchors.bottomMargin: -margins * 0.7
371 anchors.right: parent.right
372 anchors.rightMargin: -margins * 0.1
379 mainWindow.showIndicatorDrawer(controlPopup, control)