1pragma ComponentBehavior: Bound
7import QGroundControl.Controls
8import QGroundControl.GPS
10// Drawer of the GPS indicator: vehicle GPS, GNSS receiver, corrections, and GCS position.
15 readonly property GPSReceiver _receiver: QGroundControl.gpsManager.receiver
16 readonly property NTRIPSettings _ntripSettings: QGroundControl.settingsManager.ntripSettings
17 // Connecting to a configured caster is the common field action, so it is offered without opening settings.
18 readonly property bool _ntripConfigured: root._ntripSettings.userVisible
19 && root._ntripSettings.ntripServerHostAddress.rawValue !== ""
20 readonly property VehicleGPSFactGroup _gps: root.activeVehicle ? root.activeVehicle.gps : null
21 readonly property bool _vehicleGps: !!root._gps && root._gps.telemetryAvailable
22 readonly property real _preferredStatusWidth: ScreenTools.defaultFontPixelWidth * 36
23 readonly property real _preferredSettingsWidth: ScreenTools.defaultFontPixelWidth * 56
24 readonly property real _sideBySideWidth: root._preferredStatusWidth + root._preferredSettingsWidth
25 + root.spacing * 2 + 1
26 property real availableWidth: root.Window.width > 0 ? root.Window.width - ScreenTools.defaultFontPixelHeight * 4
27 : root._sideBySideWidth
28 readonly property bool _compact: root.availableWidth < root._sideBySideWidth
29 // Settings stay usable, rather than collapsing, on windows narrower than the reserved margins.
30 readonly property real _settingsWidth: Math.max(ScreenTools.defaultFontPixelWidth * 30,
31 Math.min(root._preferredSettingsWidth,
32 root.availableWidth - (root._compact ? 0 : root._preferredStatusWidth) - root.spacing * 2 - 1))
34 // A vehicle GPS value, labelled with its description, shown while the vehicle reports it.
35 component MeasurementLabel: LabelledLabel {
36 property Fact fact: null
37 property bool nonNegative: false
39 visible: !!fact && Number.isFinite(fact.value) && (!nonNegative || fact.value >= 0)
40 label: fact ? fact.shortDescription : ""
41 labelText: fact ? fact.valueString + (fact.units ? " " + fact.units : "") : ""
44 // A resilience state, shown while the receiver reports it.
45 component StateLabel: LabelledLabel {
46 required property bool reported
47 required property Fact fact
50 labelText: reported ? fact.enumStringValue : ""
53 // Only states the receiver reports are listed.
54 component ResilienceGroup: SettingsGroupLayout {
57 required property VehicleGPSFactGroup facts
58 readonly property bool reported: !!facts
59 && (facts.jammingReported || facts.spoofingReported
60 || facts.authenticationReported)
62 Layout.minimumWidth: 0
66 label: qsTr("Jamming")
67 reported: group.facts?.jammingReported ?? false
68 fact: group.facts?.jammingState ?? null
71 label: qsTr("Spoofing")
72 reported: group.facts?.spoofingReported ?? false
73 fact: group.facts?.spoofingState ?? null
76 label: qsTr("Authentication")
77 reported: group.facts?.authenticationReported ?? false
78 fact: group.facts?.authenticationState ?? null
82 contentComponent: Component {
84 // On narrow screens the expanded view replaces status instead of requiring horizontal scrolling.
85 width: root.expanded && root._compact ? 0 : Math.min(root._preferredStatusWidth, root.availableWidth)
86 visible: !root.expanded || !root._compact
87 spacing: ScreenTools.defaultFontPixelHeight / 2
90 Layout.minimumWidth: 0
91 heading: qsTr("Vehicle GPS Status")
92 visible: root._vehicleGps
95 label: qsTr("Satellites")
96 labelText: root._gps?.count.valueString ?? ""
99 label: root._gps?.lock.shortDescription ?? ""
100 labelText: root._gps?.lock.enumStringValue ?? ""
103 objectName: "vehicleGpsHdop"
104 fact: root._gps?.hdop ?? null
107 objectName: "vehicleGpsVdop"
108 fact: root._gps?.vdop ?? null
111 objectName: "vehicleGpsHorizontalAccuracy"
112 fact: root._gps?.horizontalAccuracy ?? null
116 objectName: "vehicleGpsVerticalAccuracy"
117 fact: root._gps?.verticalAccuracy ?? null
121 objectName: "vehicleGpsRtkBaseline"
122 fact: root._gps?.rtkBaseline ?? null
125 objectName: "vehicleGpsRtkRate"
126 fact: root._gps?.rtkRate ?? null
129 objectName: "vehicleGpsRtkSatellites"
130 fact: root._gps?.rtkSatellites ?? null
134 fact: root._gps?.courseOverGround ?? null
137 label: qsTr("GPS Error")
138 labelText: root._gps?.systemErrorText ?? ""
139 visible: (root._gps?.systemErrors.value ?? 0) > 0
143 // Each receiver that reports is listed; the headings name them only when both do.
146 objectName: "gps1Resilience"
147 heading: gps2Resilience.reported ? qsTr("GPS 1 Resilience") : qsTr("GPS Resilience Status")
153 objectName: "gps2Resilience"
154 heading: gps1Resilience.reported ? qsTr("GPS 2 Resilience") : qsTr("GPS Resilience Status")
155 facts: root.activeVehicle?.gps2 ?? null
159 Layout.minimumWidth: 0
160 showWhenDisconnected: !root._vehicleGps
161 disconnectedText: qsTr("No GNSS receiver connected. Expand for settings.")
165 objectName: "gpsIndicatorCorrections"
166 Layout.minimumWidth: 0
167 showWhenInactive: false
170 NTRIPConnectionStatus {
171 objectName: "gpsIndicatorNtrip"
172 Layout.minimumWidth: 0
173 heading: qsTr("NTRIP")
174 visible: root._ntripConfigured
178 objectName: "gpsIndicatorGcsPosition"
179 Layout.minimumWidth: 0
180 sourceEditable: false
181 showCoordinates: false
185 visible: root._receiver.errorMessage.length > 0
186 text: root._receiver.errorMessage
191 // The indicator's loader sizes the panel from its implicit width. A layout would compute it from its contents, and
192 // GPSNoteLabel's zero preferred width keeps the notes from adding any, so a plain item supplies the width.
193 expandedComponent: Component {
195 implicitWidth: root._settingsWidth
196 implicitHeight: settingsPanel.implicitHeight
198 GPSReceiverSettings {
200 objectName: "gpsReceiverSettings"
202 // The status column shows the error unless the compact layout hides it.
203 showErrorMessage: root._compact