QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
MAVLinkChart.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Controls
3import QtQuick.Layouts
4import QtGraphs
5
6import QGroundControl
7import QGroundControl.Controls
8
9ColumnLayout {
10 id: chartView
11 visible: chartController.chartFields.length > 0
12 spacing: ScreenTools.defaultFontPixelHeight
13
14 required property var inspectorController
15 required property int chartIndex
16
17 property var _seriesColors: [qgcPal.colorGreen, qgcPal.colorOrange, qgcPal.colorRed, qgcPal.colorGrey, qgcPal.colorBlue, qgcPal.colorYellow]
18
19 Component {
20 id: lineSeriesComponent
21 LineSeries { }
22 }
23
24 function addDimension(field) {
25 if (!roomForNewDimension()) return
26 var color = _seriesColors[_graphsView.seriesList.length]
27 var serie = lineSeriesComponent.createObject(_graphsView, {color: color, width: 1, axisX: axisX, axisY: axisY})
28 _graphsView.addSeries(serie)
29 chartController.addSeries(field, serie)
30 }
31
32 function delDimension(field) {
33 for (var i = 0; i < _graphsView.seriesList.length; i++) {
34 if (_graphsView.seriesList[i] === field.series) {
35 var s = _graphsView.seriesList[i]
36 _graphsView.removeSeries(s)
37 chartController.delSeries(field)
38 // Do not call s.destroy() here. QGraphsView holds an internal
39 // pointer to the series (via QPointer) that is only cleared
40 // during the next updatePolish() pass. Destroying the series
41 // before that pass — whether immediately or via Qt.callLater —
42 // causes a SIGSEGV in QGraphsView::updatePolish(). The series
43 // is parented to _graphsView so it is freed when the chart is
44 // closed. GPU/graph resources are released by removeSeries().
45 break
46 }
47 }
48 }
49
50 function roomForNewDimension() {
51 return chartController.chartFields.length < _seriesColors.length
52 }
53
54 MAVLinkChartController {
55 id: chartController
56 inspectorController: chartView.inspectorController
57 chartIndex: chartView.chartIndex
58 plotPixelWidth: Math.max(1, Math.floor(_graphsView.plotArea.width))
59 }
60
61 // -------------------------------------------------------------------------
62 // Header: Scale / Range controls + active field labels
63 // -------------------------------------------------------------------------
64 Row {
65 spacing: ScreenTools.defaultFontPixelWidth
66
67 ColumnLayout {
68 LabelledComboBox {
69 label: qsTr("Scale")
70 model: inspectorController.timeScales
71 currentIndex: chartController.rangeXIndex
72 onActivated: (index) => { chartController.rangeXIndex = index }
73 }
74
75 LabelledComboBox {
76 label: qsTr("Range")
77 model: inspectorController.rangeList
78 currentIndex: chartController.rangeYIndex
79 onActivated: (index) => { chartController.rangeYIndex = index }
80 }
81 }
82
83 ColumnLayout {
84 spacing: 0
85
86 Repeater {
87 model: chartController.chartFields
88
89 QGCLabel {
90 text: modelData.label
91 color: index < _graphsView.seriesList.length ? _graphsView.seriesList[index].color : qgcPal.text
92 font.pointSize: ScreenTools.smallFontPointSize
93 }
94 }
95 }
96 }
97
98 // -------------------------------------------------------------------------
99 // Chart
100 // -------------------------------------------------------------------------
101 GraphsView {
102 id: _graphsView
103 Layout.fillWidth: true
104 Layout.fillHeight: true
105 marginBottom: ScreenTools.defaultFontPixelHeight * 1.5
106 marginTop: 0
107 marginLeft: 0
108 marginRight: 0
109
110 theme: GraphsTheme {
111 colorScheme: qgcPal.globalTheme === QGCPalette.Light ? GraphsTheme.ColorScheme.Light : GraphsTheme.ColorScheme.Dark
112 backgroundColor: qgcPal.window
113 backgroundVisible: true
114 plotAreaBackgroundColor: qgcPal.window
115 grid.mainColor: Qt.rgba(qgcPal.text.r, qgcPal.text.g, qgcPal.text.b, 0.3)
116 grid.subColor: Qt.rgba(qgcPal.text.r, qgcPal.text.g, qgcPal.text.b, 0.15)
117 grid.mainWidth: 1
118 labelBackgroundVisible: false
119 labelTextColor: qgcPal.text
120 axisXLabelFont.family: ScreenTools.fixedFontFamily
121 axisXLabelFont.pointSize: ScreenTools.smallFontPointSize
122 axisYLabelFont.family: ScreenTools.fixedFontFamily
123 axisYLabelFont.pointSize: ScreenTools.smallFontPointSize
124 }
125
126 axisX: ValueAxis {
127 id: axisX
128 min: chartController.rangeXMin
129 max: chartController.rangeXMax
130 tickInterval: chartController.rangeXMs / 3
131 subTickCount: 0
132 labelsVisible: true
133 labelDelegate: Component {
134 Item {
135 property string text
136 implicitWidth: label.implicitWidth
137 implicitHeight: label.implicitHeight
138 Text {
139 id: label
140 text: {
141 var ms = parseFloat(parent.text)
142 if (isNaN(ms)) return parent.text
143 var d = new Date(ms)
144 return d.getMinutes().toString().padStart(2, '0') + ":" + d.getSeconds().toString().padStart(2, '0')
145 }
146 color: qgcPal.text
147 font.family: ScreenTools.fixedFontFamily
148 font.pointSize: ScreenTools.smallFontPointSize
149 }
150 }
151 }
152 }
153
154 axisY: ValueAxis {
155 id: axisY
156 min: chartController.rangeYMin
157 max: chartController.rangeYMax
158 lineVisible: false
159 }
160 }
161}